@@ -21,6 +21,8 @@ use ratatui::{
2121 widgets:: {
2222 Block ,
2323 BorderType ,
24+ List ,
25+ ListItem ,
2426 Paragraph ,
2527 Scrollbar ,
2628 ScrollbarOrientation ,
@@ -73,7 +75,7 @@ pub fn render(state: &mut State, frame: &mut Frame) {
7375 }
7476}
7577
76- fn render_key_bindings ( frame : & mut Frame , rect : Rect ) {
78+ fn render_key_bindings ( frame : & mut Frame , area : Rect ) {
7779 frame. render_widget (
7880 Paragraph :: new (
7981 Line :: default ( )
@@ -93,69 +95,44 @@ fn render_key_bindings(frame: &mut Frame, rect: Rect) {
9395 )
9496 . alignment ( Alignment :: Center ) ,
9597 ) ,
96- rect ,
98+ area ,
9799 ) ;
98100}
99101
100- fn render_list ( state : & mut State , frame : & mut Frame , rect : Rect ) {
101- frame. render_widget (
102- Block :: bordered ( )
103- . title_top ( "|Config|" . yellow ( ) )
104- . title_alignment ( Alignment :: Center )
105- . border_type ( BorderType :: Rounded )
106- . border_style ( Style :: default ( ) . fg ( Color :: Rgb ( 100 , 100 , 100 ) ) ) ,
107- rect,
108- ) ;
102+ fn render_list ( state : & mut State , frame : & mut Frame , area : Rect ) {
109103 if !state. configs . is_empty ( ) {
110- let rect =
111- Layout :: vertical ( [ Constraint :: Min ( 1 ) , Constraint :: Percentage ( 100 ) ] )
112- . split ( rect) [ 1 ] ;
113- let borders_line = 2 ;
114- let item_count = ( rect. height - borders_line) as usize ;
115- let start_offset = ( state. selected_index + 1 ) . saturating_sub ( item_count) ;
116- let rects =
117- Layout :: vertical ( [ Constraint :: Length ( 1 ) ] . repeat ( item_count) ) . split ( rect) ;
118- for ( i, config) in state
104+ let items = state
119105 . configs
120- . iter_mut ( )
121- . skip ( start_offset)
122- . take ( item_count)
123- . enumerate ( )
124- {
125- let mut style = Style :: new ( ) ;
126- if config. is_hovered {
127- style = style. yellow ( )
128- } else if state. selected_index == i + start_offset {
129- style = style. yellow ( ) ;
130- }
131- let item = Layout :: horizontal ( [
132- Constraint :: Min ( 1 ) ,
133- Constraint :: Percentage ( 100 ) ,
134- ] )
135- . split ( rects[ i] ) ;
136- config. area = rects[ i] ;
137- frame. render_widget (
138- Paragraph :: new ( Line :: from ( config. file . clone ( ) ) . style ( style) ) ,
139- item[ 1 ] ,
140- ) ;
141- }
142- if state. configs . len ( ) > rect. height as usize - 2 {
143- frame. render_stateful_widget (
144- Scrollbar :: new ( ScrollbarOrientation :: VerticalRight )
145- . begin_symbol ( Some ( "↑" ) )
146- . end_symbol ( Some ( "↓" ) ) ,
147- rect. inner ( Margin {
148- vertical : 1 ,
149- horizontal : 0 ,
150- } ) ,
151- & mut ScrollbarState :: new ( item_count) . position ( state. selected_index ) ,
152- ) ;
153- }
106+ . iter ( )
107+ . map ( |c| ListItem :: new ( c. file . to_string ( ) ) )
108+ . collect :: < Vec < ListItem > > ( ) ;
109+ let list = List :: new ( items)
110+ . block (
111+ Block :: bordered ( )
112+ . title_top ( "|Config|" . yellow ( ) )
113+ . title_alignment ( Alignment :: Center )
114+ . border_type ( BorderType :: Rounded )
115+ . border_style ( Style :: default ( ) . fg ( Color :: Rgb ( 100 , 100 , 100 ) ) ) ,
116+ )
117+ . style ( Style :: new ( ) . white ( ) )
118+ . highlight_style ( Style :: new ( ) . reversed ( ) ) ;
119+ frame. render_stateful_widget ( list, area, & mut state. list_state ) ;
120+ frame. render_stateful_widget (
121+ Scrollbar :: new ( ScrollbarOrientation :: VerticalRight )
122+ . begin_symbol ( Some ( "↑" ) )
123+ . end_symbol ( Some ( "↓" ) ) ,
124+ area. inner ( Margin {
125+ vertical : 1 ,
126+ horizontal : 0 ,
127+ } ) ,
128+ & mut ScrollbarState :: new ( state. configs . len ( ) )
129+ . position ( state. list_state . selected ( ) . unwrap_or_default ( ) ) ,
130+ ) ;
154131 }
155132}
156133
157- fn render_changelog ( state : & mut State , frame : & mut Frame , rect : Rect ) {
158- state. markdown . area = rect . inner ( Margin {
134+ fn render_changelog ( state : & mut State , frame : & mut Frame , area : Rect ) {
135+ state. markdown . area = area . inner ( Margin {
159136 horizontal : 1 ,
160137 vertical : 1 ,
161138 } ) ;
@@ -222,7 +199,7 @@ fn render_changelog(state: &mut State, frame: &mut Frame, rect: Rect) {
222199 Line :: from ( format ! ( "|{}|" , env!( "CARGO_PKG_VERSION" ) ) )
223200 . right_aligned ( ) ,
224201 ) ,
225- rect ,
202+ area ,
226203 ) ;
227204 if let Some ( component) = & mut state. markdown . component {
228205 let mut height = 2 ;
@@ -241,7 +218,7 @@ fn render_changelog(state: &mut State, frame: &mut Frame, rect: Rect) {
241218 Scrollbar :: new ( ScrollbarOrientation :: VerticalRight )
242219 . begin_symbol ( Some ( "↑" ) )
243220 . end_symbol ( Some ( "↓" ) ) ,
244- rect . inner ( Margin {
221+ area . inner ( Margin {
245222 vertical : 1 ,
246223 horizontal : 0 ,
247224 } ) ,
@@ -252,8 +229,8 @@ fn render_changelog(state: &mut State, frame: &mut Frame, rect: Rect) {
252229
253230 if state. is_generating {
254231 let throbber_area = Rect :: new (
255- rect . left ( ) . saturating_add ( 2 ) ,
256- rect . bottom ( ) . saturating_sub ( 1 ) ,
232+ area . left ( ) . saturating_add ( 2 ) ,
233+ area . bottom ( ) . saturating_sub ( 1 ) ,
257234 1 ,
258235 1 ,
259236 ) ;
@@ -273,20 +250,20 @@ fn render_changelog(state: &mut State, frame: &mut Frame, rect: Rect) {
273250 }
274251}
275252
276- fn render_error ( state : & mut State , frame : & mut Frame , rect : Rect ) {
253+ fn render_error ( state : & mut State , frame : & mut Frame , area : Rect ) {
277254 if let Some ( error) = & state. error {
278255 frame. render_widget (
279256 Block :: bordered ( )
280257 . title_top ( "|Error|" . red ( ) . into_centered_line ( ) )
281258 . border_type ( BorderType :: Rounded )
282259 . border_style ( Style :: default ( ) . fg ( Color :: Rgb ( 100 , 100 , 100 ) ) ) ,
283- rect ,
260+ area ,
284261 ) ;
285262 frame. render_widget (
286263 Paragraph :: new ( Line :: from ( error. clone ( ) ) )
287264 . alignment ( Alignment :: Center )
288265 . wrap ( Wrap { trim : false } ) ,
289- rect . inner ( Margin {
266+ area . inner ( Margin {
290267 horizontal : 1 ,
291268 vertical : 1 ,
292269 } ) ,
0 commit comments