remove horizontal line array methods on SeriesCommon, fix horizontal lines callbacks

This commit is contained in:
louisnw
2024-03-30 17:42:06 +00:00
parent e9f21b3b0e
commit 3ead45f858
20 changed files with 689 additions and 644 deletions

View File

@ -82,15 +82,22 @@ class Window:
background_color, border_color, border_width, heading_text_colors, background_color, border_color, border_width, heading_text_colors,
heading_background_colors, return_clicked_cells, func) heading_background_colors, return_clicked_cells, func)
def create_subchart(self, position: FLOAT = 'left', width: float = 0.5, height: float = 0.5, def create_subchart(
sync_id: Optional[str] = None, scale_candles_only: bool = False, self,
sync_crosshairs_only: bool = False, toolbox: bool = False position: FLOAT = 'left',
width: float = 0.5,
height: float = 0.5,
sync_id: Optional[str] = None,
scale_candles_only: bool = False,
sync_crosshairs_only: bool = False,
toolbox: bool = False
) -> 'AbstractChart': ) -> 'AbstractChart':
subchart = AbstractChart(self, width, height, scale_candles_only, toolbox, position=position) subchart = AbstractChart(self, width, height, scale_candles_only, toolbox, position=position)
if not sync_id: if not sync_id:
return subchart return subchart
self.run_script(f''' self.run_script(f'''
Handler.syncCharts({subchart.id}, {sync_id}, {jbool(sync_crosshairs_only)}) Handler.syncCharts({subchart.id}, {sync_id}, {jbool(sync_crosshairs_only)})
// TODO this should be in syncCharts
{subchart.id}.chart.timeScale().setVisibleLogicalRange( {subchart.id}.chart.timeScale().setVisibleLogicalRange(
{sync_id}.chart.timeScale().getVisibleLogicalRange() {sync_id}.chart.timeScale().getVisibleLogicalRange()
) )
@ -296,15 +303,15 @@ class SeriesCommon(Pane):
Creates a horizontal line at the given price. Creates a horizontal line at the given price.
""" """
return HorizontalLine(self, price, color, width, style, text, axis_label_visible, func) return HorizontalLine(self, price, color, width, style, text, axis_label_visible, func)
# TODO should these methods be removed
def remove_horizontal_line(self, price: NUM): # def remove_horizontal_line(self, price: NUM):
""" # """
Removes a horizontal line at the given price. # Removes a horizontal line at the given price.
""" # """
self.run_script(f''' # self.run_script(f'''
{self.id}.horizontal_lines.forEach(function (line) {{ # {self.id}.horizontal_lines.forEach(function (line) {{
if ({price} === line.price) line.deleteLine() # if ({price} === line._point.price) line.detach()
}})''') # }})''')
def clear_markers(self): def clear_markers(self):
""" """
@ -312,14 +319,14 @@ class SeriesCommon(Pane):
""" """
self.run_script(f'''{self.id}.markers = []; {self.id}.series.setMarkers([])''') self.run_script(f'''{self.id}.markers = []; {self.id}.series.setMarkers([])''')
def clear_horizontal_lines(self): # def clear_horizontal_lines(self):
""" # """
Clears the horizontal lines displayed on the data.\n # Clears the horizontal lines displayed on the data.\n
""" # """
self.run_script(f''' # self.run_script(f'''
{self.id}.horizontal_lines.forEach(function (line) {{{self.id}.series.removePriceLine(line.line);}}); # {self.id}.horizontal_lines.forEach(function (line) {{{self.id}.series.removePriceLine(line.line);}});
{self.id}.horizontal_lines = []; # {self.id}.horizontal_lines = [];
''') # ''')
def price_line(self, label_visible: bool = True, line_visible: bool = True, title: str = ''): def price_line(self, label_visible: bool = True, line_visible: bool = True, title: str = ''):
self.run_script(f''' self.run_script(f'''
@ -370,16 +377,27 @@ class SeriesCommon(Pane):
end_time = self._single_datetime_format(end_time) if end_time else None end_time = self._single_datetime_format(end_time) if end_time else None
return VerticalSpan(self, start_time, end_time, color) return VerticalSpan(self, start_time, end_time, color)
# TODO drawings should be in a seperate folder, and inherbit a abstract Drawing class
class HorizontalLine(Pane): class HorizontalLine(Pane):
def __init__(self, chart, price, color, width, style, text, axis_label_visible, func): def __init__(self, chart, price, color, width, style, text, axis_label_visible, func):
super().__init__(chart.win) super().__init__(chart.win)
self.price = price self.price = price
self.run_script(f''' self.run_script(f'''
{self.id} = new HorizontalLine( {self.id} = new HorizontalLine(
{chart.id}, '{self.id}', {price}, '{color}', {width}, {{price: {price}}},
{as_enum(style, LINE_STYLE)}, {jbool(axis_label_visible)}, '{text}' {{
)''') lineColor: '{color}',
lineStyle: {as_enum(style, LINE_STYLE)},
}},
callbackName={f"'{self.id}'" if func else 'null'}
)
{chart.id}.series.attachPrimitive({self.id})
''')
# {self.id} = new HorizontalLine(
# {chart.id}, '{self.id}', {price}, '{color}', {width},
# {as_enum(style, LINE_STYLE)}, {jbool(axis_label_visible)}, '{text}'
# )''')
if not func: if not func:
return return
@ -392,24 +410,24 @@ class HorizontalLine(Pane):
await func(chart, self) await func(chart, self)
self.win.handlers[self.id] = wrapper_async if asyncio.iscoroutinefunction(func) else wrapper self.win.handlers[self.id] = wrapper_async if asyncio.iscoroutinefunction(func) else wrapper
self.run_script(f'if ("toolBox" in {chart.id}) {chart.id}.toolBox.drawings.push({self.id})') self.run_script(f'{chart.id}.toolBox?.addNewDrawing({self.id})')
def update(self, price): def update(self, price: float):
""" """
Moves the horizontal line to the given price. Moves the horizontal line to the given price.
""" """
self.run_script(f'{self.id}.updatePrice({price})') self.run_script(f'{self.id}.updatePoints({{price: {price}}})')
# self.run_script(f'{self.id}.updatePrice({price})')
self.price = price self.price = price
def label(self, text: str): def label(self, text: str): # TODO
self.run_script(f'{self.id}.updateLabel("{text}")') self.run_script(f'{self.id}.updateLabel("{text}")')
def delete(self): def delete(self): # TODO test all methods
""" """
Irreversibly deletes the horizontal line. Irreversibly deletes the horizontal line.
""" """
self.run_script(f'{self.id}.deleteLine()') self.run_script(f'{self.id}.detach()')
del self
class VerticalSpan(Pane): class VerticalSpan(Pane):

View File

@ -59,9 +59,11 @@ class PyWV:
background_color='#000000') background_color='#000000')
) )
self.windows[-1].events.loaded += lambda: self.loaded_event.set()
def loop(self): def loop(self):
self.loaded_event.set() # self.loaded_event.set()
while self.is_alive: while self.is_alive:
i, arg = self.queue.get() i, arg = self.queue.get()

File diff suppressed because one or more lines are too long

View File

@ -69,10 +69,13 @@ export abstract class Drawing extends PluginBase {
public abstract updatePoints(...points: (Point | null)[]): void; public abstract updatePoints(...points: (Point | null)[]): void;
detach() { detach() {
this._options.lineColor = 'transparent';
this.requestUpdate();
this.series.detachPrimitive(this); this.series.detachPrimitive(this);
for (const s of this._listeners) { for (const s of this._listeners) {
document.body.removeEventListener(s.name, s.listener) document.body.removeEventListener(s.name, s.listener);
} }
} }
protected _subscribe(name: keyof DocumentEventMap, listener: any) { protected _subscribe(name: keyof DocumentEventMap, listener: any) {

View File

@ -1,3 +1,4 @@
import { HorizontalLine } from "../horizontal-line/horizontal-line";
import { Table } from "./table"; import { Table } from "./table";
export interface GlobalParams extends Window { export interface GlobalParams extends Window {
@ -9,6 +10,7 @@ export interface GlobalParams extends Window {
cursor: string; cursor: string;
Handler: any; Handler: any;
Table: typeof Table; Table: typeof Table;
HorizontalLine: typeof HorizontalLine;
} }
interface paneStyle { interface paneStyle {
@ -46,6 +48,7 @@ export function globalParamInit() {
} }
window.cursor = 'default'; window.cursor = 'default';
window.Table = Table; window.Table = Table;
window.HorizontalLine = HorizontalLine;
} }

View File

@ -2,6 +2,7 @@ import {
ColorType, ColorType,
CrosshairMode, CrosshairMode,
DeepPartial, DeepPartial,
HistogramStyleOptions,
IChartApi, IChartApi,
ISeriesApi, ISeriesApi,
LineStyleOptions, LineStyleOptions,
@ -9,14 +10,12 @@ import {
LogicalRangeChangeEventHandler, LogicalRangeChangeEventHandler,
MouseEventHandler, MouseEventHandler,
MouseEventParams, MouseEventParams,
SeriesMarker,
SeriesOptionsCommon, SeriesOptionsCommon,
SeriesType, SeriesType,
Time, Time,
createChart createChart
} from "lightweight-charts"; } from "lightweight-charts";
import { HorizontalLine } from "../horizontal-line/horizontal-line";
import { GlobalParams, globalParamInit } from "./global-params"; import { GlobalParams, globalParamInit } from "./global-params";
import { Legend } from "./legend"; import { Legend } from "./legend";
import { ToolBox } from "./toolbox"; import { ToolBox } from "./toolbox";
@ -41,8 +40,6 @@ export class Handler {
public chart: IChartApi; public chart: IChartApi;
public scale: Scale; public scale: Scale;
public horizontal_lines: HorizontalLine[] = [];
public markers: SeriesMarker<"">[] = [];
public precision: number = 2; public precision: number = 2;
public series: ISeriesApi<SeriesType>; public series: ISeriesApi<SeriesType>;
@ -181,8 +178,16 @@ export class Handler {
return { return {
name: name, name: name,
series: line, series: line,
horizontal_lines: [], }
markers: [], }
createHistogramSeries(name: string, options: DeepPartial<HistogramStyleOptions & SeriesOptionsCommon>) {
const line = this.chart.addHistogramSeries({...options});
this._seriesList.push(line);
this.legend.makeSeriesRow(name, line)
return {
name: name,
series: line,
} }
} }

View File

@ -160,6 +160,10 @@ export class ToolBox {
// }) // })
// } // }
addNewDrawing(d: Drawing) {
this._drawingTool.addNewDrawing(d);
}
clearDrawings() { clearDrawings() {
this._drawingTool.clearDrawings(); this._drawingTool.clearDrawings();
} }

View File

@ -6,22 +6,26 @@ import { Point } from "../drawing/data-source";
import { Drawing, InteractionState } from "../drawing/drawing"; import { Drawing, InteractionState } from "../drawing/drawing";
import { DrawingOptions } from "../drawing/options"; import { DrawingOptions } from "../drawing/options";
import { HorizontalLinePaneView } from "./pane-view"; import { HorizontalLinePaneView } from "./pane-view";
import { GlobalParams } from "../general/global-params";
declare const window: GlobalParams;
export class HorizontalLine extends Drawing { export class HorizontalLine extends Drawing {
_type = 'HorizontalLine'; _type = 'HorizontalLine';
_paneViews: HorizontalLinePaneView[]; _paneViews: HorizontalLinePaneView[];
_point: Point; _point: Point;
private _callbackName: string | null;
protected _startDragPoint: Point | null = null; protected _startDragPoint: Point | null = null;
constructor(point: Point, options: DeepPartial<DrawingOptions>) { constructor(point: Point, options: DeepPartial<DrawingOptions>, callbackName=null) {
super(options) super(options)
this._point = point; this._point = point;
this._point.time = null; // time is null for horizontal lines this._point.time = null; // time is null for horizontal lines
this._paneViews = [new HorizontalLinePaneView(this)]; this._paneViews = [new HorizontalLinePaneView(this)];
// TODO ids should be stored in an object dictionary so u can access the lines this._callbackName = callbackName;
// this.handler.horizontal_lines.push(this) TODO fix this in handler ?
} }
public updatePoints(...points: (Point | null)[]) { public updatePoints(...points: (Point | null)[]) {
@ -38,15 +42,14 @@ export class HorizontalLine extends Drawing {
case InteractionState.HOVERING: case InteractionState.HOVERING:
document.body.style.cursor = "pointer"; document.body.style.cursor = "pointer";
this._unsubscribe("mouseup", this._handleMouseUpInteraction); this._unsubscribe("mouseup", this._childHandleMouseUpInteraction);
this._subscribe("mousedown", this._handleMouseDownInteraction) this._subscribe("mousedown", this._handleMouseDownInteraction)
this.chart.applyOptions({handleScroll: true}); this.chart.applyOptions({handleScroll: true});
break; break;
case InteractionState.DRAGGING: case InteractionState.DRAGGING:
document.body.style.cursor = "grabbing"; document.body.style.cursor = "grabbing";
document.body.addEventListener("mouseup", this._handleMouseUpInteraction); this._subscribe("mouseup", this._childHandleMouseUpInteraction);
this._subscribe("mouseup", this._handleMouseUpInteraction);
this.chart.applyOptions({handleScroll: false}); this.chart.applyOptions({handleScroll: false});
break; break;
} }
@ -71,4 +74,11 @@ export class HorizontalLine extends Drawing {
if (!hoverPoint) return; if (!hoverPoint) return;
return this._moveToState(InteractionState.DRAGGING); return this._moveToState(InteractionState.DRAGGING);
} }
protected _childHandleMouseUpInteraction = () => {
this._handleMouseUpInteraction();
if (!this._callbackName) return;
console.log(window.callbackFunction);
window.callbackFunction(`${this._callbackName}_~_${this._point.price.toFixed(8)}`);
}
} }