Tui::fixed_ -> Fixed::w/h/wh

This commit is contained in:
🪞👃🪞 2024-12-17 19:26:16 +01:00
parent 9bd898ab33
commit da39c84ba4
9 changed files with 49 additions and 35 deletions

View file

@ -1,21 +1,7 @@
use crate::*;
impl<E: Engine> LayoutFixed<E> for E {}
pub trait LayoutFixed<E: Engine> {
fn fixed_x <W: Render<E>> (x: E::Unit, w: W) -> Fixed<E, W> {
Fixed::X(x, w)
}
fn fixed_y <W: Render<E>> (y: E::Unit, w: W) -> Fixed<E, W> {
Fixed::Y(y, w)
}
fn fixed_xy <W: Render<E>> (x: E::Unit, y: E::Unit, w: W) -> Fixed<E, W> {
Fixed::XY(x, y, w)
}
}
/// Enforce fixed size of drawing area
pub enum Fixed<E: Engine, T> {
pub enum Fixed<E: Engine, T: Render<E>> {
_Unused(PhantomData<E>),
/// Enforce fixed width
X(E::Unit, T),
@ -25,7 +11,7 @@ pub enum Fixed<E: Engine, T> {
XY(E::Unit, E::Unit, T),
}
impl<E: Engine, T> Fixed<E, T> {
impl<E: Engine, T: Render<E>> Fixed<E, T> {
pub fn inner (&self) -> &T {
match self {
Self::X(_, i) => i,
@ -34,7 +20,17 @@ impl<E: Engine, T> Fixed<E, T> {
_ => unreachable!(),
}
}
pub fn w (x: E::Unit, w: T) -> Fixed<E, T> {
Self::X(x, w)
}
pub fn h (y: E::Unit, w: T) -> Fixed<E, T> {
Self::Y(y, w)
}
pub fn wh (x: E::Unit, y: E::Unit, w: T) -> Fixed<E, T> {
Self::XY(x, y, w)
}
}
impl<E: Engine, T: Render<E>> Render<E> for Fixed<E, T> {
fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
Ok(match self {

View file

@ -80,7 +80,7 @@ render!(|self: ArrangerTui|{
add(&self.size)
})));
with_transport(col!([
Tui::fixed_y(self.splits[0], lay!([
Fixed::h(self.splits[0], lay!([
arranger(),
Tui::push_x(1, Tui::fg(
TuiTheme::title_fg(arranger_focused),
@ -877,16 +877,16 @@ impl<'a> From<(&'a ArrangerTui, usize)> for ArrangerVerticalContent<'a> {
}
}
}
render!(|self: ArrangerVerticalContent<'a>|Tui::fixed_y(
render!(|self: ArrangerVerticalContent<'a>|Fixed::h(
(self.size.h() as u16).saturating_sub(self.header_h),
col!((scene, pulses) in self.scenes.iter().zip(self.rows.iter().map(|row|row.0)) => {
let height = 1.max((pulses / PPQ) as u16);
let playing = scene.is_playing(self.tracks);
Tui::fixed_y(height, row!([
Fixed::h(height, row!([
if playing { "" } else { " " },
Tui::bold(true, scene.name.read().unwrap().as_str()),
row!((track, w) in self.cols.iter().map(|col|col.0).enumerate() => {
Tui::fixed_xy(w as u16, height, Layers::new(move |add|{
Fixed::wh(w as u16, height, Layers::new(move |add|{
let mut bg = TuiTheme::border_bg();
match (self.tracks.get(track), scene.clips.get(track)) {
(Some(track), Some(Some(phrase))) => {
@ -900,7 +900,7 @@ render!(|self: ArrangerVerticalContent<'a>|Tui::fixed_y(
bg = color.light.rgb
}
};
add(&Tui::fixed_x(w as u16, Tui::push_x(1, &name.as_str()[0..max_w])))?;
add(&Fixed::w(w as u16, Tui::push_x(1, &name.as_str()[0..max_w])))?;
},
_ => {}
};

View file

@ -26,7 +26,10 @@ pub enum GrooveboxCommand {
Sampler(SamplerCommand),
}
render!(|self:GrooveboxTui|Bsp::s(Tui::fixed_y(self.split, &self.sequencer), &self.sampler));
render!(|self:GrooveboxTui|Bsp::n(
Fixed::h(2, SequencerStatusBar::from(&self.sequencer)),
Bsp::s(Fixed::h(self.split, &self.sequencer), &self.sampler),
));
audio!(|self:GrooveboxTui,_client,_process|Control::Continue);
handle!(<Tui>|self:GrooveboxTui,input|GrooveboxCommand::execute_with_state(self, input));
input_to_command!(GrooveboxCommand: <Tui>|state:GrooveboxTui,input|match input.event() {
@ -34,4 +37,9 @@ input_to_command!(GrooveboxCommand: <Tui>|state:GrooveboxTui,input|match input.e
key_pat!(Char('l')) => GrooveboxCommand::Sampler(SamplerCommand::Import),
_ => GrooveboxCommand::Sequencer(SequencerCommand::input_to_command(&state.sequencer, input)?),
});
command!(|self:GrooveboxCommand,state:GrooveboxTui|todo!());
command!(|self:GrooveboxCommand,state:GrooveboxTui|match self {
GrooveboxCommand::Sequencer(command) =>
command.execute(&mut state.sequencer)?.map(GrooveboxCommand::Sequencer),
GrooveboxCommand::Sampler(command) =>
command.execute(&mut state.sampler)?.map(GrooveboxCommand::Sampler),
});

View file

@ -11,6 +11,16 @@ use symphonia::default::get_codecs;
pub enum SamplerCommand {
Import
}
input_to_command!(SamplerCommand: <Tui>|state:SamplerTui,input|match input.event() {
_ => return None
});
command!(|self:SamplerCommand,state:SamplerTui|match self {
SamplerCommand::Import => {
None
},
_ => todo!()
});
impl TryFrom<&Arc<RwLock<JackClient>>> for SamplerTui {
type Error = Box<dyn std::error::Error>;

View file

@ -148,8 +148,8 @@ render!(|self: SequencerTui|{
let with_size = |x|lay!([self.size, x]);
let editor = with_editbar(with_pool(Tui::fill_xy(&self.editor)));
let color = self.player.play_phrase().as_ref().map(|(_,p)|p.as_ref().map(|p|p.read().unwrap().color)).flatten().clone();
let play = Tui::fixed_xy(5, 2, PlayPause(self.clock.is_rolling()));
let transport = Tui::fixed_y(2, TransportView::from((self, color, true)));
let play = Fixed::wh(5, 2, PlayPause(self.clock.is_rolling()));
let transport = Fixed::h(2, TransportView::from((self, color, true)));
let toolbar = row!([play, col!([
PhraseSelector::play_phrase(&self.player),
PhraseSelector::next_phrase(&self.player),
@ -225,7 +225,7 @@ impl From<&SequencerTui> for SequencerStatusBar {
}
}
render!(|self: SequencerStatusBar|Tui::fixed_y(2, lay!([
render!(|self: SequencerStatusBar|Fixed::h(2, lay!([
{
let single = |binding, command|row!([" ", col!([
Tui::fg(TuiTheme::yellow(), binding),

View file

@ -126,7 +126,7 @@ render!(|self: TransportView|{
pub struct PlayPause(pub bool);
render!(|self: PlayPause|Tui::bg(
if self.0{Color::Rgb(0,128,0)}else{Color::Rgb(128,64,0)},
Tui::fixed_x(5, col!(|add|if self.0 {
Fixed::w(5, col!(|add|if self.0 {
add(&Tui::fg(Color::Rgb(0, 255, 0), col!([
" 🭍🭑🬽 ",
" 🭞🭜🭘 ",

View file

@ -245,12 +245,12 @@ render!(|self:PhraseEditStatus<'a>|row!(|add|{
&y
]);
add(&Tui::fill_x(Tui::fg_bg(fg, bg, row!(|add|{
add(&Tui::fixed_xy(26, 3, col!(![
add(&Fixed::wh(26, 3, col!(![
field(" Edit", format!("{name}")),
field(" Length", format!("{length}")),
field(" Loop", format!("{looped}")),
])))?;
add(&Tui::fixed_xy(25, 3, col!(![
add(&Fixed::wh(25, 3, col!(![
field(" Time", format!("{}",
self.0.time_point())),
field(" View", format!("{}-{} ({}*{})",
@ -259,7 +259,7 @@ render!(|self:PhraseEditStatus<'a>|row!(|add|{
self.0.time_axis(),
self.0.time_zoom()))
])))?;
add(&Tui::fixed_xy(25, 3, col!(![
add(&Fixed::wh(25, 3, col!(![
field(" Note", format!("{:4} ({:3}) {:4}",
to_note_name(self.0.note_point()),
self.0.note_point(),
@ -269,7 +269,7 @@ render!(|self:PhraseEditStatus<'a>|row!(|add|{
to_note_name(self.0.note_hi()),
self.0.note_axis()))
])))?;
add(&Tui::fixed_xy(16, 3, col!(![
add(&Fixed::wh(16, 3, col!(![
row!(!["TimeLock ", Tui::bold(true, format!("{}", self.0.time_lock()))])])))?;
Ok(())
}))))

View file

@ -263,7 +263,7 @@ pub struct PhraseSelector {
}
// TODO: Display phrases always in order of appearance
render!(|self: PhraseSelector|Tui::fixed_xy(24, 1, row!([
render!(|self: PhraseSelector|Fixed::wh(24, 1, row!([
Tui::fg(self.color.lightest.rgb, Tui::bold(true, &self.title)),
Tui::fg_bg(self.color.lighter.rgb, self.color.base.rgb, row!([
format!("{:8}", &self.name[0..8.min(self.name.len())]),

View file

@ -68,12 +68,12 @@ render!(|self: PianoHorizontal|{
let keys_width = 5;
Tui::fill_xy(Tui::bg(color.darker.rgb,
Bsp::s(
Tui::fixed_y(1, Bsp::e(
Tui::fixed_x(keys_width, ""),
Fixed::h(1, Bsp::e(
Fixed::w(keys_width, ""),
Tui::fill_x(timeline()),
)),
Bsp::e(
Tui::fixed_x(keys_width, keys()),
Fixed::w(keys_width, keys()),
Tui::fill_xy(lay!([&self.size, Tui::fill_xy(lay!([
Tui::fill_xy(notes()),
Tui::fill_xy(cursor()),