wip: global enter

This commit is contained in:
🪞👃🪞 2024-11-09 01:17:41 +01:00
parent 2105d86428
commit 9b770c468f
6 changed files with 43 additions and 28 deletions

View file

@ -8,6 +8,8 @@ pub enum FocusCommand {
Down, Down,
Left, Left,
Right, Right,
Enter,
Exit
} }
pub trait FocusGrid<T: Copy + PartialEq> { pub trait FocusGrid<T: Copy + PartialEq> {

View file

@ -74,6 +74,8 @@ pub struct Arrangement<E: Engine> {
pub color: ItemColor, pub color: ItemColor,
/// Width and height of arrangement area at last render /// Width and height of arrangement area at last render
pub size: Measure<E>, pub size: Measure<E>,
/// Whether this is currently in edit mode
pub entered: bool,
} }
/// Represents a track in the arrangement /// Represents a track in the arrangement
pub struct ArrangementTrack { pub struct ArrangementTrack {
@ -308,6 +310,7 @@ impl<E: Engine> Arrangement<E> {
focused: false, focused: false,
color: Color::Rgb(28, 35, 25).into(), color: Color::Rgb(28, 35, 25).into(),
size: Measure::new(), size: Measure::new(),
entered: false,
} }
} }
fn is_stopped (&self) -> bool { fn is_stopped (&self) -> bool {

View file

@ -2,12 +2,7 @@ use crate::*;
#[derive(Clone, PartialEq)] #[derive(Clone, PartialEq)]
pub enum ArrangerCommand { pub enum ArrangerCommand {
FocusNext, Focus(FocusCommand),
FocusPrev,
FocusUp,
FocusDown,
FocusLeft,
FocusRight,
Transport(TransportCommand), Transport(TransportCommand),
Phrases(PhrasePoolCommand), Phrases(PhrasePoolCommand),
Editor(PhraseEditorCommand), Editor(PhraseEditorCommand),
@ -41,13 +36,18 @@ pub enum ArrangementCommand {
impl<E: Engine> Command<Arranger<E>> for ArrangerCommand { impl<E: Engine> Command<Arranger<E>> for ArrangerCommand {
fn execute (self, state: &mut Arranger<E>) -> Perhaps<Self> { fn execute (self, state: &mut Arranger<E>) -> Perhaps<Self> {
use ArrangerCommand::*; use ArrangerCommand::*;
use FocusCommand::*;
match self { match self {
FocusNext => { state.focus_next(); }, Focus(command) => match command {
FocusPrev => { state.focus_prev(); }, Next => { state.focus_next(); },
FocusUp => { state.focus_up(); }, Prev => { state.focus_prev(); },
FocusDown => { state.focus_down(); }, Up => { state.focus_up(); },
FocusLeft => { state.focus_left(); }, Down => { state.focus_down(); },
FocusRight => { state.focus_right(); }, Left => { state.focus_left(); },
Right => { state.focus_right(); },
Enter => { unimplemented!() },
Exit => { unimplemented!() },
},
Transport(cmd) => if let Some(ref transport) = state.transport { Transport(cmd) => if let Some(ref transport) = state.transport {
return cmd.execute(&mut*transport.write().unwrap()).map(|x|x.map(Transport)) return cmd.execute(&mut*transport.write().unwrap()).map(|x|x.map(Transport))
}, },

View file

@ -23,7 +23,11 @@ impl Content for Arranger<Tui> {
lay!( lay!(
widget(&self.arrangement).grow_y(1).border(border), widget(&self.arrangement).grow_y(1).border(border),
widget(&self.arrangement.size), widget(&self.arrangement.size),
widget(&"[ ] Arrangement").fg(title_color).push_x(1), widget(&format!("[{}] Arrangement", if self.arrangement.entered {
""
} else {
" "
})).fg(title_color).push_x(1),
), ),
Split::right( Split::right(
self.phrases_split, self.phrases_split,
@ -544,30 +548,34 @@ impl Handle<Tui> for Arrangement<Tui> {
} }
impl MatchInput<Tui, Arranger<Tui>> for ArrangerCommand { impl MatchInput<Tui, Arranger<Tui>> for ArrangerCommand {
fn match_input (state: &Arranger<Tui>, input: &TuiInput) -> Option<Self> { fn match_input (state: &Arranger<Tui>, input: &TuiInput) -> Option<Self> {
use FocusCommand::*;
use ArrangerCommand::*;
match input.event() { match input.event() {
key!(KeyCode::Tab) => Some(Self::FocusNext), key!(KeyCode::Tab) => Some(Focus(Next)),
key!(Shift-KeyCode::Tab) => Some(Self::FocusPrev), key!(Shift-KeyCode::Tab) => Some(Focus(Prev)),
key!(KeyCode::BackTab) => Some(Self::FocusPrev), key!(KeyCode::BackTab) => Some(Focus(Prev)),
key!(Shift-KeyCode::BackTab) => Some(Self::FocusPrev), key!(Shift-KeyCode::BackTab) => Some(Focus(Prev)),
key!(KeyCode::Up) => Some(Self::FocusUp), key!(KeyCode::Up) => Some(Focus(Up)),
key!(KeyCode::Down) => Some(Self::FocusDown), key!(KeyCode::Down) => Some(Focus(Down)),
key!(KeyCode::Left) => Some(Self::FocusLeft), key!(KeyCode::Left) => Some(Focus(Left)),
key!(KeyCode::Right) => Some(Self::FocusRight), key!(KeyCode::Right) => Some(Focus(Right)),
key!(KeyCode::Char(' ')) => Some(Self::Transport(TransportCommand::PlayToggle)), key!(KeyCode::Enter) => Some(Focus(Enter)),
key!(KeyCode::Esc) => Some(Focus(Exit)),
key!(KeyCode::Char(' ')) => Some(Transport(TransportCommand::PlayToggle)),
_ => match state.focused() { _ => match state.focused() {
ArrangerFocus::Transport => state.transport.as_ref() ArrangerFocus::Transport => state.transport.as_ref()
.map(|t|TransportCommand::match_input(&*t.read().unwrap(), input) .map(|t|TransportCommand::match_input(&*t.read().unwrap(), input)
.map(Self::Transport)) .map(Transport))
.flatten(), .flatten(),
ArrangerFocus::PhrasePool => ArrangerFocus::PhrasePool =>
PhrasePoolCommand::match_input(&*state.phrases.read().unwrap(), input) PhrasePoolCommand::match_input(&*state.phrases.read().unwrap(), input)
.map(Self::Phrases), .map(Phrases),
ArrangerFocus::PhraseEditor => ArrangerFocus::PhraseEditor =>
PhraseEditorCommand::match_input(&state.editor, input) PhraseEditorCommand::match_input(&state.editor, input)
.map(Self::Editor), .map(Editor),
ArrangerFocus::Arrangement => ArrangerFocus::Arrangement =>
ArrangementCommand::match_input(&state.arrangement, &input) ArrangementCommand::match_input(&state.arrangement, &input)
.map(Self::Arrangement) .map(Arrangement)
} }
} }
} }

View file

@ -83,6 +83,8 @@ impl<E: Engine> Command<Sequencer<E>> for SequencerCommand {
Down => { state.focus_down(); }, Down => { state.focus_down(); },
Left => { state.focus_left(); }, Left => { state.focus_left(); },
Right => { state.focus_right(); }, Right => { state.focus_right(); },
Enter => { unimplemented!() },
Exit => { unimplemented!() }
}, },
Transport(command) => if let Some(ref transport) = state.transport { Transport(command) => if let Some(ref transport) = state.transport {
return command.execute(&mut*transport.write().unwrap()).map(|x|x.map(Transport)) return command.execute(&mut*transport.write().unwrap()).map(|x|x.map(Transport))

View file

@ -79,7 +79,7 @@ impl Content for PhrasePool<Tui> {
let border = Lozenge(Style::default().bg(Color::Rgb(40, 50, 30)).fg(border_color)); let border = Lozenge(Style::default().bg(Color::Rgb(40, 50, 30)).fg(border_color));
let content = content.fill_xy().bg(Color::Rgb(28, 35, 25)).border(border); let content = content.fill_xy().bg(Color::Rgb(28, 35, 25)).border(border);
let title_color = if *focused {Color::Rgb(150, 160, 90)} else {Color::Rgb(120, 130, 100)}; let title_color = if *focused {Color::Rgb(150, 160, 90)} else {Color::Rgb(120, 130, 100)};
let title = format!("[ ] Phrases ({})", phrases.len()); let title = format!("[{}] Phrases ({})", phrases.len(), " ");
let title = TuiStyle::fg(title, title_color).push_x(1); let title = TuiStyle::fg(title, title_color).push_x(1);
Layers::new(move|add|{ add(&content)?; Ok(add(&title)?) }) Layers::new(move|add|{ add(&content)?; Ok(add(&title)?) })
} }
@ -267,7 +267,7 @@ impl Content for PhraseEditor<Tui> {
let piano_roll = row!(keys, note_area).fill_x(); let piano_roll = row!(keys, note_area).fill_x();
let content = piano_roll.bg(Color::Rgb(40, 50, 30)).border(border); let content = piano_roll.bg(Color::Rgb(40, 50, 30)).border(border);
let content = lay!(content, playhead); let content = lay!(content, playhead);
let mut upper_left = format!("[ ] Sequencer"); let mut upper_left = format!("[{}] Sequencer", if *entered {""} else {" "});
if let Some(phrase) = phrase { if let Some(phrase) = phrase {
upper_left = format!("{upper_left}: {}", phrase.read().unwrap().name); upper_left = format!("{upper_left}: {}", phrase.read().unwrap().name);
} }