Skip to content

Commit

Permalink
cleaned up tabbed widget a bit
Browse files Browse the repository at this point in the history
  • Loading branch information
timfi committed Aug 11, 2021
1 parent 234567b commit 2f94ea0
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 37 deletions.
22 changes: 16 additions & 6 deletions examples/tabs.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
from rich.markdown import Markdown
from rich.syntax import Syntax

from textual.app import App
from textual import events
from textual.widgets import Placeholder, Tabs, Tab
from textual.widgets import DirectoryTree, Tabs, Tab, ScrollView, Header, Footer


class TabTest(App):
Expand All @@ -9,13 +12,20 @@ async def on_load(self, event: events.Load) -> None:

async def on_mount(self, event: events.Mount) -> None:
"""Make a simple tab arrangement."""
tab1 = Tab("First Tab Label")
await tab1.view.dock(Placeholder())
await self.view.dock(Header())
await self.view.dock(Footer(), edge="bottom")

tab1 = Tab("Rich Readme")
with open("richreadme.md", "r") as f:
await tab1.view.dock(ScrollView(Markdown(f.read())))

tab2 = Tab("Demo Code")
await tab2.view.dock(ScrollView(Syntax.from_path("tabs.py")))

tab2 = Tab("Second Tab Label")
await tab2.view.dock(Placeholder())
tab3 = Tab("Directory")
await tab3.view.dock(ScrollView(DirectoryTree("..")))

tabs = Tabs([tab1, tab2])
tabs = Tabs([tab1, tab2, tab3])
await self.view.dock(tabs)


Expand Down
52 changes: 21 additions & 31 deletions src/textual/widgets/_tabs.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,17 @@

from dataclasses import dataclass, field, InitVar
from logging import getLogger
from platform import mac_ver
from typing import Generic, Literal, TypeVar, TypedDict, cast

from rich.console import RenderableType
from rich.style import StyleType
from rich.panel import Panel
from rich.align import Align
import rich.repr

from ._button import ButtonRenderable
from ._scroll_view import ScrollView
from .. import events, views
from ..widget import Reactive, Widget
from ..view import View
Expand Down Expand Up @@ -40,8 +44,8 @@ def __init__(
HandleStyle,
{
"default": "default",
"default_hover": "bold",
"selected": "reverse",
"default_hover": "reverse",
"selected": "bold",
"selected_hover": "bold reverse",
},
)
Expand All @@ -63,7 +67,7 @@ def container(self, new: Tabs):
current_style: Reactive[StyleMode] = Reactive("default")

def render(self) -> RenderableType:
return ButtonRenderable(self.label, style=self.styles[self.current_style])
return Panel(Align.center(self.label, style=self.styles[self.current_style]))

async def on_click(self, event: events.Click) -> None:
self._container.current = self.label
Expand Down Expand Up @@ -115,10 +119,8 @@ def selected(self, new: bool):
self.handle.selected = new


@rich.repr.auto(angular=False)
class Tabs(views.GridView, can_focus=True):
_tabs: dict[str, Tab]

@rich.repr.auto
class Tabs(views.DockView):
def __init__(
self,
tabs: list[Tab],
Expand All @@ -127,39 +129,27 @@ def __init__(
) -> None:
if not tabs:
raise ValueError("Tabs requires at least on Tab to function.")
self._tabs = {tab.name: tab for tab in tabs}
self._tabs = tabs
self._init = initial_selection or tabs[0].name
super().__init__(name=name)

async def on_mount(self, event: events.Mount) -> None:
for tab in self._tabs.values():
for tab in self._tabs:
tab.bind(self)

self.grid.set_gap(1, 2)
self.grid.set_gutter(1)

max_column = len(self._tabs)
self.grid.add_column("col", fraction=1, repeat=max_column)
self.grid.add_row("labels", max_size=1)
self.grid.place(*(tab.handle for tab in self._tabs.values()))

self.grid.add_row("content", fraction=1)
self.grid.add_areas(content=f"col1-start|col{max_column}-end,content")
for tab in self._tabs.values():
self.grid.place(content=tab.view)

grid = await self.dock_grid(align=("center", "center"))
grid.add_column("col", repeat=max_column)
grid.add_row("bar", max_size=3)
grid.add_row("content")
grid.add_areas(content=f"col1-start|col{max_column}-end,content")
for tab in self._tabs:
grid.place(tab.handle, content=tab.view)
await super().on_mount(event)

self.current = self._init

current: Reactive[str] = Reactive(INIT_TAB)

def validate_current(self, val: str) -> str:
if val not in self._tabs:
raise RuntimeError(f"Unknown tab with name: {val}.")
return val

async def watch_current(self, old: str, new: str) -> None:
if old is not INIT_TAB:
self._tabs[old].selected = False
self._tabs[new].selected = True
async def watch_current(self, new: str) -> None:
for tab in self._tabs:
tab.selected = tab.name == new

0 comments on commit 2f94ea0

Please sign in to comment.