mirror of
https://github.com/Textualize/textual.git
synced 2025-10-17 02:38:12 +03:00
UnderlineBar component
This commit is contained in:
0
src/textual/renderables/__init__.py
Normal file
0
src/textual/renderables/__init__.py
Normal file
99
src/textual/renderables/tab_underline.py
Normal file
99
src/textual/renderables/tab_underline.py
Normal file
@@ -0,0 +1,99 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import random
|
||||
|
||||
from rich.color import Color, ANSI_COLOR_NAMES
|
||||
from rich.console import ConsoleOptions, Console, RenderResult
|
||||
from rich.segment import Segment
|
||||
from rich.style import Style
|
||||
|
||||
|
||||
class UnderlineBar:
|
||||
def __init__(
|
||||
self,
|
||||
highlight_range: tuple[float, float] = 0,
|
||||
range_color: Color = Color.parse("yellow"),
|
||||
other_color: Color = Color.parse("default"),
|
||||
background_color: Color = Color.parse("default"),
|
||||
width: int | None = None,
|
||||
) -> None:
|
||||
self.highlight_range = highlight_range
|
||||
self.highlight_style = Style.from_color(
|
||||
color=range_color, bgcolor=background_color
|
||||
)
|
||||
self.other_style = Style.from_color(color=other_color, bgcolor=background_color)
|
||||
self.width = width
|
||||
|
||||
def __rich_console__(
|
||||
self, console: Console, options: ConsoleOptions
|
||||
) -> RenderResult:
|
||||
half_bar_right = "╸"
|
||||
half_bar_left = "╺"
|
||||
bar = "━"
|
||||
width = self.width or options.max_width
|
||||
start, end = self.highlight_range
|
||||
|
||||
# Round start and end to nearest half
|
||||
start = round(start * 2) / 2
|
||||
end = round(end * 2) / 2
|
||||
|
||||
# start = 3.6; end = 9.6
|
||||
# full bars before = int(start) = 3
|
||||
# half_start = .6 > 0 = True
|
||||
|
||||
# Bars before highlighted range
|
||||
half_start = start - int(start) > 0
|
||||
half_end = end - int(end) > 0
|
||||
|
||||
# Non-highlighted portion of bar
|
||||
|
||||
if half_start:
|
||||
yield Segment(bar * (int(start) + 1), style=self.other_style)
|
||||
yield Segment(half_bar_left, style=self.highlight_style)
|
||||
else:
|
||||
yield Segment(bar * (int(start)), style=self.other_style)
|
||||
yield Segment(half_bar_right, style=self.other_style)
|
||||
|
||||
# If we have a half bar at start and end, we need 1 less full bar
|
||||
full_bar_width = int(end) - int(start)
|
||||
if half_start and half_end:
|
||||
full_bar_width -= 1
|
||||
|
||||
yield Segment(bar * full_bar_width, style=self.highlight_style)
|
||||
|
||||
if half_end:
|
||||
yield Segment(half_bar_right, style=self.highlight_style)
|
||||
else:
|
||||
yield Segment(half_bar_left, style=self.other_style)
|
||||
|
||||
yield Segment(bar * (int(width) - int(end)), style=self.other_style)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
console = Console()
|
||||
|
||||
def frange(start, end, step):
|
||||
current = start
|
||||
while current < end:
|
||||
yield current
|
||||
current += step
|
||||
|
||||
while current >= 0:
|
||||
yield current
|
||||
current -= step
|
||||
|
||||
start_range = frange(0, 12, 0.5)
|
||||
end_range = frange(6, 18, 0.5)
|
||||
ranges = zip(start_range, end_range)
|
||||
|
||||
for range in ranges:
|
||||
color = random.choice(list(ANSI_COLOR_NAMES.keys()))
|
||||
console.print(
|
||||
UnderlineBar(
|
||||
range,
|
||||
range_color=Color.parse(color),
|
||||
other_color=Color.parse("#4f4f4f"),
|
||||
width=18,
|
||||
)
|
||||
)
|
||||
console.print()
|
||||
Reference in New Issue
Block a user