mirror of
https://github.com/Textualize/textual.git
synced 2025-10-17 02:38:12 +03:00
Extract blend_colors from sparkline, implement opacity
This commit is contained in:
@@ -1,8 +1,17 @@
|
|||||||
|
from time import sleep
|
||||||
|
|
||||||
from rich.console import ConsoleOptions, Console, RenderResult, RenderableType
|
from rich.console import ConsoleOptions, Console, RenderResult, RenderableType
|
||||||
|
from rich.live import Live
|
||||||
|
from rich.panel import Panel
|
||||||
|
from rich.segment import Segment
|
||||||
|
from rich.style import Style
|
||||||
|
from rich.text import Text
|
||||||
|
|
||||||
|
from textual.renderables.utilities import blend_colors
|
||||||
|
|
||||||
|
|
||||||
class Opacity:
|
class Opacity:
|
||||||
"""Return a renderable with the foreground color blended into the background color.
|
"""Wrap a renderable to blend foreground color into the background color.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
renderable (RenderableType): The RenderableType to manipulate.
|
renderable (RenderableType): The RenderableType to manipulate.
|
||||||
@@ -16,4 +25,56 @@ class Opacity:
|
|||||||
def __rich_console__(
|
def __rich_console__(
|
||||||
self, console: Console, options: ConsoleOptions
|
self, console: Console, options: ConsoleOptions
|
||||||
) -> RenderResult:
|
) -> RenderResult:
|
||||||
pass
|
lines = console.render_lines(self.renderable, options)
|
||||||
|
opacity = self.value
|
||||||
|
for line in lines:
|
||||||
|
for segment in line:
|
||||||
|
style = segment.style
|
||||||
|
if not style:
|
||||||
|
yield segment
|
||||||
|
continue
|
||||||
|
fg, bg = style.color, style.bgcolor
|
||||||
|
if fg and bg:
|
||||||
|
style = Style.from_color(
|
||||||
|
color=blend_colors(bg, fg, ratio=opacity),
|
||||||
|
bgcolor=bg,
|
||||||
|
)
|
||||||
|
yield Segment(
|
||||||
|
text=segment.text,
|
||||||
|
style=style,
|
||||||
|
control=segment.control,
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
yield segment
|
||||||
|
yield ""
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
console = Console()
|
||||||
|
|
||||||
|
panel = Panel.fit(
|
||||||
|
Text("Steak: £30", style="#fcffde on #03761e"),
|
||||||
|
title="Menu",
|
||||||
|
style="#ffffff on #000000",
|
||||||
|
)
|
||||||
|
console.print(panel)
|
||||||
|
|
||||||
|
opacity_panel = Opacity(panel, value=0.5)
|
||||||
|
console.print(opacity_panel)
|
||||||
|
|
||||||
|
def frange(start, end, step):
|
||||||
|
current = start
|
||||||
|
while current < end:
|
||||||
|
yield current
|
||||||
|
current += step
|
||||||
|
|
||||||
|
while current >= 0:
|
||||||
|
yield current
|
||||||
|
current -= step
|
||||||
|
|
||||||
|
import itertools
|
||||||
|
|
||||||
|
with Live(opacity_panel, refresh_per_second=60) as live:
|
||||||
|
for value in itertools.cycle(frange(0, 1, 0.05)):
|
||||||
|
opacity_panel.value = value
|
||||||
|
sleep(0.05)
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ from rich.console import ConsoleOptions, Console, RenderResult
|
|||||||
from rich.segment import Segment
|
from rich.segment import Segment
|
||||||
from rich.style import Style
|
from rich.style import Style
|
||||||
|
|
||||||
|
from textual.renderables.utilities import blend_colors
|
||||||
|
|
||||||
T = TypeVar("T", int, float)
|
T = TypeVar("T", int, float)
|
||||||
|
|
||||||
|
|
||||||
@@ -83,34 +85,12 @@ class Sparkline:
|
|||||||
partition_summary = summary_func(partition)
|
partition_summary = summary_func(partition)
|
||||||
height_ratio = (partition_summary - minimum) / extent
|
height_ratio = (partition_summary - minimum) / extent
|
||||||
bar_index = int(height_ratio * (len(self.BARS) - 1))
|
bar_index = int(height_ratio * (len(self.BARS) - 1))
|
||||||
bar_color = _blend_colors(min_color, max_color, height_ratio)
|
bar_color = blend_colors(min_color, max_color, height_ratio)
|
||||||
bars_rendered += 1
|
bars_rendered += 1
|
||||||
bucket_index += step
|
bucket_index += step
|
||||||
yield Segment(text=self.BARS[bar_index], style=Style.from_color(bar_color))
|
yield Segment(text=self.BARS[bar_index], style=Style.from_color(bar_color))
|
||||||
|
|
||||||
|
|
||||||
def _blend_colors(color1: Color, color2: Color, ratio: float) -> Color:
|
|
||||||
"""Given two RGB colors, return a color that sits some distance between
|
|
||||||
them in RGB color space.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
color1 (Color): The first color.
|
|
||||||
color2 (Color): The second color.
|
|
||||||
ratio (float): The ratio of color1 to color2.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
Color: A Color representing the blending of the two supplied colors.
|
|
||||||
"""
|
|
||||||
r1, g1, b1 = color1.triplet
|
|
||||||
r2, g2, b2 = color2.triplet
|
|
||||||
dr = r2 - r1
|
|
||||||
dg = g2 - g1
|
|
||||||
db = b2 - b1
|
|
||||||
return Color.from_rgb(
|
|
||||||
red=r1 + dr * ratio, green=g1 + dg * ratio, blue=b1 + db * ratio
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
console = Console()
|
console = Console()
|
||||||
|
|
||||||
|
|||||||
23
src/textual/renderables/utilities.py
Normal file
23
src/textual/renderables/utilities.py
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
from rich.color import Color
|
||||||
|
|
||||||
|
|
||||||
|
def blend_colors(color1: Color, color2: Color, ratio: float) -> Color:
|
||||||
|
"""Given two RGB colors, return a color that sits some distance between
|
||||||
|
them in RGB color space.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
color1 (Color): The first color.
|
||||||
|
color2 (Color): The second color.
|
||||||
|
ratio (float): The ratio of color1 to color2.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Color: A Color representing the blending of the two supplied colors.
|
||||||
|
"""
|
||||||
|
r1, g1, b1 = color1.triplet
|
||||||
|
r2, g2, b2 = color2.triplet
|
||||||
|
dr = r2 - r1
|
||||||
|
dg = g2 - g1
|
||||||
|
db = b2 - b1
|
||||||
|
return Color.from_rgb(
|
||||||
|
red=r1 + dr * ratio, green=g1 + dg * ratio, blue=b1 + db * ratio
|
||||||
|
)
|
||||||
Reference in New Issue
Block a user