mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-08 04:36:45 +01:00
wip: focus refactor, e40
This commit is contained in:
parent
94a16b9dbc
commit
364769a2e0
10 changed files with 198 additions and 279 deletions
|
|
@ -3,32 +3,32 @@ use crate::*;
|
|||
/// Stores and displays time-related info.
|
||||
pub struct TransportTui {
|
||||
pub jack: Arc<RwLock<JackClient>>,
|
||||
pub state: TransportModel,
|
||||
pub clock: ClockModel,
|
||||
pub size: Measure<Tui>,
|
||||
pub cursor: (usize, usize),
|
||||
pub focus: FocusState<AppFocus<TransportFocus>>,
|
||||
}
|
||||
|
||||
/// Root view for standalone `tek_sequencer`.
|
||||
pub struct SequencerTui {
|
||||
pub jack: Arc<RwLock<JackClient>>,
|
||||
pub transport: TransportModel,
|
||||
pub phrases: PhrasesModel,
|
||||
pub player: PhrasePlayerModel,
|
||||
pub editor: PhraseEditorModel,
|
||||
pub size: Measure<Tui>,
|
||||
pub cursor: (usize, usize),
|
||||
pub split: u16,
|
||||
pub entered: bool,
|
||||
/// MIDI output buffer
|
||||
pub note_buf: Vec<u8>,
|
||||
/// MIDI output buffer
|
||||
pub midi_buf: Vec<Vec<Vec<u8>>>,
|
||||
pub jack: Arc<RwLock<JackClient>>,
|
||||
pub clock: ClockModel,
|
||||
pub phrases: PhrasesModel,
|
||||
pub player: PhrasePlayerModel,
|
||||
pub editor: PhraseEditorModel,
|
||||
pub size: Measure<Tui>,
|
||||
pub cursor: (usize, usize),
|
||||
pub split: u16,
|
||||
pub entered: bool,
|
||||
pub note_buf: Vec<u8>,
|
||||
pub midi_buf: Vec<Vec<Vec<u8>>>,
|
||||
pub focus: FocusState<AppFocus<SequencerFocus>>,
|
||||
}
|
||||
|
||||
/// Root view for standalone `tek_arranger`
|
||||
pub struct ArrangerTui {
|
||||
pub jack: Arc<RwLock<JackClient>>,
|
||||
pub transport: TransportModel,
|
||||
pub clock: ClockModel,
|
||||
pub phrases: PhrasesModel,
|
||||
pub tracks: Vec<ArrangerTrack>,
|
||||
pub scenes: Vec<ArrangerScene>,
|
||||
|
|
@ -43,10 +43,8 @@ pub struct ArrangerTui {
|
|||
pub menu_bar: Option<MenuBar<Tui, Self, ArrangerCommand>>,
|
||||
pub status_bar: Option<ArrangerStatus>,
|
||||
pub history: Vec<ArrangerCommand>,
|
||||
/// MIDI output buffer
|
||||
pub note_buf: Vec<u8>,
|
||||
/// MIDI output buffer
|
||||
pub midi_buf: Vec<Vec<Vec<u8>>>,
|
||||
/// MIDI editor state
|
||||
pub editor: PhraseEditorModel,
|
||||
pub note_buf: Vec<u8>,
|
||||
pub midi_buf: Vec<Vec<Vec<u8>>>,
|
||||
pub editor: PhraseEditorModel,
|
||||
pub focus: FocusState<AppFocus<ArrangerFocus>>,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,20 +18,20 @@ impl<'a, T: TransportViewState> Content for TransportView<'a, T> {
|
|||
|
||||
row!(
|
||||
state.transport_selected().wrap(focused, TransportFocus::Bpm, &Outset::X(1u16, {
|
||||
let bpm = state.bpm_value();
|
||||
let bpm = state.transport_bpm_value();
|
||||
row! { "BPM ", format!("{}.{:03}", bpm as usize, (bpm * 1000.0) % 1000.0) }
|
||||
})),
|
||||
//let quant = state.focus().wrap(state.focused(), TransportFocus::Quant, &Outset::X(1u16, row! {
|
||||
//"QUANT ", ppq_to_name(state.0.quant as usize)
|
||||
//})),
|
||||
state.transport_selected().wrap(focused, TransportFocus::Sync, &Outset::X(1u16, row! {
|
||||
"SYNC ", pulses_to_name(state.sync_value() as usize)
|
||||
"SYNC ", pulses_to_name(state.transport_sync_value() as usize)
|
||||
}))
|
||||
).align_w().fill_x(),
|
||||
|
||||
state.transport_selected().wrap(focused, TransportFocus::Clock, &{
|
||||
let time1 = state.format_beat();
|
||||
let time2 = state.format_msu();
|
||||
let time1 = state.transport_format_beat();
|
||||
let time2 = state.transport_format_msu();
|
||||
row!("B" ,time1.as_str(), " T", time2.as_str()).outset_x(1)
|
||||
}).align_e().fill_x(),
|
||||
|
||||
|
|
|
|||
|
|
@ -17,15 +17,6 @@ impl Debug for ClockModel {
|
|||
}
|
||||
}
|
||||
|
||||
impl Debug for TransportModel {
|
||||
fn fmt (&self, f: &mut Formatter<'_>) -> DebugResult {
|
||||
f.debug_struct("TransportModel")
|
||||
.field("clock", &self.clock)
|
||||
.field("focus", &self.focus)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for TransportTui {
|
||||
fn fmt (&self, f: &mut Formatter<'_>) -> DebugResult {
|
||||
f.debug_struct("Measure")
|
||||
|
|
|
|||
|
|
@ -1,9 +1,16 @@
|
|||
use crate::*;
|
||||
|
||||
/// Which item of the transport toolbar is focused
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
pub enum TransportFocus {
|
||||
pub enum AppFocus<T: Copy + Debug + PartialEq> {
|
||||
/// The menu bar is focused
|
||||
Menu,
|
||||
/// The app content is focused
|
||||
Content(T)
|
||||
}
|
||||
|
||||
/// Which item of the transport toolbar is focused
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
pub enum TransportFocus {
|
||||
Bpm,
|
||||
Sync,
|
||||
PlayPause,
|
||||
|
|
@ -13,10 +20,8 @@ pub enum TransportFocus {
|
|||
/// Sections in the sequencer app that may be focused
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||
pub enum SequencerFocus {
|
||||
/// The menu bar is focused
|
||||
Menu,
|
||||
/// The transport (toolbar) is focused
|
||||
Transport,
|
||||
Transport(TransportFocus),
|
||||
/// The phrase list (pool) is focused
|
||||
Phrases,
|
||||
/// The phrase editor (sequencer) is focused
|
||||
|
|
@ -25,10 +30,8 @@ pub enum SequencerFocus {
|
|||
/// Sections in the arranger app that may be focused
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||
pub enum ArrangerFocus {
|
||||
/// The menu bar is focused
|
||||
Menu,
|
||||
/// The transport (toolbar) is focused
|
||||
Transport,
|
||||
Transport(TransportFocus),
|
||||
/// The arrangement (grid) is focused
|
||||
Arranger,
|
||||
/// The phrase list (pool) is focused
|
||||
|
|
@ -45,7 +48,6 @@ impl TransportFocus {
|
|||
Self::Quant => Self::Sync,
|
||||
Self::Sync => Self::Clock,
|
||||
Self::Clock => Self::PlayPause,
|
||||
Self::Menu => { todo!() },
|
||||
}
|
||||
}
|
||||
pub fn prev (&mut self) {
|
||||
|
|
@ -55,7 +57,6 @@ impl TransportFocus {
|
|||
Self::Quant => Self::Bpm,
|
||||
Self::Sync => Self::Quant,
|
||||
Self::Clock => Self::Sync,
|
||||
Self::Menu => { todo!() },
|
||||
}
|
||||
}
|
||||
pub fn wrap <'a, W: Widget<Engine = Tui>> (
|
||||
|
|
@ -68,135 +69,67 @@ impl TransportFocus {
|
|||
}
|
||||
}
|
||||
|
||||
impl FocusGrid for TransportTui {
|
||||
type Item = TransportFocus;
|
||||
fn focus_cursor (&self) -> (usize, usize) {
|
||||
self.cursor
|
||||
}
|
||||
fn focus_cursor_mut (&mut self) -> &mut (usize, usize) {
|
||||
&mut self.cursor
|
||||
}
|
||||
fn focus_layout (&self) -> &[&[Self::Item]] {
|
||||
use TransportFocus::*;
|
||||
&[
|
||||
&[Menu],
|
||||
&[Bpm, Sync, PlayPause, Clock, Quant],
|
||||
]
|
||||
}
|
||||
fn focus_update (&mut self) {
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
|
||||
//impl HasFocus for SequencerTui {
|
||||
//type Item = SequencerFocus;
|
||||
//}
|
||||
|
||||
//impl FocusEnter for SequencerTui {
|
||||
//type Item = SequencerFocus;
|
||||
//fn focus_enter (&mut self) {
|
||||
//let focused = self.focused();
|
||||
//if !self.entered {
|
||||
//self.entered = true;
|
||||
//// TODO
|
||||
//}
|
||||
//}
|
||||
//fn focus_exit (&mut self) {
|
||||
//if self.entered {
|
||||
//self.entered = false;
|
||||
//// TODO
|
||||
//}
|
||||
//}
|
||||
//fn focus_entered (&self) -> Option<Self::Item> {
|
||||
//if self.entered {
|
||||
//Some(self.focused())
|
||||
//} else {
|
||||
//None
|
||||
//}
|
||||
//}
|
||||
//}
|
||||
|
||||
impl FocusGrid for SequencerTui {
|
||||
type Item = SequencerFocus;
|
||||
fn focus_cursor (&self) -> (usize, usize) {
|
||||
self.cursor
|
||||
}
|
||||
fn focus_cursor_mut (&mut self) -> &mut (usize, usize) {
|
||||
&mut self.cursor
|
||||
}
|
||||
fn focus_layout (&self) -> &[&[Self::Item]] {
|
||||
use SequencerFocus::*;
|
||||
&[
|
||||
&[Menu, Menu ],
|
||||
&[Transport, Transport ],
|
||||
&[Phrases, PhraseEditor],
|
||||
]
|
||||
}
|
||||
fn focus_update (&mut self) {
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
|
||||
//impl FocusEnter for ArrangerTui {
|
||||
//type Item = ArrangerFocus;
|
||||
//fn focus_enter (&mut self) {
|
||||
//self.entered = true;
|
||||
////use ArrangerFocus::*;
|
||||
////let focused = self.focused();
|
||||
////if !self.entered {
|
||||
////self.entered = focused == Arranger;
|
||||
////self.editor.entered = focused == PhraseEditor;
|
||||
////self.phrases.entered = focused == Phrases;
|
||||
////}
|
||||
//}
|
||||
//fn focus_exit (&mut self) {
|
||||
//self.entered = false;
|
||||
////if self.entered {
|
||||
////self.entered = false;
|
||||
////self.editor.entered = false;
|
||||
////self.phrases.entered = false;
|
||||
////}
|
||||
//}
|
||||
//fn focus_entered (&self) -> Option<Self::Item> {
|
||||
//if self.entered {
|
||||
//Some(self.focused())
|
||||
//} else {
|
||||
//None
|
||||
//}
|
||||
//}
|
||||
//}
|
||||
|
||||
/// Focus layout of arranger app
|
||||
impl FocusGrid for ArrangerTui {
|
||||
type Item = ArrangerFocus;
|
||||
fn focus_cursor (&self) -> (usize, usize) {
|
||||
self.cursor
|
||||
}
|
||||
fn focus_cursor_mut (&mut self) -> &mut (usize, usize) {
|
||||
&mut self.cursor
|
||||
}
|
||||
fn focus_layout (&self) -> &[&[Self::Item]] {
|
||||
use ArrangerFocus::*;
|
||||
&[
|
||||
&[Menu, Menu ],
|
||||
&[Transport, Transport ],
|
||||
&[Arranger, Arranger ],
|
||||
&[Phrases, PhraseEditor],
|
||||
]
|
||||
}
|
||||
fn focus_update (&mut self) {
|
||||
use ArrangerFocus::*;
|
||||
let focused = self.focused();
|
||||
if let Some(mut status_bar) = self.status_bar {
|
||||
status_bar.update(&(
|
||||
self.focused(),
|
||||
self.selected,
|
||||
focused == PhraseEditor && self.entered
|
||||
))
|
||||
macro_rules! impl_focus {
|
||||
($Struct:ident $Focus:ident $Grid:expr) => {
|
||||
impl HasFocus for $Struct {
|
||||
type Item = AppFocus<$Focus>;
|
||||
/// Get the currently focused item.
|
||||
fn focused (&self) -> Self::Item {
|
||||
self.focus.inner()
|
||||
}
|
||||
/// Get the currently focused item.
|
||||
fn set_focused (&mut self, to: Self::Item) {
|
||||
self.focus.set_inner(to)
|
||||
}
|
||||
}
|
||||
impl HasEnter for $Struct {
|
||||
/// Get the currently focused item.
|
||||
fn entered (&self) -> bool {
|
||||
self.focus.is_entered()
|
||||
}
|
||||
/// Get the currently focused item.
|
||||
fn set_entered (&mut self, entered: bool) {
|
||||
if entered {
|
||||
self.focus.to_entered()
|
||||
} else {
|
||||
self.focus.to_focused()
|
||||
}
|
||||
}
|
||||
}
|
||||
impl FocusGrid for $Struct {
|
||||
fn focus_cursor (&self) -> (usize, usize) {
|
||||
self.cursor
|
||||
}
|
||||
fn focus_cursor_mut (&mut self) -> &mut (usize, usize) {
|
||||
&mut self.cursor
|
||||
}
|
||||
fn focus_layout (&self) -> &[&[AppFocus<$Focus>]] {
|
||||
use AppFocus::*;
|
||||
use $Focus::*;
|
||||
&$Grid
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl_focus!(TransportTui TransportFocus [
|
||||
&[Menu],
|
||||
&[Content(Bpm), Content(Sync), Content(PlayPause), Content(Clock), Content(Quant)],
|
||||
]);
|
||||
|
||||
impl_focus!(SequencerTui SequencerFocus [
|
||||
&[Menu, Menu ],
|
||||
&[Content(Transport), Content(Transport) ],
|
||||
&[Content(Phrases), Content(PhraseEditor)],
|
||||
]);
|
||||
|
||||
impl_focus!(ArrangerTui ArrangerFocus [
|
||||
&[Menu, Menu ],
|
||||
&[Content(Transport), Content(Transport) ],
|
||||
&[Content(Arranger), Content(Arranger) ],
|
||||
&[Content(Phrases), Content(PhraseEditor)],
|
||||
]);
|
||||
|
||||
/// Focused field of `PhraseLength`
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub enum PhraseLengthFocus {
|
||||
|
|
|
|||
|
|
@ -72,45 +72,45 @@ macro_rules! impl_midi_player {
|
|||
}
|
||||
impl MidiInputApi for $Struct {
|
||||
fn midi_ins (&self) -> &Vec<Port<jack::MidiIn>> {
|
||||
todo!("midi_ins")
|
||||
&self$(.$field)*.midi_ins
|
||||
}
|
||||
fn midi_ins_mut (&self) -> &mut Vec<Port<jack::MidiIn>> {
|
||||
todo!("midi_ins_mut")
|
||||
fn midi_ins_mut (&mut self) -> &mut Vec<Port<jack::MidiIn>> {
|
||||
&mut self$(.$field)*.midi_ins
|
||||
}
|
||||
fn recording (&self) -> bool {
|
||||
todo!("recording")
|
||||
self$(.$field)*.recording
|
||||
}
|
||||
fn recording_mut (&mut self) -> &mut bool {
|
||||
todo!("recording_mut")
|
||||
&mut self$(.$field)*.recording
|
||||
}
|
||||
fn monitoring (&self) -> bool {
|
||||
todo!("monitoring")
|
||||
self$(.$field)*.monitoring
|
||||
}
|
||||
fn monitoring_mut (&mut self) -> &mut bool {
|
||||
todo!("monitoring_mut")
|
||||
&mut self$(.$field)*.monitoring
|
||||
}
|
||||
fn overdub (&self) -> bool {
|
||||
todo!("overdub")
|
||||
self$(.$field)*.overdub
|
||||
}
|
||||
fn overdub_mut (&mut self) -> &mut bool {
|
||||
todo!("overdub_mut")
|
||||
&mut self$(.$field)*.overdub
|
||||
}
|
||||
fn notes_in (&self) -> &Arc<RwLock<[bool; 128]>> {
|
||||
todo!("notes_in")
|
||||
&self$(.$field)*.notes_in
|
||||
}
|
||||
}
|
||||
impl MidiOutputApi for $Struct {
|
||||
fn midi_outs (&self) -> &Vec<Port<jack::MidiOut>> {
|
||||
todo!("midi_outs")
|
||||
&self$(.$field)*.midi_outs
|
||||
}
|
||||
fn midi_outs_mut (&mut self) -> &mut Vec<Port<jack::MidiOut>> {
|
||||
todo!("midi_outs_mut")
|
||||
&mut self$(.$field)*.midi_outs
|
||||
}
|
||||
fn midi_note (&mut self) -> &mut Vec<u8> {
|
||||
todo!("midi_note")
|
||||
&mut self$(.$field)*.note_buf
|
||||
}
|
||||
fn notes_out (&self) -> &Arc<RwLock<[bool; 128]>> {
|
||||
todo!("notes_out")
|
||||
&self$(.$field)*.notes_in
|
||||
}
|
||||
}
|
||||
impl MidiPlayerApi for $Struct {}
|
||||
|
|
|
|||
|
|
@ -6,9 +6,10 @@ impl TryFrom<&Arc<RwLock<JackClient>>> for TransportTui {
|
|||
fn try_from (jack: &Arc<RwLock<JackClient>>) -> Usually<Self> {
|
||||
Ok(Self {
|
||||
jack: jack.clone(),
|
||||
state: TransportModel::from(&Arc::new(jack.read().unwrap().transport())),
|
||||
clock: ClockModel::from(&Arc::new(jack.read().unwrap().transport())),
|
||||
size: Measure::new(),
|
||||
cursor: (0, 0),
|
||||
focus: FocusState::Entered(AppFocus::Content(TransportFocus::PlayPause))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -16,11 +17,11 @@ impl TryFrom<&Arc<RwLock<JackClient>>> for TransportTui {
|
|||
impl TryFrom<&Arc<RwLock<JackClient>>> for SequencerTui {
|
||||
type Error = Box<dyn std::error::Error>;
|
||||
fn try_from (jack: &Arc<RwLock<JackClient>>) -> Usually<Self> {
|
||||
let transport = TransportModel::from(&Arc::new(jack.read().unwrap().transport()));
|
||||
let clock = ClockModel::from(&Arc::new(jack.read().unwrap().transport()));
|
||||
Ok(Self {
|
||||
jack: jack.clone(),
|
||||
phrases: PhrasesModel::default(),
|
||||
player: PhrasePlayerModel::from(&transport.clock),
|
||||
player: PhrasePlayerModel::from(&clock),
|
||||
editor: PhraseEditorModel::default(),
|
||||
size: Measure::new(),
|
||||
cursor: (0, 0),
|
||||
|
|
@ -28,7 +29,8 @@ impl TryFrom<&Arc<RwLock<JackClient>>> for SequencerTui {
|
|||
split: 20,
|
||||
midi_buf: vec![vec![];65536],
|
||||
note_buf: vec![],
|
||||
transport,
|
||||
clock,
|
||||
focus: FocusState::Entered(AppFocus::Content(SequencerFocus::Transport(TransportFocus::PlayPause)))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -38,7 +40,7 @@ impl TryFrom<&Arc<RwLock<JackClient>>> for ArrangerTui {
|
|||
fn try_from (jack: &Arc<RwLock<JackClient>>) -> Usually<Self> {
|
||||
Ok(Self {
|
||||
jack: jack.clone(),
|
||||
transport: TransportModel::from(&Arc::new(jack.read().unwrap().transport())),
|
||||
clock: ClockModel::from(&Arc::new(jack.read().unwrap().transport())),
|
||||
phrases: PhrasesModel::default(),
|
||||
editor: PhraseEditorModel::default(),
|
||||
selected: ArrangerSelection::Clip(0, 0),
|
||||
|
|
@ -56,6 +58,7 @@ impl TryFrom<&Arc<RwLock<JackClient>>> for ArrangerTui {
|
|||
status_bar: None,
|
||||
midi_buf: vec![vec![];65536],
|
||||
note_buf: vec![],
|
||||
focus: FocusState::Entered(AppFocus::Content(ArrangerFocus::Transport(TransportFocus::PlayPause)))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,22 +32,6 @@ impl From<&Arc<Transport>> for ClockModel {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct TransportModel {
|
||||
/// State of clock and playhead
|
||||
pub(crate) clock: ClockModel,
|
||||
/// Whether the transport is focused and which part of it is selected
|
||||
pub(crate) focus: FocusState<TransportFocus>,
|
||||
}
|
||||
|
||||
impl From<&Arc<Transport>> for TransportModel {
|
||||
fn from (transport: &Arc<Transport>) -> Self {
|
||||
Self {
|
||||
clock: ClockModel::from(transport),
|
||||
focus: FocusState::Exited(TransportFocus::PlayPause),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Contains state for playing a phrase
|
||||
pub struct PhrasePlayerModel {
|
||||
/// State of clock and playhead
|
||||
|
|
@ -72,6 +56,8 @@ pub struct PhrasePlayerModel {
|
|||
pub(crate) notes_in: Arc<RwLock<[bool; 128]>>,
|
||||
/// Notes currently held at output
|
||||
pub(crate) notes_out: Arc<RwLock<[bool; 128]>>,
|
||||
/// MIDI output buffer
|
||||
pub note_buf: Vec<u8>,
|
||||
}
|
||||
|
||||
impl From<&ClockModel> for PhrasePlayerModel {
|
||||
|
|
@ -80,6 +66,7 @@ impl From<&ClockModel> for PhrasePlayerModel {
|
|||
clock: clock.clone(),
|
||||
midi_ins: vec![],
|
||||
midi_outs: vec![],
|
||||
note_buf: vec![0;8],
|
||||
reset: true,
|
||||
recording: false,
|
||||
monitoring: false,
|
||||
|
|
@ -106,8 +93,6 @@ pub struct PhraseEditorModel {
|
|||
pub(crate) note_axis: RwLock<FixedAxis<usize>>,
|
||||
/// Cursor/scroll/zoom in time axis
|
||||
pub(crate) time_axis: RwLock<ScaledAxis<usize>>,
|
||||
/// Whether this widget is focused
|
||||
pub(crate) focus: FocusState<()>,
|
||||
/// Display mode
|
||||
pub(crate) mode: bool,
|
||||
/// Notes currently held at input
|
||||
|
|
@ -127,7 +112,6 @@ impl Default for PhraseEditorModel {
|
|||
note_len: 24,
|
||||
keys: keys_vert(),
|
||||
buffer: Default::default(),
|
||||
focus: FocusState::Exited(()),
|
||||
mode: false,
|
||||
notes_in: RwLock::new([false;128]).into(),
|
||||
notes_out: RwLock::new([false;128]).into(),
|
||||
|
|
@ -158,8 +142,6 @@ pub struct PhrasesModel {
|
|||
pub(crate) scroll: usize,
|
||||
/// Mode switch
|
||||
pub(crate) mode: Option<PhrasesMode>,
|
||||
/// Whether this widget is focused
|
||||
pub(crate) focus: FocusState<()>,
|
||||
}
|
||||
|
||||
impl Default for PhrasesModel {
|
||||
|
|
@ -169,7 +151,6 @@ impl Default for PhrasesModel {
|
|||
phrase: 0.into(),
|
||||
scroll: 0,
|
||||
mode: None,
|
||||
focus: FocusState::Exited(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,16 +9,16 @@ pub struct PhraseView<'a, T: PhraseViewState>(pub &'a T);
|
|||
pub trait TransportViewState: ClockApi + Send + Sync {
|
||||
fn transport_selected (&self) -> TransportFocus;
|
||||
fn transport_focused (&self) -> bool;
|
||||
fn bpm_value (&self) -> f64 {
|
||||
fn transport_bpm_value (&self) -> f64 {
|
||||
self.bpm().get()
|
||||
}
|
||||
fn sync_value (&self) -> f64 {
|
||||
fn transport_sync_value (&self) -> f64 {
|
||||
self.sync().get()
|
||||
}
|
||||
fn format_beat (&self) -> String {
|
||||
fn transport_format_beat (&self) -> String {
|
||||
self.current().format_beat()
|
||||
}
|
||||
fn format_msu (&self) -> String {
|
||||
fn transport_format_msu (&self) -> String {
|
||||
self.current().usec.format_msu()
|
||||
}
|
||||
}
|
||||
|
|
@ -55,13 +55,13 @@ pub trait PhrasesViewState: Send + Sync {
|
|||
fn phrase_mode (&self) -> &Option<PhrasesMode>;
|
||||
}
|
||||
macro_rules! impl_phrases_view_state {
|
||||
($Struct:ident $(:: $field:ident)*) => {
|
||||
($Struct:ident $(:: $field:ident)* [$self:ident: $focus:expr] [self: $enter:expr]) => {
|
||||
impl PhrasesViewState for $Struct {
|
||||
fn phrases_focused (&self) -> bool {
|
||||
todo!()
|
||||
fn phrases_focused (&$self) -> bool {
|
||||
$focus
|
||||
}
|
||||
fn phrases_entered (&self) -> bool {
|
||||
todo!()
|
||||
fn phrases_entered (&$self) -> bool {
|
||||
$enter
|
||||
}
|
||||
fn phrases (&self) -> Vec<Arc<RwLock<Phrase>>> {
|
||||
todo!()
|
||||
|
|
@ -75,9 +75,13 @@ macro_rules! impl_phrases_view_state {
|
|||
}
|
||||
}
|
||||
}
|
||||
impl_phrases_view_state!(PhrasesModel);
|
||||
impl_phrases_view_state!(SequencerTui::phrases);
|
||||
impl_phrases_view_state!(ArrangerTui::phrases);
|
||||
impl_phrases_view_state!(PhrasesModel [self: false] [self: false]);
|
||||
impl_phrases_view_state!(SequencerTui::phrases
|
||||
[self: self.focused() == FocusState::Focused(SequencerFocus::Phrases)]
|
||||
[self: self.focused() == FocusState::Entered(SequencerFocus::Phrases)]);
|
||||
impl_phrases_view_state!(ArrangerTui::phrases
|
||||
[self: self.focused() == FocusState::Focused(ArrangerFocus::Phrases)]
|
||||
[self: self.focused() == FocusState::Entered(SequencerFocus::Phrases)]);
|
||||
|
||||
pub trait PhraseViewState: Send + Sync {
|
||||
fn phrase_editing (&self) -> &Option<Arc<RwLock<Phrase>>>;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue