implement toggleable buttons; menu items can now be changed; add horizontal line and vertical line labels

This commit is contained in:
louisnw
2024-05-31 17:25:55 +01:00
parent ca93ddbcb1
commit 7915863a64
13 changed files with 233 additions and 59 deletions

View File

@ -8,7 +8,7 @@ import pandas as pd
from .table import Table
from .toolbox import ToolBox
from .drawings import Box, HorizontalLine, TrendLine, TwoPointDrawing, VerticalSpan
from .drawings import Box, HorizontalLine, TrendLine, TwoPointDrawing, VerticalLine, VerticalSpan
from .topbar import TopBar
from .util import (
BulkRunScript, Pane, Events, IDGen, as_enum, jbool, js_json, TIME, NUM, FLOAT,
@ -728,10 +728,20 @@ class AbstractChart(Candlestick, Pane):
width: int = 2,
style: LINE_STYLE = 'solid'
) -> Line:
line = Line(self, '', color, style, width, False, False, False)
line._set_trend(start_time, value, start_time, value, ray=True, round=round)
# TODO
line = RayLine(self, '', color, style, width, False, False, False)
return line
def vertical_line(
self,
time: TIME,
color: str = '#1E80F0',
width: int = 2,
style: LINE_STYLE ='solid',
text: str = ''
) -> VerticalLine:
return VerticalLine(*locals().values())
def set_visible_range(self, start_time: TIME, end_time: TIME):
self.run_script(f'''
{self.id}.chart.timeScale().setVisibleRange({{

View File

@ -24,6 +24,13 @@ class Drawing(Pane):
"""
self.run_script(f'{self.id}.detach()')
def options(self, color='#1E80F0', style='solid', width=4):
self.run_script(f'''{self.id}.applyOptions({{
lineColor: '{color}',
lineStyle: {as_enum(style, LINE_STYLE)},
width: {width},
}})''')
class TwoPointDrawing(Drawing):
def __init__(
self,
@ -76,6 +83,8 @@ class HorizontalLine(Drawing):
{{
lineColor: '{color}',
lineStyle: {as_enum(style, LINE_STYLE)},
width: {width},
text: `{text}`,
}},
callbackName={f"'{self.id}'" if func else 'null'}
)
@ -103,22 +112,25 @@ class HorizontalLine(Drawing):
# self.run_script(f'{self.id}.updatePrice({price})')
self.price = price
def label(self, text: str): # TODO
self.run_script(f'{self.id}.updateLabel("{text}")')
def options(self, color='#1E80F0', style='solid', width=4, text=''):
super().options(color, style, width)
self.run_script(f'{self.id}.applyOptions({{text: `{text}`}})')
class VerticalLine(Drawing):
def __init__(self, chart, time, color, width, style, text, axis_label_visible, func):
def __init__(self, chart, time, color, width, style, text, func=None):
super().__init__(chart, func)
self.time = time
self.run_script(f'''
{self.id} = new Lib.VerticalLine(
{{time: {time}}},
{{time: {self.chart._single_datetime_format(time)}}},
{{
lineColor: '{color}',
lineStyle: {as_enum(style, LINE_STYLE)},
width: {width},
text: `{text}`,
}},
callbackName={f"'{self.id}'" if func else 'null'}
)
@ -130,8 +142,9 @@ class VerticalLine(Drawing):
# self.run_script(f'{self.id}.updatePrice({price})')
self.price = price
def label(self, text: str): # TODO
self.run_script(f'{self.id}.updateLabel("{text}")')
def options(self, color='#1E80F0', style='solid', width=4, text=''):
super().options(color, style, width)
self.run_script(f'{self.id}.applyOptions({{text: `{text}`}})')
class Box(TwoPointDrawing):
@ -188,13 +201,14 @@ class TrendLine(TwoPointDrawing):
end_value,
round,
{
"lineColor": f'"line_color"',
"lineColor": f'"{line_color}"',
"width": width,
"lineStyle": as_enum(style, LINE_STYLE)
},
func
)
# TODO reimplement/fix
class VerticalSpan(Pane):
def __init__(self, series: 'SeriesCommon', start_time: Union[TIME, tuple, list], end_time: Optional[TIME] = None,
color: str = 'rgba(252, 219, 3, 0.2)'):

File diff suppressed because one or more lines are too long

View File

@ -8,12 +8,15 @@ ALIGN = Literal['left', 'right']
class Widget(Pane):
def __init__(self, topbar, value, func: callable = None):
def __init__(self, topbar, value, func: callable = None, convert_boolean=False):
super().__init__(topbar.win)
self.value = value
def wrapper(v):
self.value = v
if convert_boolean:
self.value = False if v == 'false' else True
else:
self.value = v
func(topbar._chart)
async def async_wrapper(v):
@ -54,6 +57,7 @@ class MenuWidget(Widget):
{self.id} = {topbar.id}.makeMenu({list(options)}, "{default}", {jbool(separator)}, "{self.id}", "{align}")
''')
# TODO this will probably need to be fixed
def set(self, option):
if option not in self.options:
raise ValueError(f"Option {option} not in menu options ({self.options})")
@ -63,15 +67,19 @@ class MenuWidget(Widget):
''')
self.win.handlers[self.id](option)
def update_items(self, *items: str):
self.options = list(items)
self.run_script(f'{self.id}.updateMenuItems({self.options})')
class ButtonWidget(Widget):
def __init__(self, topbar, button, separator, align, func):
super().__init__(topbar, value=button, func=func)
def __init__(self, topbar, button, separator, align, toggle, func):
super().__init__(topbar, value=False, func=func, convert_boolean=toggle)
self.run_script(
f'{self.id} = {topbar.id}.makeButton("{button}", "{self.id}", {jbool(separator)}, true, "{align}")')
f'{self.id} = {topbar.id}.makeButton("{button}", "{self.id}", {jbool(separator)}, true, "{align}", {jbool(toggle)})')
def set(self, string):
self.value = string
# self.value = string
self.run_script(f'{self.id}.elem.innerText = "{string}"')
@ -112,6 +120,6 @@ class TopBar(Pane):
self._widgets[name] = TextWidget(self, initial_text, align)
def button(self, name, button_text: str, separator: bool = True,
align: ALIGN = 'left', func: callable = None):
align: ALIGN = 'left', toggle: bool = False, func: callable = None):
self._create()
self._widgets[name] = ButtonWidget(self, button_text, separator, align, func)
self._widgets[name] = ButtonWidget(self, button_text, separator, align, toggle, func)