mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-06 19:56:42 +01:00
wip: focus refactor, e13
This commit is contained in:
parent
364769a2e0
commit
6127aa4b30
9 changed files with 110 additions and 65 deletions
|
|
@ -34,11 +34,8 @@ pub enum SequencerCommand {
|
|||
Editor(PhraseCommand),
|
||||
}
|
||||
|
||||
impl<T> Command<T> for SequencerCommand
|
||||
where
|
||||
T: ClockApi + PhrasesControl + PhraseEditorControl + FocusGrid<Item = SequencerFocus>
|
||||
{
|
||||
fn execute (self, state: &mut T) -> Perhaps<Self> {
|
||||
impl Command<SequencerTui> for SequencerCommand {
|
||||
fn execute (self, state: &mut SequencerTui) -> Perhaps<Self> {
|
||||
use SequencerCommand::*;
|
||||
Ok(match self {
|
||||
Focus(cmd) => cmd.execute(state)?.map(Focus),
|
||||
|
|
@ -258,7 +255,7 @@ pub enum PhraseCommand {
|
|||
TimeZoomSet(usize),
|
||||
}
|
||||
|
||||
impl<T: PhraseEditorControl> Command<T> for PhraseCommand {
|
||||
impl<T: PhraseEditorControl + HasEnter> Command<T> for PhraseCommand {
|
||||
fn execute (self, state: &mut T) -> Perhaps<Self> {
|
||||
use PhraseCommand::*;
|
||||
Ok(match self {
|
||||
|
|
|
|||
|
|
@ -1,24 +1,36 @@
|
|||
use crate::*;
|
||||
|
||||
pub trait TransportControl: ClockApi {
|
||||
fn transport_focused (&self) -> TransportFocus;
|
||||
fn transport_focused (&self) -> Option<TransportFocus>;
|
||||
}
|
||||
|
||||
impl TransportControl for TransportTui {
|
||||
fn transport_focused (&self) -> TransportFocus {
|
||||
self.state.focus.inner()
|
||||
fn transport_focused (&self) -> Option<TransportFocus> {
|
||||
if let AppFocus::Content(focus) = self.focus.inner() {
|
||||
Some(focus)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TransportControl for SequencerTui {
|
||||
fn transport_focused (&self) -> TransportFocus {
|
||||
self.transport.focus.inner()
|
||||
fn transport_focused (&self) -> Option<TransportFocus> {
|
||||
if let AppFocus::Content(SequencerFocus::Transport(focus)) = self.focus.inner() {
|
||||
Some(focus)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TransportControl for ArrangerTui {
|
||||
fn transport_focused (&self) -> TransportFocus {
|
||||
self.transport.focus.inner()
|
||||
fn transport_focused (&self) -> Option<TransportFocus> {
|
||||
if let AppFocus::Content(ArrangerFocus::Transport(focus)) = self.focus.inner() {
|
||||
Some(focus)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,7 +21,6 @@ impl Debug for TransportTui {
|
|||
fn fmt (&self, f: &mut Formatter<'_>) -> DebugResult {
|
||||
f.debug_struct("Measure")
|
||||
.field("jack", &self.jack)
|
||||
.field("state", &self.state)
|
||||
.field("size", &self.size)
|
||||
.field("cursor", &self.cursor)
|
||||
.finish()
|
||||
|
|
|
|||
|
|
@ -118,16 +118,53 @@ impl_focus!(TransportTui TransportFocus [
|
|||
]);
|
||||
|
||||
impl_focus!(SequencerTui SequencerFocus [
|
||||
&[Menu, Menu ],
|
||||
&[Content(Transport), Content(Transport) ],
|
||||
&[Content(Phrases), Content(PhraseEditor)],
|
||||
&[
|
||||
Menu,
|
||||
Menu,
|
||||
Menu,
|
||||
Menu,
|
||||
Menu,
|
||||
], &[
|
||||
Content(Transport(TransportFocus::Bpm)),
|
||||
Content(Transport(TransportFocus::Sync)),
|
||||
Content(Transport(TransportFocus::PlayPause)),
|
||||
Content(Transport(TransportFocus::Clock)),
|
||||
Content(Transport(TransportFocus::Quant))
|
||||
], &[
|
||||
Content(Phrases),
|
||||
Content(Phrases),
|
||||
Content(PhraseEditor),
|
||||
Content(PhraseEditor),
|
||||
Content(PhraseEditor),
|
||||
],
|
||||
]);
|
||||
|
||||
impl_focus!(ArrangerTui ArrangerFocus [
|
||||
&[Menu, Menu ],
|
||||
&[Content(Transport), Content(Transport) ],
|
||||
&[Content(Arranger), Content(Arranger) ],
|
||||
&[Content(Phrases), Content(PhraseEditor)],
|
||||
&[
|
||||
Menu,
|
||||
Menu,
|
||||
Menu,
|
||||
Menu,
|
||||
Menu,
|
||||
], &[
|
||||
Content(Transport(TransportFocus::Bpm)),
|
||||
Content(Transport(TransportFocus::Sync)),
|
||||
Content(Transport(TransportFocus::PlayPause)),
|
||||
Content(Transport(TransportFocus::Clock)),
|
||||
Content(Transport(TransportFocus::Quant))
|
||||
], &[
|
||||
Content(Arranger),
|
||||
Content(Arranger),
|
||||
Content(Arranger),
|
||||
Content(Arranger),
|
||||
Content(Arranger),
|
||||
], &[
|
||||
Content(Phrases),
|
||||
Content(Phrases),
|
||||
Content(PhraseEditor),
|
||||
Content(PhraseEditor),
|
||||
Content(PhraseEditor),
|
||||
],
|
||||
]);
|
||||
|
||||
/// Focused field of `PhraseLength`
|
||||
|
|
|
|||
|
|
@ -175,9 +175,9 @@ impl_jack_api!(TransportTui::jack);
|
|||
impl_jack_api!(SequencerTui::jack);
|
||||
impl_jack_api!(ArrangerTui::jack);
|
||||
|
||||
impl_clock_api!(TransportTui::state::clock);
|
||||
impl_clock_api!(SequencerTui::transport::clock);
|
||||
impl_clock_api!(ArrangerTui::transport::clock);
|
||||
impl_clock_api!(TransportTui::clock);
|
||||
impl_clock_api!(SequencerTui::clock);
|
||||
impl_clock_api!(ArrangerTui::clock);
|
||||
impl_clock_api!(PhrasePlayerModel::clock);
|
||||
impl_clock_api!(ArrangerTrack::player::clock);
|
||||
|
||||
|
|
@ -192,5 +192,9 @@ impl_midi_player!(PhrasePlayerModel);
|
|||
impl_phrases_control!(SequencerTui);
|
||||
impl_phrases_control!(ArrangerTui);
|
||||
|
||||
impl_phrase_editor_control!(SequencerTui [SequencerFocus::PhraseEditor]);
|
||||
impl_phrase_editor_control!(ArrangerTui [ArrangerFocus::PhraseEditor]);
|
||||
impl_phrase_editor_control!(SequencerTui [
|
||||
AppFocus::Content(SequencerFocus::PhraseEditor)
|
||||
]);
|
||||
impl_phrase_editor_control!(ArrangerTui [
|
||||
AppFocus::Content(ArrangerFocus::PhraseEditor)
|
||||
]);
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ impl<T: TransportControl> InputToCommand<Tui, T> for TransportCommand {
|
|||
use ClockCommand::{SetBpm, SetQuant, SetSync};
|
||||
use TransportFocus as Focused;
|
||||
use TransportCommand::{Focus, Clock};
|
||||
let focused = state.transport_focused();
|
||||
let focused = state.transport_focused().unwrap();
|
||||
Some(match input.event() {
|
||||
key!(Left) => Focus(FocusCommand::Prev),
|
||||
key!(Right) => Focus(FocusCommand::Next),
|
||||
|
|
@ -47,39 +47,35 @@ impl<T: TransportControl> InputToCommand<Tui, T> for TransportCommand {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T> InputToCommand<Tui, T> for SequencerCommand
|
||||
where
|
||||
T: SequencerControl + TransportControl + PhrasesControl + PhraseEditorControl
|
||||
+ HasFocus<Item = SequencerFocus>
|
||||
+ FocusGrid<Item = SequencerFocus>
|
||||
{
|
||||
fn input_to_command (state: &T, input: &TuiInput) -> Option<Self> {
|
||||
impl InputToCommand<Tui, SequencerTui> for SequencerCommand {
|
||||
fn input_to_command (state: &SequencerTui, input: &TuiInput) -> Option<Self> {
|
||||
use FocusCommand::*;
|
||||
use SequencerCommand::*;
|
||||
match input.event() {
|
||||
key!(KeyCode::Tab) => Some(Self::Focus(Next)),
|
||||
key!(Shift-KeyCode::Tab) => Some(Self::Focus(Prev)),
|
||||
key!(KeyCode::BackTab) => Some(Self::Focus(Prev)),
|
||||
key!(Shift-KeyCode::BackTab) => Some(Self::Focus(Prev)),
|
||||
key!(KeyCode::Up) => Some(Self::Focus(Up)),
|
||||
key!(KeyCode::Down) => Some(Self::Focus(Down)),
|
||||
key!(KeyCode::Left) => Some(Self::Focus(Left)),
|
||||
key!(KeyCode::Right) => Some(Self::Focus(Right)),
|
||||
_ => Some(match state.focused() {
|
||||
SequencerFocus::Transport => {
|
||||
Some(match input.event() {
|
||||
key!(KeyCode::Tab) => Self::Focus(Next),
|
||||
key!(Shift-KeyCode::Tab) => Self::Focus(Prev),
|
||||
key!(KeyCode::BackTab) => Self::Focus(Prev),
|
||||
key!(Shift-KeyCode::BackTab) => Self::Focus(Prev),
|
||||
key!(KeyCode::Up) => Self::Focus(Up),
|
||||
key!(KeyCode::Down) => Self::Focus(Down),
|
||||
key!(KeyCode::Left) => Self::Focus(Left),
|
||||
key!(KeyCode::Right) => Self::Focus(Right),
|
||||
_ => match state.focused() {
|
||||
AppFocus::Menu => todo!(),
|
||||
AppFocus::Content(SequencerFocus::Transport(_)) => {
|
||||
use TransportCommand::{Clock, Focus};
|
||||
match TransportCommand::input_to_command(state, input)? {
|
||||
Clock(command) => { todo!() },
|
||||
Focus(command) => { todo!() },
|
||||
}
|
||||
},
|
||||
SequencerFocus::Phrases =>
|
||||
AppFocus::Content(SequencerFocus::Phrases) =>
|
||||
Phrases(PhrasesCommand::input_to_command(state, input)?),
|
||||
SequencerFocus::PhraseEditor =>
|
||||
AppFocus::Content(SequencerFocus::PhraseEditor) =>
|
||||
Editor(PhraseCommand::input_to_command(state, input)?),
|
||||
_ => return None,
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -100,22 +96,22 @@ impl InputToCommand<Tui, ArrangerTui> for ArrangerCommand {
|
|||
key!(KeyCode::Esc) => Self::Focus(Exit),
|
||||
key!(KeyCode::Char(' ')) => Self::Clock(ClockCommand::Play(None)),
|
||||
_ => match state.focused() {
|
||||
ArrangerFocus::Menu => { todo!() },
|
||||
ArrangerFocus::Transport => {
|
||||
AppFocus::Menu => todo!(),
|
||||
AppFocus::Content(ArrangerFocus::Transport(_)) => {
|
||||
use TransportCommand::{Clock, Focus};
|
||||
match TransportCommand::input_to_command(state, input)? {
|
||||
Clock(command) => { todo!() },
|
||||
Focus(command) => { todo!() }
|
||||
}
|
||||
},
|
||||
ArrangerFocus::PhraseEditor => Editor(
|
||||
AppFocus::Content(ArrangerFocus::PhraseEditor) => Editor(
|
||||
PhraseCommand::input_to_command(state, input)?
|
||||
),
|
||||
ArrangerFocus::Phrases => match input.event() {
|
||||
AppFocus::Content(ArrangerFocus::Phrases) => match input.event() {
|
||||
key!(KeyCode::Char('e')) => EditPhrase(state.phrase_editing().clone()),
|
||||
_ => Phrases(PhrasesCommand::input_to_command(state, input)?)
|
||||
},
|
||||
ArrangerFocus::Arranger => {
|
||||
AppFocus::Content(ArrangerFocus::Arranger) => {
|
||||
use ArrangerSelection as Select;
|
||||
use ArrangerTrackCommand as Track;
|
||||
use ArrangerClipCommand as Clip;
|
||||
|
|
@ -348,7 +344,7 @@ impl<T: PhrasesControl> InputToCommand<Tui, T> for PhraseRenameCommand {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: PhraseEditorControl> InputToCommand<Tui, T> for PhraseCommand {
|
||||
impl<T: PhraseEditorControl + HasEnter> InputToCommand<Tui, T> for PhraseCommand {
|
||||
fn input_to_command (state: &T, from: &TuiInput) -> Option<Self> {
|
||||
use PhraseCommand::*;
|
||||
Some(match from.event() {
|
||||
|
|
|
|||
|
|
@ -223,7 +223,7 @@ impl ArrangerTracksApi<ArrangerTrack> for ArrangerTui {
|
|||
width: name.len() + 2,
|
||||
name: Arc::new(name.into()),
|
||||
color: color.unwrap_or_else(||ItemColor::random()),
|
||||
player: PhrasePlayerModel::from(&self.transport.clock),
|
||||
player: PhrasePlayerModel::from(&self.clock),
|
||||
};
|
||||
self.tracks_mut().push(track);
|
||||
let index = self.tracks().len() - 1;
|
||||
|
|
|
|||
|
|
@ -94,8 +94,8 @@ impl StatusBar for ArrangerStatus {
|
|||
}
|
||||
fn update (&mut self, (focused, selected, entered): &Self::State) {
|
||||
*self = match focused {
|
||||
ArrangerFocus::Menu => { todo!() },
|
||||
ArrangerFocus::Transport => ArrangerStatus::Transport,
|
||||
//ArrangerFocus::Menu => { todo!() },
|
||||
ArrangerFocus::Transport(_) => ArrangerStatus::Transport,
|
||||
ArrangerFocus::Arranger => match selected {
|
||||
ArrangerSelection::Mix => ArrangerStatus::ArrangerMix,
|
||||
ArrangerSelection::Track(_) => ArrangerStatus::ArrangerTrack,
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ macro_rules! impl_transport_view_state {
|
|||
($Struct:ident :: $field:ident) => {
|
||||
impl TransportViewState for $Struct {
|
||||
fn transport_selected (&self) -> TransportFocus {
|
||||
self.$field.focus.inner()
|
||||
self.focused().inner()
|
||||
}
|
||||
fn transport_focused (&self) -> bool {
|
||||
true
|
||||
|
|
@ -34,16 +34,16 @@ macro_rules! impl_transport_view_state {
|
|||
}
|
||||
}
|
||||
}
|
||||
impl_transport_view_state!(TransportTui::state);
|
||||
impl_transport_view_state!(SequencerTui::transport);
|
||||
impl_transport_view_state!(ArrangerTui::transport);
|
||||
impl_transport_view_state!(TransportTui::clock);
|
||||
impl_transport_view_state!(SequencerTui::clock);
|
||||
impl_transport_view_state!(ArrangerTui::clock);
|
||||
|
||||
pub trait ArrangerViewState {
|
||||
fn arranger_focused (&self) -> bool;
|
||||
}
|
||||
impl ArrangerViewState for ArrangerTui {
|
||||
fn arranger_focused (&self) -> bool {
|
||||
self.focused() == ArrangerFocus::Arranger
|
||||
self.focused() == AppFocus::Content(ArrangerFocus::Arranger)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue