From 33be333b4131b24f5561bbc3720d2ac91fc87d2e Mon Sep 17 00:00:00 2001 From: louisnw Date: Mon, 9 Oct 2023 17:30:40 +0100 Subject: [PATCH] - legend 'text' parameter for displaying static text - table 'resize' method --- lightweight_charts/abstract.py | 29 ++++++++++++++++++----------- lightweight_charts/js/funcs.js | 24 +++++++++++++----------- lightweight_charts/js/table.js | 8 ++++++-- lightweight_charts/table.py | 4 +++- 4 files changed, 40 insertions(+), 25 deletions(-) diff --git a/lightweight_charts/abstract.py b/lightweight_charts/abstract.py index 9af92e6..30c8b55 100644 --- a/lightweight_charts/abstract.py +++ b/lightweight_charts/abstract.py @@ -174,9 +174,8 @@ class SeriesCommon(Pane): def _push_to_legend(self): self.run_script(f''' {self._chart.id}.lines.push({self.id}) - if ('legend' in {self._chart.id}) {{ - {self._chart.id}.legend.lines.push({self._chart.id}.legend.makeLineRow({self.id})) - }}''') + {self._chart.id}.legend.lines.push({self._chart.id}.legend.makeLineRow({self.id})) + ''') @staticmethod def _format_labels(data, labels, index, exclude_lowercase): @@ -469,11 +468,9 @@ class Line(SeriesCommon): self._chart._lines.remove(self) if self in self._chart._lines else None self.run_script(f''' {self._chart.id}.chart.removeSeries({self.id}.series) - if ('legend' in {self._chart.id}) {{ - {self._chart.id}.legend.lines.forEach(line => {{ - if (line.line === {self.id}) {self._chart.id}.legend.div.removeChild(line.row) - }}) - }} + {self._chart.id}.legend.lines.forEach(line => {{ + if (line.line === {self.id}) {self._chart.id}.legend.div.removeChild(line.row) + }}) delete {self.id} ''') @@ -877,15 +874,25 @@ class AbstractChart(Candlestick, Pane): }})''') def legend(self, visible: bool = False, ohlc: bool = True, percent: bool = True, lines: bool = True, - color: str = 'rgb(191, 195, 203)', font_size: int = 11, font_family: str = 'Monaco'): + color: str = 'rgb(191, 195, 203)', font_size: int = 11, font_family: str = 'Monaco', + text: str = ''): """ Configures the legend of the chart. """ + l_id = f'{self.id}.legend' if not visible: + self.run_script(f'{l_id}.div.style.display = "none"') return self.run_script(f''' - {self.id}.legend = new Legend( {self.id}, {jbool(ohlc)}, {jbool(percent)}, {jbool(lines)}, - '{color}', {font_size}, '{font_family}') + {l_id}.div.style.display = 'flex' + {l_id}.ohlcEnabled = {jbool(ohlc)} + {l_id}.percentEnabled = {jbool(percent)} + {l_id}.linesEnabled = {jbool(lines)} + {l_id}.div.style.color = '{color}' + {l_id}.color = '{color}' + {l_id}.div.style.fontSize = '{font_size}px' + {l_id}.div.style.fontFamily = '{font_family}' + {l_id}.text.innerText = '{text}' ''') def spinner(self, visible): diff --git a/lightweight_charts/js/funcs.js b/lightweight_charts/js/funcs.js index 364f063..9082353 100644 --- a/lightweight_charts/js/funcs.js +++ b/lightweight_charts/js/funcs.js @@ -54,6 +54,7 @@ if (!window.Chart) { }, handleScroll: {vertTouchDrag: true}, }) + this.legend = new Legend(this) this.wrapper.style.display = 'flex' this.wrapper.style.flexDirection = 'column' this.wrapper.style.position = 'relative' @@ -180,8 +181,11 @@ if (!window.Chart) { window.HorizontalLine = HorizontalLine class Legend { - constructor(chart, ohlcEnabled, percentEnabled, linesEnabled, - color = 'rgb(191, 195, 203)', fontSize = '11', fontFamily = 'Monaco') { + constructor(chart) { + this.ohlcEnabled = false + this.percentEnabled = false + this.linesEnabled = false + this.div = document.createElement('div') this.div.style.position = 'absolute' this.div.style.zIndex = '3000' @@ -191,17 +195,15 @@ if (!window.Chart) { this.div.style.display = 'flex' this.div.style.flexDirection = 'column' this.div.style.maxWidth = `${(chart.scale.width * 100) - 8}vw` - this.div.style.color = color - this.div.style.fontSize = fontSize + 'px' - this.div.style.fontFamily = fontFamily + + this.text = document.createElement('span') + this.text.style.lineHeight = '1.8' this.candle = document.createElement('div') + this.div.appendChild(this.text) this.div.appendChild(this.candle) chart.div.appendChild(this.div) - this.color = color - - this.linesEnabled = linesEnabled this.makeLines(chart) let legendItemFormat = (num, decimal) => num.toFixed(decimal).toString().padStart(8, ' ') @@ -228,11 +230,11 @@ if (!window.Chart) { | C ${legendItemFormat(data.close, chart.precision)} ` let percentMove = ((data.close - data.open) / data.open) * 100 let percent = `| ${percentMove >= 0 ? '+' : ''}${percentMove.toFixed(2)} %` - finalString += ohlcEnabled ? ohlc : '' - finalString += percentEnabled ? percent : '' + finalString += this.ohlcEnabled ? ohlc : '' + finalString += this.percentEnabled ? percent : '' let volumeData = param.seriesData.get(chart.volumeSeries) - if (volumeData) finalString += ohlcEnabled ? `
V ${shorthandFormat(volumeData.value)}` : '' + if (volumeData) finalString += this.ohlcEnabled ? `
V ${shorthandFormat(volumeData.value)}` : '' } this.candle.innerHTML = finalString + '' this.lines.forEach((line) => { diff --git a/lightweight_charts/js/table.js b/lightweight_charts/js/table.js index 89dd734..d684d7a 100644 --- a/lightweight_charts/js/table.js +++ b/lightweight_charts/js/table.js @@ -15,8 +15,7 @@ if (!window.Table) { this.container.style.float = position } this.container.style.zIndex = '2000' - this.container.style.width = width <= 1 ? width * 100 + '%' : width + 'px' - this.container.style.height = height <= 1 ? height * 100 + '%' : height + 'px' + this.reSize(width, height) this.container.style.display = 'flex' this.container.style.flexDirection = 'column' this.container.style.justifyContent = 'space-between' @@ -157,6 +156,11 @@ if (!window.Table) { this[type].push(textBox) } } + + reSize(width, height) { + this.container.style.width = width <= 1 ? width * 100 + '%' : width + 'px' + this.container.style.height = height <= 1 ? height * 100 + '%' : height + 'px' + } } window.Table = Table } diff --git a/lightweight_charts/table.py b/lightweight_charts/table.py index 42b4fd9..2a3c06f 100644 --- a/lightweight_charts/table.py +++ b/lightweight_charts/table.py @@ -12,7 +12,7 @@ class Section(Pane): def __call__(self, number_of_text_boxes: int, func: callable = None): if func: - self.win.handlers[self.id] = lambda boxId: func(self._table.id, int(boxId)) + self.win.handlers[self.id] = lambda boxId: func(self._table, int(boxId)) self.run_script(f''' {self._table.id}.makeSection("{self.id}", "{self.type}", {number_of_text_boxes}, {"true" if func else ""}) ''') @@ -104,6 +104,8 @@ class Table(Pane, dict): def format(self, column: str, format_str: str): self._formatters[column] = format_str + def resize(self, width: NUM, height: NUM): self.run_script(f'{self.id}.reSize({width}, {height})') + def visible(self, visible: bool): self.is_shown = visible self.run_script(f"""