Skip to content

Commit 6865e4d

Browse files
committed
wip: refactor(tweaker): revamp tweak tool in Rust
1 parent 11fac82 commit 6865e4d

13 files changed

Lines changed: 694 additions & 141 deletions

src/configure.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,12 @@ mod ui;
44
pub async fn configure() -> anyhow::Result<()> {
55
let res = app::run(&mut ratatui::init()).await;
66
ratatui::restore();
7+
8+
// Print any successful message to the user once the TUI is closed
79
if let Ok(msg) = &res
810
&& !msg.is_empty()
911
{
1012
println!("{}", msg);
1113
}
12-
res.map(|_| ())
14+
res.map(|_| ()) // Delete the success message
1315
}

src/configure/app/ir_enabler.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -341,7 +341,7 @@ impl App {
341341
async fn handle_term_event(&mut self, event: Event) -> Result<()> {
342342
match event {
343343
Event::Key(key_event) if key_event.kind == KeyEventKind::Press => {
344-
self.handle_key_press(key_event.code.into()).await?;
344+
self.handle_key_press(key_event.code).await?;
345345
}
346346
_ => {}
347347
};

src/configure/ui.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ mod keys {
5050
pub const KEY_CONTINUE: Key = Key::new(KeyCode::Enter, "Continue", Color::Green);
5151
pub const KEY_YES: Key = Key::new(KeyCode::Char('y'), "Yes", Color::Green);
5252
pub const KEY_NO: Key = Key::new(KeyCode::Char('n'), "No", Color::Red);
53+
pub const KEY_EDIT: Key = Key::new(KeyCode::Enter, "Edit", Color::Green);
5354
}
5455

5556
#[cfg(test)]

src/configure/ui/ir_enabler.rs

Lines changed: 25 additions & 136 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
use 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
};
56
use crate::video::stream::Image;
67

78
use 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.
260138
pub fn ui<A>(frame: &mut Frame, app: &mut A)
261139
where
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

Comments
 (0)