From 7746abc9eefce13572985d1960599545bd258ecd Mon Sep 17 00:00:00 2001 From: unspeaker Date: Sun, 18 May 2025 18:54:30 +0300 Subject: [PATCH] euphuckingwrecka --- config/config_arranger.edn | 18 ++--- config/keys_dialog.edn | 0 crates/app/src/api.rs | 130 ++++++++++++++++++------------------- crates/app/src/model.rs | 15 +++-- crates/app/src/view.rs | 15 +++-- 5 files changed, 92 insertions(+), 86 deletions(-) create mode 100644 config/keys_dialog.edn diff --git a/config/config_arranger.edn b/config/config_arranger.edn index 247b5c6c..9d89764a 100644 --- a/config/config_arranger.edn +++ b/config/config_arranger.edn @@ -4,6 +4,7 @@ (keys (layer-if :focus-editor "./keys_editor.edn") + (layer-if :focus-dialog "./keys_dialog.edn") (layer-if :focus-message "./keys_message.edn") (layer-if :focus-device-add "./keys_device_add.edn") (layer-if :focus-browser "./keys_browser.edn") @@ -21,11 +22,12 @@ (bsp/a :view-dialog (bsp/w :view-meters-output (bsp/e :view-meters-input - (bsp/n (fixed/y 2 :view-status-h2) - (bsp/n :view-tracks-inputs - (bsp/s :view-tracks-devices - (bsp/s :view-tracks-outputs - (bsp/s :view-tracks-names - (fill/xy (either :focus-editor - (bsp/e :view-scenes-names :view-editor) - :view-scenes))))))))))) + (bsp/n :view-history + (bsp/n (fixed/y 2 :view-status-h2) + (bsp/n :view-tracks-inputs + (bsp/s :view-tracks-devices + (bsp/s :view-tracks-outputs + (bsp/s :view-tracks-names + (fill/xy (either :focus-editor + (bsp/e :view-scenes-names :view-editor) + :view-scenes)))))))))))) diff --git a/config/keys_dialog.edn b/config/keys_dialog.edn new file mode 100644 index 00000000..e69de29b diff --git a/crates/app/src/api.rs b/crates/app/src/api.rs index 71b88e0a..4e381025 100644 --- a/crates/app/src/api.rs +++ b/crates/app/src/api.rs @@ -4,27 +4,69 @@ type MaybeClip = Option>>; macro_rules! ns { ($C:ty, $s:expr, $a:expr, $W:expr) => { <$C>::try_from_expr($s, $a).map($W) } } macro_rules! cmd { ($cmd:expr) => {{ $cmd; None }}; } macro_rules! cmd_todo { ($msg:literal) => {{ println!($msg); None }}; } -handle!(TuiIn: |self: App, input|Ok(if let Some(command) = self.config.keys.command(self, input) { - // FIXME failed commands not persisted in undo history - let undo = command.clone().execute(self)?; - self.history.push((command, undo)); - Some(true) -} else { - None -})); +handle!(TuiIn: |self: App, input|self.handle_tui_key_with_history(input)); +impl App { + fn handle_tui_key_with_history (&mut self, input: &TuiIn) -> Perhaps { + Ok(if let Some(command) = self.config.keys.command(self, input) { + // FIXME failed commands not persisted in undo history + let undo = command.clone().execute(self)?; + self.history.push((command, undo)); + Some(true) + } else { + None + }) + } +} #[tengri_proc::command(App)] impl AppCommand { - fn cancel_dialog (app: &mut App) -> Perhaps { - app.toggle_dialog(None); - Ok(None) - } fn toggle_editor (app: &mut App, value: bool) -> Perhaps { app.toggle_editor(Some(value)); Ok(None) } - //fn color (app: &mut App, theme: ItemTheme) -> Perhaps { - //Ok(app.set_color(Some(theme)).map(|theme|Self::Color{theme})) - //} + fn editor (app: &mut App, command: MidiEditCommand) -> Perhaps { + Ok(if let Some(editor) = app.editor_mut() { + let undo = command.clone().delegate(editor, |command|AppCommand::Editor{command})?; + // update linked sampler after editor action + app.project.sampler_mut().map(|sampler|match command { + // autoselect: automatically select sample in sampler + MidiEditCommand::SetNotePos { pos } => { sampler.set_note_pos(pos); }, + _ => {} + }); + undo + } else { + None + }) + } + fn dialog (app: &mut App, command: DialogCommand) -> Perhaps { + Ok(command.delegate(&mut app.dialog, |command|Self::Dialog{command})?) + } + fn project (app: &mut App, command: ArrangementCommand) -> Perhaps { + Ok(command.delegate(&mut app.project, |command|Self::Project{command})?) + } + fn clock (app: &mut App, command: ClockCommand) -> Perhaps { + Ok(command.execute(app.clock_mut())?.map(|command|Self::Clock{command})) + } + fn sampler (app: &mut App, command: SamplerCommand) -> Perhaps { + Ok(app.project.sampler_mut() + .map(|s|command.delegate(s, |command|Self::Sampler{command})) + .transpose()? + .flatten()) + } + fn pool (app: &mut App, command: PoolCommand) -> Perhaps { + let undo = command.clone().delegate(&mut app.pool, |command|AppCommand::Pool{command})?; + // update linked editor after pool action + match command { + // autoselect: automatically load selected clip in editor + PoolCommand::Select { .. } | + // autocolor: update color in all places simultaneously + PoolCommand::Clip { command: PoolClipCommand::SetColor { .. } } => { + let clip = app.pool.clip().clone(); + app.editor_mut().map(|editor|editor.set_clip(clip.as_ref())) + }, + _ => None + }; + Ok(undo) + } fn enqueue (app: &mut App, clip: Option>>) -> Perhaps { todo!() } @@ -34,10 +76,6 @@ impl AppCommand { fn zoom (app: &mut App, zoom: usize) -> Perhaps { todo!() } - //fn launch (app: &mut App) -> Perhaps { - //app.project.launch(); - //Ok(None) - //} fn select (app: &mut App, selection: Selection) -> Perhaps { *app.project.selection_mut() = selection; //todo! @@ -65,53 +103,13 @@ impl AppCommand { app.tracks_stop_all(); Ok(None) } - fn dialog (app: &mut App, command: DialogCommand) -> Perhaps { - Ok(command.delegate(&mut app.dialog, |command|Self::Dialog{command})?) - } - fn project (app: &mut App, command: ArrangementCommand) -> Perhaps { - Ok(command.delegate(&mut app.project, |command|Self::Project{command})?) - } - fn clock (app: &mut App, command: ClockCommand) -> Perhaps { - Ok(command.execute(app.clock_mut())?.map(|command|Self::Clock{command})) - } - fn editor (app: &mut App, command: MidiEditCommand) -> Perhaps { - Ok(if let Some(editor) = app.editor_mut() { - let undo = command.clone().delegate(editor, |command|AppCommand::Editor{command})?; - // update linked sampler after editor action - app.project.sampler_mut().map(|sampler|match command { - // autoselect: automatically select sample in sampler - MidiEditCommand::SetNotePos { pos } => { sampler.set_note_pos(pos); }, - _ => {} - }); - undo - } else { - None - }) - } - fn sampler (app: &mut App, command: SamplerCommand) -> Perhaps { - Ok(app.project.sampler_mut() - .map(|s|command.delegate(s, |command|Self::Sampler{command})) - .transpose()? - .flatten()) - } - fn pool (app: &mut App, command: PoolCommand) -> Perhaps { - let undo = command.clone().delegate( - &mut app.pool, - |command|AppCommand::Pool{command} - )?; - // update linked editor after pool action - match command { - // autoselect: automatically load selected clip in editor - PoolCommand::Select { .. } | - // autocolor: update color in all places simultaneously - PoolCommand::Clip { command: PoolClipCommand::SetColor { .. } } => { - let clip = app.pool.clip().clone(); - app.editor_mut().map(|editor|editor.set_clip(clip.as_ref())) - }, - _ => None - }; - Ok(undo) - } + //fn color (app: &mut App, theme: ItemTheme) -> Perhaps { + //Ok(app.set_color(Some(theme)).map(|theme|Self::Color{theme})) + //} + //fn launch (app: &mut App) -> Perhaps { + //app.project.launch(); + //Ok(None) + //} } impl<'state> Context<'state, ClockCommand> for App { fn get <'source> (&'state self, iter: &mut TokenIter<'source>) -> Option { diff --git a/crates/app/src/model.rs b/crates/app/src/model.rs index feffe3bf..9d833fab 100644 --- a/crates/app/src/model.rs +++ b/crates/app/src/model.rs @@ -179,6 +179,9 @@ impl App { fn focus_editor (&self) -> bool { self.project.editor.is_some() } + fn focus_dialog (&self) -> bool { + self.dialog.is_some() + } fn focus_message (&self) -> bool { matches!(self.dialog, Some(Dialog::Message(..))) } @@ -451,13 +454,11 @@ impl Configuration { let cond = cond.unwrap(); println!("ok"); map.add_layer_if( - Box::new(move |state|{ - let mut exp = exp.clone(); - let value = Context::get(state, &mut format!(":{cond}").as_str().into()).unwrap_or(false); - if value { - panic!("layer-if cond={cond:?} exp={exp:?} value={value:?}"); - } - value + Box::new(move |state: &App|{ + Context::get(state, + &mut format!("{cond}").as_str().into()) + .unwrap_or_else(||panic!( + "missing input layer conditional {cond} from {exp:?}")) }), keys ); diff --git a/crates/app/src/view.rs b/crates/app/src/view.rs index c3c94321..9381c07f 100644 --- a/crates/app/src/view.rs +++ b/crates/app/src/view.rs @@ -7,6 +7,11 @@ impl App { pub fn view_nil (&self) -> impl Content + use<'_> { "nil" } + pub fn view_history (&self) -> impl Content { + Fill::x(Align::w(self.history.last() + .map(|last|FieldH(self.color, format!("History ({})", self.history.len()), + Fill::x(Align::w(format!("{:?}", last.0))))))); + } pub fn view_status_h2 (&self) -> impl Content + use<'_> { self.update_clock(); let theme = self.color; @@ -24,25 +29,25 @@ impl App { ) ) ))); + add(&" "); { let cache = self.view_cache.read().unwrap(); - add(&Fixed::x(16, Align::w(Bsp::s( + add(&Fixed::x(13, Align::w(Bsp::s( FieldH(theme, "Beat", cache.beat.view.clone()), FieldH(theme, "Time", cache.time.view.clone()), )))); - add(&Fixed::x(16, Align::w(Bsp::s( + add(&Fixed::x(13, Align::w(Bsp::s( Fill::x(Align::w(FieldH(theme, "BPM", cache.bpm.view.clone()))), Fill::x(Align::w(FieldH(theme, "SR ", cache.sr.view.clone()))), )))); - add(&Fixed::x(16, Align::w(Bsp::s( + add(&Fixed::x(13, Align::w(Bsp::s( Fill::x(Align::w(FieldH(theme, "Buf", cache.buf.view.clone()))), Fill::x(Align::w(FieldH(theme, "Lat", cache.lat.view.clone()))), )))); - add(&FieldV(theme, "Selection", Fill::x(Align::w(self.selection().describe( + add(&Fixed::x(16, FieldV(theme, "Selection", Align::w(self.selection().describe( self.tracks(), self.scenes() ))))); - add(&FieldV(theme, "History", Fill::x(Align::w(format!("{}", self.history.len()))))); } })) }