use crate::*;
/// A three-column layout.
pub(crate) struct Tryptich {
pub top: bool,
pub h: u16,
pub left: (u16, A),
pub middle: (u16, B),
pub right: (u16, C),
}
impl Tryptich<(), (), ()> {
pub fn center (h: u16) -> Self {
Self { h, top: false, left: (0, ()), middle: (0, ()), right: (0, ()) }
}
pub fn top (h: u16) -> Self {
Self { h, top: true, left: (0, ()), middle: (0, ()), right: (0, ()) }
}
}
impl Tryptich {
pub fn left (self, w: u16, content: D) -> Tryptich {
Tryptich { left: (w, content), ..self }
}
pub fn middle (self, w: u16, content: D) -> Tryptich {
Tryptich { middle: (w, content), ..self }
}
pub fn right (self, w: u16, content: D) -> Tryptich {
Tryptich { right: (w, content), ..self }
}
}
impl Content for Tryptich
where A: Content, B: Content, C: Content {
fn content (&self) -> impl Render {
let Self { top, h, left: (w_a, ref a), middle: (w_b, ref b), right: (w_c, ref c) } = *self;
Fixed::y(h, if top {
Bsp::a(
Fill::x(Align::n(Fixed::x(w_b, Align::x(Tui::bg(Reset, b))))),
Bsp::a(
Fill::x(Align::nw(Fixed::x(w_a, Tui::bg(Reset, a)))),
Fill::x(Align::ne(Fixed::x(w_c, Tui::bg(Reset, c)))),
),
)
} else {
Bsp::a(
Fill::xy(Align::c(Fixed::x(w_b, Align::x(Tui::bg(Reset, b))))),
Bsp::a(
Fill::xy(Align::w(Fixed::x(w_a, Tui::bg(Reset, a)))),
Fill::xy(Align::e(Fixed::x(w_c, Tui::bg(Reset, c)))),
),
)
})
}
}
pub(crate) fn wrap (
bg: Color, fg: Color, content: impl Content
) -> impl Content {
Bsp::e(Tui::fg_bg(bg, Reset, "▐"),
Bsp::w(Tui::fg_bg(bg, Reset, "▌"),
Tui::fg_bg(fg, bg, content)))
}
pub(crate) fn button_2 <'a, K, L> (
key: K, label: L, editing: bool,
) -> impl Content + 'a where
K: Content + 'a,
L: Content + 'a,
{
let key = Tui::fg_bg(Tui::g(0), Tui::orange(), Bsp::e(
Tui::fg_bg(Tui::orange(), Reset, "▐"),
Bsp::e(key, Tui::fg(Tui::g(96), "▐"))
));
let label = When::new(!editing, Tui::fg_bg(Tui::g(255), Tui::g(96), label));
Tui::bold(true, Bsp::e(key, label))
}
pub(crate) fn button_3 <'a, K, L, V> (
key: K,
label: L,
value: V,
editing: bool,
) -> impl Content + 'a where
K: Content + 'a,
L: Content + 'a,
V: Content + 'a,
{
let key = Tui::fg_bg(Tui::g(0), Tui::orange(),
Bsp::e(Tui::fg_bg(Tui::orange(), Reset, "▐"), Bsp::e(key, Tui::fg(if editing {
Tui::g(128)
} else {
Tui::g(96)
}, "▐"))));
let label = Bsp::e(
When::new(!editing, Bsp::e(
Tui::fg_bg(Tui::g(255), Tui::g(96), label),
Tui::fg_bg(Tui::g(128), Tui::g(96), "▐"),
)),
Bsp::e(
Tui::fg_bg(Tui::g(224), Tui::g(128), value),
Tui::fg_bg(Tui::g(128), Reset, "▌"),
));
Tui::bold(true, Bsp::e(key, label))
}
pub(crate) fn heading <'a> (
key: &'a str,
label: &'a str,
count: usize,
content: impl Content + Send + Sync + 'a,
editing: bool,
) -> impl Content + 'a {
let count = format!("{count}");
Fill::xy(Align::w(Bsp::s(Fill::x(Align::w(button_3(key, label, count, editing))), content)))
}
pub(crate) fn io_ports <'a, T: PortsSizes<'a>> (
fg: Color, bg: Color, iter: impl Fn()->T + Send + Sync + 'a
) -> impl Content + 'a {
Map::new(iter,
move|(index, name, connections, y, y2), _|map_south(y as u16, (y2-y) as u16, Bsp::s(
Fill::x(Tui::bold(true, Tui::fg_bg(fg, bg, Align::w(Bsp::e(" ", name))))),
Map::new(||connections.iter(), move|connect, index|map_south(index as u16, 1,
Fill::x(Align::w(Tui::bold(false, Tui::fg_bg(fg, bg,
&connect.info)))))))))
}
pub(crate) fn io_conns <'a, T: PortsSizes<'a>> (
fg: Color, bg: Color, iter: impl Fn()->T + Send + Sync + 'a
) -> impl Content + 'a {
Map::new(iter,
move|(index, name, connections, y, y2), _|map_south(y as u16, (y2-y) as u16, Bsp::s(
Fill::x(Tui::bold(true, wrap(bg, fg, Fill::x(Align::w("▞▞▞▞ ▞▞▞▞"))))),
Map::new(||connections.iter(), move|connect, index|map_south(index as u16, 1,
Fill::x(Align::w(Tui::bold(false, wrap(bg, fg, Fill::x(""))))))))))
}
pub(crate) fn per_track_top <'a, T: Content + 'a, U: TracksSizes<'a>> (
width: u16,
tracks: impl Fn() -> U + Send + Sync + 'a,
callback: impl Fn(usize, &'a Track)->T + Send + Sync + 'a
) -> impl Content + 'a {
Align::x(Tui::bg(Reset, Map::new(tracks, move|(index, track, x1, x2), _|{
let width = (x2 - x1) as u16;
map_east(x1 as u16, width, Fixed::x(width, Tui::fg_bg(
track.color.lightest.rgb,
track.color.base.rgb,
callback(index, track)
)))
})))
}
pub(crate) fn per_track <'a, T: Content + 'a, U: TracksSizes<'a>> (
width: u16,
tracks: impl Fn() -> U + Send + Sync + 'a,
callback: impl Fn(usize, &'a Track)->T + Send + Sync + 'a
) -> impl Content + 'a {
per_track_top(
width,
tracks,
move|index, track|Fill::y(Align::y(callback(index, track)))
)
}
#[cfg(test)] mod test {
use super::*;
#[test] fn test_view () {
let _ = button_2("", "", true);
let _ = button_2("", "", false);
let _ = button_3("", "", "", true);
let _ = button_3("", "", "", false);
let _ = heading("", "", 0, "", true);
let _ = heading("", "", 0, "", false);
let _ = wrap(Reset, Reset, "");
}
}