WIP: better precision?
This commit is contained in:
@@ -11,6 +11,7 @@ use crate::widgets::{Orientation, Scope, Spectrum};
|
||||
|
||||
const HEADER_COLOR: Color = Color::Rgb(100, 160, 180);
|
||||
const DIVIDER_COLOR: Color = Color::Rgb(60, 65, 70);
|
||||
const SCROLL_INDICATOR_COLOR: Color = Color::Rgb(80, 85, 95);
|
||||
|
||||
pub fn render(frame: &mut Frame, app: &App, area: Rect) {
|
||||
let [left_col, _, right_col] = Layout::horizontal([
|
||||
@@ -40,20 +41,105 @@ fn render_settings_section(frame: &mut Frame, app: &App, area: Rect) {
|
||||
height: inner.height.saturating_sub(1),
|
||||
};
|
||||
|
||||
let devices_height = devices_section_height(app);
|
||||
// Calculate section heights
|
||||
let devices_lines = devices_section_height(app) as usize;
|
||||
let settings_lines: usize = 8; // header(1) + divider(1) + 6 rows
|
||||
let samples_lines: usize = 6; // header(1) + divider(1) + content(3) + hint(1)
|
||||
let total_lines = devices_lines + 1 + settings_lines + 1 + samples_lines;
|
||||
|
||||
let [devices_area, _, settings_area, _, samples_area] = Layout::vertical([
|
||||
Constraint::Length(devices_height),
|
||||
Constraint::Length(1),
|
||||
Constraint::Length(8),
|
||||
Constraint::Length(1),
|
||||
Constraint::Min(6),
|
||||
])
|
||||
.areas(padded);
|
||||
let max_visible = padded.height as usize;
|
||||
|
||||
render_devices(frame, app, devices_area);
|
||||
render_settings(frame, app, settings_area);
|
||||
render_samples(frame, app, samples_area);
|
||||
// Calculate scroll offset based on focused section
|
||||
let (focus_start, focus_height) = match app.audio.section {
|
||||
EngineSection::Devices => (0, devices_lines),
|
||||
EngineSection::Settings => (devices_lines + 1, settings_lines),
|
||||
EngineSection::Samples => (devices_lines + 1 + settings_lines + 1, samples_lines),
|
||||
};
|
||||
|
||||
let scroll_offset = if total_lines <= max_visible {
|
||||
0
|
||||
} else {
|
||||
// Keep focused section in view (top-aligned when possible)
|
||||
let focus_end = focus_start + focus_height;
|
||||
if focus_end <= max_visible {
|
||||
0
|
||||
} else {
|
||||
focus_start.min(total_lines.saturating_sub(max_visible))
|
||||
}
|
||||
};
|
||||
|
||||
let viewport_top = padded.y as i32;
|
||||
let viewport_bottom = (padded.y + padded.height) as i32;
|
||||
|
||||
// Render each section at adjusted position
|
||||
let mut y = viewport_top - scroll_offset as i32;
|
||||
|
||||
// Devices section
|
||||
let devices_top = y;
|
||||
let devices_bottom = y + devices_lines as i32;
|
||||
if devices_bottom > viewport_top && devices_top < viewport_bottom {
|
||||
let clipped_y = devices_top.max(viewport_top) as u16;
|
||||
let clipped_height =
|
||||
(devices_bottom.min(viewport_bottom) - devices_top.max(viewport_top)) as u16;
|
||||
let devices_area = Rect {
|
||||
x: padded.x,
|
||||
y: clipped_y,
|
||||
width: padded.width,
|
||||
height: clipped_height,
|
||||
};
|
||||
render_devices(frame, app, devices_area);
|
||||
}
|
||||
y += devices_lines as i32 + 1; // +1 for blank line
|
||||
|
||||
// Settings section
|
||||
let settings_top = y;
|
||||
let settings_bottom = y + settings_lines as i32;
|
||||
if settings_bottom > viewport_top && settings_top < viewport_bottom {
|
||||
let clipped_y = settings_top.max(viewport_top) as u16;
|
||||
let clipped_height =
|
||||
(settings_bottom.min(viewport_bottom) - settings_top.max(viewport_top)) as u16;
|
||||
let settings_area = Rect {
|
||||
x: padded.x,
|
||||
y: clipped_y,
|
||||
width: padded.width,
|
||||
height: clipped_height,
|
||||
};
|
||||
render_settings(frame, app, settings_area);
|
||||
}
|
||||
y += settings_lines as i32 + 1;
|
||||
|
||||
// Samples section
|
||||
let samples_top = y;
|
||||
let samples_bottom = y + samples_lines as i32;
|
||||
if samples_bottom > viewport_top && samples_top < viewport_bottom {
|
||||
let clipped_y = samples_top.max(viewport_top) as u16;
|
||||
let clipped_height =
|
||||
(samples_bottom.min(viewport_bottom) - samples_top.max(viewport_top)) as u16;
|
||||
let samples_area = Rect {
|
||||
x: padded.x,
|
||||
y: clipped_y,
|
||||
width: padded.width,
|
||||
height: clipped_height,
|
||||
};
|
||||
render_samples(frame, app, samples_area);
|
||||
}
|
||||
|
||||
// Scroll indicators
|
||||
let indicator_style = Style::new().fg(SCROLL_INDICATOR_COLOR);
|
||||
let indicator_x = padded.x + padded.width.saturating_sub(1);
|
||||
|
||||
if scroll_offset > 0 {
|
||||
let up_indicator = Paragraph::new("▲").style(indicator_style);
|
||||
frame.render_widget(up_indicator, Rect::new(indicator_x, padded.y, 1, 1));
|
||||
}
|
||||
|
||||
if scroll_offset + max_visible < total_lines {
|
||||
let down_indicator = Paragraph::new("▼").style(indicator_style);
|
||||
frame.render_widget(
|
||||
down_indicator,
|
||||
Rect::new(indicator_x, padded.y + padded.height.saturating_sub(1), 1, 1),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn render_visualizers(frame: &mut Frame, app: &App, area: Rect) {
|
||||
@@ -241,6 +327,7 @@ fn render_settings(frame: &mut Frame, app: &App, area: Rect) {
|
||||
let buffer_focused = section_focused && app.audio.setting_kind == SettingKind::BufferSize;
|
||||
let polyphony_focused = section_focused && app.audio.setting_kind == SettingKind::Polyphony;
|
||||
let nudge_focused = section_focused && app.audio.setting_kind == SettingKind::Nudge;
|
||||
let lookahead_focused = section_focused && app.audio.setting_kind == SettingKind::Lookahead;
|
||||
|
||||
let nudge_ms = app.metrics.nudge_ms;
|
||||
let nudge_label = if nudge_ms == 0.0 {
|
||||
@@ -249,6 +336,12 @@ fn render_settings(frame: &mut Frame, app: &App, area: Rect) {
|
||||
format!("{nudge_ms:+.1} ms")
|
||||
};
|
||||
|
||||
let lookahead_label = if app.audio.config.lookahead_ms == 0 {
|
||||
"off".to_string()
|
||||
} else {
|
||||
format!("{} ms", app.audio.config.lookahead_ms)
|
||||
};
|
||||
|
||||
let rows = vec![
|
||||
Row::new(vec![
|
||||
Span::styled(
|
||||
@@ -305,6 +398,17 @@ fn render_settings(frame: &mut Frame, app: &App, area: Rect) {
|
||||
),
|
||||
render_selector(&nudge_label, nudge_focused, highlight, normal),
|
||||
]),
|
||||
Row::new(vec![
|
||||
Span::styled(
|
||||
if lookahead_focused {
|
||||
"> Lookahead"
|
||||
} else {
|
||||
" Lookahead"
|
||||
},
|
||||
label_style,
|
||||
),
|
||||
render_selector(&lookahead_label, lookahead_focused, highlight, normal),
|
||||
]),
|
||||
Row::new(vec![
|
||||
Span::styled(" Sample rate", label_style),
|
||||
Span::styled(
|
||||
|
||||
Reference in New Issue
Block a user