Загрузка данных
import { IChartApi, ISeriesApi, SeriesType } from 'lightweight-charts';
import { BehaviorSubject, distinctUntilChanged, Observable, Subscription } from 'rxjs';
import { DOMObject, DOMObjectParams } from '@core/DOMObject';
import { DrawingInteraction, ISeriesDrawing } from '@core/Drawings/common';
import { DrawingSnapshotItem } from '@core/DrawingsManager';
import { Hotkeys, Keys } from '@core/Hotkeys';
import { DrawingsNames } from '@src/constants';
import { SeriesStrategies } from '@src/modules/series-strategies/SeriesFactory';
import { SettingsTab, SettingsValues, ToolbarSettingField } from '@src/types/settings';
type IDrawing = DOMObject;
interface DrawingParams extends DOMObjectParams {
drawingName: DrawingsNames;
lwcChart: IChartApi;
mainSeries: SeriesStrategies;
onDelete: (id: string) => void;
construct: (
chart: IChartApi,
series: ISeriesApi<SeriesType>,
interaction: DrawingInteraction,
) => ISeriesDrawing;
selected$: Observable<boolean>;
isSelected: () => boolean;
select: () => void;
isLocked?: boolean;
hotkeys: Hotkeys;
setCopyPasteBuffer: (copiedObject: DrawingSnapshotItem) => void;
resetActiveTool: () => void;
}
export class Drawing extends DOMObject implements IDrawing {
private lwcDrawing: ISeriesDrawing;
private mainSeries: SeriesStrategies;
private drawingName: DrawingsNames;
private hotkeys: Hotkeys;
private lockedSubject: BehaviorSubject<boolean>;
private subscriptions = new Subscription();
private escapeUnregisterHash: string | null = null;
private deleteUnregisterHash: string | null = null;
private copyUnregisterHash: string | null = null;
constructor({
lwcChart,
name,
mainSeries,
drawingName,
id,
onDelete,
zIndex,
moveUp,
moveDown,
construct,
selected$,
isSelected,
select,
isLocked = false,
paneId,
hotkeys,
setCopyPasteBuffer,
resetActiveTool,
}: DrawingParams) {
super({ id, name, zIndex, onDelete, moveUp, moveDown, paneId });
this.hotkeys = hotkeys;
this.mainSeries = mainSeries;
this.drawingName = drawingName;
this.lockedSubject = new BehaviorSubject(isLocked);
const interaction: DrawingInteraction = {
selected$,
locked$: this.lockedSubject.pipe(distinctUntilChanged()),
isSelected,
isLocked: () => this.lockedSubject.value,
select,
};
this.lwcDrawing = construct(lwcChart, mainSeries, interaction);
this.onDelete = onDelete;
this.escapeUnregisterHash = hotkeys.register({
keys: [Keys.escape],
callback: () => {
this.delete();
resetActiveTool();
},
});
this.subscriptions.add(
selected$.subscribe((isSelected) => {
if (isSelected) {
this.registerSelectedHotkeys(setCopyPasteBuffer);
return;
}
this.unregisterSelectedHotkeys();
}),
);
this.afterCreation(() => {
hotkeys.unregister({
keys: [Keys.escape],
hash: this.escapeUnregisterHash,
});
this.escapeUnregisterHash = null;
});
}
public delete(): void {
this.destroy();
super.delete();
}
public getDrawingName(): DrawingsNames {
return this.drawingName;
}
public getLwcDrawing(): ISeriesDrawing {
return this.lwcDrawing;
}
public show(): void {
this.lwcDrawing.show();
super.show();
}
public hide(): void {
this.lwcDrawing.hide();
super.hide();
}
public rebind = (nextMainSeries: SeriesStrategies): void => {
this.lwcDrawing.rebind(nextMainSeries);
this.mainSeries = nextMainSeries;
};
public isCreationPending(): boolean {
return this.lwcDrawing.isCreationPending();
}
public subscribeIsLocked(callback: (isLocked: boolean) => void): Subscription {
return this.lockedSubject.pipe(distinctUntilChanged()).subscribe(callback);
}
public subscribeSettings(callback: (settings: SettingsValues) => void): Subscription {
return this.lwcDrawing.subscribeSettings(callback);
}
public isLocked(): boolean {
return this.lockedSubject.value;
}
public toggleLock(): void {
this.lockedSubject.next(!this.lockedSubject.value);
}
public async waitForCreation(): Promise<void> {
return this.lwcDrawing.waitTillReady();
}
public shouldShowInObjectTree(): boolean {
return this.lwcDrawing.shouldShowInObjectTree();
}
public getState(): unknown {
return this.lwcDrawing.getState();
}
public setState(state: unknown): void {
this.lwcDrawing.setState(state);
}
public getSettings(): SettingsValues {
return this.lwcDrawing.getSettings();
}
public updateSettings(settings: SettingsValues): void {
this.lwcDrawing.updateSettings(settings);
}
public getSettingsTabs(): SettingsTab[] {
return this.lwcDrawing.getSettingsTabs();
}
public getToolbarSettings(): ToolbarSettingField[] {
return this.getSettingsTabs()
.flatMap((tab) => tab.fields)
.filter((field): field is ToolbarSettingField => field.toolbar !== undefined);
}
public hasSettings(): boolean {
return this.getSettingsTabs().some((tab) => tab.fields.length > 0);
}
public destroy(): void {
this.subscriptions.unsubscribe();
this.unregisterSelectedHotkeys();
this.hotkeys.unregister({
keys: [Keys.escape],
hash: this.escapeUnregisterHash,
});
this.lockedSubject.complete();
this.mainSeries.detachPrimitive(this.lwcDrawing);
this.lwcDrawing.destroy();
}
private registerSelectedHotkeys(
setCopyPasteBuffer: (copiedObject: DrawingSnapshotItem) => void,
): void {
this.deleteUnregisterHash = this.hotkeys.register({
keys: [Keys.delete],
callback: () => {
this.delete();
},
});
this.copyUnregisterHash = this.hotkeys.register({
keys: [Keys.control, Keys.c],
callback: () => {
if (this.isCreationPending()) {
return;
}
setCopyPasteBuffer({
id: this.id,
drawingName: this.getDrawingName(),
state: this.getState(),
isLocked: this.isLocked(),
});
},
});
}
private unregisterSelectedHotkeys(): void {
this.hotkeys.unregister({
keys: [Keys.delete],
hash: this.deleteUnregisterHash,
});
this.hotkeys.unregister({
keys: [Keys.control, Keys.c],
hash: this.copyUnregisterHash,
});
this.deleteUnregisterHash = null;
this.copyUnregisterHash = null;
}
private async afterCreation(callback: () => void): Promise<void> {
await this.lwcDrawing.waitTillReady();
callback();
}
}
import { IChartApi, ISeriesApi, SeriesType } from 'lightweight-charts';
import { DrawingsNames } from '@src/constants';
import { EventManager } from '@src/core';
import { DrawingInteraction, ISeriesDrawing } from '@src/core/Drawings/common';
export type ActiveDrawingTool = DrawingsNames | 'crosshair';
interface DrawingParams {
chart: IChartApi;
series: ISeriesApi<SeriesType>;
eventManager: EventManager;
container: HTMLElement;
interaction: DrawingInteraction;
removeSelf: () => void;
openSettings: () => void;
}
export interface DrawingConfig {
singleInstance?: boolean;
construct: (params: DrawingParams) => ISeriesDrawing;
}