@@ -4,95 +4,90 @@ use ratatui::{
4
4
crossterm:: event:: { self , Event , KeyCode , KeyEvent , KeyEventKind } ,
5
5
prelude:: { Constraint , Frame , Layout , Rect , Style , Stylize , Text } ,
6
6
widgets:: { Paragraph , Wrap } ,
7
+ DefaultTerminal ,
7
8
} ;
8
9
use tui_popup:: { Popup , PopupState } ;
9
10
10
- mod terminal;
11
-
12
11
fn main ( ) -> Result < ( ) > {
13
- let mut terminal = terminal:: init ( ) ?;
14
- let mut app = App :: default ( ) ;
15
- while !app. should_exit {
16
- terminal. draw ( |frame| app. render ( frame) ) ?;
17
- app. handle_events ( ) ?;
18
- }
19
- terminal:: restore ( ) ?;
20
- Ok ( ( ) )
12
+ color_eyre:: install ( ) ?;
13
+ let terminal = ratatui:: init ( ) ;
14
+ let result = run ( terminal) ;
15
+ ratatui:: restore ( ) ;
16
+ result
21
17
}
22
18
23
- #[ derive( Default ) ]
24
- struct App {
25
- popup : PopupState ,
26
- should_exit : bool ,
19
+ fn run ( mut terminal : DefaultTerminal ) -> Result < ( ) > {
20
+ let mut state = PopupState :: default ( ) ;
21
+ let mut exit = false ;
22
+ while !exit {
23
+ terminal. draw ( |frame| draw ( frame, & mut state) ) ?;
24
+ handle_events ( & mut state, & mut exit) ?;
25
+ }
26
+ Ok ( ( ) )
27
27
}
28
28
29
- impl App {
30
- fn render ( & mut self , frame : & mut Frame ) {
31
- let [ background_area, status_area] =
32
- Layout :: vertical ( [ Constraint :: Min ( 0 ) , Constraint :: Length ( 1 ) ] ) . areas ( frame. area ( ) ) ;
33
-
34
- let background = Self :: background ( background_area) ;
35
- frame. render_widget ( background, background_area) ;
29
+ fn draw ( frame : & mut Frame , state : & mut PopupState ) {
30
+ let vertical = Layout :: vertical ( [ Constraint :: Min ( 0 ) , Constraint :: Length ( 1 ) ] ) ;
31
+ let [ background_area, status_area] = vertical. areas ( frame. area ( ) ) ;
36
32
37
- let popup = Self :: popup_widget ( ) ;
38
- frame. render_stateful_widget_ref ( popup, background_area, & mut self . popup ) ;
39
-
40
- // must be called after rendering the popup widget as it relies on the popup area being set
41
- let status_bar = self . status_bar ( ) ;
42
- frame. render_widget ( status_bar, status_area) ;
43
- }
33
+ render_background ( frame, background_area) ;
34
+ render_popup ( frame, background_area, state) ;
35
+ render_status_bar ( frame, status_area, state) ;
36
+ }
44
37
45
- fn background ( area : Rect ) -> Paragraph < ' static > {
46
- let lorem_ipsum = lipsum ( area. area ( ) as usize / 5 ) ;
47
- Paragraph :: new ( lorem_ipsum)
48
- . wrap ( Wrap { trim : false } )
49
- . dark_gray ( )
50
- }
38
+ fn render_background ( frame : & mut Frame , area : Rect ) {
39
+ let lorem_ipsum = lipsum ( area. area ( ) as usize / 5 ) ;
40
+ let background = Paragraph :: new ( lorem_ipsum)
41
+ . wrap ( Wrap { trim : false } )
42
+ . dark_gray ( ) ;
43
+ frame. render_widget ( background, area) ;
44
+ }
51
45
52
- fn popup_widget ( ) -> Popup < ' static , Text < ' static > > {
53
- Popup :: new ( Text :: from_iter ( [
54
- "q: exit" ,
55
- "r: reset" ,
56
- "j: move down" ,
57
- "k: move up" ,
58
- "h: move left" ,
59
- "l: move right" ,
60
- ] ) )
46
+ fn render_popup ( frame : & mut Frame , area : Rect , state : & mut PopupState ) {
47
+ let body = Text :: from_iter ( [
48
+ "q: exit" ,
49
+ "r: reset" ,
50
+ "j: move down" ,
51
+ "k: move up" ,
52
+ "h: move left" ,
53
+ "l: move right" ,
54
+ ] ) ;
55
+ let popup = Popup :: new ( & body)
61
56
. title ( "Popup" )
62
- . style ( Style :: new ( ) . white ( ) . on_blue ( ) )
63
- }
64
-
65
- /// Status bar at the bottom of the screen
66
- ///
67
- /// Must be called after rendering the popup widget as it relies on the popup area being set
68
- fn status_bar ( & self ) -> Paragraph < ' static > {
69
- let popup_area = self . popup . area ( ) . unwrap_or_default ( ) ;
70
- let text = format ! ( "Popup area: {popup_area:?}" ) ;
71
- Paragraph :: new ( text) . style ( Style :: new ( ) . white ( ) . on_black ( ) )
72
- }
57
+ . style ( Style :: new ( ) . white ( ) . on_blue ( ) ) ;
58
+ frame. render_stateful_widget ( popup, area, state) ;
59
+ }
73
60
74
- fn handle_events ( & mut self ) -> Result < ( ) > {
75
- match event:: read ( ) ? {
76
- Event :: Key ( event) => self . handle_key_event ( event) ,
77
- Event :: Mouse ( event) => self . popup . handle_mouse_event ( event) ,
78
- _ => ( ) ,
79
- } ;
80
- Ok ( ( ) )
81
- }
61
+ /// Status bar at the bottom of the screen
62
+ ///
63
+ /// Must be called after rendering the popup widget as it relies on the popup area being set
64
+ fn render_status_bar ( frame : & mut Frame , area : Rect , state : & mut PopupState ) {
65
+ let popup_area = state. area ( ) . unwrap_or_default ( ) ;
66
+ let text = format ! ( "Popup area: {popup_area:?}" ) ;
67
+ let paragraph = Paragraph :: new ( text) . style ( Style :: new ( ) . white ( ) . on_black ( ) ) ;
68
+ frame. render_widget ( paragraph, area) ;
69
+ }
82
70
83
- fn handle_key_event ( & mut self , event : KeyEvent ) {
84
- if event. kind != KeyEventKind :: Press {
85
- return ;
86
- }
87
- match event. code {
88
- KeyCode :: Char ( 'q' ) | KeyCode :: Esc => self . should_exit = true ,
89
- KeyCode :: Char ( 'r' ) => self . popup = PopupState :: default ( ) ,
90
- // TODO: move handling to PopupState (e.g. move_up, move_down, etc. or move(Move:Up))
91
- KeyCode :: Char ( 'j' ) | KeyCode :: Down => self . popup . move_by ( 0 , 1 ) ,
92
- KeyCode :: Char ( 'k' ) | KeyCode :: Up => self . popup . move_by ( 0 , -1 ) ,
93
- KeyCode :: Char ( 'h' ) | KeyCode :: Left => self . popup . move_by ( -1 , 0 ) ,
94
- KeyCode :: Char ( 'l' ) | KeyCode :: Right => self . popup . move_by ( 1 , 0 ) ,
95
- _ => { }
71
+ fn handle_events ( popup : & mut PopupState , exit : & mut bool ) -> Result < ( ) > {
72
+ match event:: read ( ) ? {
73
+ Event :: Key ( event) if event. kind == KeyEventKind :: Press => {
74
+ handle_key_event ( event, popup, exit)
96
75
}
76
+ Event :: Mouse ( event) => popup. handle_mouse_event ( event) ,
77
+ _ => ( ) ,
78
+ } ;
79
+ Ok ( ( ) )
80
+ }
81
+
82
+ fn handle_key_event ( event : KeyEvent , popup : & mut PopupState , exit : & mut bool ) {
83
+ match event. code {
84
+ KeyCode :: Char ( 'q' ) | KeyCode :: Esc => * exit = true ,
85
+ KeyCode :: Char ( 'r' ) => * popup = PopupState :: default ( ) ,
86
+ // TODO: move handling to PopupState (e.g. move_up, move_down, etc. or move(Move:Up))
87
+ KeyCode :: Char ( 'j' ) | KeyCode :: Down => popup. move_by ( 0 , 1 ) ,
88
+ KeyCode :: Char ( 'k' ) | KeyCode :: Up => popup. move_by ( 0 , -1 ) ,
89
+ KeyCode :: Char ( 'h' ) | KeyCode :: Left => popup. move_by ( -1 , 0 ) ,
90
+ KeyCode :: Char ( 'l' ) | KeyCode :: Right => popup. move_by ( 1 , 0 ) ,
91
+ _ => { }
97
92
}
98
93
}
0 commit comments