wip: modularize dialog

This commit is contained in:
🪞👃🪞 2025-05-18 18:32:39 +03:00
parent baad8254a2
commit 3e9545fe26
17 changed files with 171 additions and 173 deletions

View file

@ -1,27 +1,19 @@
use crate::*;
use std::path::PathBuf;
type MaybeClip = Option<Arc<RwLock<MidiClip>>>;
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) {
let undo = command.execute(self)?;
if let Some(undo) = undo {
self.history.push(undo);
}
// 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 dialog (app: &mut App, dialog: Option<Dialog>) -> Perhaps<Self> {
app.toggle_dialog(dialog);
Ok(None)
}
#[tengri_proc::command(App)]
impl AppCommand {
fn cancel_dialog (app: &mut App) -> Perhaps<Self> {
app.toggle_dialog(None);
Ok(None)
@ -73,11 +65,8 @@ handle!(TuiIn: |self: App, input|Ok(if let Some(command) = self.config.keys.comm
app.tracks_stop_all();
Ok(None)
}
fn sampler (app: &mut App, command: SamplerCommand) -> Perhaps<Self> {
Ok(app.project.sampler_mut()
.map(|s|command.delegate(s, |command|Self::Sampler{command}))
.transpose()?
.flatten())
fn dialog (app: &mut App, command: DialogCommand) -> Perhaps<Self> {
Ok(command.delegate(&mut app.dialog, |command|Self::Dialog{command})?)
}
fn project (app: &mut App, command: ArrangementCommand) -> Perhaps<Self> {
Ok(command.delegate(&mut app.project, |command|Self::Project{command})?)
@ -85,9 +74,6 @@ handle!(TuiIn: |self: App, input|Ok(if let Some(command) = self.config.keys.comm
fn clock (app: &mut App, command: ClockCommand) -> Perhaps<Self> {
Ok(command.execute(app.clock_mut())?.map(|command|Self::Clock{command}))
}
fn message (app: &mut App, command: MessageCommand) -> Perhaps<Self> {
Ok(command.delegate(app, |command|Self::Message{command})?)
}
fn editor (app: &mut App, command: MidiEditCommand) -> Perhaps<Self> {
Ok(if let Some(editor) = app.editor_mut() {
let undo = command.clone().delegate(editor, |command|AppCommand::Editor{command})?;
@ -102,6 +88,12 @@ handle!(TuiIn: |self: App, input|Ok(if let Some(command) = self.config.keys.comm
None
})
}
fn sampler (app: &mut App, command: SamplerCommand) -> Perhaps<Self> {
Ok(app.project.sampler_mut()
.map(|s|command.delegate(s, |command|Self::Sampler{command}))
.transpose()?
.flatten())
}
fn pool (app: &mut App, command: PoolCommand) -> Perhaps<Self> {
let undo = command.clone().delegate(
&mut app.pool,
@ -121,40 +113,33 @@ handle!(TuiIn: |self: App, input|Ok(if let Some(command) = self.config.keys.comm
Ok(undo)
}
}
impl<'state> Context<'state, ClockCommand> for App {
fn get <'source> (&'state self, iter: &mut TokenIter<'source>) -> Option<ClockCommand> {
Context::get(&self.clock(), iter)
}
}
impl<'state> Context<'state, MidiEditCommand> for App {
fn get <'source> (&'state self, iter: &mut TokenIter<'source>) -> Option<MidiEditCommand> {
self.editor().map(|e|Context::get(e, iter)).flatten()
}
}
impl<'state> Context<'state, PoolCommand> for App {
fn get <'source> (&'state self, iter: &mut TokenIter<'source>) -> Option<PoolCommand> {
Context::get(&self.pool, iter)
}
}
impl<'state> Context<'state, SamplerCommand> for App {
fn get <'source> (&'state self, iter: &mut TokenIter<'source>) -> Option<SamplerCommand> {
self.project.sampler().map(|p|Context::get(p, iter)).flatten()
}
}
impl<'state> Context<'state, ArrangementCommand> for App {
fn get <'source> (&'state self, iter: &mut TokenIter<'source>) -> Option<ArrangementCommand> {
Context::get(&self.project, iter)
}
}
#[tengri_proc::command(App)] impl MessageCommand {
fn dismiss (app: &mut App) -> Perhaps<Self> {
app.dialog = None;
Ok(None)
impl<'state> Context<'state, DialogCommand> for App {
fn get <'source> (&'state self, iter: &mut TokenIter<'source>) -> Option<DialogCommand> {
Context::get(&self, iter)
}
}

View file

@ -18,7 +18,7 @@ pub struct App {
/// Contains the currently edited musical arrangement
pub project: Arrangement,
/// Undo history
pub history: Vec<AppCommand>,
pub history: Vec<(AppCommand, Option<AppCommand>)>,
// Dialog overlay
pub dialog: Option<Dialog>,
// Cache of formatted strings
@ -179,9 +179,6 @@ impl App {
fn focus_editor (&self) -> bool {
self.project.editor.is_some()
}
fn is_editing (&self) -> bool {
self.project.editor.is_some()
}
fn focus_message (&self) -> bool {
matches!(self.dialog, Some(Dialog::Message(..)))
}
@ -192,16 +189,20 @@ impl App {
self.browser().is_some()
}
fn focus_clip (&self) -> bool {
!self.is_editing() && self.selection().is_clip()
!self.focus_editor() && matches!(self.selection(),
Selection::TrackClip{..})
}
fn focus_track (&self) -> bool {
!self.is_editing() && self.selection().is_track()
!self.focus_editor() && matches!(self.selection(),
Selection::Track(..))
}
fn focus_scene (&self) -> bool {
!self.is_editing() && self.selection().is_scene()
!self.focus_editor() && matches!(self.selection(),
Selection::Scene(..))
}
fn focus_mix (&self) -> bool {
!self.is_editing() && self.selection().is_mix()
!self.focus_editor() && matches!(self.selection(),
Selection::Mix)
}
fn focus_pool_import (&self) -> bool {
matches!(self.pool.mode, Some(PoolMode::Import(..)))
@ -260,29 +261,32 @@ impl App {
fn scene_count (&self) -> usize {
self.scenes().len()
}
fn scene_selection (&self) -> Option<usize> {
fn scene_selected (&self) -> Option<usize> {
self.selection().scene()
}
fn track_count (&self) -> usize {
self.tracks().len()
}
fn track_selection (&self) -> Option<usize> {
fn track_selected (&self) -> Option<usize> {
self.selection().track()
}
fn select_scene (&self) -> Selection {
self.selection().select_scene(self.tracks().len())
}
fn select_scene_next (&self) -> Selection {
self.selection().scene_next(self.scenes().len())
self.selection().select_scene_next(self.scenes().len())
}
fn select_scene_prev (&self) -> Selection {
self.selection().scene_prev()
self.selection().select_scene_prev()
}
fn select_track_header (&self) -> Selection {
self.selection().track_header(self.tracks().len())
fn select_track (&self) -> Selection {
self.selection().select_track(self.tracks().len())
}
fn select_track_next (&self) -> Selection {
self.selection().track_next(self.tracks().len())
self.selection().select_track_next(self.tracks().len())
}
fn select_track_prev (&self) -> Selection {
self.selection().track_prev()
self.selection().select_track_prev()
}
fn clip_selected (&self) -> Option<Arc<RwLock<MidiClip>>> {
match self.selection() {

View file

@ -42,6 +42,7 @@ impl App {
self.tracks(),
self.scenes()
)))));
add(&FieldV(theme, "History", Fill::x(Align::w(format!("{}", self.history.len())))));
}
}))
}