mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-07 12:16:42 +01:00
refactor + not sure whats up with the double padding
This commit is contained in:
parent
39407c9760
commit
c51d1cf643
10 changed files with 388 additions and 393 deletions
|
|
@ -13,7 +13,15 @@ impl HelpModal {
|
||||||
Self { cursor: 0, search: None, exited: false }
|
Self { cursor: 0, search: None, exited: false }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exit!(HelpModal);
|
|
||||||
|
impl Exit for HelpModal {
|
||||||
|
fn exited (&self) -> bool {
|
||||||
|
self.exited
|
||||||
|
}
|
||||||
|
fn exit (&mut self) {
|
||||||
|
self.exited = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
render!(HelpModal |self, buf, area|{
|
render!(HelpModal |self, buf, area|{
|
||||||
make_dim(buf);
|
make_dim(buf);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,12 @@
|
||||||
use crate::*;
|
use crate::*;
|
||||||
|
|
||||||
|
submod! {
|
||||||
|
focus
|
||||||
|
handle
|
||||||
|
keymap
|
||||||
|
layout
|
||||||
|
}
|
||||||
|
|
||||||
/// Entry point for main loop
|
/// Entry point for main loop
|
||||||
pub trait App<T: Engine> {
|
pub trait App<T: Engine> {
|
||||||
fn run (self, context: T) -> Usually<T>;
|
fn run (self, context: T) -> Usually<T>;
|
||||||
|
|
@ -31,13 +38,122 @@ pub trait Engine: Send + Sync + Sized {
|
||||||
) -> Perhaps<Self::Area>;
|
) -> Perhaps<Self::Area>;
|
||||||
}
|
}
|
||||||
|
|
||||||
submod! {
|
pub trait Widget: Send + Sync {
|
||||||
collect
|
type Engine: Engine;
|
||||||
component
|
fn layout (&self, to: <<Self as Widget>::Engine as Engine>::Area) ->
|
||||||
exit
|
Perhaps<<<Self as Widget>::Engine as Engine>::Area>
|
||||||
focus
|
{
|
||||||
handle
|
Ok(Some(to))
|
||||||
keymap
|
}
|
||||||
layout
|
fn render (&self, to: &mut Self::Engine) ->
|
||||||
//render
|
Perhaps<<<Self as Widget>::Engine as Engine>::Area>;
|
||||||
}
|
}
|
||||||
|
impl<'a, E: Engine> Widget for Box<dyn Widget<Engine = E> + 'a> {
|
||||||
|
type Engine = E;
|
||||||
|
fn layout (&self, to: E::Area) -> Perhaps<E::Area> {
|
||||||
|
(**self).layout(to)
|
||||||
|
}
|
||||||
|
fn render (&self, to: &mut E) -> Perhaps<E::Area> {
|
||||||
|
(**self).render(to)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<E: Engine> Widget for &dyn Widget<Engine = E> {
|
||||||
|
type Engine = E;
|
||||||
|
fn layout (&self, to: E::Area) -> Perhaps<E::Area> {
|
||||||
|
(*self).layout(to)
|
||||||
|
}
|
||||||
|
fn render (&self, to: &mut E) -> Perhaps<E::Area> {
|
||||||
|
(*self).render(to)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<E: Engine> Widget for &mut dyn Widget<Engine = E> {
|
||||||
|
type Engine = E;
|
||||||
|
fn layout (&self, to: E::Area) -> Perhaps<E::Area> {
|
||||||
|
(**self).layout(to)
|
||||||
|
}
|
||||||
|
fn render (&self, to: &mut E) -> Perhaps<E::Area> {
|
||||||
|
(**self).render(to)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<E: Engine, W: Widget<Engine = E>> Widget for Arc<W> {
|
||||||
|
type Engine = E;
|
||||||
|
fn layout (&self, to: E::Area) -> Perhaps<E::Area> {
|
||||||
|
self.as_ref().layout(to)
|
||||||
|
}
|
||||||
|
fn render (&self, to: &mut E) -> Perhaps<E::Area> {
|
||||||
|
self.as_ref().render(to)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<E: Engine, W: Widget<Engine = E>> Widget for Mutex<W> {
|
||||||
|
type Engine = E;
|
||||||
|
fn layout (&self, to: E::Area) -> Perhaps<E::Area> {
|
||||||
|
self.lock().unwrap().layout(to)
|
||||||
|
}
|
||||||
|
fn render (&self, to: &mut E) -> Perhaps<E::Area> {
|
||||||
|
self.lock().unwrap().render(to)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<E: Engine, W: Widget<Engine = E>> Widget for RwLock<W> {
|
||||||
|
type Engine = E;
|
||||||
|
fn layout (&self, to: E::Area) -> Perhaps<E::Area> {
|
||||||
|
self.read().unwrap().layout(to)
|
||||||
|
}
|
||||||
|
fn render (&self, to: &mut E) -> Perhaps<E::Area> {
|
||||||
|
self.read().unwrap().render(to)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<E: Engine, W: Widget<Engine = E>> Widget for Option<W> {
|
||||||
|
type Engine = E;
|
||||||
|
fn layout (&self, to: E::Area) -> Perhaps<E::Area> {
|
||||||
|
Ok(self.as_ref().map(|widget|widget.layout(to)).transpose()?.flatten())
|
||||||
|
}
|
||||||
|
fn render (&self, to: &mut E) -> Perhaps<E::Area> {
|
||||||
|
Ok(self.as_ref().map(|widget|widget.render(to)).transpose()?.flatten())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait Content: Send + Sync {
|
||||||
|
type Engine: Engine;
|
||||||
|
fn content (&self) -> impl Widget<Engine = <Self as Content>::Engine>;
|
||||||
|
}
|
||||||
|
//impl<E> Content<E> for () where E: Engine {
|
||||||
|
//fn content (&self) -> impl Widget<E> {
|
||||||
|
//()
|
||||||
|
//}
|
||||||
|
//}
|
||||||
|
impl<E: Engine, W: Content<Engine = E>> Widget for W {
|
||||||
|
type Engine = E;
|
||||||
|
fn layout (&self, to: E::Area) -> Perhaps<E::Area> {
|
||||||
|
self.content().layout(to)
|
||||||
|
}
|
||||||
|
fn render (&self, to: &mut E) -> Perhaps<E::Area> {
|
||||||
|
match self.layout(to.area())? {
|
||||||
|
Some(area) => to.render_in(area, &self.content()),
|
||||||
|
None => Ok(None)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A UI component.
|
||||||
|
pub trait Component<E: Engine>: Widget<Engine = E> + Handle<E> {}
|
||||||
|
|
||||||
|
/// Everything that implements [Render] and [Handle] is a [Component].
|
||||||
|
impl<E: Engine, C: Widget<Engine = E> + Handle<E>> Component<E> for C {}
|
||||||
|
|
||||||
|
pub trait Exit: Send {
|
||||||
|
fn exited (&self) -> bool;
|
||||||
|
fn exit (&mut self);
|
||||||
|
fn boxed (self) -> Box<dyn Exit> where Self: Sized + 'static {
|
||||||
|
Box::new(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Marker trait for [Component]s that can [Exit]
|
||||||
|
pub trait ExitableComponent<E>: Exit + Component<E> where E: Engine {
|
||||||
|
/// Perform type erasure for collecting heterogeneous components.
|
||||||
|
fn boxed (self) -> Box<dyn ExitableComponent<E>> where Self: Sized + 'static {
|
||||||
|
Box::new(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<E: Engine, C: Component<E> + Exit> ExitableComponent<E> for C {}
|
||||||
|
|
|
||||||
|
|
@ -1,121 +0,0 @@
|
||||||
use crate::*;
|
|
||||||
|
|
||||||
pub enum Collected<'a, E: Engine> {
|
|
||||||
Box(Box<dyn Widget<Engine = E> + 'a>),
|
|
||||||
Ref(&'a (dyn Widget<Engine = E> + 'a)),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, E: Engine> Widget for Collected<'a, E> {
|
|
||||||
type Engine = E;
|
|
||||||
fn layout (&self, area: E::Area) -> Perhaps<E::Area> {
|
|
||||||
match self {
|
|
||||||
Self::Box(inner) => (*inner).layout(area),
|
|
||||||
Self::Ref(inner) => (*inner).layout(area),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn render (&self, to: &mut E) -> Perhaps<E::Area> {
|
|
||||||
match self {
|
|
||||||
Self::Box(inner) => (*inner).render(to),
|
|
||||||
Self::Ref(inner) => (*inner).render(to),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Collection<'a, E: Engine>(
|
|
||||||
pub Vec<Collected<'a, E>>
|
|
||||||
);
|
|
||||||
|
|
||||||
impl<'a, E: Engine> Collection<'a, E> {
|
|
||||||
pub fn new () -> Self {
|
|
||||||
Self(vec![])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait Collect<'a, E: Engine> {
|
|
||||||
fn add_box (self, item: Box<dyn Widget<Engine = E> + 'a>) -> Self;
|
|
||||||
fn add_ref (self, item: &'a dyn Widget<Engine = E>) -> Self;
|
|
||||||
fn add <R: Widget<Engine = E> + Sized + 'a> (self, item: R) -> Self
|
|
||||||
where Self: Sized
|
|
||||||
{
|
|
||||||
self.add_box(Box::new(item))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, E: Engine> Collect<'a, E> for Collection<'a, E> {
|
|
||||||
fn add_box (mut self, item: Box<dyn Widget<Engine = E> + 'a>) -> Self {
|
|
||||||
self.0.push(Collected::Box(item));
|
|
||||||
self
|
|
||||||
}
|
|
||||||
fn add_ref (mut self, item: &'a dyn Widget<Engine = E>) -> Self {
|
|
||||||
self.0.push(Collected::Ref(item));
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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> {
|
|
||||||
pub fn new (build: F) -> Self {
|
|
||||||
Self(build, Default::default())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// this actually works, except for the type inference
|
|
||||||
//pub struct Layers<'a, E: Engine + 'a, I: std::iter::IntoIterator<Item = &'a dyn Render<E>>>(
|
|
||||||
//pub &'a I
|
|
||||||
//);
|
|
||||||
|
|
||||||
#[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 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Split<'a, E: Engine> {
|
|
||||||
pub items: Collection<'a, E>,
|
|
||||||
pub direction: Direction,
|
|
||||||
pub focus: Option<usize>
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, E: Engine> Split<'a, E> {
|
|
||||||
pub fn new (direction: Direction) -> Self {
|
|
||||||
Self {
|
|
||||||
items: Collection::new(),
|
|
||||||
direction,
|
|
||||||
focus: None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn down () -> Self {
|
|
||||||
Self::new(Direction::Down)
|
|
||||||
}
|
|
||||||
pub fn right () -> Self {
|
|
||||||
Self::new(Direction::Right)
|
|
||||||
}
|
|
||||||
pub fn focus (mut self, focus: Option<usize>) -> Self {
|
|
||||||
self.focus = focus;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, E: Engine> Collect<'a, E> for Split<'a, E> {
|
|
||||||
fn add_box (mut self, item: Box<dyn Widget<Engine = E> + 'a>) -> Self {
|
|
||||||
self.items = self.items.add_box(item);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
fn add_ref (mut self, item: &'a dyn Widget<Engine = E>) -> Self {
|
|
||||||
self.items = self.items.add_ref(item);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,103 +0,0 @@
|
||||||
use crate::*;
|
|
||||||
|
|
||||||
pub trait Widget: Send + Sync {
|
|
||||||
type Engine: Engine;
|
|
||||||
fn layout (&self, to: <<Self as Widget>::Engine as Engine>::Area) ->
|
|
||||||
Perhaps<<<Self as Widget>::Engine as Engine>::Area>
|
|
||||||
{
|
|
||||||
Ok(Some(to))
|
|
||||||
}
|
|
||||||
fn render (&self, to: &mut Self::Engine) ->
|
|
||||||
Perhaps<<<Self as Widget>::Engine as Engine>::Area>;
|
|
||||||
}
|
|
||||||
impl<'a, E: Engine> Widget for Box<dyn Widget<Engine = E> + 'a> {
|
|
||||||
type Engine = E;
|
|
||||||
fn layout (&self, to: E::Area) -> Perhaps<E::Area> {
|
|
||||||
(**self).layout(to)
|
|
||||||
}
|
|
||||||
fn render (&self, to: &mut E) -> Perhaps<E::Area> {
|
|
||||||
(**self).render(to)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl<E: Engine> Widget for &dyn Widget<Engine = E> {
|
|
||||||
type Engine = E;
|
|
||||||
fn layout (&self, to: E::Area) -> Perhaps<E::Area> {
|
|
||||||
(*self).layout(to)
|
|
||||||
}
|
|
||||||
fn render (&self, to: &mut E) -> Perhaps<E::Area> {
|
|
||||||
(*self).render(to)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl<E: Engine> Widget for &mut dyn Widget<Engine = E> {
|
|
||||||
type Engine = E;
|
|
||||||
fn layout (&self, to: E::Area) -> Perhaps<E::Area> {
|
|
||||||
(**self).layout(to)
|
|
||||||
}
|
|
||||||
fn render (&self, to: &mut E) -> Perhaps<E::Area> {
|
|
||||||
(**self).render(to)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl<E: Engine, W: Widget<Engine = E>> Widget for Arc<W> {
|
|
||||||
type Engine = E;
|
|
||||||
fn layout (&self, to: E::Area) -> Perhaps<E::Area> {
|
|
||||||
self.as_ref().layout(to)
|
|
||||||
}
|
|
||||||
fn render (&self, to: &mut E) -> Perhaps<E::Area> {
|
|
||||||
self.as_ref().render(to)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl<E: Engine, W: Widget<Engine = E>> Widget for Mutex<W> {
|
|
||||||
type Engine = E;
|
|
||||||
fn layout (&self, to: E::Area) -> Perhaps<E::Area> {
|
|
||||||
self.lock().unwrap().layout(to)
|
|
||||||
}
|
|
||||||
fn render (&self, to: &mut E) -> Perhaps<E::Area> {
|
|
||||||
self.lock().unwrap().render(to)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl<E: Engine, W: Widget<Engine = E>> Widget for RwLock<W> {
|
|
||||||
type Engine = E;
|
|
||||||
fn layout (&self, to: E::Area) -> Perhaps<E::Area> {
|
|
||||||
self.read().unwrap().layout(to)
|
|
||||||
}
|
|
||||||
fn render (&self, to: &mut E) -> Perhaps<E::Area> {
|
|
||||||
self.read().unwrap().render(to)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl<E: Engine, W: Widget<Engine = E>> Widget for Option<W> {
|
|
||||||
type Engine = E;
|
|
||||||
fn layout (&self, to: E::Area) -> Perhaps<E::Area> {
|
|
||||||
Ok(self.as_ref().map(|widget|widget.layout(to)).transpose()?.flatten())
|
|
||||||
}
|
|
||||||
fn render (&self, to: &mut E) -> Perhaps<E::Area> {
|
|
||||||
Ok(self.as_ref().map(|widget|widget.render(to)).transpose()?.flatten())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait Content: Send + Sync {
|
|
||||||
type Engine: Engine;
|
|
||||||
fn content (&self) -> impl Widget<Engine = <Self as Content>::Engine>;
|
|
||||||
}
|
|
||||||
//impl<E> Content<E> for () where E: Engine {
|
|
||||||
//fn content (&self) -> impl Widget<E> {
|
|
||||||
//()
|
|
||||||
//}
|
|
||||||
//}
|
|
||||||
impl<E: Engine, W: Content<Engine = E>> Widget for W {
|
|
||||||
type Engine = E;
|
|
||||||
fn layout (&self, to: E::Area) -> Perhaps<E::Area> {
|
|
||||||
self.content().layout(to)
|
|
||||||
}
|
|
||||||
fn render (&self, to: &mut E) -> Perhaps<E::Area> {
|
|
||||||
match self.layout(to.area())? {
|
|
||||||
Some(area) => to.render_in(area, &self.content()),
|
|
||||||
None => Ok(None)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A UI component.
|
|
||||||
pub trait Component<E: Engine>: Widget<Engine = E> + Handle<E> {}
|
|
||||||
|
|
||||||
/// Everything that implements [Render] and [Handle] is a [Component].
|
|
||||||
impl<E: Engine, C: Widget<Engine = E> + Handle<E>> Component<E> for C {}
|
|
||||||
|
|
@ -1,32 +0,0 @@
|
||||||
use crate::*;
|
|
||||||
|
|
||||||
pub trait Exit: Send {
|
|
||||||
fn exited (&self) -> bool;
|
|
||||||
fn exit (&mut self);
|
|
||||||
fn boxed (self) -> Box<dyn Exit> where Self: Sized + 'static {
|
|
||||||
Box::new(self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[macro_export] macro_rules! exit {
|
|
||||||
($T:ty) => {
|
|
||||||
impl Exit for $T {
|
|
||||||
fn exited (&self) -> bool {
|
|
||||||
self.exited
|
|
||||||
}
|
|
||||||
fn exit (&mut self) {
|
|
||||||
self.exited = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Marker trait for [Component]s that can [Exit]
|
|
||||||
pub trait ExitableComponent<E>: Exit + Component<E> where E: Engine {
|
|
||||||
/// Perform type erasure for collecting heterogeneous components.
|
|
||||||
fn boxed (self) -> Box<dyn ExitableComponent<E>> where Self: Sized + 'static {
|
|
||||||
Box::new(self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<E: Engine, C: Component<E> + Exit> ExitableComponent<E> for C {}
|
|
||||||
|
|
@ -1,7 +1,137 @@
|
||||||
use crate::*;
|
use crate::*;
|
||||||
|
|
||||||
|
pub enum Collected<'a, E: Engine> {
|
||||||
|
Box(Box<dyn Widget<Engine = E> + 'a>),
|
||||||
|
Ref(&'a (dyn Widget<Engine = E> + 'a)),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, E: Engine> Widget for Collected<'a, E> {
|
||||||
|
type Engine = E;
|
||||||
|
fn layout (&self, area: E::Area) -> Perhaps<E::Area> {
|
||||||
|
match self {
|
||||||
|
Self::Box(inner) => (*inner).layout(area),
|
||||||
|
Self::Ref(inner) => (*inner).layout(area),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn render (&self, to: &mut E) -> Perhaps<E::Area> {
|
||||||
|
match self {
|
||||||
|
Self::Box(inner) => (*inner).render(to),
|
||||||
|
Self::Ref(inner) => (*inner).render(to),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Collection<'a, E: Engine>(
|
||||||
|
pub Vec<Collected<'a, E>>
|
||||||
|
);
|
||||||
|
|
||||||
|
impl<'a, E: Engine> Collection<'a, E> {
|
||||||
|
pub fn new () -> Self {
|
||||||
|
Self(vec![])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait Collect<'a, E: Engine> {
|
||||||
|
fn add_box (self, item: Box<dyn Widget<Engine = E> + 'a>) -> Self;
|
||||||
|
fn add_ref (self, item: &'a dyn Widget<Engine = E>) -> Self;
|
||||||
|
fn add <R: Widget<Engine = E> + Sized + 'a> (self, item: R) -> Self
|
||||||
|
where Self: Sized
|
||||||
|
{
|
||||||
|
self.add_box(Box::new(item))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, E: Engine> Collect<'a, E> for Collection<'a, E> {
|
||||||
|
fn add_box (mut self, item: Box<dyn Widget<Engine = E> + 'a>) -> Self {
|
||||||
|
self.0.push(Collected::Box(item));
|
||||||
|
self
|
||||||
|
}
|
||||||
|
fn add_ref (mut self, item: &'a dyn Widget<Engine = E>) -> Self {
|
||||||
|
self.0.push(Collected::Ref(item));
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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> {
|
||||||
|
pub fn new (build: F) -> Self {
|
||||||
|
Self(build, Default::default())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[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 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Split<'a, E: Engine> {
|
||||||
|
pub items: Collection<'a, E>,
|
||||||
|
pub direction: Direction,
|
||||||
|
pub focus: Option<usize>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, E: Engine> Split<'a, E> {
|
||||||
|
pub fn new (direction: Direction) -> Self {
|
||||||
|
Self {
|
||||||
|
items: Collection::new(),
|
||||||
|
direction,
|
||||||
|
focus: None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn down () -> Self {
|
||||||
|
Self::new(Direction::Down)
|
||||||
|
}
|
||||||
|
pub fn right () -> Self {
|
||||||
|
Self::new(Direction::Right)
|
||||||
|
}
|
||||||
|
pub fn focus (mut self, focus: Option<usize>) -> Self {
|
||||||
|
self.focus = focus;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, E: Engine> Collect<'a, E> for Split<'a, E> {
|
||||||
|
fn add_box (mut self, item: Box<dyn Widget<Engine = E> + 'a>) -> Self {
|
||||||
|
self.items = self.items.add_box(item);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
fn add_ref (mut self, item: &'a dyn Widget<Engine = E>) -> Self {
|
||||||
|
self.items = self.items.add_ref(item);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Override X and Y coordinates, aligning to corner, side, or center of area
|
/// Override X and Y coordinates, aligning to corner, side, or center of area
|
||||||
pub enum Align<L> { Center(L), NW(L), N(L), NE(L), W(L), E(L), SW(L), S(L), SE(L) }
|
pub enum Align<L> {
|
||||||
|
Center(L),
|
||||||
|
NW(L),
|
||||||
|
N(L),
|
||||||
|
NE(L),
|
||||||
|
W(L),
|
||||||
|
E(L),
|
||||||
|
SW(L),
|
||||||
|
S(L),
|
||||||
|
SE(L)
|
||||||
|
}
|
||||||
|
|
||||||
impl<T> Align<T> {
|
impl<T> Align<T> {
|
||||||
pub fn inner (&self) -> &T {
|
pub fn inner (&self) -> &T {
|
||||||
|
|
@ -20,7 +150,24 @@ impl<T> Align<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Enforce minimum size of drawing area
|
/// Enforce minimum size of drawing area
|
||||||
pub enum Min<U: Number, T> { W(U, T), H(U, T), WH(U, U, T), }
|
pub enum Min<U: Number, T> {
|
||||||
|
/// Enforce minimum width
|
||||||
|
W(U, T),
|
||||||
|
/// Enforce minimum height
|
||||||
|
H(U, T),
|
||||||
|
/// Enforce minimum width and height
|
||||||
|
WH(U, U, T),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<N: Number, T> Min<N, T> {
|
||||||
|
fn inner (&self) -> &T {
|
||||||
|
match self {
|
||||||
|
Self::W(_, inner) => inner,
|
||||||
|
Self::H(_, inner) => inner,
|
||||||
|
Self::WH(_, _, inner) => inner,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<E: Engine, T: Widget<Engine = E>> Widget for Min<E::Unit, T> {
|
impl<E: Engine, T: Widget<Engine = E>> Widget for Min<E::Unit, T> {
|
||||||
type Engine = E;
|
type Engine = E;
|
||||||
|
|
@ -43,18 +190,31 @@ impl<E: Engine, T: Widget<Engine = E>> Widget for Min<E::Unit, T> {
|
||||||
// 🡘 🡙 ←🡙→
|
// 🡘 🡙 ←🡙→
|
||||||
self.layout(to.area())?
|
self.layout(to.area())?
|
||||||
.map(|area|to.with_area(area.x(), area.y(), area.w(), area.h()))
|
.map(|area|to.with_area(area.x(), area.y(), area.w(), area.h()))
|
||||||
.map(|to|match self {
|
.map(|to|self.inner().render(to))
|
||||||
Self::W(_, inner) => inner,
|
|
||||||
Self::H(_, inner) => inner,
|
|
||||||
Self::WH(_, _, inner) => inner,
|
|
||||||
}.render(to))
|
|
||||||
.transpose()
|
.transpose()
|
||||||
.map(|x|x.flatten())
|
.map(|x|x.flatten())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Enforce maximum size of drawing area
|
/// Enforce maximum size of drawing area
|
||||||
pub enum Max<U: Number, T> { W(U, T), H(U, T), WH(U, U, T), }
|
pub enum Max<U: Number, T> {
|
||||||
|
/// Enforce maximum width
|
||||||
|
W(U, T),
|
||||||
|
/// Enforce maximum height
|
||||||
|
H(U, T),
|
||||||
|
/// Enforce maximum width and height
|
||||||
|
WH(U, U, T),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<N: Number, T> Max<N, T> {
|
||||||
|
fn inner (&self) -> &T {
|
||||||
|
match self {
|
||||||
|
Self::W(_, inner) => inner,
|
||||||
|
Self::H(_, inner) => inner,
|
||||||
|
Self::WH(_, _, inner) => inner,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<E: Engine, T: Widget<Engine = E>> Widget for Max<E:: Unit, T> {
|
impl<E: Engine, T: Widget<Engine = E>> Widget for Max<E:: Unit, T> {
|
||||||
type Engine = E;
|
type Engine = E;
|
||||||
|
|
@ -76,18 +236,31 @@ impl<E: Engine, T: Widget<Engine = E>> Widget for Max<E:: Unit, T> {
|
||||||
fn render (&self, to: &mut E) -> Perhaps<E::Area> {
|
fn render (&self, to: &mut E) -> Perhaps<E::Area> {
|
||||||
self.layout(to.area())?
|
self.layout(to.area())?
|
||||||
.map(|area|to.with_area(area.x(), area.y(), area.w(), area.h()))
|
.map(|area|to.with_area(area.x(), area.y(), area.w(), area.h()))
|
||||||
.map(|to|match self {
|
.map(|to|self.inner().render(to))
|
||||||
Self::W(_, inner) => inner,
|
|
||||||
Self::H(_, inner) => inner,
|
|
||||||
Self::WH(_, _, inner) => inner,
|
|
||||||
}.render(to))
|
|
||||||
.transpose()
|
.transpose()
|
||||||
.map(|x|x.flatten())
|
.map(|x|x.flatten())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Expand drawing area
|
/// Expand drawing area
|
||||||
pub enum Outset<U: Number, T> { W(U, T), H(U, T), WH(U, U, T), }
|
pub enum Outset<N: Number, T> {
|
||||||
|
/// Increase width
|
||||||
|
W(N, T),
|
||||||
|
/// Increase height
|
||||||
|
H(N, T),
|
||||||
|
/// Increase width and height
|
||||||
|
WH(N, N, T)
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<N: Number, T> Outset<N, T> {
|
||||||
|
fn inner (&self) -> &T {
|
||||||
|
match self {
|
||||||
|
Self::W(_, inner) => inner,
|
||||||
|
Self::H(_, inner) => inner,
|
||||||
|
Self::WH(_, _, inner) => inner,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<E: Engine, T: Widget<Engine = E>> Widget for Outset<E::Unit, T> {
|
impl<E: Engine, T: Widget<Engine = E>> Widget for Outset<E::Unit, T> {
|
||||||
type Engine = E;
|
type Engine = E;
|
||||||
|
|
@ -100,25 +273,38 @@ impl<E: Engine, T: Widget<Engine = E>> Widget for Outset<E::Unit, T> {
|
||||||
item.layout([area.x(), area.y() - *h, area.w(), area.h() + *h].into())
|
item.layout([area.x(), area.y() - *h, area.w(), area.h() + *h].into())
|
||||||
},
|
},
|
||||||
Self::WH(w, h, item) => if area.x() < *w || area.y() < *h { Ok(None) } else {
|
Self::WH(w, h, item) => if area.x() < *w || area.y() < *h { Ok(None) } else {
|
||||||
item.layout([area.x()-*w, area.y() - *h, area.w() + *w, area.h() + *h].into())
|
item.layout([area.x()- *w, area.y() - *h, area.w() + *w, area.h() + *h].into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn render (&self, to: &mut E) -> Perhaps<E::Area> {
|
fn render (&self, to: &mut E) -> Perhaps<E::Area> {
|
||||||
self.layout(to.area())?
|
self.layout(to.area())?
|
||||||
.map(|area|to.with_area(area.x(), area.y(), area.w(), area.h()))
|
.map(|area|to.with_area(area.x(), area.y(), area.w(), area.h()))
|
||||||
.map(|to|match self {
|
.map(|to|self.inner().render(to))
|
||||||
Self::W(_, inner) => inner,
|
|
||||||
Self::H(_, inner) => inner,
|
|
||||||
Self::WH(_, _, inner) => inner,
|
|
||||||
}.render(to))
|
|
||||||
.transpose()
|
.transpose()
|
||||||
.map(|x|x.flatten())
|
.map(|x|x.flatten())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Shrink drawing area
|
/// Shrink drawing area
|
||||||
pub enum Inset<U: Number, T> { W(U, T), H(U, T), WH(U, U, T), }
|
pub enum Inset<N: Number, T> {
|
||||||
|
/// Decrease width
|
||||||
|
W(N, T),
|
||||||
|
/// Decrease height
|
||||||
|
H(N, T),
|
||||||
|
/// Decrease width and height
|
||||||
|
WH(N, N, T),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<N: Number, T: Widget> Inset<N, T> {
|
||||||
|
fn inner (&self) -> &T {
|
||||||
|
match self {
|
||||||
|
Self::W(_, inner) => inner,
|
||||||
|
Self::H(_, inner) => inner,
|
||||||
|
Self::WH(_, _, inner) => inner,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<E: Engine, T: Widget<Engine = E>> Widget for Inset<E::Unit, T> {
|
impl<E: Engine, T: Widget<Engine = E>> Widget for Inset<E::Unit, T> {
|
||||||
type Engine = E;
|
type Engine = E;
|
||||||
|
|
@ -138,18 +324,28 @@ impl<E: Engine, T: Widget<Engine = E>> Widget for Inset<E::Unit, T> {
|
||||||
fn render (&self, to: &mut E) -> Perhaps<E::Area> {
|
fn render (&self, to: &mut E) -> Perhaps<E::Area> {
|
||||||
self.layout(to.area())?
|
self.layout(to.area())?
|
||||||
.map(|area|to.with_area(area.x(), area.y(), area.w(), area.h()))
|
.map(|area|to.with_area(area.x(), area.y(), area.w(), area.h()))
|
||||||
.map(|to|match self {
|
.map(|to|self.inner().render(to))
|
||||||
Self::W(_, inner) => inner,
|
|
||||||
Self::H(_, inner) => inner,
|
|
||||||
Self::WH(_, _, inner) => inner,
|
|
||||||
}.render(to))
|
|
||||||
.transpose()
|
.transpose()
|
||||||
.map(|x|x.flatten())
|
.map(|x|x.flatten())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Move origin point of drawing area
|
/// Move origin point of drawing area
|
||||||
pub enum Offset<U: Number, T: Widget> { X(U, T), Y(U, T), XY(U, U, T), }
|
pub enum Offset<N: Number, T: Widget> {
|
||||||
|
X(N, T),
|
||||||
|
Y(N, T),
|
||||||
|
XY(N, N, T),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<N: Number, T: Widget> Offset<N, T> {
|
||||||
|
fn inner (&self) -> &T {
|
||||||
|
match self {
|
||||||
|
Self::X(_, inner) => inner,
|
||||||
|
Self::Y(_, inner) => inner,
|
||||||
|
Self::XY(_, _, inner) => inner,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<E: Engine, T: Widget<Engine = E>> Widget for Offset<E::Unit, T> {
|
impl<E: Engine, T: Widget<Engine = E>> Widget for Offset<E::Unit, T> {
|
||||||
type Engine = E;
|
type Engine = E;
|
||||||
|
|
@ -169,11 +365,7 @@ impl<E: Engine, T: Widget<Engine = E>> Widget for Offset<E::Unit, T> {
|
||||||
fn render (&self, to: &mut E) -> Perhaps<E::Area> {
|
fn render (&self, to: &mut E) -> Perhaps<E::Area> {
|
||||||
self.layout(to.area())?
|
self.layout(to.area())?
|
||||||
.map(|area|to.with_area(area.x(), area.y(), area.w(), area.h()))
|
.map(|area|to.with_area(area.x(), area.y(), area.w(), area.h()))
|
||||||
.map(|to|match self {
|
.map(|to|self.inner().render(to))
|
||||||
Self::X(_, inner) => inner,
|
|
||||||
Self::Y(_, inner) => inner,
|
|
||||||
Self::XY(_, _, inner) => inner,
|
|
||||||
}.render(to))
|
|
||||||
.transpose()
|
.transpose()
|
||||||
.map(|x|x.flatten())
|
.map(|x|x.flatten())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,87 +0,0 @@
|
||||||
use crate::*;
|
|
||||||
|
|
||||||
///// Render to output.
|
|
||||||
//pub trait Render<E: Engine>: Send + Sync {
|
|
||||||
//fn render (&self, to: &mut E) -> Perhaps<E::Rendered>;
|
|
||||||
//}
|
|
||||||
|
|
||||||
//impl<E: Engine> Render<E> for () {
|
|
||||||
//fn render (&self, to: &mut E) -> Perhaps<E::Rendered> {
|
|
||||||
//Ok(None)
|
|
||||||
//}
|
|
||||||
//}
|
|
||||||
|
|
||||||
///// Options can be rendered optionally.
|
|
||||||
//impl<R, E: Engine> Render<E> for Option<R> where R: Render<E> {
|
|
||||||
//fn render (&self, to: &mut E) -> Perhaps<E::Rendered> {
|
|
||||||
//match self {
|
|
||||||
//Some(component) => component.render(to),
|
|
||||||
//None => Ok(None)
|
|
||||||
//}
|
|
||||||
//}
|
|
||||||
//}
|
|
||||||
|
|
||||||
///// Boxed references can be rendered.
|
|
||||||
//impl<'a, E: Engine> Render<E> for Box<dyn Render<E> + 'a> {
|
|
||||||
//fn render (&self, to: &mut E) -> Perhaps<E::Rendered> {
|
|
||||||
//(**self).render(to)
|
|
||||||
//}
|
|
||||||
//}
|
|
||||||
//impl<'a, E: Engine> Render<E> for Box<dyn Layout<E> + 'a> {
|
|
||||||
//fn render (&self, to: &mut E) -> Perhaps<E::Rendered> {
|
|
||||||
//(**self).render(to)
|
|
||||||
//}
|
|
||||||
//}
|
|
||||||
//impl<'a, E: Engine> Render<E> for Box<dyn Component<E> + 'a> {
|
|
||||||
//fn render (&self, to: &mut E) -> Perhaps<E::Rendered> {
|
|
||||||
//(**self).render(to)
|
|
||||||
//}
|
|
||||||
//}
|
|
||||||
|
|
||||||
///// Immutable references can be rendered.
|
|
||||||
//impl<R, E: Engine> Render<E> for &R where R: Render<E> {
|
|
||||||
//fn render (&self, to: &mut E) -> Perhaps<E::Rendered> {
|
|
||||||
//(*self).render(to)
|
|
||||||
//}
|
|
||||||
//}
|
|
||||||
|
|
||||||
///// Mutable references can be rendered.
|
|
||||||
//impl<R, E: Engine> Render<E> for &mut R where R: Render<E> {
|
|
||||||
//fn render (&self, to: &mut E) -> Perhaps<E::Rendered> {
|
|
||||||
//(**self).render(to)
|
|
||||||
//}
|
|
||||||
//}
|
|
||||||
|
|
||||||
///// Counted references can be rendered.
|
|
||||||
//impl<R, E: Engine> Render<E> for Arc<R> where R: Render<E> {
|
|
||||||
//fn render (&self, to: &mut E) -> Perhaps<E::Rendered> {
|
|
||||||
//self.as_ref().render(to)
|
|
||||||
//}
|
|
||||||
//}
|
|
||||||
|
|
||||||
///// References behind a [Mutex] can be rendered.
|
|
||||||
//impl<R, E: Engine> Render<E> for Mutex<R> where R: Render<E> {
|
|
||||||
//fn render (&self, to: &mut E) -> Perhaps<E::Rendered> {
|
|
||||||
//self.lock().unwrap().render(to)
|
|
||||||
//}
|
|
||||||
//}
|
|
||||||
|
|
||||||
///// References behind a [RwLock] can be rendered.
|
|
||||||
//impl<R, E: Engine> Render<E> for RwLock<R> where R: Render<E> {
|
|
||||||
//fn render (&self, to: &mut E) -> Perhaps<E::Rendered> {
|
|
||||||
//self.read().unwrap().render(to)
|
|
||||||
//}
|
|
||||||
//}
|
|
||||||
|
|
||||||
// FIXME: components are now 2 thunks (layout and render).
|
|
||||||
// maybe this resolves the conflict describe below?
|
|
||||||
///// Boxed closures can be rendered.
|
|
||||||
/////
|
|
||||||
///// Rendering unboxed closures should also be possible;
|
|
||||||
///// but in practice implementing the trait for an unboxed
|
|
||||||
///// `Fn` closure causes an impl conflict.
|
|
||||||
//impl<'a, E: Engine> Render<E> for Box<dyn Fn(&mut E) -> Perhaps<E::Rendered> + Send + Sync + 'a> {
|
|
||||||
//fn render (&self, to: &mut E) -> Perhaps<E::Rendered> {
|
|
||||||
//(*self)(to)
|
|
||||||
//}
|
|
||||||
//}
|
|
||||||
|
|
@ -58,6 +58,19 @@ where
|
||||||
F: Send + Sync + Fn(&mut dyn FnMut(&dyn Widget<Engine = Tui>)->Usually<()>)->Usually<()>
|
F: Send + Sync + Fn(&mut dyn FnMut(&dyn Widget<Engine = Tui>)->Usually<()>)->Usually<()>
|
||||||
{
|
{
|
||||||
type Engine = Tui;
|
type Engine = Tui;
|
||||||
|
fn layout (&self, area: [u16;4]) -> Perhaps<[u16;4]> {
|
||||||
|
let [x, y, ..] = area;
|
||||||
|
let mut w = 0;
|
||||||
|
let mut h = 0;
|
||||||
|
(self.0)(&mut |layer| {
|
||||||
|
if let Some(layer_area) = layer.layout(area)? {
|
||||||
|
w = w.max(layer_area.w());
|
||||||
|
h = h.max(layer_area.h());
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
})?;
|
||||||
|
Ok(Some([x, y, w, h]))
|
||||||
|
}
|
||||||
fn render (&self, to: &mut Tui) -> Perhaps<[u16;4]> {
|
fn render (&self, to: &mut Tui) -> Perhaps<[u16;4]> {
|
||||||
self.layout(to.area())?
|
self.layout(to.area())?
|
||||||
.map(|area|(self.0)(&mut |layer| {
|
.map(|area|(self.0)(&mut |layer| {
|
||||||
|
|
@ -74,9 +87,10 @@ impl<T: Widget<Engine = Tui>> Widget for Align<T> {
|
||||||
Ok(self.inner().layout(outer_area)?.map(|inner_area|match self {
|
Ok(self.inner().layout(outer_area)?.map(|inner_area|match self {
|
||||||
Self::Center(_) => {
|
Self::Center(_) => {
|
||||||
let [_, _, w, h] = inner_area.xywh();
|
let [_, _, w, h] = inner_area.xywh();
|
||||||
let offset_x = (outer_area.w() - w) / 2;
|
let offset_x = (outer_area.w() / 2).saturating_sub(w / 2);
|
||||||
let offset_y = (outer_area.h() - h) / 2;
|
let offset_y = (outer_area.h() / 2).saturating_sub(h / 2);
|
||||||
[outer_area.x() + offset_x, outer_area.y() + offset_y, w, h]
|
let result = [outer_area.x() + offset_x, outer_area.y() + offset_y, w, h];
|
||||||
|
result
|
||||||
},
|
},
|
||||||
Self::NW(_) => { todo!() },
|
Self::NW(_) => { todo!() },
|
||||||
Self::N(_) => { todo!() },
|
Self::N(_) => { todo!() },
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,14 @@ pub struct AddSampleModal {
|
||||||
_search: Option<String>,
|
_search: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
exit!(AddSampleModal);
|
impl Exit for AddSampleModal {
|
||||||
|
fn exited (&self) -> bool {
|
||||||
|
self.exited
|
||||||
|
}
|
||||||
|
fn exit (&mut self) {
|
||||||
|
self.exited = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Widget for AddSampleModal {
|
impl Widget for AddSampleModal {
|
||||||
type Engine = Tui;
|
type Engine = Tui;
|
||||||
|
|
@ -63,6 +70,7 @@ impl Widget for AddSampleModal {
|
||||||
//Lozenge(Style::default()).draw(to)
|
//Lozenge(Style::default()).draw(to)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Handle<Tui> for AddSampleModal {
|
impl Handle<Tui> for AddSampleModal {
|
||||||
fn handle (&mut self, from: &Tui) -> Perhaps<bool> {
|
fn handle (&mut self, from: &Tui) -> Perhaps<bool> {
|
||||||
if handle_keymap(self, &from.event(), KEYMAP_ADD_SAMPLE)? {
|
if handle_keymap(self, &from.event(), KEYMAP_ADD_SAMPLE)? {
|
||||||
|
|
|
||||||
|
|
@ -37,15 +37,15 @@ impl Content for Demo<Tui> {
|
||||||
//Align::Center("FOO")
|
//Align::Center("FOO")
|
||||||
//Layers2::new(|_|Ok(()))
|
//Layers2::new(|_|Ok(()))
|
||||||
//Layers2::new(|add|add(&Align::Center("FOO")))
|
//Layers2::new(|add|add(&Align::Center("FOO")))
|
||||||
Layers::new(|add|{
|
//Align::Center(&self.items[self.index] as &dyn Widget<Engine = Tui>)
|
||||||
add(&FillBg(Color::Rgb(0,128,128)))?;
|
Align::Center(Layers::new(|add|{
|
||||||
|
add(&Outset::WH(1, 1, FillBg(Color::Rgb(0,128,128))))?;
|
||||||
add(&Layers::new(|add|{
|
add(&Layers::new(|add|{
|
||||||
add(&Align::Center("....."))?;
|
add(&Align::Center("....."))?;
|
||||||
add(&Align::Center("FOO"))?;
|
add(&Align::Center("FOO"))?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}))
|
}))
|
||||||
})
|
}))
|
||||||
//Align::Center(&self.items[self.index] as &dyn Widget<Engine = Tui>)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue