Adding some additional parameters for customising tabs

This commit is contained in:
Darren Burns
2022-02-16 16:41:42 +00:00
parent 1c9e91e1ff
commit 363cec1a4b
4 changed files with 59 additions and 34 deletions

View File

@@ -16,15 +16,23 @@ class PanelWidget(Widget):
class BasicApp(App):
"""Sandbox application used for testing/development by Textual developers"""
def on_load(self):
"""Bind keys here."""
self.bind("tab", "toggle_class('#sidebar', '-active')")
self.bind("a", "toggle_class('#header', '-visible')")
self.bind("c", "toggle_class('#content', '-content-visible')")
self.bind("d", "toggle_class('#footer', 'dim')")
def on_key(self, event: events.Key) -> None:
tab_keys = {
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.tabs = Tabs(
[
Tab("One", name="one"),
Tab("Two", name="two"),
Tab("Three", name="three"),
Tab("Four", name="four"),
Tab("Five", name="five"),
Tab("Six", name="six"),
Tab("SixHundred", name="seven"),
Tab("Eight", name="eight"),
],
active_tab="three",
tab_padding=1,
)
self.tab_keys = {
"1": "one",
"2": "two",
"3": "three",
@@ -34,22 +42,18 @@ class BasicApp(App):
"7": "seven",
"8": "eight",
}
self.tabs.active_tab_name = tab_keys.get(event.key, "one")
def on_load(self):
"""Bind keys here."""
self.bind("tab", "toggle_class('#sidebar', '-active')")
self.bind("a", "toggle_class('#header', '-visible')")
self.bind("c", "toggle_class('#content', '-content-visible')")
self.bind("d", "toggle_class('#footer', 'dim')")
def on_key(self, event: events.Key) -> None:
self.tabs.active_tab_name = self.tab_keys.get(event.key, "one")
def on_mount(self):
self.tabs = Tabs(
[
Tab("One", name="one"),
Tab("Two", name="two"),
Tab("Three", name="three"),
Tab("Four", name="four"),
Tab("Five", name="five"),
Tab("Six", name="six"),
Tab("Seven", name="seven"),
Tab("Eight", name="eight"),
],
active_tab="three",
)
"""Build layout here."""
self.mount(
header=self.tabs,

View File

@@ -1,7 +1,7 @@
/* CSS file for dev_sandbox.py */
$text: #f0f0f0;
$primary: #021720;
$primary: #262626;
$secondary:#95d52a;
$background: #262626;

View File

@@ -32,11 +32,13 @@ class TabHeadersRenderable:
active_tab_name: str | None = None,
width: int | None = None,
tab_padding: int | None = None,
inactive_tab_opacity: float = 0.5,
):
self.tabs = {tab.name: tab for tab in tabs}
self.active_tab_name = active_tab_name or next(iter(self.tabs))
self.width = width
self.tab_padding = tab_padding
self.inactive_tab_opacity = inactive_tab_opacity
self._range_cache: dict[str, tuple[int, int]] = {}
@@ -70,20 +72,22 @@ class TabHeadersRenderable:
end="",
style=Style(
color="#f0f0f0",
bgcolor="#021720",
bgcolor="#262626",
meta={"@click": f"activate_tab('{tab.name}')"},
),
)
# Cache and move to next label
len_label = len(tab.label)
len_label = cell_len(tab.label)
self._range_cache[tab.name] = (char_index, char_index + len_label)
char_index += len_label + label_pad * 2
if tab.name == self.active_tab_name:
yield tab_content
else:
dimmed_tab_content = Opacity(tab_content, opacity=0.5)
dimmed_tab_content = Opacity(
tab_content, opacity=self.inactive_tab_opacity
)
segments = list(console.render(dimmed_tab_content))
yield from segments

View File

@@ -2,8 +2,8 @@ from __future__ import annotations
from rich.console import Console, ConsoleOptions, RenderableType, RenderResult
from rich.segment import Segment
from rich.style import StyleType
from textual import log
from textual.reactive import Reactive
from textual.renderables._tab_headers import TabHeadersRenderable, Tab
from textual.renderables.underline_bar import UnderlineBar
@@ -15,11 +15,17 @@ class TabsRenderable:
self,
tabs: list[Tab],
active_tab_name: str,
tab_padding: int | None = None,
bar_offset: float = 0.0,
active_bar_style: StyleType,
inactive_bar_style: StyleType,
inactive_text_opacity: float,
tab_padding: int | None,
bar_offset: float,
):
self.tabs = tabs
self.active_tab_name = active_tab_name
self.active_bar_style = active_bar_style
self.inactive_bar_style = inactive_bar_style
self.inactive_text_opacity = inactive_text_opacity
self.tab_padding = tab_padding
self.bar_offset = bar_offset
@@ -30,6 +36,7 @@ class TabsRenderable:
self.tabs,
active_tab_name=self.active_tab_name,
tab_padding=self.tab_padding,
inactive_tab_opacity=self.inactive_text_opacity,
)
yield from console.render(headers)
yield Segment.line()
@@ -50,13 +57,14 @@ class TabsRenderable:
underline = UnderlineBar(
highlight_range=(bar_start, bar_end),
highlight_style="#95d52a",
highlight_style=self.active_bar_style,
background_style=self.inactive_bar_style,
)
yield from console.render(underline)
class Tabs(Widget):
"""Widget for displaying tab headers"""
"""Horizontal tabs"""
active_tab_name: Reactive[str] = Reactive("")
bar_offset: Reactive[float] = Reactive(0.0)
@@ -65,13 +73,20 @@ class Tabs(Widget):
self,
tabs: list[Tab],
active_tab: str | None = None,
active_bar_style: StyleType = "#1BB152",
inactive_bar_style: StyleType = "#455058",
tab_padding: int | None = None,
inactive_text_opacity: float = 0.5,
) -> None:
super().__init__()
self.tabs = tabs
self.active_tab_name = active_tab or tabs[0].name
# TODO: Handle empty tabs
self.active_tab_name = active_tab or tabs[0]
self.active_bar_style = active_bar_style
self.inactive_bar_style = inactive_bar_style
self.bar_offset = float(self.get_tab_index(active_tab) or 0)
self.inactive_text_opacity = inactive_text_opacity
self._used = False
self.tab_padding = tab_padding
@@ -81,7 +96,6 @@ class Tabs(Widget):
def watch_active_tab_name(self, tab_name: str) -> None:
target_tab_index = self.get_tab_index(tab_name)
log("bar_offset", self.bar_offset)
self.animate(
"bar_offset", float(target_tab_index), easing="out_cubic", duration=0.3
)
@@ -98,5 +112,8 @@ class Tabs(Widget):
self.tabs,
tab_padding=self.tab_padding,
active_tab_name=self.active_tab_name,
active_bar_style=self.active_bar_style,
inactive_bar_style=self.inactive_bar_style,
bar_offset=self.bar_offset,
inactive_text_opacity=self.inactive_text_opacity,
)