add Exit trait to modals

This commit is contained in:
🪞👃🪞 2024-07-12 16:05:16 +03:00
parent 0cc8d88e5f
commit 33e5f47526
6 changed files with 67 additions and 33 deletions

View file

@ -47,7 +47,7 @@ impl AppPaths {
} }
} }
pub struct SetupModal(pub Option<Arc<XdgApp>>); pub struct SetupModal(pub Option<Arc<XdgApp>>, pub bool);
render!(SetupModal |self, buf, area| { render!(SetupModal |self, buf, area| {
for cell in buf.content.iter_mut() { for cell in buf.content.iter_mut() {
@ -83,9 +83,17 @@ handle!(SetupModal |self, e| {
.. ..
})) = e { })) = e {
AppPaths::new(&self.0.as_ref().unwrap())?.create()?; AppPaths::new(&self.0.as_ref().unwrap())?.create()?;
self.0 = None; self.exit();
Ok(true) Ok(true)
} else { } else {
Ok(false) Ok(false)
} }
}); });
impl Exit for SetupModal {
fn exited (&self) -> bool {
self.1
}
fn exit (&mut self) {
self.1 = true
}
}

View file

@ -6,7 +6,9 @@ handle!{
App |self, e| { App |self, e| {
if let Some(ref mut modal) = self.modal { if let Some(ref mut modal) = self.modal {
if modal.handle(e)? { if modal.handle(e)? {
if modal.exited() {
self.modal = None; self.modal = None;
}
return Ok(true) return Ok(true)
}; };
} }
@ -145,10 +147,12 @@ pub const KEYMAP: &'static [KeyBinding<App>] = keymap!(App {
fn focus_next (app: &mut App) -> Usually<bool> { fn focus_next (app: &mut App) -> Usually<bool> {
app.section.next(); app.section.next();
app.transport.focused = app.section == AppSection::Transport;
Ok(true) Ok(true)
} }
fn focus_prev (app: &mut App) -> Usually<bool> { fn focus_prev (app: &mut App) -> Usually<bool> {
app.section.prev(); app.section.prev();
app.transport.focused = app.section == AppSection::Transport;
Ok(true) Ok(true)
} }

View file

@ -41,6 +41,14 @@ pub trait Component: Render + Handle + Sync {
} }
} }
pub trait Exit: Component {
fn exited (&self) -> bool;
fn exit (&mut self);
fn boxed (self) -> Box<dyn Exit> where Self: Sized + 'static {
Box::new(self)
}
}
/// Anything that implements `Render` + `Handle` can be used as a UI component. /// Anything that implements `Render` + `Handle` can be used as a UI component.
impl<T: Render + Handle + Sync> Component for T {} impl<T: Render + Handle + Sync> Component for T {}

View file

@ -34,7 +34,7 @@ pub struct App {
/// Display buffer for sequencer /// Display buffer for sequencer
pub seq_buf: BufferedSequencerView, pub seq_buf: BufferedSequencerView,
/// Optional modal dialog /// Optional modal dialog
pub modal: Option<Box<dyn Component>>, pub modal: Option<Box<dyn Exit>>,
/// Currently focused section /// Currently focused section
pub section: AppSection, pub section: AppSection,
/// Whether the current focus section has input priority /// Whether the current focus section has input priority
@ -57,8 +57,6 @@ pub struct App {
xdg: Option<Arc<XdgApp>>, xdg: Option<Arc<XdgApp>>,
/// Main audio outputs. /// Main audio outputs.
audio_outs: Vec<Arc<Port<Unowned>>>, audio_outs: Vec<Arc<Port<Unowned>>>,
/// Tick enable?
metronome: bool,
/// Number of frames requested by process callback /// Number of frames requested by process callback
chunk_size: usize, chunk_size: usize,
@ -78,10 +76,8 @@ impl App {
chunk_size: 0, chunk_size: 0,
entered: true, entered: true,
jack: Some(jack), jack: Some(jack),
metronome: false,
midi_in: None, midi_in: None,
midi_ins: vec![], midi_ins: vec![],
modal: first_run.then(||crate::config::SetupModal(Some(xdg.clone())).boxed()),
note_cursor: 0, note_cursor: 0,
note_start: 2, note_start: 2,
scene_cursor: 1, scene_cursor: 1,
@ -92,6 +88,9 @@ impl App {
time_cursor: 0, time_cursor: 0,
track_cursor: 1, track_cursor: 1,
tracks: vec![], tracks: vec![],
modal: first_run.then(
||Exit::boxed(crate::config::SetupModal(Some(xdg.clone()), false))
),
xdg: Some(xdg), xdg: Some(xdg),
}) })
} }

View file

@ -1,6 +1,7 @@
use crate::core::*; use crate::core::*;
pub struct TransportToolbar { pub struct TransportToolbar {
pub metronome: bool,
pub mode: bool, pub mode: bool,
pub focused: bool, pub focused: bool,
pub entered: bool, pub entered: bool,
@ -22,6 +23,7 @@ impl TransportToolbar {
pub fn new (transport: Option<Transport>) -> Self { pub fn new (transport: Option<Transport>) -> Self {
Self { Self {
transport, transport,
metronome: false,
mode: false, mode: false,
focused: false, focused: false,
entered: false, entered: false,

View file

@ -3,18 +3,27 @@ use crate::{core::*, view::*};
pub struct HelpModal { pub struct HelpModal {
cursor: usize, cursor: usize,
search: Option<String>, search: Option<String>,
exited: bool,
} }
impl HelpModal { impl HelpModal {
pub fn new () -> Self { pub fn new () -> Self {
Self { cursor: 0, search: None } Self { cursor: 0, search: None, exited: false }
}
}
impl Exit for HelpModal {
fn exited (&self) -> bool {
self.exited
}
fn exit (&mut self) {
self.exited = true;
} }
} }
render!(HelpModal |self, buf, area|{ render!(HelpModal |self, buf, area|{
for cell in buf.content.iter_mut() { for cell in buf.content.iter_mut() {
cell.bg = ratatui::style::Color::Rgb(44,44,44); cell.bg = ratatui::style::Color::Rgb(30,30,30);
cell.fg = ratatui::style::Color::Rgb(88,88,88); cell.fg = ratatui::style::Color::Rgb(100,100,100);
cell.modifier = ratatui::style::Modifier::DIM; cell.modifier = ratatui::style::Modifier::DIM;
} }
let width = 64.min(area.width * 3 / 5); let width = 64.min(area.width * 3 / 5);
@ -40,25 +49,28 @@ render!(HelpModal |self, buf, area|{
for i in 0..height-3 { for i in 0..height-3 {
let y = y + i; let y = y + i;
if let Some(command) = crate::control::KEYMAP_FOCUS.get(i as usize) { if let Some(command) = crate::control::KEYMAP_FOCUS.get(i as usize) {
format!("{:?}", command.0).blit(buf, x, y, Some(Style::default().bold()))?; format!("{:?}", command.0).blit(buf, x, y, Some(Style::default().white().bold()))?;
command.2.blit(buf, x + 11, y, Some(Style::default().bold()))?; command.2.blit(buf, x + 11, y, Some(Style::default().white().bold()))?;
command.3.blit(buf, x + 26, y, None)?; command.3.blit(buf, x + 26, y, Some(Style::default().white().dim()))?;
} else if let Some(command) = crate::control::KEYMAP.get((i as usize) - crate::control::KEYMAP_FOCUS.len()) { } else if let Some(command) = crate::control::KEYMAP.get((i as usize) - crate::control::KEYMAP_FOCUS.len()) {
format!("{:?}", command.0).blit(buf, x, y, Some(Style::default().bold()))?; format!("{:?}", command.0).blit(buf, x, y, Some(Style::default().white().bold()))?;
command.2.blit(buf, x + 11, y, Some(Style::default().bold()))?; command.2.blit(buf, x + 11, y, Some(Style::default().white().bold()))?;
command.3.blit(buf, x + 26, y, None)?; command.3.blit(buf, x + 26, y, Some(Style::default().white().dim()))?;
} else { } else {
break break
} }
} }
let hi_area = Rect { x: area.x + 1, width: area.width - 2, y: area.y + 3 + self.cursor as u16, height: 1 }; let hi_area = Rect { x: area.x + 1, width: area.width - 2, y: area.y + 3 + self.cursor as u16, height: 1 };
fill_bg(buf, hi_area, Nord::bg_hi(true, true)); fill_bg(buf, hi_area, Nord::bg_hi(true, true));
fill_fg(buf, hi_area, Color::Reset); fill_fg(buf, hi_area, Color::White);
Lozenge(Style::default()).draw(buf, area) Lozenge(Style::default()).draw(buf, area)
}); });
handle!(HelpModal |self, e| { handle!(HelpModal |self, e| {
Ok(handle_keymap(self, e, KEYMAP_HELP)? || match e { if handle_keymap(self, e, KEYMAP_HELP)? {
return Ok(true)
}
Ok(match e {
AppEvent::Input(Event::Key(KeyEvent { AppEvent::Input(Event::Key(KeyEvent {
code: KeyCode::Char(c), code: KeyCode::Char(c),
modifiers: KeyModifiers::NONE, .. modifiers: KeyModifiers::NONE, ..
@ -67,22 +79,23 @@ handle!(HelpModal |self, e| {
self.search = Some(String::new()); self.search = Some(String::new());
} }
self.search.as_mut().unwrap().push(*c); self.search.as_mut().unwrap().push(*c);
false true
}, },
_ => false _ => true
}) })
}); });
pub const KEYMAP_HELP: &'static [KeyBinding<HelpModal>] = keymap!(HelpModal { pub const KEYMAP_HELP: &'static [KeyBinding<HelpModal>] = keymap!(HelpModal {
[Esc, NONE, "help_close", "close help dialog", |_: &mut HelpModal|{ [Esc, NONE, "help_close", "close help dialog", |modal: &mut HelpModal|{
modal.exit();
Ok(true) Ok(true)
}], }],
[Up, NONE, "help_prev", "select previous command", |modal: &mut HelpModal|{ [Up, NONE, "help_prev", "select previous command", |modal: &mut HelpModal|{
modal.cursor = modal.cursor.saturating_sub(1); modal.cursor = modal.cursor.saturating_sub(1);
Ok(false) Ok(true)
}], }],
[Down, NONE, "help_next", "select next command", |modal: &mut HelpModal|{ [Down, NONE, "help_next", "select next command", |modal: &mut HelpModal|{
modal.cursor = modal.cursor + 1; modal.cursor = modal.cursor + 1;
Ok(false) Ok(true)
}], }],
}); });