From 3b73da86e0e2ab5c3049a00e051a98b8aa4b14f1 Mon Sep 17 00:00:00 2001 From: unspeaker Date: Mon, 9 Dec 2024 18:31:53 +0100 Subject: [PATCH] wip6 (60e): --- crates/tek/src/{api/mod.rs => api.rs} | 0 crates/tek/src/{core/mod.rs => core.rs} | 0 crates/tek/src/{layout/mod.rs => layout.rs} | 6 +- crates/tek/src/layout/README.md | 1 - crates/tek/src/layout/fixed.rs | 2 +- crates/tek/src/layout/inset_outset.rs | 7 - crates/tek/src/layout/layers.rs | 5 + crates/tek/src/layout/min_max.rs | 62 ++++---- crates/tek/src/layout/push_pull.rs | 3 - crates/tek/src/layout/stack.rs | 30 ++-- crates/tek/src/{tui/mod.rs => tui.rs} | 1 - crates/tek/src/tui/app_sequencer.rs | 2 +- crates/tek/src/tui/app_transport.rs | 5 +- crates/tek/src/tui/ctrl_arranger.rs | 14 +- crates/tek/src/tui/ctrl_file_browser.rs | 9 +- crates/tek/src/tui/ctrl_phrase_editor.rs | 2 - crates/tek/src/tui/ctrl_transport.rs | 11 +- crates/tek/src/tui/engine_layout.rs | 1 - crates/tek/src/tui/view_arranger.rs | 164 ++++++++++---------- crates/tek/src/tui/view_file_browser.rs | 4 +- crates/tek/src/tui/view_phrase_editor.rs | 2 +- crates/tek/src/tui/view_phrase_length.rs | 18 +-- crates/tek/src/tui/view_sequencer.rs | 75 ++++----- crates/tek/src/tui/view_status_bar.rs | 13 +- crates/tek/src/tui/view_transport.rs | 2 +- 25 files changed, 212 insertions(+), 227 deletions(-) rename crates/tek/src/{api/mod.rs => api.rs} (100%) rename crates/tek/src/{core/mod.rs => core.rs} (100%) rename crates/tek/src/{layout/mod.rs => layout.rs} (63%) delete mode 100644 crates/tek/src/layout/README.md rename crates/tek/src/{tui/mod.rs => tui.rs} (99%) delete mode 100644 crates/tek/src/tui/engine_layout.rs diff --git a/crates/tek/src/api/mod.rs b/crates/tek/src/api.rs similarity index 100% rename from crates/tek/src/api/mod.rs rename to crates/tek/src/api.rs diff --git a/crates/tek/src/core/mod.rs b/crates/tek/src/core.rs similarity index 100% rename from crates/tek/src/core/mod.rs rename to crates/tek/src/core.rs diff --git a/crates/tek/src/layout/mod.rs b/crates/tek/src/layout.rs similarity index 63% rename from crates/tek/src/layout/mod.rs rename to crates/tek/src/layout.rs index 91996fe6..11926aa5 100644 --- a/crates/tek/src/layout/mod.rs +++ b/crates/tek/src/layout.rs @@ -1,3 +1,5 @@ +// manja s grozde; ikebana s chiaroscuro + use crate::*; submod! { @@ -18,7 +20,3 @@ submod! { split stack } - -#[macro_export] macro_rules! lay { - ($($expr:expr),* $(,)?) => { Layers::new(move|add|{ $(add(&$expr)?;)* Ok(()) }) } -} diff --git a/crates/tek/src/layout/README.md b/crates/tek/src/layout/README.md deleted file mode 100644 index 6d622181..00000000 --- a/crates/tek/src/layout/README.md +++ /dev/null @@ -1 +0,0 @@ -manja s grozde i ikebana s chiaroscuro diff --git a/crates/tek/src/layout/fixed.rs b/crates/tek/src/layout/fixed.rs index e82cbf7c..a73c54ba 100644 --- a/crates/tek/src/layout/fixed.rs +++ b/crates/tek/src/layout/fixed.rs @@ -1,6 +1,6 @@ use crate::*; -impl> LayoutFixed for W {} +impl LayoutFixed for E {} pub trait LayoutFixed { fn fixed_x > (x: E::Unit, w: W) -> Fixed { diff --git a/crates/tek/src/layout/inset_outset.rs b/crates/tek/src/layout/inset_outset.rs index 55c359a1..2985aecf 100644 --- a/crates/tek/src/layout/inset_outset.rs +++ b/crates/tek/src/layout/inset_outset.rs @@ -25,7 +25,6 @@ pub trait LayoutInsetOutset: LayoutPushPull + LayoutShrinkGrow /// Shrink from each side pub enum Inset { - _Unused(PhantomData), /// Decrease width X(E::Unit, T), /// Decrease height @@ -40,7 +39,6 @@ impl> Inset { Self::X(_, i) => i, Self::Y(_, i) => i, Self::XY(_, _, i) => i, - _ => unreachable!(), } } } @@ -51,14 +49,12 @@ impl> Render for Inset { Self::X(x, inner) => E::push_x(*x, E::shrink_x(*x, inner)), Self::Y(y, inner) => E::push_y(*y, E::shrink_y(*y, inner)), Self::XY(x, y, inner) => E::push_xy(*x, *y, E::shrink_xy(*x, *y, inner)), - _ => unreachable!(), }.render(to) } } /// Grow on each side pub enum Outset> { - _Unused(PhantomData), /// Increase width X(E::Unit, T), /// Increase height @@ -74,7 +70,6 @@ impl> Outset { Self::X(_, i) => i, Self::Y(_, i) => i, Self::XY(_, _, i) => i, - _ => unreachable!(), } } } @@ -85,7 +80,6 @@ impl> Render for Outset { Self::X(x, ref inner) => E::grow_x(x + x, inner), Self::Y(y, ref inner) => E::grow_y(y + y, inner), Self::XY(x, y, ref inner) => E::grow_xy(x + x, y + y, inner), - _ => unreachable!(), }.min_size(to) } fn render (&self, to: &mut E::Output) -> Usually<()> { @@ -93,7 +87,6 @@ impl> Render for Outset { Self::X(x, ref inner) => E::push_x(x, inner), Self::Y(y, ref inner) => E::push_y(y, inner), Self::XY(x, y, ref inner) => E::push_xy(x, y, inner), - _ => unreachable!(), }.render(to) } } diff --git a/crates/tek/src/layout/layers.rs b/crates/tek/src/layout/layers.rs index 9fe07ecd..d9eef72d 100644 --- a/crates/tek/src/layout/layers.rs +++ b/crates/tek/src/layout/layers.rs @@ -1,5 +1,10 @@ use crate::*; +#[macro_export] macro_rules! lay { + ($(move)*|$add:ident|$expr:expr) => { Layers::new($(move)*|$add|$expr) }; + ($($expr:expr),* $(,)?) => { Layers::new(move|add|{ $(add(&$expr)?;)* Ok(()) }) } +} + pub struct Layers< E: Engine, F: Send + Sync + Fn(&mut dyn FnMut(&dyn Render)->Usually<()>)->Usually<()> diff --git a/crates/tek/src/layout/min_max.rs b/crates/tek/src/layout/min_max.rs index 042f7421..42312bab 100644 --- a/crates/tek/src/layout/min_max.rs +++ b/crates/tek/src/layout/min_max.rs @@ -3,41 +3,57 @@ use crate::*; impl LayoutMinMax for E {} pub trait LayoutMinMax { - fn min_x > (x: E::Unit, w: W) -> Min { + fn min_x > (x: E::Unit, w: W) -> Min { Min::X(x, w) } - fn min_y > (y: E::Unit, w: W) -> Min { + fn min_y > (y: E::Unit, w: W) -> Min { Min::Y(y, w) } - fn min_xy > (x: E::Unit, y: E::Unit, w: W) -> Min { + fn min_xy > (x: E::Unit, y: E::Unit, w: W) -> Min { Min::XY(x, y, w) } - fn max_x > (x: E::Unit, w: W) -> Max { + fn max_x > (x: E::Unit, w: W) -> Max { Max::X(x, w) } - fn max_y > (y: E::Unit, w: W) -> Max { + fn max_y > (y: E::Unit, w: W) -> Max { Max::Y(y, w) } - fn max_xy > (x: E::Unit, y: E::Unit, w: W) -> Max { + fn max_xy > (x: E::Unit, y: E::Unit, w: W) -> Max { Max::XY(x, y, w) } } /// Enforce minimum size of drawing area -pub enum Min { +pub enum Min> { /// Enforce minimum width - X(U, T), + X(E::Unit, T), /// Enforce minimum height - Y(U, T), + Y(E::Unit, T), /// Enforce minimum width and height - XY(U, U, T), + XY(E::Unit, E::Unit, T), } -impl Min { + +/// Enforce maximum size of drawing area +pub enum Max> { + /// Enforce maximum width + X(E::Unit, T), + /// Enforce maximum height + Y(E::Unit, T), + /// Enforce maximum width and height + XY(E::Unit, E::Unit, T), +} + +impl> Min { pub fn inner (&self) -> &T { - match self { Self::X(_, i) => i, Self::Y(_, i) => i, Self::XY(_, _, i) => i, } + match self { + Self::X(_, i) => i, + Self::Y(_, i) => i, + Self::XY(_, _, i) => i, + } } } -impl> Render for Min { + +impl> Render for Min { fn min_size (&self, to: E::Size) -> Perhaps { Ok(self.inner().min_size(to)?.map(|to|match *self { Self::X(w, _) => [to.w().max(w), to.h()], @@ -53,23 +69,17 @@ impl> Render for Min { } } -/// Enforce maximum size of drawing area -pub enum Max { - /// Enforce maximum width - X(U, T), - /// Enforce maximum height - Y(U, T), - /// Enforce maximum width and height - XY(U, U, T), -} - -impl Max { +impl> Max { fn inner (&self) -> &T { - match self { Self::X(_, i) => i, Self::Y(_, i) => i, Self::XY(_, _, i) => i, } + match self { + Self::X(_, i) => i, + Self::Y(_, i) => i, + Self::XY(_, _, i) => i, + } } } -impl> Render for Max { +impl> Render for Max { fn min_size (&self, to: E::Size) -> Perhaps { Ok(self.inner().min_size(to)?.map(|to|match *self { Self::X(w, _) => [to.w().min(w), to.h()], diff --git a/crates/tek/src/layout/push_pull.rs b/crates/tek/src/layout/push_pull.rs index f06c9e22..2b83bd0e 100644 --- a/crates/tek/src/layout/push_pull.rs +++ b/crates/tek/src/layout/push_pull.rs @@ -39,7 +39,6 @@ impl> Push { Self::X(_, i) => i, Self::Y(_, i) => i, Self::XY(_, _, i) => i, - _ => unreachable!(), } } pub fn x (&self) -> E::Unit { @@ -47,7 +46,6 @@ impl> Push { Self::X(x, _) => *x, Self::Y(_, _) => E::Unit::default(), Self::XY(x, _, _) => *x, - _ => unreachable!(), } } pub fn y (&self) -> E::Unit { @@ -55,7 +53,6 @@ impl> Push { Self::X(_, _) => E::Unit::default(), Self::Y(y, _) => *y, Self::XY(_, y, _) => *y, - _ => unreachable!(), } } } diff --git a/crates/tek/src/layout/stack.rs b/crates/tek/src/layout/stack.rs index ac383989..482afd42 100644 --- a/crates/tek/src/layout/stack.rs +++ b/crates/tek/src/layout/stack.rs @@ -1,31 +1,35 @@ use crate::*; #[macro_export] macro_rules! col { - ($($expr:expr),* $(,)?) => { Stack::down(move|add|{ $(add(&$expr)?;)* Ok(()) }) }; + ($(move)?|$add:ident|$expr:expr) => { Stack::down($(move)?|$add|$expr) }; ($pat:pat in $collection:expr => $item:expr) => { Stack::down(move |add|{ for $pat in $collection { add(&$item)?; } Ok(()) }) - } + }; + ($($expr:expr),* $(,)?) => { Stack::down(move|add|{ $(add(&$expr)?;)* Ok(()) }) }; } #[macro_export] macro_rules! col_up { - ($($expr:expr),* $(,)?) => { Stack::down(move|add|{ $(add(&$expr)?;)* Ok(()) }) }; + ($(move)?|$add:ident|$expr:expr) => { Stack::up($(move)?|$add|$expr) }; ($pat:pat in $collection:expr => $item:expr) => { Stack::up(move |add|{ for $pat in $collection { add(&$item)?; } Ok(()) }) - } + }; + ($($expr:expr),* $(,)?) => { Stack::up(move|add|{ $(add(&$expr)?;)* Ok(()) }) }; } #[macro_export] macro_rules! row { - ($($expr:expr),* $(,)?) => { Stack::right(move|add|{ $(add(&$expr)?;)* Ok(()) }) }; + ($(move)?|$add:ident|$expr:expr) => { + Stack::right($(move)?|$add|$expr) + }; ($pat:pat in $collection:expr => $item:expr) => { - Stack::right(move |add|{ - for $pat in $collection { add(&$item)?; } - Ok(()) - }) - } + Stack::right(move |add|{ for $pat in $collection { add(&$item)?; } Ok(()) }) + }; + ($($expr:expr),* $(,)?) => { + Stack::right(move|add|{ $(add(&$expr)?;)* Ok(()) }) + }; } pub struct Stack< @@ -100,7 +104,7 @@ where (self.0)(&mut |component: &dyn Render| { let max = to.h().minus(h); if max > E::Unit::ZERO() { - let item = component.max_y(to.h() - h); + let item = Tui::max_y(to.h() - h, component); let size = item.min_size(to)?.map(|size|size.wh()); if let Some([width, height]) = size { h = h + height.into(); @@ -134,7 +138,7 @@ where Direction::Down => { (self.0)(&mut |item| { if h < area.h() { - let item = item.push_y(h).max_y(area.h() - h); + let item = Tui::max_y(area.h() - h, Tui::push_y(h, item)); let show = item.min_size(area.wh().into())?.map(|s|s.wh()); if let Some([width, height]) = show { item.render(to)?; @@ -148,7 +152,7 @@ where Direction::Right => { (self.0)(&mut |item| { if w < area.w() { - let item = item.push_x(w).max_x(area.w() - w); + let item = Tui::max_x(area.w() - w, Tui::push_x(w, item)); let show = item.min_size(area.wh().into())?.map(|s|s.wh()); if let Some([width, height]) = show { item.render(to)?; diff --git a/crates/tek/src/tui/mod.rs b/crates/tek/src/tui.rs similarity index 99% rename from crates/tek/src/tui/mod.rs rename to crates/tek/src/tui.rs index 2fd4e52e..61a024fb 100644 --- a/crates/tek/src/tui/mod.rs +++ b/crates/tek/src/tui.rs @@ -3,7 +3,6 @@ use crate::*; submod! { engine_focus engine_input - engine_layout engine_output engine_style diff --git a/crates/tek/src/tui/app_sequencer.rs b/crates/tek/src/tui/app_sequencer.rs index 15e1ab44..ebbd47fa 100644 --- a/crates/tek/src/tui/app_sequencer.rs +++ b/crates/tek/src/tui/app_sequencer.rs @@ -128,7 +128,7 @@ impl StatusBar for SequencerStatusBar { fn hotkey_fg () -> Color { TuiTheme::hotkey_fg() } - fn update (&mut self, state: &SequencerTui) { + fn update (&mut self, _: &SequencerTui) { todo!() } } diff --git a/crates/tek/src/tui/app_transport.rs b/crates/tek/src/tui/app_transport.rs index bb566084..8d9e8adf 100644 --- a/crates/tek/src/tui/app_transport.rs +++ b/crates/tek/src/tui/app_transport.rs @@ -90,12 +90,11 @@ impl StatusBar for TransportStatusBar { fn hotkey_fg () -> Color { TuiTheme::hotkey_fg() } - fn update (&mut self, state: &()) { + fn update (&mut self, _: &()) { todo!() } } render!(|self: TransportStatusBar|{ - todo!(); - "" + "todo" }); diff --git a/crates/tek/src/tui/ctrl_arranger.rs b/crates/tek/src/tui/ctrl_arranger.rs index b478240d..7a05492b 100644 --- a/crates/tek/src/tui/ctrl_arranger.rs +++ b/crates/tek/src/tui/ctrl_arranger.rs @@ -34,7 +34,7 @@ impl Command for ArrangerCommand { Phrases(cmd) => cmd.execute(&mut state.phrases)?.map(Phrases), Editor(cmd) => cmd.execute(&mut state.editor)?.map(Editor), Clock(cmd) => cmd.execute(state)?.map(Clock), - Zoom(zoom) => { todo!(); }, + Zoom(_) => { todo!(); }, Select(selected) => { *state.selected_mut() = selected; None @@ -45,22 +45,22 @@ impl Command for ArrangerCommand { } impl Command for ArrangerSceneCommand { - fn execute (self, state: &mut ArrangerTui) -> Perhaps { - todo!(); + fn execute (self, _state: &mut ArrangerTui) -> Perhaps { + //todo!(); Ok(None) } } impl Command for ArrangerTrackCommand { - fn execute (self, state: &mut ArrangerTui) -> Perhaps { - todo!(); + fn execute (self, _state: &mut ArrangerTui) -> Perhaps { + //todo!(); Ok(None) } } impl Command for ArrangerClipCommand { - fn execute (self, state: &mut ArrangerTui) -> Perhaps { - todo!(); + fn execute (self, _state: &mut ArrangerTui) -> Perhaps { + //todo!(); Ok(None) } } diff --git a/crates/tek/src/tui/ctrl_file_browser.rs b/crates/tek/src/tui/ctrl_file_browser.rs index e47bf817..fc530b7b 100644 --- a/crates/tek/src/tui/ctrl_file_browser.rs +++ b/crates/tek/src/tui/ctrl_file_browser.rs @@ -38,7 +38,6 @@ impl Command for FileBrowserCommand { } }, _ => todo!(), - _ => unreachable!() }, Some(PhrasesMode::Export(index, ref mut browser)) => match self { Cancel => { @@ -62,7 +61,7 @@ impl InputToCommand for FileBrowserCommand { fn input_to_command (state: &PhraseListModel, from: &TuiInput) -> Option { use KeyCode::{Up, Down, Right, Left, Enter, Esc, Char, Backspace}; use FileBrowserCommand::*; - if let Some(PhrasesMode::Import(index, browser)) = state.phrases_mode() { + if let Some(PhrasesMode::Import(_index, browser)) = state.phrases_mode() { Some(match from.event() { key!(Up) => Select( browser.index.overflowing_sub(1).0.min(browser.len().saturating_sub(1)) @@ -73,19 +72,19 @@ impl InputToCommand for FileBrowserCommand { key!(Right) => Chdir(browser.cwd.clone()), key!(Left) => Chdir(browser.cwd.clone()), key!(Enter) => Confirm, - key!(Char(c)) => { todo!() }, + key!(Char(_)) => { todo!() }, key!(Backspace) => { todo!() }, key!(Esc) => Self::Cancel, _ => return None }) - } else if let Some(PhrasesMode::Export(index, browser)) = state.phrases_mode() { + } else if let Some(PhrasesMode::Export(_index, browser)) = state.phrases_mode() { Some(match from.event() { key!(Up) => Select(browser.index.overflowing_sub(1).0.min(browser.len())), key!(Down) => Select(browser.index.saturating_add(1) % browser.len()), key!(Right) => Chdir(browser.cwd.clone()), key!(Left) => Chdir(browser.cwd.clone()), key!(Enter) => Confirm, - key!(Char(c)) => { todo!() }, + key!(Char(_)) => { todo!() }, key!(Backspace) => { todo!() }, key!(Esc) => Self::Cancel, _ => return None diff --git a/crates/tek/src/tui/ctrl_phrase_editor.rs b/crates/tek/src/tui/ctrl_phrase_editor.rs index 919391e9..6209ffe7 100644 --- a/crates/tek/src/tui/ctrl_phrase_editor.rs +++ b/crates/tek/src/tui/ctrl_phrase_editor.rs @@ -60,7 +60,6 @@ impl InputToCommand for PhraseCommand { _ => return None }, } - _ => return None }) } } @@ -119,7 +118,6 @@ impl Command for PhraseCommand { } None }, - _ => unreachable!() }) } } diff --git a/crates/tek/src/tui/ctrl_transport.rs b/crates/tek/src/tui/ctrl_transport.rs index 6ef05509..4ed360c7 100644 --- a/crates/tek/src/tui/ctrl_transport.rs +++ b/crates/tek/src/tui/ctrl_transport.rs @@ -14,16 +14,9 @@ pub enum TransportCommand { impl Command for TransportCommand { fn execute (self, state: &mut T) -> Perhaps { - use TransportCommand::{Focus, Clock}; - use FocusCommand::{Next, Prev}; - use ClockCommand::{SetBpm, SetQuant, SetSync}; Ok(match self { - Focus(cmd) => cmd.execute(state)?.map(Focus), - Clock(cmd) => cmd.execute(state)?.map(Clock), - //Clock(SetBpm(bpm)) => Some(Clock(SetBpm(state.bpm().set(bpm)))), - //Clock(SetQuant(quant)) => Some(Clock(SetQuant(state.quant().set(quant)))), - //Clock(SetSync(sync)) => Some(Clock(SetSync(state.sync().set(sync)))), - _ => return Ok(None) + Self::Focus(cmd) => cmd.execute(state)?.map(Self::Focus), + Self::Clock(cmd) => cmd.execute(state)?.map(Self::Clock), }) } } diff --git a/crates/tek/src/tui/engine_layout.rs b/crates/tek/src/tui/engine_layout.rs deleted file mode 100644 index c7b7e813..00000000 --- a/crates/tek/src/tui/engine_layout.rs +++ /dev/null @@ -1 +0,0 @@ -use crate::*; diff --git a/crates/tek/src/tui/view_arranger.rs b/crates/tek/src/tui/view_arranger.rs index 75f7cc5d..d129b369 100644 --- a/crates/tek/src/tui/view_arranger.rs +++ b/crates/tek/src/tui/view_arranger.rs @@ -105,95 +105,91 @@ pub fn arranger_content_vertical ( let any_size = |_|Ok(Some([0,0])); // track titles - let header = Tui::reduce( - tracks.iter().zip(cols.iter().map(|col|col.0)), - |prev, (track, w)|{ - // name and width of track - let name = track.name().read().unwrap(); - let max_w = w.saturating_sub(1).min(name.len()).max(2); - let name = format!("▎{}", &name[0..max_w]); - let name = Tui::bold(true, name); - // beats elapsed - let elapsed = if let Some((_, Some(phrase))) = track.player.play_phrase().as_ref() { - let length = phrase.read().unwrap().length; - let elapsed = track.player.pulses_since_start().unwrap(); - let elapsed = timebase.format_beats_1_short( - (elapsed as usize % length) as f64 - ); - format!("▎+{elapsed:>}") + let header = row!((track, w) in tracks.iter().zip(cols.iter().map(|col|col.0)) => { + // name and width of track + let name = track.name().read().unwrap(); + let max_w = w.saturating_sub(1).min(name.len()).max(2); + let name = format!("▎{}", &name[0..max_w]); + let name = Tui::bold(true, name); + // beats elapsed + let elapsed = if let Some((_, Some(phrase))) = track.player.play_phrase().as_ref() { + let length = phrase.read().unwrap().length; + let elapsed = track.player.pulses_since_start().unwrap(); + let elapsed = timebase.format_beats_1_short( + (elapsed as usize % length) as f64 + ); + format!("▎+{elapsed:>}") + } else { + String::from("▎") + }; + // beats until switchover + let until_next = track.player.next_phrase().as_ref().map(|(t, _)|{ + let target = t.pulse.get(); + let current = current.pulse.get(); + if target > current { + let remaining = target - current; + format!("▎-{:>}", timebase.format_beats_0_short(remaining)) } else { - String::from("▎") - }; - // beats until switchover - let until_next = track.player.next_phrase().as_ref().map(|(t, _)|{ - let target = t.pulse.get(); - let current = current.pulse.get(); - if target > current { - let remaining = target - current; - format!("▎-{:>}", timebase.format_beats_0_short(remaining)) - } else { - String::new() - } - }).unwrap_or(String::from("▎")); - let timer = Tui::to_south(until_next, elapsed); - // name of active MIDI input - let input = format!("▎>{}", track.player.midi_ins().get(0) - .map(|port|port.short_name()) - .transpose()? - .unwrap_or("(none)".into())); - // name of active MIDI output - let output = format!("▎<{}", track.player.midi_outs().get(0) - .map(|port|port.short_name()) - .transpose()? - .unwrap_or("(none)".into())); - //Tui::to_east(prev, Tui::push_x(scenes_w, - //Tui::bg(track.color().rgb, - //Tui::min_xy(w as u16, header_h, - //Tui::to_south(name, timer))))) - prev - } - ); + String::new() + } + }).unwrap_or(String::from("▎")); + let timer = Tui::to_south(until_next, elapsed); + // name of active MIDI input + let input = format!("▎>{}", track.player.midi_ins().get(0) + .map(|port|port.short_name()) + .transpose()? + .unwrap_or("(none)".into())); + // name of active MIDI output + let output = format!("▎<{}", track.player.midi_outs().get(0) + .map(|port|port.short_name()) + .transpose()? + .unwrap_or("(none)".into())); + Tui::push_x(scenes_w, + Tui::bg(track.color().rgb, + Tui::min_xy(w as u16, header_h, + Tui::to_south(name, timer)))) + }); - let height = (view.size.h() as u16).saturating_sub(header_h); - let scene_rows = scenes.iter().zip(rows.iter().map(|row|row.0)); - let content = Tui::fixed_y(height, Tui::reduce(scene_rows, |prev, (scene, pulses)| { - let height = 1.max((pulses / PPQ) as u16); - let playing = scene.is_playing(tracks); - Tui::fixed_y( - height, - Tui::to_east( + let content = Tui::fixed_y( + (view.size.h() as u16).saturating_sub(header_h), + col!((scene, pulses) in scenes.iter().zip(rows.iter().map(|row|row.0)) => { + let height = 1.max((pulses / PPQ) as u16); + let playing = scene.is_playing(tracks); + Tui::fixed_y( + height, Tui::to_east( - if playing { "▶ " } else { " " }, - Tui::bold(true, scene.name.read().unwrap().as_str()) - ), - Tui::iter( - cols.iter().map(|col|col.0).enumerate(), - |(track, w)|Tui::fixed_xy(w as u16, height, Layers::new(move |add|{ - let mut bg = clip_bg; - match (tracks.get(track), scene.clips.get(track)) { - (Some(track), Some(Some(phrase))) => { - let name = &(phrase as &Arc>).read().unwrap().name; - let name = format!("{}", name); - let max_w = name.len().min((w as usize).saturating_sub(2)); - let color = phrase.read().unwrap().color; - add(&name.as_str()[0..max_w].push_x(1).fixed_x(w as u16))?; - bg = color.dark.rgb; - if let Some((_, Some(ref playing))) = track.player.play_phrase() { - if *playing.read().unwrap() == *phrase.read().unwrap() { - bg = color.light.rgb - } - }; - }, - _ => {} - }; - add(&Background(bg)) - })) + Tui::to_east( + if playing { "▶ " } else { " " }, + Tui::bold(true, scene.name.read().unwrap().as_str()) + ), + row!((track, w) in cols.iter().map(|col|col.0).enumerate() => { + Tui::fixed_xy(w as u16, height, Layers::new(move |add|{ + let mut bg = clip_bg; + match (tracks.get(track), scene.clips.get(track)) { + (Some(track), Some(Some(phrase))) => { + let name = &(phrase as &Arc>).read().unwrap().name; + let name = format!("{}", name); + let max_w = name.len().min((w as usize).saturating_sub(2)); + let color = phrase.read().unwrap().color; + bg = color.dark.rgb; + if let Some((_, Some(ref playing))) = track.player.play_phrase() { + if *playing.read().unwrap() == *phrase.read().unwrap() { + bg = color.light.rgb + } + }; + add(&Tui::fixed_x(w as u16, Tui::push_x(1, &name.as_str()[0..max_w])))?; + }, + _ => {} + }; + //add(&Background(bg)) + Ok(()) + })) + }) ) ) - ) - })); + })); - let arrangement = Layers::new(move |add|{ + let arrangement = Tui::bg(bg.rgb, lay!(move|add|{ // column separators add(&Widget::new(any_size, move|to: &mut TuiOutput|{ let style = Some(Style::default().fg(sep_fg)); @@ -273,7 +269,7 @@ pub fn arranger_content_vertical ( else { area.clip_w(scenes_w).clip_h(header_h) }, &CORNERS)? }) })) - }).bg(bg.rgb); + })); let color = TuiTheme::title_fg(view.arranger_focused()); let size = format!("{}x{}", view.size.w(), view.size.h()); let lower_right = Tui::at_se(Tui::fill_xy(Tui::pull_x(1, Tui::fg(color, size)))); diff --git a/crates/tek/src/tui/view_file_browser.rs b/crates/tek/src/tui/view_file_browser.rs index 2886d7d3..2d21e8ea 100644 --- a/crates/tek/src/tui/view_file_browser.rs +++ b/crates/tek/src/tui/view_file_browser.rs @@ -6,13 +6,13 @@ impl Content for FileBrowser { let mut i = 0; for (_, name) in self.dirs.iter() { if i >= self.scroll { - add(&TuiStyle::bold(name.as_str(), i == self.index))?; + add(&Tui::bold(i == self.index, name.as_str()))?; } i += 1; } for (_, name) in self.files.iter() { if i >= self.scroll { - add(&TuiStyle::bold(name.as_str(), i == self.index))?; + add(&Tui::bold(i == self.index, name.as_str()))?; } i += 1; } diff --git a/crates/tek/src/tui/view_phrase_editor.rs b/crates/tek/src/tui/view_phrase_editor.rs index 026f18d9..c18826e1 100644 --- a/crates/tek/src/tui/view_phrase_editor.rs +++ b/crates/tek/src/tui/view_phrase_editor.rs @@ -229,7 +229,7 @@ impl PhraseViewMode { let style = Some(Style::default().fg(Color::Rgb(192, 192, 192)).bg(Color::Rgb(0, 0, 0))); match self { Self::PianoHorizontal { .. } => { - let [x0, y0, _, h] = to.area().xywh(); + let [x0, y0, _, _] = to.area().xywh(); for (y, note) in (note_lo..=note_hi).rev().enumerate() { to.blit(&match note % 12 { 11 => "██", diff --git a/crates/tek/src/tui/view_phrase_length.rs b/crates/tek/src/tui/view_phrase_length.rs index 9af4aa64..79e0bee1 100644 --- a/crates/tek/src/tui/view_phrase_length.rs +++ b/crates/tek/src/tui/view_phrase_length.rs @@ -1,19 +1,19 @@ use crate::*; render!(|self:PhraseLength|{ - let bars = self.bars_string().as_str(); - let beats = self.beats_string().as_str(); - let ticks = self.ticks_string().as_str(); - Tui::reduce(match self.focus { + let bars = ||self.bars_string(); + let beats = ||self.beats_string(); + let ticks = ||self.ticks_string(); + row!(|add|(match self.focus { None => - [" ", bars, "B", beats, "b", ticks, "T"], + add(&row!(" ", bars(), "B", beats(), "b", ticks(), "T")), Some(PhraseLengthFocus::Bar) => - ["[", bars, "]", beats, "b", ticks, "T"], + add(&row!("[", bars(), "]", beats(), "b", ticks(), "T")), Some(PhraseLengthFocus::Beat) => - [" ", bars, "[", beats, "]", ticks, "T"], + add(&row!(" ", bars(), "[", beats(), "]", ticks(), "T")), Some(PhraseLengthFocus::Tick) => - [" ", bars, "B", beats, "[", ticks, "]"], - }.iter(), Tui::to_east) + add(&row!(" ", bars(), "B", beats(), "[", ticks(), "]")), + })) //Layers::new(move|add|{ //match self.focus { //None => add(&row!( diff --git a/crates/tek/src/tui/view_sequencer.rs b/crates/tek/src/tui/view_sequencer.rs index ae20af5b..80b16050 100644 --- a/crates/tek/src/tui/view_sequencer.rs +++ b/crates/tek/src/tui/view_sequencer.rs @@ -18,7 +18,7 @@ render!(|self: SequencerTui|{ TransportView::from(self), Tui::min_y( 20, - Tui::split_right( + Tui::to_east( 20, Tui::to_south( Tui::fixed_y(4, play), @@ -35,46 +35,39 @@ render!(|self: SequencerTui|{ }); render!(|self: SequencerStatusBar|{ + let orange = Color::Rgb(255,128,0); - let yellow = Color::Rgb(255,255,0); - let light = Color::Rgb(100,100,100); - let dark = Color::Rgb(100,100,100); - let black = Color::Rgb(0,0,0); - let modeline = Tui::to_east( - Tui::bg( - orange, - Tui::fg( - black, - Tui::bold( - true, - Tui::text(self.mode)))), - Tui::bg( - light, - Tui::reduce( - self.help.iter(), - |(prefix, hotkey, suffix)|Tui::reduce( - Tui::to_east, - [widget(&" "), widget(*prefix), widget(Tui::fg(yellow, *hotkey)), widget(*suffix)] - ), - ) + + let modeline = { + let light = Color::Rgb(100,100,100); + let yellow = Color::Rgb(255,255,0); + let black = Color::Rgb(0,0,0); + Tui::to_east( + Tui::bg(orange, Tui::fg(black, Tui::bold(true, self.mode))), + Tui::bg(light, row!((prefix, hotkey, suffix) in self.help.iter() => { + row!(" ", prefix, Tui::fg(yellow, *hotkey), suffix) + })) ) - ); - let statusbar = Tui::bg( - dark, - Tui::reduce( - Tui::to_east, - [ - Tui::fg(orange, widget(&self.cpu)), - Tui::fg(orange, widget(&self.res)), - Tui::fg(orange, widget(&self.size)), - ] - ) - ); - if self.width > 60 { - return Stack::Right(modeline, statusbar); - } - if self.width > 0 { - return Stack::Down(modeline, statusbar); - } - return Stack::None + }; + + let statusbar = { + let dark = Color::Rgb(100,100,100); + let cpu = &self.cpu; + let res = &self.res; + let size = &self.size; + Tui::bg(dark, row!( + Tui::fg(orange, cpu), + Tui::fg(orange, res), + Tui::fg(orange, size), + )) + }; + + lay!(|add|if self.width > 60 { + add(&row!(modeline, statusbar)) + } else if self.width > 0 { + add(&col!(modeline, statusbar)) + } else { + Ok(()) + }) + }); diff --git a/crates/tek/src/tui/view_status_bar.rs b/crates/tek/src/tui/view_status_bar.rs index 3c318918..5b919be9 100644 --- a/crates/tek/src/tui/view_status_bar.rs +++ b/crates/tek/src/tui/view_status_bar.rs @@ -10,11 +10,14 @@ pub trait StatusBar: Render { Self: Sized { let hotkey_fg = Self::hotkey_fg(); - Tui::reduce(commands.iter(), |prev, [a, b, c]| - Tui::to_east(prev, - Tui::to_east(a, - Tui::to_east(Tui::fg(hotkey_fg, Tui::bold(true, b)), - c)))) + row!([a, b, c] in commands.iter() => { + row!(a, Tui::fg(hotkey_fg, Tui::bold(true, b)), c) + }) + //Tui::reduce(commands.iter(), |prev, [a, b, c]| + //Tui::to_east(prev, + //Tui::to_east(a, + //Tui::to_east(Tui::fg(hotkey_fg, Tui::bold(true, b)), + //c)))) } fn with <'a> (state: &'a Self::State, content: impl Render) -> impl Render diff --git a/crates/tek/src/tui/view_transport.rs b/crates/tek/src/tui/view_transport.rs index 6d08ae13..59fbc597 100644 --- a/crates/tek/src/tui/view_transport.rs +++ b/crates/tek/src/tui/view_transport.rs @@ -21,7 +21,7 @@ pub struct TransportView { } render!(|self: TransportView|{ - let Self { state, selected, focused, bpm, sync, quant, beat, msu, } = self; + let Self { state, .. } = self;// selected, focused, bpm, sync, quant, beat, msu, } = self; let world = Tui::to_east("│World ", Tui::to_east(format!("│0 (0)"), //sample(chunk) Tui::to_east(format!("│00m00s000u"), /*msu*/ format!("│00B 0b 00/00"), /*bbt*/))); let timer = Tui::either(