mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-07 04:06:45 +01:00
move containers to space 🪐
This commit is contained in:
parent
2073bb541d
commit
35b37e3e3a
3 changed files with 514 additions and 520 deletions
|
|
@ -288,448 +288,6 @@ pub fn handle_keymap <T> (
|
|||
}
|
||||
}
|
||||
|
||||
pub struct Split<
|
||||
E: Engine,
|
||||
F: Send + Sync + Fn(&mut dyn FnMut(&dyn Widget<Engine = E>)->Usually<()>)->Usually<()>
|
||||
>(pub F, pub Direction, PhantomData<E>);
|
||||
|
||||
impl<
|
||||
E: Engine,
|
||||
F: Send + Sync + Fn(&mut dyn FnMut(&dyn Widget<Engine = E>)->Usually<()>)->Usually<()>
|
||||
> Split<E, F> {
|
||||
#[inline]
|
||||
pub fn new (direction: Direction, build: F) -> Self {
|
||||
Self(build, direction, Default::default())
|
||||
}
|
||||
#[inline]
|
||||
pub fn right (build: F) -> Self {
|
||||
Self::new(Direction::Right, build)
|
||||
}
|
||||
#[inline]
|
||||
pub fn down (build: F) -> Self {
|
||||
Self::new(Direction::Down, build)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Layers<
|
||||
E: Engine,
|
||||
F: Send + Sync + Fn(&mut dyn FnMut(&dyn Widget<Engine = E>)->Usually<()>)->Usually<()>
|
||||
>(pub F, PhantomData<E>);
|
||||
|
||||
impl<
|
||||
E: Engine,
|
||||
F: Send + Sync + Fn(&mut dyn FnMut(&dyn Widget<Engine = E>)->Usually<()>)->Usually<()>
|
||||
> Layers<E, F> {
|
||||
#[inline]
|
||||
pub fn new (build: F) -> Self {
|
||||
Self(build, Default::default())
|
||||
}
|
||||
}
|
||||
|
||||
//pub fn collect <'a, E: Engine, const N: usize> (
|
||||
//items: &'a [&'a dyn Widget<Engine = E>;N]
|
||||
//) -> impl Send + Sync + Fn(&'a mut dyn FnMut(&'a dyn Widget<Engine = E>)->Usually<()>)->Usually<()> + '_ {
|
||||
//|add: &'a mut dyn FnMut(&'a dyn Widget<Engine = E>)->Usually<()>| {
|
||||
//for item in items.iter() {
|
||||
//add(item)?;
|
||||
//}
|
||||
//Ok(())
|
||||
//}
|
||||
//}
|
||||
|
||||
//`Layers<_, impl (Fn(&mut dyn FnMut(&dyn Widget<Engine = _>) -> Result<(), Box<...>>) -> ... ) + Send + Sync>`
|
||||
//`Layers<Tui, impl (Fn(&mut dyn FnMut(&dyn Widget<Engine = Tui>) -> Result<(), Box<(dyn std::error::Error + 'static)>>) -> Result<(), Box<(dyn std::error::Error + 'static)>>) + Send + Sync + '_>`
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub enum Direction {
|
||||
Up,
|
||||
Down,
|
||||
Left,
|
||||
Right,
|
||||
}
|
||||
|
||||
impl Direction {
|
||||
pub fn is_down (&self) -> bool {
|
||||
match self { Self::Down => true, _ => false }
|
||||
}
|
||||
pub fn is_right (&self) -> bool {
|
||||
match self { Self::Right => true, _ => false }
|
||||
}
|
||||
}
|
||||
|
||||
/// Override X and Y coordinates, aligning to corner, side, or center of area
|
||||
pub enum Align<L> {
|
||||
/// Draw at center of container
|
||||
Center(L),
|
||||
/// Draw at center of X axis
|
||||
X(L),
|
||||
/// Draw at center of Y axis
|
||||
Y(L),
|
||||
/// Draw at upper left corner of contaier
|
||||
NW(L),
|
||||
/// Draw at center of upper edge of container
|
||||
N(L),
|
||||
/// Draw at right left corner of contaier
|
||||
NE(L),
|
||||
/// Draw at center of left edge of container
|
||||
W(L),
|
||||
/// Draw at center of right edge of container
|
||||
E(L),
|
||||
/// Draw at lower left corner of container
|
||||
SW(L),
|
||||
/// Draw at center of lower edge of container
|
||||
S(L),
|
||||
/// Draw at lower right edge of container
|
||||
SE(L)
|
||||
}
|
||||
|
||||
impl<T> Align<T> {
|
||||
pub fn inner (&self) -> &T {
|
||||
match self {
|
||||
Self::Center(inner) => inner,
|
||||
Self::X(inner) => inner,
|
||||
Self::Y(inner) => inner,
|
||||
Self::NW(inner) => inner,
|
||||
Self::N(inner) => inner,
|
||||
Self::NE(inner) => inner,
|
||||
Self::W(inner) => inner,
|
||||
Self::E(inner) => inner,
|
||||
Self::SW(inner) => inner,
|
||||
Self::S(inner) => inner,
|
||||
Self::SE(inner) => inner,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn align<T, N: Number, R: Area<N> + From<[N;4]>> (align: &Align<T>, outer: R, inner: R) -> Option<R> {
|
||||
if outer.w() < inner.w() || outer.h() < inner.h() {
|
||||
None
|
||||
} else {
|
||||
let [ox, oy, ow, oh] = outer.xywh();
|
||||
let [ix, iy, iw, ih] = inner.xywh();
|
||||
Some(match align {
|
||||
Align::Center(_) => [ox + (ow - iw) / 2.into(), oy + (oh - ih) / 2.into(), iw, ih,].into(),
|
||||
Align::X(_) => [ox + (ow - iw) / 2.into(), iy, iw, ih,].into(),
|
||||
Align::Y(_) => [ix, oy + (oh - ih) / 2.into(), iw, ih,].into(),
|
||||
Align::NW(_) => [ox, oy, iw, ih,].into(),
|
||||
Align::N(_) => [ox + (ow - iw) / 2.into(), oy, iw, ih,].into(),
|
||||
Align::NE(_) => [ox + ow - iw, oy, iw, ih,].into(),
|
||||
Align::W(_) => [ox, oy + (oh - ih) / 2.into(), iw, ih,].into(),
|
||||
Align::E(_) => [ox + ow - iw, oy + (oh - ih) / 2.into(), iw, ih,].into(),
|
||||
Align::SW(_) => [ox, oy + oh - ih, iw, ih,].into(),
|
||||
Align::S(_) => [ox + (ow - iw) / 2.into(), oy + oh - ih, iw, ih,].into(),
|
||||
Align::SE(_) => [ox + ow - iw, oy + oh - ih, iw, ih,].into(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Engine, T: Widget<Engine = E>> Widget for Align<T> {
|
||||
type Engine = E;
|
||||
fn layout (&self, outer_area: E::Size) -> Perhaps<E::Size> {
|
||||
self.inner().layout(outer_area)
|
||||
}
|
||||
fn render (&self, to: &mut E::Output) -> Usually<()> {
|
||||
let outer_area = to.area();
|
||||
Ok(if let Some(inner_size) = self.layout(outer_area.wh().into())? {
|
||||
let inner_area = outer_area.clip(inner_size);
|
||||
if let Some(aligned) = align(&self, outer_area.into(), inner_area.into()) {
|
||||
to.render_in(aligned, self.inner())?
|
||||
} else {
|
||||
()
|
||||
}
|
||||
} else {
|
||||
()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Enforce fixed size of drawing area
|
||||
pub enum Fixed<U: Number, T> {
|
||||
/// Enforce fixed width
|
||||
X(U, T),
|
||||
/// Enforce fixed height
|
||||
Y(U, T),
|
||||
/// Enforce fixed width and height
|
||||
XY(U, U, T),
|
||||
}
|
||||
|
||||
impl<N: Number, T> Fixed<N, T> {
|
||||
pub fn inner (&self) -> &T {
|
||||
match self { Self::X(_, i) => i, Self::Y(_, i) => i, Self::XY(_, _, i) => i, }
|
||||
}
|
||||
}
|
||||
|
||||
/// Enforce minimum size of drawing area
|
||||
pub enum Min<U: Number, T> {
|
||||
/// Enforce minimum width
|
||||
X(U, T),
|
||||
/// Enforce minimum height
|
||||
Y(U, T),
|
||||
/// Enforce minimum width and height
|
||||
XY(U, U, T),
|
||||
}
|
||||
impl<N: Number, T> Min<N, T> {
|
||||
pub fn inner (&self) -> &T {
|
||||
match self { Self::X(_, i) => i, Self::Y(_, i) => i, Self::XY(_, _, i) => i, }
|
||||
}
|
||||
}
|
||||
impl<E: Engine, T: Widget<Engine = E>> Widget for Min<E::Unit, T> {
|
||||
type Engine = E;
|
||||
fn layout (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||
Ok(self.inner().layout(to)?.map(|to|match *self {
|
||||
Self::X(w, _) => [to.w().max(w), to.h()],
|
||||
Self::Y(h, _) => [to.w(), to.h().max(h)],
|
||||
Self::XY(w, h, _) => [to.w().max(w), to.h().max(h)],
|
||||
}.into()))
|
||||
}
|
||||
// TODO: 🡘 🡙 ←🡙→
|
||||
fn render (&self, to: &mut E::Output) -> Usually<()> {
|
||||
Ok(self.layout(to.area().wh().into())?
|
||||
.map(|size|to.render_in(to.area().clip(size).into(), self.inner()))
|
||||
.transpose()?.unwrap_or(()))
|
||||
}
|
||||
}
|
||||
|
||||
/// Enforce maximum size of drawing area
|
||||
pub enum Max<U: Number, T> {
|
||||
/// Enforce maximum width
|
||||
X(U, T),
|
||||
/// Enforce maximum height
|
||||
Y(U, T),
|
||||
/// Enforce maximum width and height
|
||||
XY(U, U, T),
|
||||
}
|
||||
|
||||
impl<N: Number, T> Max<N, T> {
|
||||
fn inner (&self) -> &T {
|
||||
match self { Self::X(_, i) => i, Self::Y(_, i) => i, Self::XY(_, _, i) => i, }
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Engine, T: Widget<Engine = E>> Widget for Max<E:: Unit, T> {
|
||||
type Engine = E;
|
||||
fn layout (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||
Ok(self.inner().layout(to)?.map(|to|match *self {
|
||||
Self::X(w, _) => [to.w().min(w), to.h()],
|
||||
Self::Y(h, _) => [to.w(), to.h().min(h)],
|
||||
Self::XY(w, h, _) => [to.w().min(w), to.h().min(h)],
|
||||
}.into()))
|
||||
}
|
||||
fn render (&self, to: &mut E::Output) -> Usually<()> {
|
||||
Ok(self.layout(to.area().wh().into())?
|
||||
.map(|size|to.render_in(to.area().clip(size).into(), self.inner()))
|
||||
.transpose()?.unwrap_or(()))
|
||||
}
|
||||
}
|
||||
|
||||
/// Expand drawing area
|
||||
pub enum Grow<N: Number, T> {
|
||||
/// Increase width
|
||||
X(N, T),
|
||||
/// Increase height
|
||||
Y(N, T),
|
||||
/// Increase width and height
|
||||
XY(N, N, T)
|
||||
}
|
||||
|
||||
impl<N: Number, T> Grow<N, T> {
|
||||
fn inner (&self) -> &T {
|
||||
match self { Self::X(_, i) => i, Self::Y(_, i) => i, Self::XY(_, _, i) => i, }
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Engine, T: Widget<Engine = E>> Widget for Grow<E::Unit, T> {
|
||||
type Engine = E;
|
||||
fn layout (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||
Ok(self.inner().layout(to)?.map(|to|match *self {
|
||||
Self::X(w, _) => [to.w() + w, to.h()],
|
||||
Self::Y(h, _) => [to.w(), to.h() + h],
|
||||
Self::XY(w, h, _) => [to.w() + w, to.h() + h],
|
||||
}.into()))
|
||||
}
|
||||
fn render (&self, to: &mut E::Output) -> Usually<()> {
|
||||
Ok(self.layout(to.area().wh().into())?
|
||||
.map(|size|to.render_in(to.area().clip(size).into(), self.inner()))
|
||||
.transpose()?.unwrap_or(()))
|
||||
}
|
||||
}
|
||||
|
||||
/// Shrink drawing area
|
||||
pub enum Shrink<N: Number, T> {
|
||||
/// Decrease width
|
||||
X(N, T),
|
||||
/// Decrease height
|
||||
Y(N, T),
|
||||
/// Decrease width and height
|
||||
XY(N, N, T),
|
||||
}
|
||||
|
||||
impl<N: Number, T: Widget> Shrink<N, T> {
|
||||
fn inner (&self) -> &T {
|
||||
match self { Self::X(_, i) => i, Self::Y(_, i) => i, Self::XY(_, _, i) => i, }
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Engine, T: Widget<Engine = E>> Widget for Shrink<E::Unit, T> {
|
||||
type Engine = E;
|
||||
fn layout (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||
Ok(self.inner().layout(to)?.map(|to|match *self {
|
||||
Self::X(w, _) => [to.w() - w, to.h()],
|
||||
Self::Y(h, _) => [to.w(), to.h() - h],
|
||||
Self::XY(w, h, _) => [to.w() - w, to.h() - h]
|
||||
}.into()))
|
||||
}
|
||||
fn render (&self, to: &mut E::Output) -> Usually<()> {
|
||||
Ok(self.layout(to.area().wh().into())?
|
||||
.map(|size|to.render_in(to.area().clip(size).into(), self.inner()))
|
||||
.transpose()?.unwrap_or(()))
|
||||
}
|
||||
}
|
||||
|
||||
/// Shrink from each side
|
||||
pub enum Inset<N: Number, T> {
|
||||
/// Decrease width
|
||||
X(N, T),
|
||||
/// Decrease height
|
||||
Y(N, T),
|
||||
/// Decrease width and height
|
||||
XY(N, N, T),
|
||||
}
|
||||
|
||||
impl<N: Number, T: Widget> Inset<N, T> {
|
||||
pub fn inner (&self) -> &T {
|
||||
match self { Self::X(_, i) => i, Self::Y(_, i) => i, Self::XY(_, _, i) => i, }
|
||||
}
|
||||
}
|
||||
|
||||
/// Grow on each side
|
||||
pub enum Outset<N: Number, T> {
|
||||
/// Increase width
|
||||
X(N, T),
|
||||
/// Increase height
|
||||
Y(N, T),
|
||||
/// Increase width and height
|
||||
XY(N, N, T),
|
||||
}
|
||||
|
||||
impl<N: Number, T: Widget> Outset<N, T> {
|
||||
pub fn inner (&self) -> &T {
|
||||
match self { Self::X(_, i) => i, Self::Y(_, i) => i, Self::XY(_, _, i) => i, }
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Engine, T: Widget<Engine = E>> Widget for Inset<E::Unit, T> {
|
||||
type Engine = E;
|
||||
fn layout (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||
match *self {
|
||||
Self::X(x, ref inner) => Shrink::X(x + x, inner as &dyn Widget<Engine = E>),
|
||||
Self::Y(y, ref inner) => Shrink::Y(y + y, inner as &dyn Widget<Engine = E>),
|
||||
Self::XY(x, y, ref inner) => Shrink::XY(x + x, y + y, inner as &dyn Widget<Engine = E>),
|
||||
}.layout(to)
|
||||
}
|
||||
fn render (&self, to: &mut E::Output) -> Usually<()> {
|
||||
match *self {
|
||||
Self::X(x, ref inner) => Plus::X(x, inner as &dyn Widget<Engine = E>),
|
||||
Self::Y(y, ref inner) => Plus::Y(y, inner as &dyn Widget<Engine = E>),
|
||||
Self::XY(x, y, ref inner) => Plus::XY(x, y, inner as &dyn Widget<Engine = E>),
|
||||
}.render(to)
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Engine, T: Widget<Engine = E>> Widget for Outset<E::Unit, T> {
|
||||
type Engine = E;
|
||||
fn layout (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||
match *self {
|
||||
Self::X(x, ref inner) => Grow::X(x + x, inner as &dyn Widget<Engine = E>),
|
||||
Self::Y(y, ref inner) => Grow::Y(y + y, inner as &dyn Widget<Engine = E>),
|
||||
Self::XY(x, y, ref inner) => Grow::XY(x + x, y + y, inner as &dyn Widget<Engine = E>),
|
||||
}.layout(to)
|
||||
}
|
||||
fn render (&self, to: &mut E::Output) -> Usually<()> {
|
||||
match *self {
|
||||
Self::X(x, ref inner) => Plus::X(x, inner as &dyn Widget<Engine = E>),
|
||||
Self::Y(y, ref inner) => Plus::Y(y, inner as &dyn Widget<Engine = E>),
|
||||
Self::XY(x, y, ref inner) => Plus::XY(x, y, inner as &dyn Widget<Engine = E>),
|
||||
}.render(to)
|
||||
}
|
||||
}
|
||||
|
||||
/// Move origin point of drawing area
|
||||
pub enum Plus<N: Number, T: Widget> {
|
||||
/// Move origin to the right
|
||||
X(N, T),
|
||||
/// Move origin downwards
|
||||
Y(N, T),
|
||||
/// Move origin to the right and downwards
|
||||
XY(N, N, T),
|
||||
}
|
||||
|
||||
impl<N: Number, T: Widget> Plus<N, T> {
|
||||
fn inner (&self) -> &T {
|
||||
match self { Self::X(_, i) => i, Self::Y(_, i) => i, Self::XY(_, _, i) => i, }
|
||||
}
|
||||
fn x (&self) -> N {
|
||||
match self { Self::X(x, _) => *x, Self::Y(_, _) => N::default(), Self::XY(x, _, _) => *x }
|
||||
}
|
||||
fn y (&self) -> N {
|
||||
match self { Self::X(_, _) => N::default(), Self::Y(y, _) => *y, Self::XY(_, y, _) => *y }
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Engine, T: Widget<Engine = E>> Widget for Plus<E::Unit, T> {
|
||||
type Engine = E;
|
||||
fn layout (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||
self.inner().layout(to)
|
||||
}
|
||||
fn render (&self, to: &mut E::Output) -> Usually<()> {
|
||||
let area = to.area();
|
||||
Ok(self.layout(area.wh().into())?
|
||||
.map(|size|to.render_in(match *self {
|
||||
Self::X(x, _) => [area.x() + x, area.y(), size.w(), size.h()],
|
||||
Self::Y(y, _) => [area.x(), area.y() + y, size.w(), size.h()],
|
||||
Self::XY(x, y, _) => [area.x() + x, area.y() + y, size.w(), size.h()],
|
||||
}.into(), self.inner())).transpose()?.unwrap_or(()))
|
||||
}
|
||||
}
|
||||
|
||||
/// Move origin point of drawing area
|
||||
pub enum Minus<N: Number, T: Widget> {
|
||||
/// Move origin to the right
|
||||
X(N, T),
|
||||
/// Move origin downwards
|
||||
Y(N, T),
|
||||
/// Move origin to the right and downwards
|
||||
XY(N, N, T),
|
||||
}
|
||||
|
||||
impl<N: Number, T: Widget> Minus<N, T> {
|
||||
fn inner (&self) -> &T {
|
||||
match self { Self::X(_, i) => i, Self::Y(_, i) => i, Self::XY(_, _, i) => i, }
|
||||
}
|
||||
fn x (&self) -> N {
|
||||
match self { Self::X(x, _) => *x, Self::Y(_, _) => N::default(), Self::XY(x, _, _) => *x }
|
||||
}
|
||||
fn y (&self) -> N {
|
||||
match self { Self::X(_, _) => N::default(), Self::Y(y, _) => *y, Self::XY(_, y, _) => *y }
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Engine, T: Widget<Engine = E>> Widget for Minus<E::Unit, T> {
|
||||
type Engine = E;
|
||||
fn layout (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||
self.inner().layout(to)
|
||||
}
|
||||
fn render (&self, to: &mut E::Output) -> Usually<()> {
|
||||
let area = to.area();
|
||||
Ok(self.layout(area.wh().into())?
|
||||
.map(|size|to.render_in(match *self {
|
||||
Self::X(x, _) => [area.x().minus(x), area.y(), size.w(), size.h()],
|
||||
Self::Y(y, _) => [area.x(), area.y().minus(y), size.w(), size.h()],
|
||||
Self::XY(x, y, _) => [area.x().minus(x), area.y().minus(y), size.w(), size.h()],
|
||||
}.into(), self.inner())).transpose()?.unwrap_or(()))
|
||||
}
|
||||
}
|
||||
|
||||
/// A component that may contain [Focusable] components.
|
||||
pub trait Focus <const N: usize, E: Engine>: Widget<Engine = E> + Handle<E> {
|
||||
fn focus (&self) -> usize;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,43 @@
|
|||
use crate::*;
|
||||
|
||||
macro_rules! impl_axis_common { ($A:ident $T:ty) => {
|
||||
impl $A<$T> {
|
||||
pub fn start_inc (&mut self) -> $T {
|
||||
self.start += 1;
|
||||
self.start
|
||||
}
|
||||
pub fn start_dec (&mut self) -> $T {
|
||||
self.start = self.start.saturating_sub(1);
|
||||
self.start
|
||||
}
|
||||
pub fn point_inc (&mut self) -> Option<$T> {
|
||||
self.point = self.point.map(|p|p + 1);
|
||||
self.point
|
||||
}
|
||||
pub fn point_dec (&mut self) -> Option<$T> {
|
||||
self.point = self.point.map(|p|p.saturating_sub(1));
|
||||
self.point
|
||||
}
|
||||
}
|
||||
} }
|
||||
|
||||
pub struct FixedAxis<T> {
|
||||
pub start: T,
|
||||
pub point: Option<T>
|
||||
}
|
||||
|
||||
impl_axis_common!(FixedAxis u16);
|
||||
impl_axis_common!(FixedAxis usize);
|
||||
|
||||
pub struct ScaledAxis<T> {
|
||||
pub start: T,
|
||||
pub scale: T,
|
||||
pub point: Option<T>
|
||||
}
|
||||
|
||||
impl_axis_common!(ScaledAxis u16);
|
||||
impl_axis_common!(ScaledAxis usize);
|
||||
|
||||
// TODO: return impl Point and impl Size instead of [N;x]
|
||||
// to disambiguate between usage of 2-"tuple"s
|
||||
|
||||
|
|
@ -69,46 +107,444 @@ impl<N: Number> Area<N> for [N;4] {
|
|||
#[inline] fn h (&self) -> N { self[3] }
|
||||
}
|
||||
|
||||
macro_rules! impl_axis_common { ($A:ident $T:ty) => {
|
||||
impl $A<$T> {
|
||||
pub fn start_inc (&mut self) -> $T {
|
||||
self.start += 1;
|
||||
self.start
|
||||
}
|
||||
pub fn start_dec (&mut self) -> $T {
|
||||
self.start = self.start.saturating_sub(1);
|
||||
self.start
|
||||
}
|
||||
pub fn point_inc (&mut self) -> Option<$T> {
|
||||
self.point = self.point.map(|p|p + 1);
|
||||
self.point
|
||||
}
|
||||
pub fn point_dec (&mut self) -> Option<$T> {
|
||||
self.point = self.point.map(|p|p.saturating_sub(1));
|
||||
self.point
|
||||
}
|
||||
pub struct Split<
|
||||
E: Engine,
|
||||
F: Send + Sync + Fn(&mut dyn FnMut(&dyn Widget<Engine = E>)->Usually<()>)->Usually<()>
|
||||
>(pub F, pub Direction, PhantomData<E>);
|
||||
|
||||
impl<
|
||||
E: Engine,
|
||||
F: Send + Sync + Fn(&mut dyn FnMut(&dyn Widget<Engine = E>)->Usually<()>)->Usually<()>
|
||||
> Split<E, F> {
|
||||
#[inline]
|
||||
pub fn new (direction: Direction, build: F) -> Self {
|
||||
Self(build, direction, Default::default())
|
||||
}
|
||||
} }
|
||||
|
||||
pub struct FixedAxis<T> {
|
||||
pub start: T,
|
||||
pub point: Option<T>
|
||||
}
|
||||
|
||||
impl_axis_common!(FixedAxis u16);
|
||||
impl_axis_common!(FixedAxis usize);
|
||||
|
||||
pub struct ScaledAxis<T> {
|
||||
pub start: T,
|
||||
pub scale: T,
|
||||
pub point: Option<T>
|
||||
}
|
||||
|
||||
impl_axis_common!(ScaledAxis u16);
|
||||
impl_axis_common!(ScaledAxis usize);
|
||||
|
||||
impl<T: Copy> ScaledAxis<T> {
|
||||
pub fn scale_mut (&mut self, cb: &impl Fn(T)->T) {
|
||||
self.scale = cb(self.scale)
|
||||
#[inline]
|
||||
pub fn right (build: F) -> Self {
|
||||
Self::new(Direction::Right, build)
|
||||
}
|
||||
#[inline]
|
||||
pub fn down (build: F) -> Self {
|
||||
Self::new(Direction::Down, build)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Layers<
|
||||
E: Engine,
|
||||
F: Send + Sync + Fn(&mut dyn FnMut(&dyn Widget<Engine = E>)->Usually<()>)->Usually<()>
|
||||
>(pub F, PhantomData<E>);
|
||||
|
||||
impl<
|
||||
E: Engine,
|
||||
F: Send + Sync + Fn(&mut dyn FnMut(&dyn Widget<Engine = E>)->Usually<()>)->Usually<()>
|
||||
> Layers<E, F> {
|
||||
#[inline]
|
||||
pub fn new (build: F) -> Self {
|
||||
Self(build, Default::default())
|
||||
}
|
||||
}
|
||||
|
||||
//pub fn collect <'a, E: Engine, const N: usize> (
|
||||
//items: &'a [&'a dyn Widget<Engine = E>;N]
|
||||
//) -> impl Send + Sync + Fn(&'a mut dyn FnMut(&'a dyn Widget<Engine = E>)->Usually<()>)->Usually<()> + '_ {
|
||||
//|add: &'a mut dyn FnMut(&'a dyn Widget<Engine = E>)->Usually<()>| {
|
||||
//for item in items.iter() {
|
||||
//add(item)?;
|
||||
//}
|
||||
//Ok(())
|
||||
//}
|
||||
//}
|
||||
|
||||
//`Layers<_, impl (Fn(&mut dyn FnMut(&dyn Widget<Engine = _>) -> Result<(), Box<...>>) -> ... ) + Send + Sync>`
|
||||
//`Layers<Tui, impl (Fn(&mut dyn FnMut(&dyn Widget<Engine = Tui>) -> Result<(), Box<(dyn std::error::Error + 'static)>>) -> Result<(), Box<(dyn std::error::Error + 'static)>>) + Send + Sync + '_>`
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub enum Direction {
|
||||
Up,
|
||||
Down,
|
||||
Left,
|
||||
Right,
|
||||
}
|
||||
|
||||
impl Direction {
|
||||
pub fn is_down (&self) -> bool {
|
||||
match self { Self::Down => true, _ => false }
|
||||
}
|
||||
pub fn is_right (&self) -> bool {
|
||||
match self { Self::Right => true, _ => false }
|
||||
}
|
||||
}
|
||||
|
||||
/// Override X and Y coordinates, aligning to corner, side, or center of area
|
||||
pub enum Align<L> {
|
||||
/// Draw at center of container
|
||||
Center(L),
|
||||
/// Draw at center of X axis
|
||||
X(L),
|
||||
/// Draw at center of Y axis
|
||||
Y(L),
|
||||
/// Draw at upper left corner of contaier
|
||||
NW(L),
|
||||
/// Draw at center of upper edge of container
|
||||
N(L),
|
||||
/// Draw at right left corner of contaier
|
||||
NE(L),
|
||||
/// Draw at center of left edge of container
|
||||
W(L),
|
||||
/// Draw at center of right edge of container
|
||||
E(L),
|
||||
/// Draw at lower left corner of container
|
||||
SW(L),
|
||||
/// Draw at center of lower edge of container
|
||||
S(L),
|
||||
/// Draw at lower right edge of container
|
||||
SE(L)
|
||||
}
|
||||
|
||||
impl<T> Align<T> {
|
||||
pub fn inner (&self) -> &T {
|
||||
match self {
|
||||
Self::Center(inner) => inner,
|
||||
Self::X(inner) => inner,
|
||||
Self::Y(inner) => inner,
|
||||
Self::NW(inner) => inner,
|
||||
Self::N(inner) => inner,
|
||||
Self::NE(inner) => inner,
|
||||
Self::W(inner) => inner,
|
||||
Self::E(inner) => inner,
|
||||
Self::SW(inner) => inner,
|
||||
Self::S(inner) => inner,
|
||||
Self::SE(inner) => inner,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn align<T, N: Number, R: Area<N> + From<[N;4]>> (align: &Align<T>, outer: R, inner: R) -> Option<R> {
|
||||
if outer.w() < inner.w() || outer.h() < inner.h() {
|
||||
None
|
||||
} else {
|
||||
let [ox, oy, ow, oh] = outer.xywh();
|
||||
let [ix, iy, iw, ih] = inner.xywh();
|
||||
Some(match align {
|
||||
Align::Center(_) => [ox + (ow - iw) / 2.into(), oy + (oh - ih) / 2.into(), iw, ih,].into(),
|
||||
Align::X(_) => [ox + (ow - iw) / 2.into(), iy, iw, ih,].into(),
|
||||
Align::Y(_) => [ix, oy + (oh - ih) / 2.into(), iw, ih,].into(),
|
||||
Align::NW(_) => [ox, oy, iw, ih,].into(),
|
||||
Align::N(_) => [ox + (ow - iw) / 2.into(), oy, iw, ih,].into(),
|
||||
Align::NE(_) => [ox + ow - iw, oy, iw, ih,].into(),
|
||||
Align::W(_) => [ox, oy + (oh - ih) / 2.into(), iw, ih,].into(),
|
||||
Align::E(_) => [ox + ow - iw, oy + (oh - ih) / 2.into(), iw, ih,].into(),
|
||||
Align::SW(_) => [ox, oy + oh - ih, iw, ih,].into(),
|
||||
Align::S(_) => [ox + (ow - iw) / 2.into(), oy + oh - ih, iw, ih,].into(),
|
||||
Align::SE(_) => [ox + ow - iw, oy + oh - ih, iw, ih,].into(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Engine, T: Widget<Engine = E>> Widget for Align<T> {
|
||||
type Engine = E;
|
||||
fn layout (&self, outer_area: E::Size) -> Perhaps<E::Size> {
|
||||
self.inner().layout(outer_area)
|
||||
}
|
||||
fn render (&self, to: &mut E::Output) -> Usually<()> {
|
||||
let outer_area = to.area();
|
||||
Ok(if let Some(inner_size) = self.layout(outer_area.wh().into())? {
|
||||
let inner_area = outer_area.clip(inner_size);
|
||||
if let Some(aligned) = align(&self, outer_area.into(), inner_area.into()) {
|
||||
to.render_in(aligned, self.inner())?
|
||||
} else {
|
||||
()
|
||||
}
|
||||
} else {
|
||||
()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Enforce fixed size of drawing area
|
||||
pub enum Fixed<U: Number, T> {
|
||||
/// Enforce fixed width
|
||||
X(U, T),
|
||||
/// Enforce fixed height
|
||||
Y(U, T),
|
||||
/// Enforce fixed width and height
|
||||
XY(U, U, T),
|
||||
}
|
||||
|
||||
impl<N: Number, T> Fixed<N, T> {
|
||||
pub fn inner (&self) -> &T {
|
||||
match self { Self::X(_, i) => i, Self::Y(_, i) => i, Self::XY(_, _, i) => i, }
|
||||
}
|
||||
}
|
||||
|
||||
/// Enforce minimum size of drawing area
|
||||
pub enum Min<U: Number, T> {
|
||||
/// Enforce minimum width
|
||||
X(U, T),
|
||||
/// Enforce minimum height
|
||||
Y(U, T),
|
||||
/// Enforce minimum width and height
|
||||
XY(U, U, T),
|
||||
}
|
||||
impl<N: Number, T> Min<N, T> {
|
||||
pub fn inner (&self) -> &T {
|
||||
match self { Self::X(_, i) => i, Self::Y(_, i) => i, Self::XY(_, _, i) => i, }
|
||||
}
|
||||
}
|
||||
impl<E: Engine, T: Widget<Engine = E>> Widget for Min<E::Unit, T> {
|
||||
type Engine = E;
|
||||
fn layout (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||
Ok(self.inner().layout(to)?.map(|to|match *self {
|
||||
Self::X(w, _) => [to.w().max(w), to.h()],
|
||||
Self::Y(h, _) => [to.w(), to.h().max(h)],
|
||||
Self::XY(w, h, _) => [to.w().max(w), to.h().max(h)],
|
||||
}.into()))
|
||||
}
|
||||
// TODO: 🡘 🡙 ←🡙→
|
||||
fn render (&self, to: &mut E::Output) -> Usually<()> {
|
||||
Ok(self.layout(to.area().wh().into())?
|
||||
.map(|size|to.render_in(to.area().clip(size).into(), self.inner()))
|
||||
.transpose()?.unwrap_or(()))
|
||||
}
|
||||
}
|
||||
|
||||
/// Enforce maximum size of drawing area
|
||||
pub enum Max<U: Number, T> {
|
||||
/// Enforce maximum width
|
||||
X(U, T),
|
||||
/// Enforce maximum height
|
||||
Y(U, T),
|
||||
/// Enforce maximum width and height
|
||||
XY(U, U, T),
|
||||
}
|
||||
|
||||
impl<N: Number, T> Max<N, T> {
|
||||
fn inner (&self) -> &T {
|
||||
match self { Self::X(_, i) => i, Self::Y(_, i) => i, Self::XY(_, _, i) => i, }
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Engine, T: Widget<Engine = E>> Widget for Max<E:: Unit, T> {
|
||||
type Engine = E;
|
||||
fn layout (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||
Ok(self.inner().layout(to)?.map(|to|match *self {
|
||||
Self::X(w, _) => [to.w().min(w), to.h()],
|
||||
Self::Y(h, _) => [to.w(), to.h().min(h)],
|
||||
Self::XY(w, h, _) => [to.w().min(w), to.h().min(h)],
|
||||
}.into()))
|
||||
}
|
||||
fn render (&self, to: &mut E::Output) -> Usually<()> {
|
||||
Ok(self.layout(to.area().wh().into())?
|
||||
.map(|size|to.render_in(to.area().clip(size).into(), self.inner()))
|
||||
.transpose()?.unwrap_or(()))
|
||||
}
|
||||
}
|
||||
|
||||
/// Expand drawing area
|
||||
pub enum Grow<N: Number, T> {
|
||||
/// Increase width
|
||||
X(N, T),
|
||||
/// Increase height
|
||||
Y(N, T),
|
||||
/// Increase width and height
|
||||
XY(N, N, T)
|
||||
}
|
||||
|
||||
impl<N: Number, T> Grow<N, T> {
|
||||
fn inner (&self) -> &T {
|
||||
match self { Self::X(_, i) => i, Self::Y(_, i) => i, Self::XY(_, _, i) => i, }
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Engine, T: Widget<Engine = E>> Widget for Grow<E::Unit, T> {
|
||||
type Engine = E;
|
||||
fn layout (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||
Ok(self.inner().layout(to)?.map(|to|match *self {
|
||||
Self::X(w, _) => [to.w() + w, to.h()],
|
||||
Self::Y(h, _) => [to.w(), to.h() + h],
|
||||
Self::XY(w, h, _) => [to.w() + w, to.h() + h],
|
||||
}.into()))
|
||||
}
|
||||
fn render (&self, to: &mut E::Output) -> Usually<()> {
|
||||
Ok(self.layout(to.area().wh().into())?
|
||||
.map(|size|to.render_in(to.area().clip(size).into(), self.inner()))
|
||||
.transpose()?.unwrap_or(()))
|
||||
}
|
||||
}
|
||||
|
||||
/// Shrink drawing area
|
||||
pub enum Shrink<N: Number, T> {
|
||||
/// Decrease width
|
||||
X(N, T),
|
||||
/// Decrease height
|
||||
Y(N, T),
|
||||
/// Decrease width and height
|
||||
XY(N, N, T),
|
||||
}
|
||||
|
||||
impl<N: Number, T: Widget> Shrink<N, T> {
|
||||
fn inner (&self) -> &T {
|
||||
match self { Self::X(_, i) => i, Self::Y(_, i) => i, Self::XY(_, _, i) => i, }
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Engine, T: Widget<Engine = E>> Widget for Shrink<E::Unit, T> {
|
||||
type Engine = E;
|
||||
fn layout (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||
Ok(self.inner().layout(to)?.map(|to|match *self {
|
||||
Self::X(w, _) => [to.w() - w, to.h()],
|
||||
Self::Y(h, _) => [to.w(), to.h() - h],
|
||||
Self::XY(w, h, _) => [to.w() - w, to.h() - h]
|
||||
}.into()))
|
||||
}
|
||||
fn render (&self, to: &mut E::Output) -> Usually<()> {
|
||||
Ok(self.layout(to.area().wh().into())?
|
||||
.map(|size|to.render_in(to.area().clip(size).into(), self.inner()))
|
||||
.transpose()?.unwrap_or(()))
|
||||
}
|
||||
}
|
||||
|
||||
/// Shrink from each side
|
||||
pub enum Inset<N: Number, T> {
|
||||
/// Decrease width
|
||||
X(N, T),
|
||||
/// Decrease height
|
||||
Y(N, T),
|
||||
/// Decrease width and height
|
||||
XY(N, N, T),
|
||||
}
|
||||
|
||||
impl<N: Number, T: Widget> Inset<N, T> {
|
||||
pub fn inner (&self) -> &T {
|
||||
match self { Self::X(_, i) => i, Self::Y(_, i) => i, Self::XY(_, _, i) => i, }
|
||||
}
|
||||
}
|
||||
|
||||
/// Grow on each side
|
||||
pub enum Outset<N: Number, T> {
|
||||
/// Increase width
|
||||
X(N, T),
|
||||
/// Increase height
|
||||
Y(N, T),
|
||||
/// Increase width and height
|
||||
XY(N, N, T),
|
||||
}
|
||||
|
||||
impl<N: Number, T: Widget> Outset<N, T> {
|
||||
pub fn inner (&self) -> &T {
|
||||
match self { Self::X(_, i) => i, Self::Y(_, i) => i, Self::XY(_, _, i) => i, }
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Engine, T: Widget<Engine = E>> Widget for Inset<E::Unit, T> {
|
||||
type Engine = E;
|
||||
fn layout (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||
match *self {
|
||||
Self::X(x, ref inner) => Shrink::X(x + x, inner as &dyn Widget<Engine = E>),
|
||||
Self::Y(y, ref inner) => Shrink::Y(y + y, inner as &dyn Widget<Engine = E>),
|
||||
Self::XY(x, y, ref inner) => Shrink::XY(x + x, y + y, inner as &dyn Widget<Engine = E>),
|
||||
}.layout(to)
|
||||
}
|
||||
fn render (&self, to: &mut E::Output) -> Usually<()> {
|
||||
match *self {
|
||||
Self::X(x, ref inner) => Plus::X(x, inner as &dyn Widget<Engine = E>),
|
||||
Self::Y(y, ref inner) => Plus::Y(y, inner as &dyn Widget<Engine = E>),
|
||||
Self::XY(x, y, ref inner) => Plus::XY(x, y, inner as &dyn Widget<Engine = E>),
|
||||
}.render(to)
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Engine, T: Widget<Engine = E>> Widget for Outset<E::Unit, T> {
|
||||
type Engine = E;
|
||||
fn layout (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||
match *self {
|
||||
Self::X(x, ref inner) => Grow::X(x + x, inner as &dyn Widget<Engine = E>),
|
||||
Self::Y(y, ref inner) => Grow::Y(y + y, inner as &dyn Widget<Engine = E>),
|
||||
Self::XY(x, y, ref inner) => Grow::XY(x + x, y + y, inner as &dyn Widget<Engine = E>),
|
||||
}.layout(to)
|
||||
}
|
||||
fn render (&self, to: &mut E::Output) -> Usually<()> {
|
||||
match *self {
|
||||
Self::X(x, ref inner) => Plus::X(x, inner as &dyn Widget<Engine = E>),
|
||||
Self::Y(y, ref inner) => Plus::Y(y, inner as &dyn Widget<Engine = E>),
|
||||
Self::XY(x, y, ref inner) => Plus::XY(x, y, inner as &dyn Widget<Engine = E>),
|
||||
}.render(to)
|
||||
}
|
||||
}
|
||||
|
||||
/// Move origin point of drawing area
|
||||
pub enum Plus<N: Number, T: Widget> {
|
||||
/// Move origin to the right
|
||||
X(N, T),
|
||||
/// Move origin downwards
|
||||
Y(N, T),
|
||||
/// Move origin to the right and downwards
|
||||
XY(N, N, T),
|
||||
}
|
||||
|
||||
impl<N: Number, T: Widget> Plus<N, T> {
|
||||
fn inner (&self) -> &T {
|
||||
match self { Self::X(_, i) => i, Self::Y(_, i) => i, Self::XY(_, _, i) => i, }
|
||||
}
|
||||
fn x (&self) -> N {
|
||||
match self { Self::X(x, _) => *x, Self::Y(_, _) => N::default(), Self::XY(x, _, _) => *x }
|
||||
}
|
||||
fn y (&self) -> N {
|
||||
match self { Self::X(_, _) => N::default(), Self::Y(y, _) => *y, Self::XY(_, y, _) => *y }
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Engine, T: Widget<Engine = E>> Widget for Plus<E::Unit, T> {
|
||||
type Engine = E;
|
||||
fn layout (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||
self.inner().layout(to)
|
||||
}
|
||||
fn render (&self, to: &mut E::Output) -> Usually<()> {
|
||||
let area = to.area();
|
||||
Ok(self.layout(area.wh().into())?
|
||||
.map(|size|to.render_in(match *self {
|
||||
Self::X(x, _) => [area.x() + x, area.y(), size.w(), size.h()],
|
||||
Self::Y(y, _) => [area.x(), area.y() + y, size.w(), size.h()],
|
||||
Self::XY(x, y, _) => [area.x() + x, area.y() + y, size.w(), size.h()],
|
||||
}.into(), self.inner())).transpose()?.unwrap_or(()))
|
||||
}
|
||||
}
|
||||
|
||||
/// Move origin point of drawing area
|
||||
pub enum Minus<N: Number, T: Widget> {
|
||||
/// Move origin to the right
|
||||
X(N, T),
|
||||
/// Move origin downwards
|
||||
Y(N, T),
|
||||
/// Move origin to the right and downwards
|
||||
XY(N, N, T),
|
||||
}
|
||||
|
||||
impl<N: Number, T: Widget> Minus<N, T> {
|
||||
fn inner (&self) -> &T {
|
||||
match self { Self::X(_, i) => i, Self::Y(_, i) => i, Self::XY(_, _, i) => i, }
|
||||
}
|
||||
fn x (&self) -> N {
|
||||
match self { Self::X(x, _) => *x, Self::Y(_, _) => N::default(), Self::XY(x, _, _) => *x }
|
||||
}
|
||||
fn y (&self) -> N {
|
||||
match self { Self::X(_, _) => N::default(), Self::Y(y, _) => *y, Self::XY(_, y, _) => *y }
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Engine, T: Widget<Engine = E>> Widget for Minus<E::Unit, T> {
|
||||
type Engine = E;
|
||||
fn layout (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||
self.inner().layout(to)
|
||||
}
|
||||
fn render (&self, to: &mut E::Output) -> Usually<()> {
|
||||
let area = to.area();
|
||||
Ok(self.layout(area.wh().into())?
|
||||
.map(|size|to.render_in(match *self {
|
||||
Self::X(x, _) => [area.x().minus(x), area.y(), size.w(), size.h()],
|
||||
Self::Y(y, _) => [area.x(), area.y().minus(y), size.w(), size.h()],
|
||||
Self::XY(x, y, _) => [area.x().minus(x), area.y().minus(y), size.w(), size.h()],
|
||||
}.into(), self.inner())).transpose()?.unwrap_or(()))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ impl<E: Engine> TransportToolbar<E> {
|
|||
}
|
||||
}
|
||||
pub fn toggle_play (&mut self) -> Usually<()> {
|
||||
self.playing.toggle();
|
||||
self.playing.toggle()?;
|
||||
Ok(())
|
||||
}
|
||||
pub fn update (&mut self, scope: &ProcessScope) -> (bool, usize, usize, usize, usize, f64) {
|
||||
|
|
@ -146,40 +146,6 @@ impl<E: Engine> TransportToolbar<E> {
|
|||
self.sync.value
|
||||
}
|
||||
}
|
||||
impl Focus<5, Tui> for TransportToolbar<Tui> {
|
||||
fn focus (&self) -> usize {
|
||||
self.focus
|
||||
}
|
||||
fn focus_mut (&mut self) -> &mut usize {
|
||||
&mut self.focus
|
||||
}
|
||||
fn focusable (&self) -> [&dyn Focusable<Tui>;5] {
|
||||
[
|
||||
&self.playing as &dyn Focusable<Tui>,
|
||||
&self.bpm as &dyn Focusable<Tui>,
|
||||
&self.quant as &dyn Focusable<Tui>,
|
||||
&self.sync as &dyn Focusable<Tui>,
|
||||
&self.clock as &dyn Focusable<Tui>,
|
||||
]
|
||||
}
|
||||
fn focusable_mut (&mut self) -> [&mut dyn Focusable<Tui>;5] {
|
||||
[
|
||||
&mut self.playing as &mut dyn Focusable<Tui>,
|
||||
&mut self.bpm as &mut dyn Focusable<Tui>,
|
||||
&mut self.quant as &mut dyn Focusable<Tui>,
|
||||
&mut self.sync as &mut dyn Focusable<Tui>,
|
||||
&mut self.clock as &mut dyn Focusable<Tui>,
|
||||
]
|
||||
}
|
||||
}
|
||||
impl Focusable<Tui> for TransportToolbar<Tui> {
|
||||
fn is_focused (&self) -> bool {
|
||||
self.focused
|
||||
}
|
||||
fn set_focused (&mut self, focused: bool) {
|
||||
self.focused = focused
|
||||
}
|
||||
}
|
||||
impl<E: Engine> Audio for TransportToolbar<E> {
|
||||
fn process (&mut self, _: &Client, scope: &ProcessScope) -> Control {
|
||||
self.update(&scope);
|
||||
|
|
@ -214,6 +180,40 @@ impl Content for TransportToolbar<Tui> {
|
|||
})
|
||||
}
|
||||
}
|
||||
impl Focus<5, Tui> for TransportToolbar<Tui> {
|
||||
fn focus (&self) -> usize {
|
||||
self.focus
|
||||
}
|
||||
fn focus_mut (&mut self) -> &mut usize {
|
||||
&mut self.focus
|
||||
}
|
||||
fn focusable (&self) -> [&dyn Focusable<Tui>;5] {
|
||||
[
|
||||
&self.playing as &dyn Focusable<Tui>,
|
||||
&self.bpm as &dyn Focusable<Tui>,
|
||||
&self.quant as &dyn Focusable<Tui>,
|
||||
&self.sync as &dyn Focusable<Tui>,
|
||||
&self.clock as &dyn Focusable<Tui>,
|
||||
]
|
||||
}
|
||||
fn focusable_mut (&mut self) -> [&mut dyn Focusable<Tui>;5] {
|
||||
[
|
||||
&mut self.playing as &mut dyn Focusable<Tui>,
|
||||
&mut self.bpm as &mut dyn Focusable<Tui>,
|
||||
&mut self.quant as &mut dyn Focusable<Tui>,
|
||||
&mut self.sync as &mut dyn Focusable<Tui>,
|
||||
&mut self.clock as &mut dyn Focusable<Tui>,
|
||||
]
|
||||
}
|
||||
}
|
||||
impl Focusable<Tui> for TransportToolbar<Tui> {
|
||||
fn is_focused (&self) -> bool {
|
||||
self.focused
|
||||
}
|
||||
fn set_focused (&mut self, focused: bool) {
|
||||
self.focused = focused
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
|
@ -260,8 +260,8 @@ impl Content for TransportPlayPauseButton<Tui> {
|
|||
type Engine = Tui;
|
||||
fn content (&self) -> impl Widget<Engine = Tui> {
|
||||
Layers::new(|add|{
|
||||
//add(&self.focused.then_some(CORNERS))?;
|
||||
add(&Styled(match self.value {
|
||||
add(&self.focused.then_some(CORNERS))?;
|
||||
add(&Plus::X(1, Min::Y(2, Styled(match self.value {
|
||||
Some(TransportState::Stopped) => Some(GRAY_DIM.bold()),
|
||||
Some(TransportState::Starting) => Some(GRAY_NOT_DIM_BOLD),
|
||||
Some(TransportState::Rolling) => Some(WHITE_NOT_DIM_BOLD),
|
||||
|
|
@ -271,7 +271,7 @@ impl Content for TransportPlayPauseButton<Tui> {
|
|||
Some(TransportState::Starting) => "READY ...",
|
||||
Some(TransportState::Stopped) => "⏹ STOPPED",
|
||||
_ => unreachable!(),
|
||||
}))?;
|
||||
}))))?;
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue