11from __future__ import annotations
22
33from rich .console import Console , ConsoleOptions , RenderResult
4- from rich .style import StyleType
4+ from rich .style import Style , StyleType
55from rich .text import Text
66
7+ from textual .color import Gradient
8+
79
810class Bar :
911 """Thin horizontal bar with a portion highlighted.
@@ -12,7 +14,8 @@ class Bar:
1214 highlight_range: The range to highlight.
1315 highlight_style: The style of the highlighted range of the bar.
1416 background_style: The style of the non-highlighted range(s) of the bar.
15- width: The width of the bar, or ``None`` to fill available width.
17+ width: The width of the bar, or `None` to fill available width.
18+ gradient. Optional gradient object.
1619 """
1720
1821 def __init__ (
@@ -22,12 +25,14 @@ def __init__(
2225 background_style : StyleType = "grey37" ,
2326 clickable_ranges : dict [str , tuple [int , int ]] | None = None ,
2427 width : int | None = None ,
28+ gradient : Gradient | None = None ,
2529 ) -> None :
2630 self .highlight_range = highlight_range
2731 self .highlight_style = highlight_style
2832 self .background_style = background_style
2933 self .clickable_ranges = clickable_ranges or {}
3034 self .width = width
35+ self .gradient = gradient
3136
3237 def __rich_console__ (
3338 self , console : Console , options : ConsoleOptions
@@ -67,18 +72,23 @@ def __rich_console__(
6772 if not half_start and start > 0 :
6873 output_bar .append (Text (half_bar_right , style = background_style , end = "" ))
6974
75+ highlight_bar = Text ("" , end = "" )
7076 # The highlighted portion
7177 bar_width = int (end ) - int (start )
7278 if half_start :
73- output_bar .append (
79+ highlight_bar .append (
7480 Text (
7581 half_bar_left + bar * (bar_width - 1 ), style = highlight_style , end = ""
7682 )
7783 )
7884 else :
79- output_bar .append (Text (bar * bar_width , style = highlight_style , end = "" ))
85+ highlight_bar .append (Text (bar * bar_width , style = highlight_style , end = "" ))
8086 if half_end :
81- output_bar .append (Text (half_bar_right , style = highlight_style , end = "" ))
87+ highlight_bar .append (Text (half_bar_right , style = highlight_style , end = "" ))
88+
89+ if self .gradient is not None :
90+ _apply_gradient (highlight_bar , self .gradient , width )
91+ output_bar .append (highlight_bar )
8292
8393 # The non-highlighted tail
8494 if not half_end and end - width != 0 :
@@ -96,45 +106,29 @@ def __rich_console__(
96106 yield output_bar
97107
98108
99- if __name__ == "__main__" :
100- import random
101- from time import sleep
102-
103- from rich .color import ANSI_COLOR_NAMES
104-
105- console = Console ()
106-
107- def frange (start , end , step ):
108- current = start
109- while current < end :
110- yield current
111- current += step
112-
113- while current >= 0 :
114- yield current
115- current -= step
116-
117- step = 0.1
118- start_range = frange (0.5 , 10.5 , step )
119- end_range = frange (10 , 20 , step )
120- ranges = zip (start_range , end_range )
109+ def _apply_gradient (text : Text , gradient : Gradient , width : int ) -> None :
110+ """Apply a gradient to a Rich Text instance.
121111
122- console .print (Bar (width = 20 ), f" (.0, .0)" )
123-
124- for range in ranges :
125- color = random .choice (list (ANSI_COLOR_NAMES .keys ()))
126- console .print (
127- Bar (range , highlight_style = color , width = 20 ),
128- f" { range } " ,
112+ Args:
113+ text: A Text object.
114+ gradient: A Textual gradient.
115+ width: Width of gradient.
116+ """
117+ if not width :
118+ return
119+ assert width > 0
120+ from_color = Style .from_color
121+ get_rich_color = gradient .get_rich_color
122+
123+ max_width = width - 1
124+ if not max_width :
125+ text .stylize (from_color (gradient .get_color (0 ).rich_color ))
126+ return
127+ text_length = len (text )
128+ for offset in range (text_length ):
129+ bar_offset = text_length - offset
130+ text .stylize (
131+ from_color (get_rich_color (bar_offset / max_width )),
132+ offset ,
133+ offset + 1 ,
129134 )
130-
131- from rich .live import Live
132-
133- bar = Bar (highlight_range = (0 , 4.5 ), width = 80 )
134- with Live (bar , refresh_per_second = 60 ) as live :
135- while True :
136- bar .highlight_range = (
137- bar .highlight_range [0 ] + 0.1 ,
138- bar .highlight_range [1 ] + 0.1 ,
139- )
140- sleep (0.005 )
0 commit comments