wip: removing Render and Layout from core

This commit is contained in:
🪞👃🪞 2024-09-09 15:12:34 +03:00
parent c4a5ee7b6e
commit eeb323b742
11 changed files with 148 additions and 165 deletions

View file

@ -16,13 +16,13 @@ pub trait Device<E: Engine>: Component<E> + Process {
}
/// All things that implement the required traits can be treated as `Device`.
impl<D, E: Engine> Device<E> for D where D: Component<E> + Process {}
impl<E: Engine, W: Widget<Engine = E> + Process> Device<E> for W {}
impl<'a, E: Engine> Render<E> for Box<dyn Device<E> + 'a> {
fn render (&self, to: &mut E) -> Perhaps<E::Rendered> {
(**self).render(to)
}
}
//impl<'a, E: Engine> Render<E> for Box<dyn Device<E> + 'a> {
//fn render (&self, to: &mut E) -> Perhaps<E::Rendered> {
//(**self).render(to)
//}
//}
/// Wraps [Client] or [DynamicAsyncClient] in place.
pub enum JackClient {

View file

@ -16,7 +16,7 @@ impl<E: Engine> std::fmt::Debug for JackDevice<E> {
f.debug_struct("JackDevice").field("ports", &self.ports).finish()
}
}
impl<E: Engine> Render<E> for JackDevice<E> {
impl<E: Engine> Widget for JackDevice<E> {
fn render (&self, to: &mut E) -> Perhaps<E::Rendered> {
self.state.read().unwrap().render(to)
}

View file

@ -35,5 +35,5 @@ submod! {
handle
keymap
layout
render
//render
}

View file

@ -1,25 +1,24 @@
use crate::*;
pub enum Collected<'a, E: Engine> {
Box(Box<dyn Layout<E> + 'a>),
Ref(&'a (dyn Layout<E> + 'a)),
Box(Box<dyn Widget<Engine = E> + 'a>),
Ref(&'a (dyn Widget<Engine = E> + 'a)),
}
impl<'a, E: Engine> Render<E> for Collected<'a, E> {
fn render (&self, to: &mut E) -> Perhaps<E::Rendered> {
match self {
Self::Box(inner) => (*inner).render(to),
Self::Ref(inner) => (*inner).render(to),
}
}
}
impl<'a, E: Engine> Layout<E> for Collected<'a, E> {
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::Rendered> {
match self {
Self::Box(inner) => (*inner).render(to),
Self::Ref(inner) => (*inner).render(to),
}
}
}
pub struct Collection<'a, E: Engine>(
@ -33,9 +32,9 @@ impl<'a, E: Engine> Collection<'a, E> {
}
pub trait Collect<'a, E: Engine> {
fn add_box (self, item: Box<dyn Layout<E> + 'a>) -> Self;
fn add_ref (self, item: &'a dyn Layout<E>) -> Self;
fn add <R: Layout<E> + Sized + 'a> (self, item: R) -> Self
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))
@ -43,17 +42,17 @@ pub trait Collect<'a, E: Engine> {
}
impl<'a, E: Engine> Collect<'a, E> for Collection<'a, E> {
fn add_box (mut self, item: Box<dyn Layout<E> + 'a>) -> Self {
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 Layout<E>) -> Self {
fn add_ref (mut self, item: &'a dyn Widget<Engine = E>) -> Self {
self.0.push(Collected::Ref(item));
self
}
}
pub struct Layers<'a, E: Engine>(pub &'a [&'a dyn Layout<E>]);
pub struct Layers<'a, E: Engine>(pub &'a [&'a dyn Widget<Engine = E>]);
// this actually works, except for the type inference
//pub struct Layers<'a, E: Engine + 'a, I: std::iter::IntoIterator<Item = &'a dyn Render<E>>>(
@ -69,11 +68,11 @@ impl<'a, E: Engine> Layered<'a, E> {
}
impl<'a, E: Engine> Collect<'a, E> for Layered<'a, E> {
fn add_box (mut self, item: Box<dyn Layout<E> + 'a>) -> Self {
fn add_box (mut self, item: Box<dyn Widget<Engine = E> + 'a>) -> Self {
self.0 = self.0.add_box(item);
self
}
fn add_ref (mut self, item: &'a dyn Layout<E>) -> Self {
fn add_ref (mut self, item: &'a dyn Widget<Engine = E>) -> Self {
self.0 = self.0.add_ref(item);
self
}
@ -118,11 +117,11 @@ impl<'a, E: Engine> Split<'a, E> {
}
impl<'a, E: Engine> Collect<'a, E> for Split<'a, E> {
fn add_box (mut self, item: Box<dyn Layout<E> + 'a>) -> Self {
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 Layout<E>) -> Self {
fn add_ref (mut self, item: &'a dyn Widget<Engine = E>) -> Self {
self.items = self.items.add_ref(item);
self
}

View file

@ -1,10 +1,10 @@
use crate::*;
/// A UI component.
pub trait Component<E: Engine>: Render<E> + Handle<E> + Layout<E> {}
pub trait Component<E: Engine>: Widget<Engine = E> + Handle<E> {}
/// Everything that implements [Render] and [Handle] is a [Component].
impl<E: Engine, C: Render<E> + Handle<E> + Layout<E>> Component<E> for C {}
impl<E: Engine, C: Widget<Engine = E> + Handle<E>> Component<E> for C {}
/// Marker trait for [Component]s that can [Exit]
pub trait ExitableComponent<E>: Exit + Component<E> where E: Engine {

View file

@ -1,7 +1,7 @@
use crate::*;
/// A component that may contain [Focusable] components.
pub trait Focus <const N: usize, E: Engine>: Render<E> + Handle<E> {
pub trait Focus <const N: usize, E: Engine>: Widget<Engine = E> + Handle<E> {
fn focus (&self) -> usize;
fn focus_mut (&mut self) -> &mut usize;
fn focusable (&self) -> [&dyn Focusable<E>;N];
@ -33,13 +33,13 @@ pub trait Focus <const N: usize, E: Engine>: Render<E> + Handle<E> {
}
/// A component that may be focused.
pub trait Focusable<E: Engine>: Render<E> + Handle<E> {
pub trait Focusable<E: Engine>: Widget<Engine = E> + Handle<E> {
fn is_focused (&self) -> bool;
fn set_focused (&mut self, focused: bool);
}
impl<F: Focusable<E>, E: Engine> Focusable<E> for Option<F>
where Option<F>: Render<E>
where Option<F>: Widget<Engine = E>
{
fn is_focused (&self) -> bool {
match self {

View file

@ -2,46 +2,46 @@ use crate::*;
// TODO: Convert to component
// pub enum Align { Center, NW, N, NE, E, SE, S, SW, W, }
pub fn center_box (area: [u16;4], w: u16, h: u16) -> [u16;4] {
let width = w.min(area.w() * 3 / 5);
let height = h.min(area.w() * 3 / 5);
let x = area.x() + (area.w() - width) / 2;
let y = area.y() + (area.h() - height) / 2;
[x, y, width, height]
}
//pub fn center_box (area: [u16;4], w: u16, h: u16) -> [u16;4] {
//let width = w.min(area.w() * 3 / 5);
//let height = h.min(area.w() * 3 / 5);
//let x = area.x() + (area.w() - width) / 2;
//let y = area.y() + (area.h() - height) / 2;
//[x, y, width, height]
//}
/// Trait for structs that compute drawing area before rendering
pub trait Layout<E: Engine>: Render<E> {
fn layout (&self, area: E::Area) -> Perhaps<E::Area>;
}
impl<'a, E: Engine> Layout<E> for Box<dyn Layout<E> + 'a> {
fn layout (&self, area: E::Area) -> Perhaps<E::Area> {
(**self).layout(area)
}
}
impl<'a, E: Engine> Layout<E> for Box<dyn Component<E> + 'a> {
fn layout (&self, area: E::Area) -> Perhaps<E::Area> {
(**self).layout(area)
}
}
impl<E: Engine, T: Layout<E>> Layout<E> for &T {
fn layout (&self, area: E::Area) -> Perhaps<E::Area> {
(*self).layout(area)
}
}
impl<E: Engine, T: Layout<E>> Layout<E> for &mut T {
fn layout (&self, area: E::Area) -> Perhaps<E::Area> {
(**self).layout(area)
}
}
impl<E: Engine, T: Layout<E>> Layout<E> for Option<T> {
fn layout (&self, area: E::Area) -> Perhaps<E::Area> {
match self {
Some(layout) => layout.layout(area),
None => Ok(None)
}
}
}
///// Trait for structs that compute drawing area before rendering
//pub trait Layout<E: Engine>: Render<E> {
//fn layout (&self, area: E::Area) -> Perhaps<E::Area>;
//}
//impl<'a, E: Engine> Layout<E> for Box<dyn Layout<E> + 'a> {
//fn layout (&self, area: E::Area) -> Perhaps<E::Area> {
//(**self).layout(area)
//}
//}
//impl<'a, E: Engine> Layout<E> for Box<dyn Component<E> + 'a> {
//fn layout (&self, area: E::Area) -> Perhaps<E::Area> {
//(**self).layout(area)
//}
//}
//impl<E: Engine, T: Layout<E>> Layout<E> for &T {
//fn layout (&self, area: E::Area) -> Perhaps<E::Area> {
//(*self).layout(area)
//}
//}
//impl<E: Engine, T: Layout<E>> Layout<E> for &mut T {
//fn layout (&self, area: E::Area) -> Perhaps<E::Area> {
//(**self).layout(area)
//}
//}
//impl<E: Engine, T: Layout<E>> Layout<E> for Option<T> {
//fn layout (&self, area: E::Area) -> Perhaps<E::Area> {
//match self {
//Some(layout) => layout.layout(area),
//None => Ok(None)
//}
//}
//}
/// 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) }

View file

@ -1,77 +1,77 @@
use crate::*;
/// Render to output.
pub trait Render<E: Engine>: Send + Sync {
fn render (&self, to: &mut E) -> Perhaps<E::Rendered>;
}
///// 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)
}
}
//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)
}
}
}
///// 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)
}
}
///// 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)
}
}
///// 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)
}
}
///// 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)
}
}
///// 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 [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)
}
}
///// 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?

View file

@ -98,12 +98,11 @@ macro_rules! border {
const SE: &'static str = $se;
$($x)*
}
impl Layout<Tui> for $T {
impl Widget for $T {
type Engine = Tui;
fn layout (&self, area: [u16;4]) -> Perhaps<[u16;4]> {
Ok(Some(area))
}
}
impl Render<Tui> for $T {
fn render (&self, to: &mut Tui) -> Perhaps<[u16;4]> {
self.draw(to)
}

View file

@ -1,14 +1,12 @@
use crate::*;
impl Layout<Tui> for &str {
impl Widget for &str {
type Engine = Tui;
fn layout (&self, area: [u16;4]) -> Perhaps<[u16;4]> {
let [x, y, ..] = area;
// TODO: line breaks
Ok(Some([x, y, self.len() as u16, 1]))
}
}
impl Render<Tui> for &str {
fn render (&self, to: &mut Tui) -> Perhaps<[u16;4]> {
let area = self.layout(to.area())?.unwrap();
to.blit(&self, area.x(), area.y(), None)?;
@ -16,15 +14,13 @@ impl Render<Tui> for &str {
}
}
pub struct Styled<T: Layout<Tui>>(pub Option<Style>, pub T);
pub struct Styled<T: Widget<Engine = Tui>>(pub Option<Style>, pub T);
impl Layout<Tui> for Styled<&str> {
impl Widget for Styled<&str> {
type Engine = Tui;
fn layout (&self, area: [u16;4]) -> Perhaps<[u16;4]> {
Ok(Some([area.x(), area.y(), self.1.len() as u16, 1]))
}
}
impl Render<Tui> for Styled<&str> {
fn render (&self, to: &mut Tui) -> Perhaps<[u16;4]> {
let area = self.layout(to.area())?.unwrap();
Ok(Some([area.x(), area.y(), self.1.len() as u16, 1]))
@ -33,12 +29,11 @@ impl Render<Tui> for Styled<&str> {
pub struct FillBg(pub Color);
impl Layout<Tui> for FillBg {
impl Widget for FillBg {
type Engine = Tui;
fn layout (&self, area: [u16;4]) -> Perhaps<[u16;4]> {
Ok(Some(area))
}
}
impl Render<Tui> for FillBg {
fn render (&self, to: &mut Tui) -> Perhaps<[u16;4]> {
to.fill_bg(to.area(), self.0);
Ok(Some(to.area))

View file

@ -1,25 +1,15 @@
use crate::*;
impl<'a> Render<Tui> for Layered<'a, Tui> {
fn render (&self, to: &mut Tui) -> Perhaps<[u16;4]> {
let area = to.area();
for layer in self.0.0.iter() {
layer.render(to)?;
}
Ok(Some(area))
}
}
impl<'a> Layout<Tui> for Split<'a, Tui> {
impl<'a> Widget for Split<'a, Tui> {
type Engine = Tui;
fn layout (&self, area: [u16;4]) -> Perhaps<[u16;4]> {
todo!()
}
}
impl<'a> Render<Tui> for Split<'a, Tui> {
fn render (&self, to: &mut Tui) -> Perhaps<[u16;4]> {
Ok(Some(self.render_areas(to)?.0))
}
}
// TODO
impl<'a> Split<'a, Tui> {
pub fn render_areas (&self, to: &mut Tui) -> Usually<([u16;4], Vec<Option<[u16;4]>>)> {