Загрузка данных
diff --git a/src/core/CompareManager.ts b/src/core/CompareManager.ts
index e289018a3e2a395f445c4c2b8238dbdf486d75d1..3de5f5476c0e76e35a3eb08ac64b7eaf9a2251b3 100644
--- a/src/core/CompareManager.ts
+++ b/src/core/CompareManager.ts
@@ -70,8 +70,11 @@ export class CompareManager {
private async setup(initialIndicators: IndicatorSnapshot[]) {
for (const indicator of initialIndicators) {
+ if (indicator.indicatorType !== undefined) {
+ continue;
+ }
+
if (indicator.config && indicator.config.label) {
- // условие проверки compare ли это
const serie = indicator.config.series[0];
const compareMode =
diff --git a/src/core/Indicator.ts b/src/core/Indicator.ts
index ebb76629e488befed391a92cdc0fc59b6ccbe785..b0d9ee7fb83a2a45da4a06df81aa5bb3188bb8e5 100644
--- a/src/core/Indicator.ts
+++ b/src/core/Indicator.ts
@@ -75,10 +75,6 @@ export class Indicator extends DOMObject implements ISerializable<IndicatorSnaps
});
}
- public deletable = (): boolean => {
- return this.associatedPane.isMainPane() || this.associatedPane.isLast();
- };
-
public getLabel = () => {
if (this.config.label) {
return this.config.label;
@@ -207,7 +203,7 @@ export class Indicator extends DOMObject implements ISerializable<IndicatorSnaps
mainSymbol$: this.mainSymbol$,
mainSerie$: this.associatedPane.getMainSerie(),
showSymbolLabel: false,
- paneIndex: this.associatedPane.getId(),
+ paneIndex: this.associatedPane.paneIndex(),
indicatorReference: this,
});
diff --git a/src/core/Legend.ts b/src/core/Legend.ts
index 68e535fba69b812517f3a6f6664d4a0182f715aa..dbb1feeabbb5f7b1e11745785ce0aaf743b97108 100644
--- a/src/core/Legend.ts
+++ b/src/core/Legend.ts
@@ -17,6 +17,7 @@ export interface LegendParams {
subscribeChartEvent: ChartMouseEvents['subscribe'];
mainSeries: BehaviorSubject<SeriesStrategies | null> | null;
paneId: number;
+ paneIndex: () => number;
openIndicatorSettings: (id: IndicatorsIds, indicator: Indicator) => void;
}
@@ -85,6 +86,7 @@ export class Legend {
private tooltipVisability = new BehaviorSubject<boolean>(false);
private tooltipPos = new BehaviorSubject<null | Point>(null);
private paneId: number;
+ private paneIndex: () => number;
private openIndicatorSettings: (id: IndicatorsIds, indicator: Indicator) => void;
private subscriptions = new Subscription();
@@ -98,11 +100,13 @@ export class Legend {
subscribeChartEvent,
mainSeries,
paneId,
+ paneIndex,
openIndicatorSettings,
}: LegendParams) {
this.config = config;
this.eventManager = eventManager;
this.paneId = paneId;
+ this.paneIndex = paneIndex;
this.openIndicatorSettings = openIndicatorSettings;
this.subscriptions.add(
@@ -210,8 +214,6 @@ export class Legend {
indicatorSeries.set(serieName, { ...value, name: indicator.getSeriesLabel(serieName) });
}
- const remove = indicator.deletable() ? () => indicator.delete() : undefined;
-
model.push({
id: indicator.getId(),
name: indicator.getLabel(),
@@ -219,7 +221,7 @@ export class Legend {
Record<keyof Ohlc, { value: number | string | Time; color: string; name?: string }>
>,
isIndicator: true,
- remove,
+ remove: () => indicator.delete(),
settings:
indicatorType && indicator.hasSettings()
? () => this.openIndicatorSettings(indicatorType, indicator)
@@ -240,7 +242,7 @@ export class Legend {
return;
}
- if (this.paneId === param.paneIndex) {
+ if (this.paneIndex() === param.paneIndex) {
this.tooltipVisability.next(true);
} else {
this.tooltipVisability.next(false);
@@ -289,8 +291,6 @@ export class Legend {
indicatorSeries.set(serieName, { ...value, name: indicator.getSeriesLabel(serieName) });
}
- const remove = indicator.deletable() ? () => indicator.delete() : undefined;
-
model.push({
id: indicator.getId(),
name: indicator.getLabel(),
@@ -298,7 +298,7 @@ export class Legend {
Record<keyof Ohlc, { value: number | string | Time; color: string; name?: string }>
>,
isIndicator: true,
- remove,
+ remove: () => indicator.delete(),
settings:
indicatorType && indicator.hasSettings()
? () => this.openIndicatorSettings(indicatorType, indicator)
diff --git a/src/core/Pane.tsx b/src/core/Pane.tsx
index 11749e0df614ed28b0b8cb9e83a202d75e9b6d01..1ff22c5f792809b6c289a687ae36470d77db0641 100644
--- a/src/core/Pane.tsx
+++ b/src/core/Pane.tsx
@@ -16,7 +16,7 @@ import { ReactRenderer } from '@core/ReactRenderer';
import { TooltipService } from '@core/Tooltip';
import { UIRenderer } from '@core/UIRenderer';
import { EntitySettingsModal } from '@src/components/EntitySettingsModal';
-import { DrawingsNames, indicatorLabelById } from '@src/constants';
+import { DrawingsNames, indicatorLabelById, MAIN_PANE_INDEX } from '@src/constants';
import { ModalRenderer } from '@src/core/ModalRenderer';
import { SeriesFactory, SeriesStrategies } from '@src/modules/series-strategies/SeriesFactory';
import { t } from '@src/translations';
@@ -73,8 +73,7 @@ export class Pane implements ISerializable<PaneSnapshot> {
private subscribeChartEvent: ChartMouseEvents['subscribe'];
private onDelete: () => void;
private subscriptions = new Subscription();
-
- private last = false; // временное решение чтобы блочить удаление не последнего пейна
+ private paneContainerSyncFrameId: number | null = null;
constructor({
lwcChart,
@@ -99,14 +98,14 @@ export class Pane implements ISerializable<PaneSnapshot> {
this.isMain = isMainPane ?? false;
this.id = id;
- this.initializeLegend({ ohlcConfig });
-
if (isMainPane) {
- this.lwcPane = this.lwcChart.panes()[this.id];
+ this.lwcPane = this.lwcChart.panes()[MAIN_PANE_INDEX];
} else {
this.lwcPane = this.lwcChart.addPane(true);
}
+ this.initializeLegend({ ohlcConfig });
+
this.tooltip = new TooltipService({
config: tooltipConfig,
legend: this.legend,
@@ -153,18 +152,10 @@ export class Pane implements ISerializable<PaneSnapshot> {
);
}
- public setIsLast(isLast: boolean): void {
- this.last = isLast;
- }
-
public isMainPane = () => {
return this.isMain;
};
- public isLast = () => {
- return this.last;
- };
-
public getDrawingsSnapshot(): DrawingsManagerSnapshot {
return this.drawingsManager.getSnapshot();
}
@@ -181,6 +172,10 @@ export class Pane implements ISerializable<PaneSnapshot> {
return this.id;
};
+ public paneIndex = () => {
+ return this.lwcPane.paneIndex();
+ };
+
public setIndicator(indicatorId: string, indicator: Indicator): void {
const map = this.indicatorsMap.value;
@@ -197,7 +192,7 @@ export class Pane implements ISerializable<PaneSnapshot> {
this.indicatorsMap.next(map);
if (map.size === 0 && !this.isMain) {
- this.destroy();
+ this.onDelete();
}
}
@@ -211,15 +206,7 @@ export class Pane implements ISerializable<PaneSnapshot> {
this.paneOverlayContainer = paneOverlayContainer;
this.legendRenderer = new ReactRenderer(legendContainer);
- requestAnimationFrame(() => {
- setTimeout(() => {
- const lwcPaneElement = this.lwcPane.getHTMLElement();
- if (!lwcPaneElement) return;
- lwcPaneElement.style.position = 'relative';
- lwcPaneElement.appendChild(legendContainer);
- lwcPaneElement.appendChild(paneOverlayContainer);
- }, 0);
- });
+ this.schedulePaneContainerSync();
// todo: переписать код ниже под логику пейнов
// /*
@@ -265,6 +252,7 @@ export class Pane implements ISerializable<PaneSnapshot> {
subscribeChartEvent: this.subscribeChartEvent,
mainSeries: this.isMain ? this.mainSeries : null,
paneId: this.id,
+ paneIndex: this.paneIndex,
openIndicatorSettings: (indicatorId, indicator) => {
let settings = indicator.getSettings();
@@ -310,6 +298,27 @@ export class Pane implements ISerializable<PaneSnapshot> {
});
}
+ public schedulePaneContainerSync(): void {
+ if (this.paneContainerSyncFrameId !== null) {
+ return;
+ }
+
+ this.paneContainerSyncFrameId = requestAnimationFrame(() => {
+ this.paneContainerSyncFrameId = null;
+ this.syncPaneContainers();
+ });
+ }
+
+ private syncPaneContainers(): void {
+ const lwcPaneElement = this.lwcPane.getHTMLElement();
+ if (!lwcPaneElement) return;
+
+ lwcPaneElement.style.position = 'relative';
+
+ lwcPaneElement.appendChild(this.legendContainer);
+ lwcPaneElement.appendChild(this.paneOverlayContainer);
+ }
+
public getSnapshot(): PaneSnapshot {
const indicators: (DOMObjectSnapshot & IndicatorSnapshot)[] = [];
@@ -328,12 +337,19 @@ export class Pane implements ISerializable<PaneSnapshot> {
}
public destroy() {
+ if (this.paneContainerSyncFrameId !== null) {
+ cancelAnimationFrame(this.paneContainerSyncFrameId);
+ this.paneContainerSyncFrameId = null;
+ }
+
this.subscriptions.unsubscribe();
this.tooltip?.destroy();
this.legend?.destroy();
this.legendRenderer.destroy();
this.tooltipRenderer?.destroy();
+ this.legendContainer.remove();
+ this.paneOverlayContainer.remove();
this.indicatorsMap.complete();
this.mainSerieSub?.unsubscribe();
@@ -343,12 +359,14 @@ export class Pane implements ISerializable<PaneSnapshot> {
this.mainSeries?.complete();
}
- try {
- this.lwcChart.removePane(this.id);
- } catch (e) {
- console.log(e);
- }
+ const paneIndex = this.paneIndex();
- this.onDelete();
+ if (paneIndex >= 0) {
+ try {
+ this.lwcChart.removePane(paneIndex);
+ } catch (e) {
+ console.log(e);
+ }
+ }
}
}
diff --git a/src/core/PaneManager.ts b/src/core/PaneManager.ts
index 158738c3a997c582a5ebc4f6cc9cf76cc1b4d8a7..d87a1ac0ec483a35bc9192192e8977b555ecf1bf 100644
--- a/src/core/PaneManager.ts
+++ b/src/core/PaneManager.ts
@@ -17,22 +17,22 @@ export class PaneManager implements ISerializable<PaneSnapshot[]> {
private mainPane: Pane;
private paneChartInheritedParams: PaneManagerParams & { isMainPane: boolean };
private panesMap: Map<number, Pane> = new Map<number, Pane>();
- private panesIdIterator = 0;
+ private nextPaneId = 0;
constructor(params: PaneManagerParams) {
this.paneChartInheritedParams = { ...params, isMainPane: false };
this.mainPane = new Pane({ ...params, isMainPane: true, id: 0, onDelete: () => {} });
- this.panesMap.set(this.panesIdIterator++, this.mainPane);
+ this.panesMap.set(this.nextPaneId++, this.mainPane);
this.setup(params.panesSnapshot);
}
private setup(panesSnapshot: PaneSnapshot[]) {
panesSnapshot.forEach((paneSnap: PaneSnapshot) => {
- const { isMain, id, indicators, drawings } = paneSnap;
+ const { isMain, id, drawings } = paneSnap;
- this.panesMap.get(id)?.destroy();
+ this.destroyPane(id, false);
if (isMain) {
this.mainPane = new Pane({ ...this.paneChartInheritedParams, isMainPane: true, id: 0, onDelete: () => {} });
@@ -41,13 +41,12 @@ export class PaneManager implements ISerializable<PaneSnapshot[]> {
this.mainPane.setDrawingsSnapshot(drawings);
} else {
- const pane = this.addPane();
+ const pane = this.addPane(undefined, id);
pane.setDrawingsSnapshot(drawings);
}
- const lastPane = Array.from(this.panesMap.values()).at(-1);
-
- lastPane?.setIsLast(true);
});
+
+ this.syncPaneContainers();
}
public getPaneById(id: number): Pane | undefined {
@@ -70,33 +69,45 @@ export class PaneManager implements ISerializable<PaneSnapshot[]> {
return this.mainPane;
};
- public addPane(dataSource?: DataSource): Pane {
- const id = this.panesIdIterator++;
+ private destroyPane(id: number, syncAfter = true): void {
+ const pane = this.panesMap.get(id);
+
+ if (!pane) {
+ return;
+ }
+
+ this.panesMap.delete(id);
+ pane.destroy();
+
+ if (syncAfter) {
+ this.syncPaneContainers();
+ }
+ }
+
+ public addPane(dataSource?: DataSource, paneId?: number): Pane {
+ const id = paneId ?? this.nextPaneId++;
+ this.nextPaneId = Math.max(this.nextPaneId, id + 1);
const newPane = new Pane({
...this.paneChartInheritedParams,
id,
dataSource: dataSource ?? null,
basedOn: dataSource ? undefined : this.mainPane,
- onDelete: () => {
- this.panesIdIterator--;
- this.panesMap.delete(id);
-
- const prevPane = Array.from(this.panesMap.values()).at(-1);
- prevPane?.setIsLast(true);
- },
+ onDelete: () => this.destroyPane(id),
});
- const prevPane = Array.from(this.panesMap.values()).at(-1);
-
- prevPane?.setIsLast(false);
- newPane.setIsLast(true);
-
this.panesMap.set(id, newPane);
+ this.syncPaneContainers();
return newPane;
}
+ private syncPaneContainers(): void {
+ this.panesMap.forEach((pane) => {
+ pane.schedulePaneContainerSync();
+ });
+ }
+
public getDrawingsManager(): DrawingsManager {
// todo: temp
return this.mainPane.getDrawingManager();