Trying to clena the mess opened by plugins
Some checks failed
Deploy Website / deploy (push) Failing after 4m53s
Some checks failed
Deploy Website / deploy (push) Failing after 4m53s
This commit is contained in:
@@ -309,6 +309,12 @@ impl App {
|
||||
.editor
|
||||
.set_completion_enabled(self.ui.show_completion);
|
||||
}
|
||||
AppCommand::SetFont(f) => self.ui.font = f,
|
||||
AppCommand::SetZoomFactor(z) => self.ui.zoom_factor = z,
|
||||
AppCommand::SetWindowSize(w, h) => {
|
||||
self.ui.window_width = w;
|
||||
self.ui.window_height = h;
|
||||
}
|
||||
AppCommand::ToggleLiveKeysFill => self.live_keys.flip_fill(),
|
||||
|
||||
// Panel
|
||||
@@ -375,8 +381,8 @@ impl App {
|
||||
AppCommand::AudioRefreshDevices => self.audio.refresh_devices(),
|
||||
|
||||
// Options page
|
||||
AppCommand::OptionsNextFocus => self.options.next_focus(),
|
||||
AppCommand::OptionsPrevFocus => self.options.prev_focus(),
|
||||
AppCommand::OptionsNextFocus => self.options.next_focus(self.plugin_mode),
|
||||
AppCommand::OptionsPrevFocus => self.options.prev_focus(self.plugin_mode),
|
||||
AppCommand::OptionsSetFocus(focus) => self.options.focus = focus,
|
||||
AppCommand::ToggleRefreshRate => self.audio.toggle_refresh_rate(),
|
||||
AppCommand::ToggleScope => self.audio.config.show_scope = !self.audio.config.show_scope,
|
||||
|
||||
@@ -30,7 +30,8 @@ impl App {
|
||||
layout: self.audio.config.layout,
|
||||
hue_rotation: self.ui.hue_rotation,
|
||||
onboarding_dismissed: self.ui.onboarding_dismissed.clone(),
|
||||
..Default::default()
|
||||
font: self.ui.font.clone(),
|
||||
zoom_factor: self.ui.zoom_factor,
|
||||
},
|
||||
link: crate::settings::LinkSettings {
|
||||
enabled: link.is_enabled(),
|
||||
|
||||
@@ -199,6 +199,9 @@ pub enum AppCommand {
|
||||
SetHueRotation(f32),
|
||||
ToggleRuntimeHighlight,
|
||||
ToggleCompletion,
|
||||
SetFont(String),
|
||||
SetZoomFactor(f32),
|
||||
SetWindowSize(u32, u32),
|
||||
|
||||
// Live keys
|
||||
ToggleLiveKeysFill,
|
||||
|
||||
@@ -88,6 +88,8 @@ pub fn init(args: InitArgs) -> Init {
|
||||
app.ui.hue_rotation = settings.display.hue_rotation;
|
||||
app.audio.config.layout = settings.display.layout;
|
||||
app.ui.onboarding_dismissed = settings.display.onboarding_dismissed.clone();
|
||||
app.ui.font = settings.display.font.clone();
|
||||
app.ui.zoom_factor = settings.display.zoom_factor;
|
||||
|
||||
let palette = settings.display.color_scheme.to_palette();
|
||||
let rotated =
|
||||
|
||||
@@ -675,8 +675,9 @@ fn handle_options_click(ctx: &mut InputContext, col: u16, row: u16, area: Rect)
|
||||
}
|
||||
|
||||
let focus = ctx.app.options.focus;
|
||||
let focus_line = focus.line_index();
|
||||
let total_lines = 35;
|
||||
let plugin_mode = ctx.app.plugin_mode;
|
||||
let focus_line = focus.line_index(plugin_mode);
|
||||
let total_lines = if plugin_mode { 43 } else { 40 };
|
||||
let max_visible = padded.height as usize;
|
||||
|
||||
let scroll_offset = if total_lines <= max_visible {
|
||||
@@ -690,7 +691,7 @@ fn handle_options_click(ctx: &mut InputContext, col: u16, row: u16, area: Rect)
|
||||
let relative_y = (row - padded.y) as usize;
|
||||
let abs_line = scroll_offset + relative_y;
|
||||
|
||||
if let Some(new_focus) = OptionsFocus::at_line(abs_line) {
|
||||
if let Some(new_focus) = OptionsFocus::at_line(abs_line, plugin_mode) {
|
||||
ctx.dispatch(AppCommand::OptionsSetFocus(new_focus));
|
||||
|
||||
// Value area starts at prefix(2) + label(20) = offset 22 from padded.x
|
||||
|
||||
@@ -26,6 +26,56 @@ pub(crate) fn cycle_option_value(ctx: &mut InputContext, right: bool) {
|
||||
OptionsFocus::ShowSpectrum => ctx.dispatch(AppCommand::ToggleSpectrum),
|
||||
OptionsFocus::ShowCompletion => ctx.dispatch(AppCommand::ToggleCompletion),
|
||||
OptionsFocus::ShowPreview => ctx.dispatch(AppCommand::TogglePreview),
|
||||
OptionsFocus::Font => {
|
||||
const FONTS: &[&str] = &["6x13", "7x13", "8x13", "9x15", "9x18", "10x20"];
|
||||
let pos = FONTS.iter().position(|f| *f == ctx.app.ui.font).unwrap_or(2);
|
||||
let new_pos = if right {
|
||||
(pos + 1) % FONTS.len()
|
||||
} else {
|
||||
(pos + FONTS.len() - 1) % FONTS.len()
|
||||
};
|
||||
ctx.dispatch(AppCommand::SetFont(FONTS[new_pos].to_string()));
|
||||
}
|
||||
OptionsFocus::ZoomFactor => {
|
||||
const ZOOMS: &[f32] = &[0.5, 0.75, 1.0, 1.25, 1.5, 1.75, 2.0];
|
||||
let pos = ZOOMS
|
||||
.iter()
|
||||
.position(|z| (z - ctx.app.ui.zoom_factor).abs() < 0.01)
|
||||
.unwrap_or(4);
|
||||
let new_pos = if right {
|
||||
(pos + 1) % ZOOMS.len()
|
||||
} else {
|
||||
(pos + ZOOMS.len() - 1) % ZOOMS.len()
|
||||
};
|
||||
ctx.dispatch(AppCommand::SetZoomFactor(ZOOMS[new_pos]));
|
||||
}
|
||||
OptionsFocus::WindowSize => {
|
||||
const WINDOW_SIZES: &[(u32, u32)] = &[
|
||||
(900, 600), (1050, 700), (1200, 800), (1350, 900), (1500, 1000),
|
||||
];
|
||||
let pos = WINDOW_SIZES
|
||||
.iter()
|
||||
.position(|&(w, h)| w == ctx.app.ui.window_width && h == ctx.app.ui.window_height)
|
||||
.unwrap_or_else(|| {
|
||||
WINDOW_SIZES
|
||||
.iter()
|
||||
.enumerate()
|
||||
.min_by_key(|&(_, &(w, h))| {
|
||||
let dw = w as i64 - ctx.app.ui.window_width as i64;
|
||||
let dh = h as i64 - ctx.app.ui.window_height as i64;
|
||||
dw * dw + dh * dh
|
||||
})
|
||||
.map(|(i, _)| i)
|
||||
.unwrap_or(2)
|
||||
});
|
||||
let new_pos = if right {
|
||||
(pos + 1) % WINDOW_SIZES.len()
|
||||
} else {
|
||||
(pos + WINDOW_SIZES.len() - 1) % WINDOW_SIZES.len()
|
||||
};
|
||||
let (w, h) = WINDOW_SIZES[new_pos];
|
||||
ctx.dispatch(AppCommand::SetWindowSize(w, h));
|
||||
}
|
||||
OptionsFocus::LinkEnabled => ctx.link.set_enabled(!ctx.link.is_enabled()),
|
||||
OptionsFocus::StartStopSync => ctx
|
||||
.link
|
||||
|
||||
@@ -11,6 +11,9 @@ pub enum OptionsFocus {
|
||||
ShowSpectrum,
|
||||
ShowCompletion,
|
||||
ShowPreview,
|
||||
Font,
|
||||
ZoomFactor,
|
||||
WindowSize,
|
||||
LinkEnabled,
|
||||
StartStopSync,
|
||||
Quantum,
|
||||
@@ -35,6 +38,9 @@ impl CyclicEnum for OptionsFocus {
|
||||
Self::ShowSpectrum,
|
||||
Self::ShowCompletion,
|
||||
Self::ShowPreview,
|
||||
Self::Font,
|
||||
Self::ZoomFactor,
|
||||
Self::WindowSize,
|
||||
Self::LinkEnabled,
|
||||
Self::StartStopSync,
|
||||
Self::Quantum,
|
||||
@@ -50,6 +56,8 @@ impl CyclicEnum for OptionsFocus {
|
||||
];
|
||||
}
|
||||
|
||||
// Line indices when Font/ZoomFactor are shown (plugin mode).
|
||||
// In terminal mode, Font/ZoomFactor are absent; all lines after ShowPreview shift up by 2.
|
||||
const FOCUS_LINES: &[(OptionsFocus, usize)] = &[
|
||||
(OptionsFocus::ColorScheme, 2),
|
||||
(OptionsFocus::HueRotation, 3),
|
||||
@@ -59,34 +67,51 @@ const FOCUS_LINES: &[(OptionsFocus, usize)] = &[
|
||||
(OptionsFocus::ShowSpectrum, 7),
|
||||
(OptionsFocus::ShowCompletion, 8),
|
||||
(OptionsFocus::ShowPreview, 9),
|
||||
(OptionsFocus::LinkEnabled, 13),
|
||||
(OptionsFocus::StartStopSync, 14),
|
||||
(OptionsFocus::Quantum, 15),
|
||||
(OptionsFocus::MidiOutput0, 25),
|
||||
(OptionsFocus::MidiOutput1, 26),
|
||||
(OptionsFocus::MidiOutput2, 27),
|
||||
(OptionsFocus::MidiOutput3, 28),
|
||||
(OptionsFocus::MidiInput0, 32),
|
||||
(OptionsFocus::MidiInput1, 33),
|
||||
(OptionsFocus::MidiInput2, 34),
|
||||
(OptionsFocus::MidiInput3, 35),
|
||||
(OptionsFocus::ResetOnboarding, 39),
|
||||
(OptionsFocus::Font, 10),
|
||||
(OptionsFocus::ZoomFactor, 11),
|
||||
(OptionsFocus::WindowSize, 12),
|
||||
(OptionsFocus::LinkEnabled, 16),
|
||||
(OptionsFocus::StartStopSync, 17),
|
||||
(OptionsFocus::Quantum, 18),
|
||||
(OptionsFocus::MidiOutput0, 28),
|
||||
(OptionsFocus::MidiOutput1, 29),
|
||||
(OptionsFocus::MidiOutput2, 30),
|
||||
(OptionsFocus::MidiOutput3, 31),
|
||||
(OptionsFocus::MidiInput0, 35),
|
||||
(OptionsFocus::MidiInput1, 36),
|
||||
(OptionsFocus::MidiInput2, 37),
|
||||
(OptionsFocus::MidiInput3, 38),
|
||||
(OptionsFocus::ResetOnboarding, 42),
|
||||
];
|
||||
|
||||
const PLUGIN_ONLY: &[OptionsFocus] = &[OptionsFocus::Font, OptionsFocus::ZoomFactor, OptionsFocus::WindowSize];
|
||||
|
||||
impl OptionsFocus {
|
||||
pub fn line_index(self) -> usize {
|
||||
FOCUS_LINES
|
||||
fn is_plugin_only(self) -> bool {
|
||||
PLUGIN_ONLY.contains(&self)
|
||||
}
|
||||
|
||||
pub fn line_index(self, plugin_mode: bool) -> usize {
|
||||
let base = FOCUS_LINES
|
||||
.iter()
|
||||
.find(|(f, _)| *f == self)
|
||||
.map(|(_, l)| *l)
|
||||
.unwrap_or(0)
|
||||
.unwrap_or(0);
|
||||
if plugin_mode || base <= 9 {
|
||||
base
|
||||
} else {
|
||||
base - 3
|
||||
}
|
||||
}
|
||||
|
||||
pub fn at_line(line: usize) -> Option<OptionsFocus> {
|
||||
FOCUS_LINES
|
||||
.iter()
|
||||
.find(|(_, l)| *l == line)
|
||||
.map(|(f, _)| *f)
|
||||
pub fn at_line(line: usize, plugin_mode: bool) -> Option<OptionsFocus> {
|
||||
FOCUS_LINES.iter().find_map(|(f, l)| {
|
||||
if f.is_plugin_only() && !plugin_mode {
|
||||
return None;
|
||||
}
|
||||
let effective = if plugin_mode || *l <= 9 { *l } else { *l - 3 };
|
||||
if effective == line { Some(*f) } else { None }
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,11 +121,25 @@ pub struct OptionsState {
|
||||
}
|
||||
|
||||
impl OptionsState {
|
||||
pub fn next_focus(&mut self) {
|
||||
self.focus = self.focus.next();
|
||||
pub fn next_focus(&mut self, plugin_mode: bool) {
|
||||
let mut f = self.focus;
|
||||
loop {
|
||||
f = f.next();
|
||||
if !f.is_plugin_only() || plugin_mode {
|
||||
break;
|
||||
}
|
||||
}
|
||||
self.focus = f;
|
||||
}
|
||||
|
||||
pub fn prev_focus(&mut self) {
|
||||
self.focus = self.focus.prev();
|
||||
pub fn prev_focus(&mut self, plugin_mode: bool) {
|
||||
let mut f = self.focus;
|
||||
loop {
|
||||
f = f.prev();
|
||||
if !f.is_plugin_only() || plugin_mode {
|
||||
break;
|
||||
}
|
||||
}
|
||||
self.focus = f;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,6 +74,10 @@ pub struct UiState {
|
||||
pub prev_page: Page,
|
||||
pub prev_show_title: bool,
|
||||
pub onboarding_dismissed: Vec<String>,
|
||||
pub font: String,
|
||||
pub zoom_factor: f32,
|
||||
pub window_width: u32,
|
||||
pub window_height: u32,
|
||||
}
|
||||
|
||||
impl Default for UiState {
|
||||
@@ -117,6 +121,10 @@ impl Default for UiState {
|
||||
prev_page: Page::default(),
|
||||
prev_show_title: true,
|
||||
onboarding_dismissed: Vec::new(),
|
||||
font: "8x13".to_string(),
|
||||
zoom_factor: 1.5,
|
||||
window_width: 1200,
|
||||
window_height: 800,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,7 +113,7 @@ pub fn render(frame: &mut Frame, app: &App, link: &LinkState, area: Rect) {
|
||||
let onboarding_str = format!("{}/6 dismissed", app.ui.onboarding_dismissed.len());
|
||||
let hue_str = format!("{}°", app.ui.hue_rotation as i32);
|
||||
|
||||
let lines: Vec<Line> = vec![
|
||||
let mut lines: Vec<Line> = vec![
|
||||
render_section_header("DISPLAY", &theme),
|
||||
render_divider(content_width, &theme),
|
||||
render_option_line(
|
||||
@@ -168,7 +168,31 @@ pub fn render(frame: &mut Frame, app: &App, link: &LinkState, area: Rect) {
|
||||
focus == OptionsFocus::ShowPreview,
|
||||
&theme,
|
||||
),
|
||||
Line::from(""),
|
||||
];
|
||||
let zoom_str = format!("{:.0}%", app.ui.zoom_factor * 100.0);
|
||||
let window_str = format!("{}x{}", app.ui.window_width, app.ui.window_height);
|
||||
if app.plugin_mode {
|
||||
lines.push(render_option_line(
|
||||
"Font",
|
||||
&app.ui.font,
|
||||
focus == OptionsFocus::Font,
|
||||
&theme,
|
||||
));
|
||||
lines.push(render_option_line(
|
||||
"Zoom",
|
||||
&zoom_str,
|
||||
focus == OptionsFocus::ZoomFactor,
|
||||
&theme,
|
||||
));
|
||||
lines.push(render_option_line(
|
||||
"Window",
|
||||
&window_str,
|
||||
focus == OptionsFocus::WindowSize,
|
||||
&theme,
|
||||
));
|
||||
}
|
||||
lines.push(Line::from(""));
|
||||
lines.extend([
|
||||
link_header,
|
||||
render_divider(content_width, &theme),
|
||||
render_option_line(
|
||||
@@ -217,12 +241,12 @@ pub fn render(frame: &mut Frame, app: &App, link: &LinkState, area: Rect) {
|
||||
focus == OptionsFocus::ResetOnboarding,
|
||||
&theme,
|
||||
),
|
||||
];
|
||||
]);
|
||||
|
||||
let total_lines = lines.len();
|
||||
let max_visible = padded.height as usize;
|
||||
|
||||
let focus_line = focus.line_index();
|
||||
let focus_line = focus.line_index(app.plugin_mode);
|
||||
|
||||
let scroll_offset = if total_lines <= max_visible {
|
||||
0
|
||||
|
||||
Reference in New Issue
Block a user