implementing Fixed constraint

This commit is contained in:
🪞👃🪞 2024-09-12 20:19:07 +03:00
parent a57bb60ac9
commit 4b19abd98a
4 changed files with 66 additions and 10 deletions

View file

@ -385,6 +385,26 @@ impl<T> Align<T> {
}
}
/// Enforce fixed size of drawing area
pub enum Fixed<U: Number, T> {
/// Enforce fixed width
W(U, T),
/// Enforce fixed height
H(U, T),
/// Enforce fixed width and height
WH(U, U, T),
}
impl<N: Number, T> Fixed<N, T> {
pub fn inner (&self) -> &T {
match self {
Self::W(_, inner) => inner,
Self::H(_, inner) => inner,
Self::WH(_, _, inner) => inner,
}
}
}
/// Enforce minimum size of drawing area
pub enum Min<U: Number, T> {
/// Enforce minimum width

View file

@ -452,6 +452,31 @@ pub const NOT_DIM_BOLD: Style = Style {
sub_modifier: Modifier::DIM,
};
impl<T: Widget<Engine = Tui>> Widget for Fixed<u16, T> {
type Engine = Tui;
fn layout (&self, area: [u16;4]) -> Perhaps<[u16;4]> {
Ok(match self {
Self::W(w, item) => if area.w() < *w { None } else {
item.layout(area)?.map(|[x, y, _, h]|[x, y, *w, h])
},
Self::H(h, item) => if area.w() < *h { None } else {
item.layout(area)?.map(|[x, y, w, _]|[x, y, w, *h])
},
Self::WH(w, h, item) => if area.w() < *w || area.h() < *h { None } else {
item.layout(area)?.map(|[x, y, _, _]|[x, y, *w, *h])
}
})
}
fn render (&self, to: &mut Tui) -> Perhaps<[u16;4]> {
// 🡘 🡙 ←🡙→
if let Some(area) = self.layout(to.area())? {
to.render_in(area, self.inner())
} else {
Ok(None)
}
}
}
impl<F> Widget for Split<Tui, F>
where
F: Send + Sync + Fn(&mut dyn FnMut(&dyn Widget<Engine = Tui>)->Usually<()>)->Usually<()>

View file

@ -379,7 +379,7 @@ impl<'a, 'b> Content for ArrangerViewVertical<'a, 'b, Tui> {
add(&ColumnSeparators(offset, cols))?;
add(&RowSeparators(rows))?;
add(&CursorFocus(state.selected, offset, cols, rows))?;
add(&Split::right(|add|{
add(&Split::down(|add|{
add(&TracksHeader(offset, cols, tracks))?;
add(&SceneRows(offset, cols, rows, tracks, scenes))
}))
@ -496,7 +496,9 @@ impl<'a> Widget for CursorFocus<'a> {
}
}
struct TracksHeader<'a>(u16, &'a[(usize, usize)], &'a [Sequencer<Tui>]);
struct TracksHeader<'a>(
u16, &'a[(usize, usize)], &'a [Sequencer<Tui>]
);
impl<'a> Content for TracksHeader<'a> {
type Engine = Tui;
@ -514,22 +516,28 @@ impl<'a> Content for TracksHeader<'a> {
}
}
struct SceneRows<'a>(u16, &'a[(usize, usize)], &'a[(usize, usize)], &'a[Sequencer<Tui>], &'a[Scene]);
struct SceneRows<'a>(
u16, &'a[(usize, usize)], &'a[(usize, usize)], &'a[Sequencer<Tui>], &'a[Scene]
);
impl<'a> Content for SceneRows<'a> {
type Engine = Tui;
fn content (&self) -> impl Widget<Engine = Tui> {
let Self(offset, columns, rows, tracks, scenes) = *self;
Split::down(move |add| {
for (scene, (_pulses, _)) in scenes.iter().zip(rows) {
add(&SceneRow(tracks, scene, columns, offset))?;
for (scene, (pulses, _)) in scenes.iter().zip(rows) {
add(&Fixed::H(1.max((pulses / 96) as u16), SceneRow(
tracks, scene, columns, offset
)))?;
}
Ok(())
})
}
}
struct SceneRow<'a>(&'a[Sequencer<Tui>], &'a Scene, &'a[(usize, usize)], u16);
struct SceneRow<'a>(
&'a[Sequencer<Tui>], &'a Scene, &'a[(usize, usize)], u16
);
impl<'a> Content for SceneRow<'a> {
type Engine = Tui;
@ -538,8 +546,10 @@ impl<'a> Content for SceneRow<'a> {
let playing = scene.is_playing(tracks);
Split::right(move |add| {
add(&Layers::new(|add|{
add(&if playing { "" } else { " " })?;
add(&scene.name.read().unwrap().as_str())?;
add(&Split::right(|add|{
add(&if playing { "" } else { " " })?;
add(&scene.name.read().unwrap().as_str())
}))?;
add(&FillBg(COLOR_BG1))
}))?;
for (track, (_w, _x)) in columns.iter().enumerate() {

View file

@ -44,11 +44,12 @@ impl Content for Demo<Tui> {
add(&Align::Center("12345"))?;
add(&Align::Center("FOO"))
}))?;
add(&Layers::new(|add|{
add(&Fixed::H(10, Layers::new(|add|{
add(&FillBg(Color::Rgb(0,0,128)))?;
add(&Align::Center("1234567"))?;
add(&Align::Center("BAR"))
}))
})))?;
Ok(())
}))
}))
}