diff --git a/docs/source/reference/topbar.md b/docs/source/reference/topbar.md index 914fc83..fcfbb8a 100644 --- a/docs/source/reference/topbar.md +++ b/docs/source/reference/topbar.md @@ -32,6 +32,18 @@ ___ +```{py:method} menu(name: str, options: tuple: default: str, separator: bool, func: callable) + +* `name`: the name of the menu which can be used to access it from the `topbar` dictionary. +* `options`: The options for each menu item. +* `default`: The initial menu option set. +* `separator`: places a separator line to the right of the menu. + +``` +___ + + + ```{py:method} textbox(name: str, initial_text: str) * `name`: the name of the text box which can be used to access it from the `topbar` dictionary. diff --git a/lightweight_charts/js/callback.js b/lightweight_charts/js/callback.js index 2b474aa..c0e7775 100644 --- a/lightweight_charts/js/callback.js +++ b/lightweight_charts/js/callback.js @@ -77,7 +77,47 @@ if (!window.TopBar) { this.reSize() return textBox } - makeButton(defaultText, callbackName, separator) { + + makeMenu(items, activeItem, separator, callbackName) { + let menu = document.createElement('div') + menu.style.position = 'absolute' + menu.style.display = 'none' + menu.style.zIndex = '100000' + menu.style.backgroundColor = '#0c0d0f' + menu.style.borderRadius = '2px' + menu.style.border = '2px solid #3C434C' + menu.style.borderTop = 'none' + menu.style.alignItems = 'flex-start' + + let menuOpen = false + items.forEach(text => { + let button = this.makeButton(text, null, false, false) + button.elem.addEventListener('click', () => { + widget.elem.innerText = button.elem.innerText+' ↓' + window.callbackFunction(`${callbackName}_~_${button.elem.innerText}`) + menu.style.display = 'none' + menuOpen = false + }); + button.elem.style.margin = '4px 4px' + button.elem.style.padding = '2px 2px' + menu.appendChild(button.elem) + }) + let widget = this.makeButton(activeItem+' ↓', null, separator) + widget.elem.addEventListener('click', () => { + menuOpen = !menuOpen + if (!menuOpen) return menu.style.display = 'none' + let rect = widget.elem.getBoundingClientRect() + menu.style.display = 'flex' + menu.style.flexDirection = 'column' + + let center = rect.x+(rect.width/2) + menu.style.left = center-(menu.clientWidth/2)+'px' + menu.style.top = rect.y+rect.height+'px' + }) + document.body.appendChild(menu) + } + + makeButton(defaultText, callbackName, separator, append=true) { let button = document.createElement('button') button.style.border = 'none' button.style.padding = '2px 5px' @@ -98,7 +138,9 @@ if (!window.TopBar) { button.addEventListener('mouseenter', () => button.style.backgroundColor = this.hoverBackgroundColor) button.addEventListener('mouseleave', () => button.style.backgroundColor = 'transparent') - button.addEventListener('click', () => window.callbackFunction(`${widget.callbackName}_~_${button.innerText}`)); + if (callbackName) { + button.addEventListener('click', () => window.callbackFunction(`${widget.callbackName}_~_${button.innerText}`)); + } button.addEventListener('mousedown', () => { button.style.backgroundColor = this.activeBackgroundColor button.style.color = this.activeTextColor @@ -110,8 +152,7 @@ if (!window.TopBar) { button.style.fontWeight = 'normal' }) if (separator) this.makeSeparator() - this.topBar.appendChild(button) - this.reSize() + if (append) this.topBar.appendChild(button); this.reSize() return widget } diff --git a/lightweight_charts/js/funcs.js b/lightweight_charts/js/funcs.js index 41d3b7d..7db60de 100644 --- a/lightweight_charts/js/funcs.js +++ b/lightweight_charts/js/funcs.js @@ -66,6 +66,15 @@ if (!window.Chart) { this.chart.resize(window.innerWidth * this.scale.width, (window.innerHeight * this.scale.height) - topBarOffset) this.wrapper.style.width = `${100 * this.scale.width}%` this.wrapper.style.height = `${100 * this.scale.height}%` + if (this.legend) { + if (this.scale.height === 0 || this.scale.width === 0) { + this.legend.div.style.display = 'none' + } + else { + this.legend.div.style.display = 'flex' + } + } + } makeCandlestickSeries() { this.markers = [] diff --git a/lightweight_charts/topbar.py b/lightweight_charts/topbar.py index c86b35c..1eaeb20 100644 --- a/lightweight_charts/topbar.py +++ b/lightweight_charts/topbar.py @@ -36,6 +36,13 @@ class SwitcherWidget(Widget): self.run_script(f'{self.id} = {topbar.id}.makeSwitcher({list(options)}, "{default}", "{self.id}")') +class MenuWidget(Widget): + def __init__(self, topbar, options, default, separator, func): + super().__init__(topbar, value=default, func=func) + self.run_script( + f'{self.id} = {topbar.id}.makeMenu({list(options)}, "{default}", {jbool(separator)}, "{self.id}")') + + class ButtonWidget(Widget): def __init__(self, topbar, button, separator, func): super().__init__(topbar, value=button, func=func) @@ -81,6 +88,10 @@ class TopBar(Pane): self._create() self._widgets[name] = SwitcherWidget(self, options, default if default else options[0], func) + def menu(self, name, options: tuple, default: str = None, separator: bool = True, func: callable = None): + self._create() + self._widgets[name] = MenuWidget(self, options, default if default else options[0], separator, func) + def textbox(self, name: str, initial_text: str = ''): self._create() self._widgets[name] = TextWidget(self, initial_text)