11use super :: {
2+ DeviceSettingsCtx , SearchSettingsCtx ,
23 keys:: { KEY_CONTINUE , KEY_EXIT , KEY_NAVIGATE , KEY_NO , KEY_YES , keys_to_line} ,
3- popup_area, render_main_window, render_video_preview,
4+ popup_area, render_full_menu , render_main_window, render_video_preview,
45} ;
56use crate :: video:: stream:: Image ;
67
78use ratatui:: {
89 Frame ,
9- layout:: { Constraint , Flex , Layout , Rect } ,
10+ layout:: { Constraint , Layout , Rect } ,
1011 style:: { Color , Style , Stylize } ,
1112 text:: { Line , Text , ToLine } ,
1213 widgets:: { Block , BorderType , Clear , HighlightSpacing , List , ListItem , ListState , Paragraph } ,
@@ -25,20 +26,6 @@ pub trait IrEnablerCtx {
2526 fn show_main_abort_prompt ( & self ) -> bool ;
2627 fn show_menu_start_prompt ( & self ) -> bool ;
2728
28- fn device_settings_list_state ( & mut self ) -> & mut ListState ;
29- fn device_valid ( & self ) -> ( String , bool ) ;
30- fn height ( & self ) -> Option < u32 > ;
31- fn width ( & self ) -> Option < u32 > ;
32- fn emitters ( & self ) -> usize ;
33- fn fps ( & self ) -> Option < u32 > ;
34-
35- fn search_settings_list_state ( & mut self ) -> & mut ListState ;
36- fn limit ( & self ) -> Option < u16 > ;
37- fn manual ( & self ) -> bool ;
38- fn analyzer_img_count ( & self ) -> u64 ;
39- fn ref_intensity_var_coef ( & self ) -> u64 ;
40- fn inc_step ( & self ) -> u8 ;
41-
4229 fn controls_list_state ( & mut self ) -> & mut ListState ;
4330 fn controls ( & self ) -> & [ crate :: video:: uvc:: XuControl ] ;
4431 fn image ( & self ) -> Option < & Image > ;
@@ -86,115 +73,6 @@ fn render_confirm_abort_popup(frame: &mut Frame, area: Rect) {
8673 frame. render_widget ( command_paragraph, command_area) ;
8774}
8875
89- /// Renders the main menu with device and search settings.
90- fn render_menu < A > ( frame : & mut Frame , area : Rect , app : & mut A )
91- where
92- A : IrEnablerCtx ,
93- {
94- let [ top_info_area, device_area, search_area, bot_info_area] = Layout :: vertical ( [
95- Constraint :: Length ( 1 ) ,
96- Constraint :: Length ( 7 ) ,
97- Constraint :: Length ( 7 ) ,
98- Constraint :: Length ( 1 ) ,
99- ] )
100- . flex ( Flex :: Center )
101- . areas ( area) ;
102-
103- let top_info_line =
104- Line :: from ( "The tool will iterate through the UVC camera controls and modify them." )
105- . blue ( )
106- . centered ( ) ;
107- frame. render_widget ( top_info_line, top_info_area) ;
108-
109- let bot_info_line = Line :: from ( vec ! [
110- "For more explanation, visit " . into( ) ,
111- "https://github.com/EmixamPP/linux-enable-ir-emitter" . underlined( ) ,
112- ] )
113- . blue ( )
114- . centered ( ) ;
115- frame. render_widget ( bot_info_line, bot_info_area) ;
116-
117- let device_block =
118- Block :: bordered ( ) . title ( Line :: from ( " Device settings " . bold ( ) ) . left_aligned ( ) ) ;
119- let device_settings_list = List :: new ( vec ! [
120- ListItem :: new( Line :: from( vec![ "Path: " . into( ) , {
121- let ( device, valid_device) = app. device_valid( ) ;
122- if valid_device {
123- device. green( )
124- } else {
125- format!( "{device} (not a grey camera device)" ) . red( )
126- }
127- } ] ) ) ,
128- ListItem :: new( Line :: from( vec![
129- "Number of emitters: " . into( ) ,
130- app. emitters( ) . to_string( ) . green( ) ,
131- ] ) ) ,
132- ListItem :: new( Line :: from( vec![
133- "Resolution height: " . into( ) ,
134- app. height( )
135- . map_or( "auto" . to_string( ) , |h| h. to_string( ) )
136- . green( ) ,
137- ] ) ) ,
138- ListItem :: new( Line :: from( vec![
139- "Resolution width: " . into( ) ,
140- app. width( )
141- . map_or( "auto" . to_string( ) , |w| w. to_string( ) )
142- . green( ) ,
143- ] ) ) ,
144- ListItem :: new( Line :: from( vec![
145- "FPS: " . into( ) ,
146- app. fps( )
147- . map_or( "auto" . to_string( ) , |f| f. to_string( ) )
148- . green( ) ,
149- ] ) ) ,
150- ] )
151- . highlight_style ( Style :: default ( ) . fg ( Color :: Yellow ) )
152- . highlight_symbol ( ">" )
153- . highlight_spacing ( HighlightSpacing :: Always )
154- . block ( device_block) ;
155- frame. render_stateful_widget (
156- device_settings_list,
157- device_area,
158- app. device_settings_list_state ( ) ,
159- ) ;
160-
161- let search_block = Block :: bordered ( )
162- . title ( Line :: from ( vec ! [ " Search settings" . bold( ) , " (advanced) " . dim( ) ] ) . left_aligned ( ) ) ;
163- let search_settings_list = List :: new ( vec ! [
164- ListItem :: new( Line :: from( vec![
165- "Manual validation: " . into( ) ,
166- app. manual( ) . to_string( ) . green( ) ,
167- ] ) ) ,
168- ListItem :: new( Line :: from( vec![
169- "Images to analyze in auto validation: " . into( ) ,
170- app. analyzer_img_count( ) . to_string( ) . green( ) ,
171- ] ) ) ,
172- ListItem :: new( Line :: from( vec![
173- "Light difference significance factor: " . into( ) ,
174- app. ref_intensity_var_coef( ) . to_string( ) . green( ) ,
175- ] ) ) ,
176- ListItem :: new( Line :: from( vec![
177- "Rejection threshold per control: " . into( ) ,
178- app. limit( )
179- . map_or( "none" . to_string( ) , |w| w. to_string( ) )
180- . green( ) ,
181- ] ) ) ,
182- ListItem :: new( Line :: from( vec![
183- "Increment step: " . into( ) ,
184- app. inc_step( ) . to_string( ) . green( ) ,
185- ] ) ) ,
186- ] )
187- . highlight_style ( Style :: default ( ) . fg ( Color :: Yellow ) )
188- . highlight_symbol ( ">" )
189- . highlight_spacing ( HighlightSpacing :: Always )
190- . block ( search_block) ;
191- frame. render_stateful_widget (
192- search_settings_list,
193- search_area,
194- app. search_settings_list_state ( ) ,
195- ) ;
196- }
197-
19876/// Renders the main application interface showing the camera preview and the list of controls,
19977/// as well as extra information for the current control.
20078///
@@ -259,12 +137,17 @@ where
259137/// Renders the application UI based on the current application state.
260138pub fn ui < A > ( frame : & mut Frame , app : & mut A )
261139where
262- A : IrEnablerCtx ,
140+ A : IrEnablerCtx + DeviceSettingsCtx + SearchSettingsCtx ,
263141{
264142 match app. view ( ) {
265143 View :: Menu => {
266144 let main_area = render_main_window ( frame, & [ KEY_NAVIGATE , KEY_CONTINUE , KEY_EXIT ] ) ;
267- render_menu ( frame, main_area, app) ;
145+ render_full_menu (
146+ frame,
147+ main_area,
148+ app,
149+ "The tool will iterate through the UVC camera controls and modify them." ,
150+ ) ;
268151 if app. show_menu_start_prompt ( ) {
269152 render_confirm_start_popup ( frame, main_area) ;
270153 }
@@ -320,6 +203,18 @@ mod tests {
320203 fn show_menu_start_prompt ( & self ) -> bool {
321204 self . show_menu_start_prompt
322205 }
206+ fn controls_list_state ( & mut self ) -> & mut ListState {
207+ & mut self . controls_list_state
208+ }
209+ fn controls ( & self ) -> & [ crate :: video:: uvc:: XuControl ] {
210+ & self . controls
211+ }
212+ fn image ( & self ) -> Option < & Image > {
213+ self . image . as_ref ( )
214+ }
215+ }
216+
217+ impl DeviceSettingsCtx for App {
323218 fn device_settings_list_state ( & mut self ) -> & mut ListState {
324219 & mut self . device_settings_list_state
325220 }
@@ -338,6 +233,9 @@ mod tests {
338233 fn fps ( & self ) -> Option < u32 > {
339234 self . fps
340235 }
236+ }
237+
238+ impl SearchSettingsCtx for App {
341239 fn search_settings_list_state ( & mut self ) -> & mut ListState {
342240 & mut self . search_settings_list_state
343241 }
@@ -356,15 +254,6 @@ mod tests {
356254 fn inc_step ( & self ) -> u8 {
357255 self . inc_step
358256 }
359- fn controls_list_state ( & mut self ) -> & mut ListState {
360- & mut self . controls_list_state
361- }
362- fn controls ( & self ) -> & [ crate :: video:: uvc:: XuControl ] {
363- & self . controls
364- }
365- fn image ( & self ) -> Option < & Image > {
366- self . image . as_ref ( )
367- }
368257 }
369258
370259 #[ test]
0 commit comments