Загрузка данных
diff --git a/src/components/Toolbar/index.tsx b/src/components/Toolbar/index.tsx
index 94f9e9ceaf1031a4a495ca728f349170430bfeff..cb86a0c2185f0020a2529e571af7ca634b8b9012 100644
--- a/src/components/Toolbar/index.tsx
+++ b/src/components/Toolbar/index.tsx
@@ -3,6 +3,8 @@ import { Button, Divider, Tooltip } from 'exchange-elements/v2';
import { Dispatch, SetStateAction, useRef, useState } from 'react';
+import { Observable } from 'rxjs';
+
import { DrawingsNames } from '@core/DrawingsManager';
import { MenuList } from '@src/components/Menu';
@@ -10,7 +12,7 @@ import SplitDropdown from '@src/components/SplitDropdown';
import { geometricShapes, measurementTools, trendLines } from '@src/components/Toolbar/constants';
-import { ensureDefined } from '@src/utils';
+import { ensureDefined, useObservable } from '@src/utils';
import {
CrossIcon,
@@ -33,6 +35,8 @@ import styles from './index.module.scss';
interface ToolbarProps {
toggleDOM: () => void;
addDrawing: (name: DrawingsNames) => void;
+ setEndlessDrawingsMode: (value: boolean) => void;
+ isEndlessDrawingsMode$: Observable<boolean>;
}
const implemented = {
@@ -46,11 +50,18 @@ const implemented = {
icons: false,
};
-export default function Toolbar({ toggleDOM, addDrawing }: ToolbarProps) {
+export default function Toolbar({
+ toggleDOM,
+ addDrawing,
+ setEndlessDrawingsMode,
+ isEndlessDrawingsMode$,
+}: ToolbarProps) {
const [selectedLineType, setSelectedLineType] = useState<DrawingsNames>(DrawingsNames.trendLine);
const [selectedMeasurementTool, setSelectedMeasurementTool] = useState(DrawingsNames.fixedProfile);
const [selectedGeometricShape, setSelectedGeometricShape] = useState(DrawingsNames.rectangle);
+ const isEndlessDrawingsMode = useObservable(isEndlessDrawingsMode$);
+
const toolbarRef = useRef<HTMLDivElement | null>(null);
const createDrawingHandler = (setter: Dispatch<SetStateAction<DrawingsNames>>) => (value: DrawingsNames) => {
@@ -230,14 +241,15 @@ export default function Toolbar({ toggleDOM, addDrawing }: ToolbarProps) {
</div>
<Divider
direction="horizontal"
- pt={{ divider: { className: classNames(styles.divider, styles.notImplemented) } }}
+ pt={{ divider: { className: classNames(styles.divider) } }}
/>
- <div className={classNames(styles.group, styles.notImplemented)}>
+ <div className={classNames(styles.group)}>
<Tooltip
tooltipClassName={styles.tooltipHint}
showMessageOnFocus
label="Магнит позволяет притягивать точки объектов к ближайшим ценам (откр., макс., мин., закр.) баров"
location="right"
+ className={styles.notImplemented}
>
<Button
size="sm"
@@ -255,8 +267,10 @@ export default function Toolbar({ toggleDOM, addDrawing }: ToolbarProps) {
>
<Button
size="sm"
- className={styles.button}
- onClick={() => {}}
+ className={`${styles.button} ${isEndlessDrawingsMode ? styles.pressed : ''}`}
+ onClick={() => {
+ setEndlessDrawingsMode(!isEndlessDrawingsMode);
+ }}
label={<PencilLockerIcon />}
/>
</Tooltip>
@@ -266,6 +280,7 @@ export default function Toolbar({ toggleDOM, addDrawing }: ToolbarProps) {
showMessageOnFocus
label="Зафиксировать все объекты"
location="right"
+ className={styles.notImplemented}
>
<Button
size="sm"
@@ -280,6 +295,7 @@ export default function Toolbar({ toggleDOM, addDrawing }: ToolbarProps) {
showMessageOnFocus
label="Скрыть все объекты рисования"
location="right"
+ className={styles.notImplemented}
>
<Button
size="sm"
diff --git a/src/core/Drawings.ts b/src/core/Drawings.ts
index e4c3881e748f4e53a1d1d470e8885ef19707ac60..651a7dd649d9111c34acb383afdd3b16d0616999 100644
--- a/src/core/Drawings.ts
+++ b/src/core/Drawings.ts
@@ -1,5 +1,9 @@
import { IChartApi, ISeriesApi, SeriesType } from 'lightweight-charts';
+import { firstValueFrom } from 'rxjs';
+
+import { filter } from 'rxjs/operators';
+
import { DOMObject, DOMObjectParams } from '@core/DOMObject';
import { ISeriesDrawing } from '@core/Drawings/common';
import { SeriesStrategies } from '@src/modules/series-strategies/SeriesFactory';
@@ -54,6 +58,10 @@ export class Drawing extends DOMObject implements IDrawing {
return this.lwcDrawing.isCreationPending();
}
+ public awaitCreation(): Promise<boolean> {
+ return firstValueFrom(this.lwcDrawing.isCreationPendingObs().pipe(filter((value) => !value)));
+ }
+
public destroy() {
this.mainSeries.detachPrimitive(this.lwcDrawing);
this.lwcDrawing.destroy();
diff --git a/src/core/Drawings/axisLine/axisLine.ts b/src/core/Drawings/axisLine/axisLine.ts
index 841ed2208185c5ea945354ecef25bd0237023745..cd7d4626beb7e7ed1b5d1502c46d258f59617fba 100644
--- a/src/core/Drawings/axisLine/axisLine.ts
+++ b/src/core/Drawings/axisLine/axisLine.ts
@@ -10,7 +10,7 @@ import {
Time,
UTCTimestamp,
} from 'lightweight-charts';
-import { Observable, Subscription } from 'rxjs';
+import { BehaviorSubject, Observable, Subscription } from 'rxjs';
import { CustomPriceAxisView, CustomTimeAxisView } from '@core/Drawings/axis';
import {
@@ -76,6 +76,7 @@ export class AxisLine implements ISeriesDrawing {
private hidden = false;
private isActive = false;
private mode: AxisLineMode = 'idle';
+ private isBusy: BehaviorSubject<boolean> = new BehaviorSubject(true);
private direction: AxisLineDirection;
private time: Time | null = null;
@@ -163,7 +164,11 @@ export class AxisLine implements ISeriesDrawing {
}
public isCreationPending(): boolean {
- return this.mode === 'idle';
+ return this.isBusy.value;
+ }
+
+ public isCreationPendingObs(): Observable<boolean> {
+ return this.isBusy.asObservable();
}
public getState(): AxisLineState {
@@ -189,6 +194,8 @@ export class AxisLine implements ISeriesDrawing {
if ('mode' in nextState && nextState.mode) {
this.mode = nextState.mode;
+
+ this.isBusy.next(this.mode === 'idle');
}
if ('time' in nextState) {
@@ -371,6 +378,7 @@ export class AxisLine implements ISeriesDrawing {
this.updateLine(point);
this.isActive = true;
+ this.isBusy.next(false);
this.mode = 'ready';
this.render();
return;
@@ -412,6 +420,7 @@ export class AxisLine implements ISeriesDrawing {
event.stopPropagation();
this.mode = 'dragging';
+ this.isBusy.next(false);
this.dragPointerId = event.pointerId;
this.hideCrosshair();
this.render();
@@ -435,6 +444,7 @@ export class AxisLine implements ISeriesDrawing {
}
this.mode = 'ready';
+ this.isBusy.next(false);
this.dragPointerId = null;
this.showCrosshair();
this.render();
diff --git a/src/core/Drawings/common.ts b/src/core/Drawings/common.ts
index 0acfe0bfdc32ddae8bd8e492e335cb8a56443f67..1c67536a3b5a1c8928f2218818f838ac7baf05ba 100644
--- a/src/core/Drawings/common.ts
+++ b/src/core/Drawings/common.ts
@@ -1,4 +1,5 @@
import { Coordinate, ISeriesApi, ISeriesPrimitive, SeriesType, Time } from 'lightweight-charts';
+import { Observable } from 'rxjs';
export interface BitmapPositionLength {
/** coordinate for use with a bitmap rendering scope */
@@ -24,6 +25,7 @@ export interface ISeriesDrawing extends ISeriesPrimitive<Time> {
rebind(series: ISeriesApi<SeriesType>): void;
destroy(): void;
isCreationPending(): boolean;
+ isCreationPendingObs(): Observable<boolean>;
}
export function positionsBox(position1Media: number, position2Media: number, pixelRatio: number): BitmapPositionLength {
diff --git a/src/core/Drawings/diapson/diapson.ts b/src/core/Drawings/diapson/diapson.ts
index 3c4ba3d553f706a326eb7e39c3fcd0dafaded05b..a5bbef7dc01939a29762bec9477502b93d2aa811 100644
--- a/src/core/Drawings/diapson/diapson.ts
+++ b/src/core/Drawings/diapson/diapson.ts
@@ -1,4 +1,4 @@
-import { Observable, Subscription } from 'rxjs';
+import { BehaviorSubject, Observable, Subscription } from 'rxjs';
import {
CustomPriceAxisPaneView,
@@ -117,6 +117,7 @@ export class Diapson implements ISeriesDrawing {
private isActive = false;
private interactionMode: InteractionMode = 'idle';
private rangeMode: DiapsonRangeMode;
+ private isBusy: BehaviorSubject<boolean> = new BehaviorSubject(true);
private startTime: Time | null = null;
private endTime: Time | null = null;
@@ -231,7 +232,11 @@ export class Diapson implements ISeriesDrawing {
}
public isCreationPending(): boolean {
- return this.interactionMode === 'idle' || this.interactionMode === 'drawing';
+ return this.isBusy.value;
+ }
+
+ public isCreationPendingObs(): Observable<boolean> {
+ return this.isBusy.asObservable();
}
public setRangeMode(nextMode: DiapsonRangeMode): void {
@@ -266,6 +271,7 @@ export class Diapson implements ISeriesDrawing {
this.hidden = typeof nextState.hidden === 'boolean' ? nextState.hidden : this.hidden;
this.isActive = typeof nextState.isActive === 'boolean' ? nextState.isActive : this.isActive;
this.interactionMode = nextState.interactionMode ?? this.interactionMode;
+ this.isBusy.next(this.interactionMode === 'idle' || this.interactionMode === 'drawing');
this.rangeMode = nextState.rangeMode ?? this.rangeMode;
this.startTime = 'startTime' in nextState ? (nextState.startTime ?? null) : this.startTime;
this.endTime = 'endTime' in nextState ? (nextState.endTime ?? null) : this.endTime;
@@ -598,6 +604,7 @@ export class Diapson implements ISeriesDrawing {
this.isActive = true;
this.interactionMode = 'drawing';
+ this.isBusy.next(true);
this.render();
}
@@ -633,11 +640,13 @@ export class Diapson implements ISeriesDrawing {
}
this.interactionMode = 'ready';
+ this.isBusy.next(false);
this.render();
}
private startDragging(point: Point, pointerId: number, dragTarget: Exclude<DiapsonHandle, null>): void {
this.interactionMode = 'dragging';
+ this.isBusy.next(false);
this.activeDragTarget = dragTarget;
this.dragPointerId = pointerId;
this.dragStartPoint = point;
@@ -648,6 +657,7 @@ export class Diapson implements ISeriesDrawing {
private finishDragging(): void {
this.interactionMode = 'ready';
+ this.isBusy.next(false);
this.clearInteractionState();
this.render();
}
@@ -663,6 +673,7 @@ export class Diapson implements ISeriesDrawing {
this.hidden = false;
this.isActive = false;
this.interactionMode = 'idle';
+ this.isBusy.next(true);
this.startTime = null;
this.endTime = null;
this.startPrice = null;
diff --git a/src/core/Drawings/ray/ray.ts b/src/core/Drawings/ray/ray.ts
index a677f6e5c4fbe67c8d2c4408d3319832a5b42f32..a8a4160440ee6ea0ae153bc1003f0dca20fecc49 100644
--- a/src/core/Drawings/ray/ray.ts
+++ b/src/core/Drawings/ray/ray.ts
@@ -10,7 +10,7 @@ import {
Time,
UTCTimestamp,
} from 'lightweight-charts';
-import { Observable, Subscription } from 'rxjs';
+import { BehaviorSubject, Observable, Subscription } from 'rxjs';
import {
CustomPriceAxisPaneView,
@@ -89,6 +89,7 @@ export class Ray implements ISeriesDrawing {
private hidden = false;
private isActive = false;
private mode: RayMode = 'idle';
+ private isBusy: BehaviorSubject<boolean> = new BehaviorSubject(true);
private startAnchor: Anchor | null = null;
private directionAnchor: Anchor | null = null;
@@ -195,7 +196,11 @@ export class Ray implements ISeriesDrawing {
}
public isCreationPending(): boolean {
- return this.mode === 'idle' || this.mode === 'drawing';
+ return this.isBusy.value;
+ }
+
+ public isCreationPendingObs(): Observable<boolean> {
+ return this.isBusy.asObservable();
}
public getState(): RayState {
@@ -221,6 +226,7 @@ export class Ray implements ISeriesDrawing {
if ('mode' in nextState && nextState.mode) {
this.mode = nextState.mode;
+ this.isBusy.next(this.mode === 'idle' || this.mode === 'drawing');
}
if ('startAnchor' in nextState) {
@@ -560,6 +566,8 @@ export class Ray implements ISeriesDrawing {
this.directionAnchor = anchor;
this.isActive = true;
this.mode = 'drawing';
+ this.isBusy.next(true);
+
this.render();
}
@@ -592,11 +600,15 @@ export class Ray implements ISeriesDrawing {
}
this.mode = 'ready';
+ this.isBusy.next(false);
+
this.render();
}
private startDragging(mode: RayMode, point: Point, pointerId: number): void {
this.mode = mode;
+ this.isBusy.next(this.mode === 'idle' || this.mode === 'drawing');
+
this.dragPointerId = pointerId;
this.dragStartPoint = point;
this.dragStateSnapshot = this.getState();
@@ -607,6 +619,7 @@ export class Ray implements ISeriesDrawing {
private finishDragging(): void {
this.mode = 'ready';
+ this.isBusy.next(false);
this.dragPointerId = null;
this.dragStartPoint = null;
this.dragStateSnapshot = null;
diff --git a/src/core/Drawings/rectangle/rectangle.ts b/src/core/Drawings/rectangle/rectangle.ts
index 922d139498fc497655deef675f6fd3d227552f43..58120f5bdd3c1874b252d56c6d5d342b2eb64c07 100644
--- a/src/core/Drawings/rectangle/rectangle.ts
+++ b/src/core/Drawings/rectangle/rectangle.ts
@@ -1,4 +1,4 @@
-import { Observable, Subscription } from 'rxjs';
+import { BehaviorSubject, Observable, Subscription } from 'rxjs';
import {
CustomPriceAxisPaneView,
@@ -100,6 +100,7 @@ export class Rectangle implements ISeriesDrawing {
private hidden = false;
private isActive = false;
private mode: RectangleMode = 'idle';
+ private isBusy: BehaviorSubject<boolean> = new BehaviorSubject(true);
private startTime: Time | null = null;
private endTime: Time | null = null;
@@ -207,7 +208,11 @@ export class Rectangle implements ISeriesDrawing {
}
public isCreationPending(): boolean {
- return this.mode === 'idle' || this.mode === 'drawing';
+ return this.isBusy.value;
+ }
+
+ public isCreationPendingObs(): Observable<boolean> {
+ return this.isBusy.asObservable();
}
public getState(): RectangleState {
@@ -235,6 +240,7 @@ export class Rectangle implements ISeriesDrawing {
if ('mode' in nextState && nextState.mode) {
this.mode = nextState.mode;
+ this.isBusy.next(this.mode === 'idle' || this.mode === 'drawing');
}
if ('startTime' in nextState) {
@@ -577,6 +583,8 @@ export class Rectangle implements ISeriesDrawing {
this.isActive = true;
this.mode = 'drawing';
+ this.isBusy.next(true);
+
this.render();
}
@@ -608,11 +616,15 @@ export class Rectangle implements ISeriesDrawing {
}
this.mode = 'ready';
+ this.isBusy.next(false);
+
this.render();
}
private startDragging(point: Point, pointerId: number, dragTarget: Exclude<RectangleHandle, null>): void {
this.mode = 'dragging';
+ this.isBusy.next(false);
+
this.activeDragTarget = dragTarget;
this.dragPointerId = pointerId;
this.dragStartPoint = point;
@@ -624,6 +636,8 @@ export class Rectangle implements ISeriesDrawing {
private finishDragging(): void {
this.mode = 'ready';
+ this.isBusy.next(false);
+
this.clearInteractionState();
this.render();
}
@@ -640,6 +654,8 @@ export class Rectangle implements ISeriesDrawing {
this.hidden = false;
this.isActive = false;
this.mode = 'idle';
+ this.isBusy.next(true);
+
this.startTime = null;
this.endTime = null;
this.startPrice = null;
diff --git a/src/core/Drawings/ruler/ruler.ts b/src/core/Drawings/ruler/ruler.ts
index b1924f2ceb8c1efbac24c20f2f0366bceee52d5d..6c6c704c40e56670baf619e5edabc0fb0b2c1765 100644
--- a/src/core/Drawings/ruler/ruler.ts
+++ b/src/core/Drawings/ruler/ruler.ts
@@ -1,4 +1,4 @@
-import { Observable, skip, Subscription } from 'rxjs';
+import { BehaviorSubject, Observable, skip, Subscription } from 'rxjs';
import {
CustomPriceAxisPaneView,
@@ -99,6 +99,7 @@ export class Ruler implements ISeriesDrawing {
private hidden = false;
private mode: RulerMode = 'idle';
+ private isBusy: BehaviorSubject<boolean> = new BehaviorSubject(true);
private startAnchor: Anchor | null = null;
private endAnchor: Anchor | null = null;
@@ -214,7 +215,11 @@ export class Ruler implements ISeriesDrawing {
}
public isCreationPending(): boolean {
- return this.mode === 'idle' || this.mode === 'placingEnd';
+ return this.isBusy.value;
+ }
+
+ public isCreationPendingObs(): Observable<boolean> {
+ return this.isBusy.asObservable();
}
public getState(): RulerState {
@@ -231,6 +236,8 @@ export class Ruler implements ISeriesDrawing {
this.hidden = nextState.hidden ?? this.hidden;
this.mode = nextState.mode ?? this.mode;
+ this.isBusy.next(this.mode === 'idle' || this.mode === 'placingEnd');
+
this.startAnchor = nextState.startAnchor ?? this.startAnchor;
this.endAnchor = nextState.endAnchor ?? this.endAnchor;
@@ -591,6 +598,8 @@ export class Ruler implements ISeriesDrawing {
this.startAnchor = anchor;
this.endAnchor = anchor;
this.mode = 'placingEnd';
+ this.isBusy.next(true);
+
this.setCrosshairVisible(false);
this.render();
return;
@@ -599,6 +608,8 @@ export class Ruler implements ISeriesDrawing {
if (this.mode === 'placingEnd') {
this.endAnchor = anchor;
this.mode = 'ready';
+ this.isBusy.next(false);
+
this.setCrosshairVisible(true);
this.render();
}
diff --git a/src/core/Drawings/sliderPosition/sliderPosition.ts b/src/core/Drawings/sliderPosition/sliderPosition.ts
index fd462d6ba06f244078b45500d910e6db4b937212..cb3003d46053a2a1d0da266a3ed0cc497cc312d3 100644
--- a/src/core/Drawings/sliderPosition/sliderPosition.ts
+++ b/src/core/Drawings/sliderPosition/sliderPosition.ts
@@ -1,4 +1,4 @@
-import { Observable, skip, Subscription } from 'rxjs';
+import { BehaviorSubject, Observable, skip, Subscription } from 'rxjs';
import {
CustomPriceAxisPaneView,
@@ -121,6 +121,7 @@ export class SliderPosition implements ISeriesDrawing {
private hidden = false;
private active = true;
private mode: SliderMode = 'idle';
+ private isBusy: BehaviorSubject<boolean> = new BehaviorSubject(true);
private side: SliderSide;
private startTime: Time | null = null;
@@ -252,7 +253,11 @@ export class SliderPosition implements ISeriesDrawing {
}
public isCreationPending(): boolean {
- return this.mode === 'idle';
+ return this.isBusy.value;
+ }
+
+ public isCreationPendingObs(): Observable<boolean> {
+ return this.isBusy.asObservable();
}
public getState(): SliderPositionState {
@@ -277,6 +282,8 @@ export class SliderPosition implements ISeriesDrawing {
this.hidden = next.hidden ?? this.hidden;
this.active = next.active ?? this.active;
this.mode = next.mode ?? this.mode;
+ this.isBusy.next(this.mode === 'idle');
+
this.startTime = next.startTime ?? this.startTime;
this.endTime = next.endTime ?? this.endTime;
this.entryPrice = next.entryPrice ?? this.entryPrice;
@@ -689,6 +696,8 @@ export class SliderPosition implements ISeriesDrawing {
this.active = true;
this.mode = 'ready';
+ this.isBusy.next(false);
+
this.render();
return;
}
@@ -718,6 +727,7 @@ export class SliderPosition implements ISeriesDrawing {
this.dragStateSnapshot = this.getState();
this.didDrag = false;
this.mode = 'dragging';
+ this.isBusy.next(false);
};
private handlePointerMove = (event: PointerEvent): void => {
@@ -745,6 +755,8 @@ export class SliderPosition implements ISeriesDrawing {
this.dragStateSnapshot = null;
this.didDrag = false;
this.mode = 'ready';
+ this.isBusy.next(false);
+
this.render();
};
diff --git a/src/core/Drawings/traectory/traectory.ts b/src/core/Drawings/traectory/traectory.ts
index 5705640615949f0c1024ac1bab00104e664dc4dd..2db579f756fbdd549932e60c6684f191a331eb21 100644
--- a/src/core/Drawings/traectory/traectory.ts
+++ b/src/core/Drawings/traectory/traectory.ts
@@ -8,7 +8,7 @@ import {
SeriesOptionsMap,
Time,
} from 'lightweight-charts';
-import { Observable } from 'rxjs';
+import { BehaviorSubject, Observable } from 'rxjs';
import { CustomPriceAxisPaneView, CustomTimeAxisPaneView } from '@core/Drawings/axis';
import {
@@ -76,6 +76,7 @@ export class Traectory implements ISeriesDrawing {
private hidden = false;
private isActive = false;
private mode: TraectoryMode = 'idle';
+ private isBusy: BehaviorSubject<boolean> = new BehaviorSubject(true);
private points: Anchor[] = [];
private previewAnchor: Anchor | null = null;
@@ -145,7 +146,11 @@ export class Traectory implements ISeriesDrawing {
}
public isCreationPending(): boolean {
- return this.mode === 'idle' || this.mode === 'drawing';
+ return this.isBusy.value;
+ }
+
+ public isCreationPendingObs(): Observable<boolean> {
+ return this.isBusy.asObservable();
}
public getState(): TraectoryState {
@@ -167,6 +172,8 @@ export class Traectory implements ISeriesDrawing {
this.hidden = typeof nextState.hidden === 'boolean' ? nextState.hidden : this.hidden;
this.isActive = typeof nextState.isActive === 'boolean' ? nextState.isActive : this.isActive;
this.mode = nextState.mode ?? this.mode;
+ this.isBusy.next(this.mode === 'idle' || this.mode === 'drawing');
+
this.points = Array.isArray(nextState.points) ? nextState.points : this.points;
this.render();
@@ -457,6 +464,8 @@ export class Traectory implements ISeriesDrawing {
this.previewAnchor = anchor;
this.isActive = true;
this.mode = 'drawing';
+ this.isBusy.next(true);
+
this.render();
}
@@ -505,11 +514,15 @@ export class Traectory implements ISeriesDrawing {
this.previewAnchor = null;
this.isActive = true;
this.mode = 'ready';
+ this.isBusy.next(false);
+
this.render();
}
private startDraggingPoint(point: Point, pointerId: number, pointIndex: number): void {
this.mode = 'dragging-point';
+ this.isBusy.next(false);
+
this.dragPointerId = pointerId;
this.dragStartPoint = point;
this.dragPointIndex = pointIndex;
@@ -521,6 +534,8 @@ export class Traectory implements ISeriesDrawing {
private startDraggingBody(point: Point, pointerId: number): void {
this.mode = 'dragging-body';
+ this.isBusy.next(false);
+
this.dragPointerId = pointerId;
this.dragStartPoint = point;
this.dragPointIndex = null;
@@ -532,6 +547,8 @@ export class Traectory implements ISeriesDrawing {
private finishDragging(): void {
this.mode = 'ready';
+ this.isBusy.next(false);
+
this.dragPointerId = null;
this.dragStartPoint = null;
this.dragPointIndex = null;
@@ -544,6 +561,8 @@ export class Traectory implements ISeriesDrawing {
private resetToIdle(): void {
this.isActive = false;
this.mode = 'idle';
+ this.isBusy.next(true);
+
this.points = [];
this.previewAnchor = null;
this.dragPointerId = null;
diff --git a/src/core/Drawings/trendLine/trendLine.ts b/src/core/Drawings/trendLine/trendLine.ts
index ce78d84c0a73fc8a553db98d7e9390099f45b71c..17c593deb09f0d9efcc3eaf525da92d645a3a1e7 100644
--- a/src/core/Drawings/trendLine/trendLine.ts
+++ b/src/core/Drawings/trendLine/trendLine.ts
@@ -10,7 +10,7 @@ import {
Time,
UTCTimestamp,
} from 'lightweight-charts';
-import { Observable, Subscription } from 'rxjs';
+import { BehaviorSubject, Observable, Subscription } from 'rxjs';
import {
CustomPriceAxisPaneView,
@@ -87,6 +87,7 @@ export class TrendLine implements ISeriesDrawing {
private hidden = false;
private isActive = false;
private mode: TrendLineMode = 'idle';
+ private isBusy: BehaviorSubject<boolean> = new BehaviorSubject(true);
private startAnchor: Anchor | null = null;
private endAnchor: Anchor | null = null;
@@ -193,7 +194,11 @@ export class TrendLine implements ISeriesDrawing {
}
public isCreationPending(): boolean {
- return this.mode === 'idle' || this.mode === 'drawing';
+ return this.isBusy.value;
+ }
+
+ public isCreationPendingObs(): Observable<boolean> {
+ return this.isBusy.asObservable();
}
public getState(): TrendLineState {
@@ -219,6 +224,7 @@ export class TrendLine implements ISeriesDrawing {
if ('mode' in nextState && nextState.mode) {
this.mode = nextState.mode;
+ this.isBusy.next(this.mode === 'idle' || this.mode === 'drawing');
}
if ('startAnchor' in nextState) {
@@ -558,6 +564,8 @@ export class TrendLine implements ISeriesDrawing {
this.endAnchor = anchor;
this.isActive = true;
this.mode = 'drawing';
+ this.isBusy.next(true);
+
this.render();
}
@@ -590,11 +598,15 @@ export class TrendLine implements ISeriesDrawing {
}
this.mode = 'ready';
+ this.isBusy.next(false);
+
this.render();
}
private startDragging(mode: TrendLineMode, point: Point, pointerId: number): void {
this.mode = mode;
+ this.isBusy.next(this.mode === 'idle' || this.mode === 'drawing');
+
this.dragPointerId = pointerId;
this.dragStartPoint = point;
this.dragStateSnapshot = this.getState();
@@ -605,6 +617,8 @@ export class TrendLine implements ISeriesDrawing {
private finishDragging(): void {
this.mode = 'ready';
+ this.isBusy.next(false);
+
this.dragPointerId = null;
this.dragStartPoint = null;
this.dragStateSnapshot = null;
diff --git a/src/core/Drawings/volumeProfile/volumeProfile.ts b/src/core/Drawings/volumeProfile/volumeProfile.ts
index 086688853b2c59a41ccac83dd4cf263e47c19b2c..c4e388607986089b038ba814101f65be514f9008 100644
--- a/src/core/Drawings/volumeProfile/volumeProfile.ts
+++ b/src/core/Drawings/volumeProfile/volumeProfile.ts
@@ -11,7 +11,7 @@ import {
Time,
UTCTimestamp,
} from 'lightweight-charts';
-import { Observable, Subscription } from 'rxjs';
+import { BehaviorSubject, Observable, Subscription } from 'rxjs';
import {
CustomPriceAxisPaneView,
@@ -120,6 +120,7 @@ export class VolumeProfile implements ISeriesDrawing {
private hidden = false;
private isActive = false;
private mode: VolumeProfileMode = 'idle';
+ private isBusy: BehaviorSubject<boolean> = new BehaviorSubject(true);
private startAnchor: Anchor | null = null;
private endAnchor: Anchor | null = null;
@@ -229,7 +230,11 @@ export class VolumeProfile implements ISeriesDrawing {
}
public isCreationPending(): boolean {
- return this.mode === 'idle' || this.mode === 'drawing';
+ return this.isBusy.value;
+ }
+
+ public isCreationPendingObs(): Observable<boolean> {
+ return this.isBusy.asObservable();
}
public getState(): VolumeProfileState {
@@ -248,6 +253,8 @@ export class VolumeProfile implements ISeriesDrawing {
this.hidden = typeof nextState.hidden === 'boolean' ? nextState.hidden : this.hidden;
this.isActive = typeof nextState.isActive === 'boolean' ? nextState.isActive : this.isActive;
this.mode = nextState.mode ?? this.mode;
+ this.isBusy.next(this.mode === 'idle' || this.mode === 'drawing');
+
this.startAnchor = nextState.startAnchor ?? this.startAnchor;
this.endAnchor = nextState.endAnchor ?? this.endAnchor;
@@ -582,6 +589,7 @@ export class VolumeProfile implements ISeriesDrawing {
this.endAnchor = anchor;
this.isActive = true;
this.mode = 'drawing';
+ this.isBusy.next(true);
this.calculateProfile();
this.render();
@@ -614,11 +622,15 @@ export class VolumeProfile implements ISeriesDrawing {
}
this.mode = 'ready';
+ this.isBusy.next(false);
+
this.render();
}
private startDragging(point: Point, pointerId: number, dragTarget: Exclude<DragTarget, null>): void {
this.mode = 'dragging';
+ this.isBusy.next(false);
+
this.activeDragTarget = dragTarget;
this.dragPointerId = pointerId;
this.dragStartPoint = point;
@@ -630,6 +642,8 @@ export class VolumeProfile implements ISeriesDrawing {
private finishDragging(): void {
this.mode = 'ready';
+ this.isBusy.next(false);
+
this.activeDragTarget = null;
this.dragPointerId = null;
this.dragStartPoint = null;
@@ -643,6 +657,8 @@ export class VolumeProfile implements ISeriesDrawing {
this.hidden = false;
this.isActive = false;
this.mode = 'idle';
+ this.isBusy.next(true);
+
this.startAnchor = null;
this.endAnchor = null;
this.profileRows = [];
diff --git a/src/core/DrawingsManager.ts b/src/core/DrawingsManager.ts
index f752c543c93aa15b431d409eb687c1119c279508..d9ebc9ba4437b69f3729872602cb13820584f2b9 100644
--- a/src/core/DrawingsManager.ts
+++ b/src/core/DrawingsManager.ts
@@ -191,7 +191,6 @@ export const drawingsMap: Record<DrawingsNames, DrawingConfig> = {
export class DrawingsManager {
private eventManager: EventManager;
private lwcChart: IChartApi;
- // private chartOptions?: ChartTypeOptions;
private drawingsQty = 0; // todo: replace with hash
private DOM: DOMModel;
private container: HTMLElement;
@@ -199,12 +198,12 @@ export class DrawingsManager {
private mainSeries: SeriesStrategies | null = null;
private subscriptions = new Subscription();
private drawings$: BehaviorSubject<Drawing[]> = new BehaviorSubject<Drawing[]>([]);
+ private isEndlessDrawingMode$: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
constructor({ eventManager, mainSeries$, lwcChart, DOM, container }: DrawingsManagerParams) {
this.DOM = DOM;
this.eventManager = eventManager;
this.lwcChart = lwcChart;
- // this.chartOptions = chartOptions;
this.container = container;
this.subscriptions.add(
@@ -217,7 +216,7 @@ export class DrawingsManager {
);
}
- public addDrawing(name: DrawingsNames) {
+ public async addDrawing(name: DrawingsNames) {
if (!this.mainSeries) {
throw new Error('[Drawings] main series is not defined');
}
@@ -253,10 +252,27 @@ export class DrawingsManager {
construct,
});
- const trendLine = this.DOM.setEntity<Drawing>(drawing);
+ const entity = this.DOM.setEntity<Drawing>(drawing);
this.drawingsQty++;
- this.drawings$.next([...this.drawings$.value, trendLine]);
+ this.drawings$.next([...this.drawings$.value, entity]);
+
+ if (this.isEndlessDrawingMode$.value) {
+ await entity.awaitCreation();
+ this.addDrawing(name);
+ }
+ }
+
+ public setEndlessDrawingMode = (value: boolean) => {
+ this.isEndlessDrawingMode$.next(value);
+
+ if (!value) {
+ this.removePendingDrawings();
+ }
+ };
+
+ public isEndlessDrawingsMode(): Observable<boolean> {
+ return this.isEndlessDrawingMode$;
}
private removeDrawing = (id: string) => {
diff --git a/src/core/MoexChart.tsx b/src/core/MoexChart.tsx
index 3fb0d6a2b7b086f12ac105f79b8b739c84d0ed20..624a7cfd953b7c09887f58c9bf88d424f140fa0d 100644
--- a/src/core/MoexChart.tsx
+++ b/src/core/MoexChart.tsx
@@ -232,6 +232,8 @@ export class MoexChart {
// todo: deal with new panes logic
this.chart.getDrawingsManager().addDrawing(name);
}}
+ setEndlessDrawingsMode={this.chart.getDrawingsManager().setEndlessDrawingMode}
+ isEndlessDrawingsMode$={this.chart.getDrawingsManager().isEndlessDrawingsMode()}
/>,
);
}