@@ -4,20 +4,28 @@ use common::{Colors, Result, Terminal};
44use ratatui:: crossterm:: event:: { self , Event , KeyCode , KeyEventKind } ;
55use ratatui:: {
66 prelude:: * ,
7- widgets:: { Block , Borders , Widget } ,
7+ widgets:: { Block , Borders , Scrollbar , Widget } ,
88} ;
99use tui_widget_list:: { ListBuilder , ListState , ListView } ;
1010
11- const SIZES : [ u16 ; 19 ] = [ 32 , 3 , 4 , 64 , 6 , 5 , 4 , 3 , 3 , 6 , 5 , 7 , 3 , 6 , 9 , 10 , 4 , 4 , 6 ] ;
11+ const ITEMS : & [ ( & str , u16 ) ] = & [
12+ ( "Header" , 3 ) ,
13+ ( "Summary" , 5 ) ,
14+ ( "Details" , 30 ) ,
15+ ( "Note A" , 4 ) ,
16+ ( "Note B" , 4 ) ,
17+ ( "Body" , 25 ) ,
18+ ( "Sidebar" , 6 ) ,
19+ ( "Note C" , 3 ) ,
20+ ( "Note D" , 3 ) ,
21+ ( "Footer" , 5 ) ,
22+ ] ;
1223
1324fn main ( ) -> Result < ( ) > {
1425 let mut terminal = Terminal :: init ( ) ?;
15-
1626 App :: default ( ) . run ( & mut terminal) ?;
17-
1827 Terminal :: reset ( ) ?;
1928 terminal. show_cursor ( ) ?;
20-
2129 Ok ( ( ) )
2230}
2331
@@ -29,7 +37,6 @@ impl App {
2937 let mut state = ListState :: default ( ) ;
3038 loop {
3139 terminal. draw_app ( self , & mut state) ?;
32-
3340 if let Event :: Key ( key) = event:: read ( ) ? {
3441 if key. kind == KeyEventKind :: Press {
3542 match key. code {
@@ -46,51 +53,61 @@ impl App {
4653
4754impl StatefulWidget for & App {
4855 type State = ListState ;
49- fn render ( self , area : Rect , buf : & mut Buffer , state : & mut Self :: State )
50- where
51- Self : Sized ,
52- {
53- let item_count = SIZES . len ( ) ;
54-
55- let block = Block :: default ( ) . borders ( Borders :: ALL ) . title ( "Outer block" ) ;
56+ fn render ( self , area : Rect , buf : & mut Buffer , state : & mut Self :: State ) {
5657 let builder = ListBuilder :: new ( move |context| {
57- let size = SIZES [ context. index ] ;
58- let mut widget = LineItem :: new ( format ! ( "Size: {size}" ) ) ;
58+ let ( title, size) = ITEMS [ context. index ] ;
59+ let label = format ! ( " {} (h={})" , title, size) ;
60+
61+ let style = if context. is_selected {
62+ Style :: default ( ) . bg ( Colors :: ORANGE ) . fg ( Colors :: CHARCOAL )
63+ } else if context. index % 2 == 0 {
64+ Style :: default ( ) . bg ( Colors :: CHARCOAL ) . fg ( Colors :: WHITE )
65+ } else {
66+ Style :: default ( ) . bg ( Colors :: BLACK ) . fg ( Colors :: WHITE )
67+ } ;
5968
60- if context. is_selected {
61- widget. line . style = widget. line . style . bg ( Color :: White ) ;
69+ let block = Block :: default ( ) . borders ( Borders :: ALL ) . style ( style) ;
70+ let inner = block. inner ( Rect :: new ( 0 , 0 , context. cross_axis_size , size) ) ;
71+ let widget = SectionItem {
72+ label,
73+ block,
74+ inner_height : inner. height ,
6275 } ;
6376
64- return ( widget, size) ;
77+ ( widget, size)
6578 } ) ;
66- let list = ListView :: new ( builder, item_count)
67- . bg ( Color :: Black )
68- . block ( block) ;
79+
80+ let list = ListView :: new ( builder, ITEMS . len ( ) )
81+ . infinite_scrolling ( false )
82+ . scrollbar ( Scrollbar :: default ( ) )
83+ . block (
84+ Block :: default ( )
85+ . borders ( Borders :: ALL )
86+ . title ( " Variable Sizes " ) ,
87+ ) ;
6988 list. render ( area, buf, state) ;
7089 }
7190}
7291
73- #[ derive( Debug , Clone ) ]
74- pub struct LineItem < ' a > {
75- line : Line < ' a > ,
92+ struct SectionItem {
93+ label : String ,
94+ block : Block < ' static > ,
95+ inner_height : u16 ,
7696}
7797
78- impl LineItem < ' _ > {
79- pub fn new ( text : String ) -> Self {
80- let span = Span :: styled ( text, Style :: default ( ) . fg ( Colors :: TEAL ) ) ;
81- let line = Line :: from ( span) . bg ( Colors :: CHARCOAL ) ;
82- Self { line }
83- }
84- }
85-
86- impl Widget for LineItem < ' _ > {
98+ impl Widget for SectionItem {
8799 fn render ( self , area : Rect , buf : & mut Buffer ) {
88- let inner = {
89- let block = Block :: default ( ) . borders ( Borders :: ALL ) ;
90- block. clone ( ) . render ( area, buf) ;
91- block. inner ( area)
92- } ;
93-
94- self . line . render ( inner, buf) ;
100+ let inner = self . block . inner ( area) ;
101+ self . block . render ( area, buf) ;
102+ if inner. height > 0 {
103+ Line :: from ( self . label ) . render ( inner, buf) ;
104+ }
105+ for row in 1 ..inner. height . min ( self . inner_height ) {
106+ let y = inner. y + row;
107+ let filler = format ! ( " line {}" , row) ;
108+ Line :: from ( filler)
109+ . style ( Style :: default ( ) . fg ( Colors :: GRAY ) )
110+ . render ( Rect :: new ( inner. x , y, inner. width , 1 ) , buf) ;
111+ }
95112 }
96113}
0 commit comments