output: update README

This commit is contained in:
🪞👃🪞 2025-08-23 12:42:51 +03:00
parent d92e5efdd0
commit 3e2b07158c
5 changed files with 28 additions and 79 deletions

View file

@ -1,75 +1,20 @@
# `tengri_output` ***tengri_output*** is an abstract interface layout framework.
## free floating layout primitives it expresses the following notions:
this crate exposes several layout operators * [**space:**](./src/space.rs) `Direction`, `Coordinate`, `Area`, `Size`, `Measure`
which work entirely in unsigned coordinates
and are generic over the trait `Content`.
most importantly, they are not dependent on rendering framework.
|operator|description| * [**output:**](./src/output.rs) `Output`, `Render`, `Content`
|-|-| * the layout operators are generic over `Render` and/or `Content`
|**`When(x, a)`**|render `a` only when `x == true`| * the traits `Render` and `Content` are generic over `Output`
|**`Either(x, a, b)`**|render `a` when `x == true`, otherwise render `b`| * implement `Output` to bring a layout to a new backend:
|**`Map(get_iterator, callback)`**|transform items in uniform way| [see `TuiOut` in `tengri_tui`](../tui/src/tui_engine/tui_output.rs)
|**`Bsp`**|concatenative layout|
|...|...|
|**`Align`**|pin content along axis|
|...|...|
|**`Fill`**|**make content's dimension equal to container's:**|
|`Fill::x(a)`|use container's width for content|
|`Fill::y(a)`|use container's height for content|
|`Fill::xy(a)`|use container's width and height for content|
|**`Fixed`**|**assign fixed dimension to content:**|
|`Fixed::x(w, a)`|use width `w` for content|
|`Fixed::y(w, a)`|use height `w` for content|
|`Fixed::xy(w, h, a)`|use width `w` and height `h` for content|
|**`Expand`/`Shrink`**|**change dimension of content:**|
|`Expand::x(n, a)`/`Shrink::x(n, a)`|increment/decrement width of content area by `n`|
|`Expand::y(n, a)`/`Shrink::y(n, a)`|increment/decrement height of content area by `m`|
|`Expand::xy(n, m, a)`/`Shrink::xy(n, m, a)`|increment/decrement width of content area by `n`, height by `m`|
|**`Min`/`Max`**|**constrain dimension of content:**|
|`Min::x(w, a)`/`Max::x(w, a)`|enforce minimum/maximum width `w` for content|
|`Min::y(h, a)`/`Max::y(h, a)`|enforce minimum/maximum height `h` for content|
|`Min::xy(w, h, a)`/`Max::xy(w, h, a)`|enforce minimum/maximum width `w` and height `h` for content|
|**`Push`/`Pull`**|**move content along axis:**|
|`Push::x(n, a)`/`Pull::x(n, a)`|increment/decrement `x` of content area|
|`Push::y(n, a)`/`Pull::y(n, a)`|increment/decrement `y` of content area|
|`Push::xy(n, m, a)`/`Pull::xy(n, m, a)`|increment/decrement `x` and `y` of content area|
**todo:** * [**layout:**](./src/layout.rs)
* sensible `Margin`/`Padding` * conditionals: `When`, `Either`
* `Reduce` * iteration: `Map`
* concatenation: `Bsp`
## example rendering loop * positioning: `Align`, `Push`, `Pull`
* sizing: `Fill`, `Fixed`, `Expand`, `Shrink`, `Min`, `Max`
the **render thread** continually invokes the * implement custom components (that may be backend-dependent):
`Content::render` method of the application [see `tui_content` in `tengri_tui`](../tui/src/tui_content)
to redraw the display. it does this efficiently
by using ratatui's double buffering.
thus, for a type to be a valid application for engine `E`,
it must implement the trait `Content<E>`, which allows
it to display content to the engine's output.
the most important thing about the `Content` trait is that
it composes:
* you can implement `Content::content` to build
`Content`s out of other `Content`s
* and/or `Content::area` for custom positioning and sizing,
* and/or `Content::render` for custom rendering
within the given `Content`'s area.
the manner of output is determined by the
`Engine::Output` type, a mutable pointer to which
is passed to the render method, e.g. in the case of
the `Tui` engine: `fn render(&self, output: &mut TuiOut)`
you can use `TuiOut::blit` and `TuiOut::place`
to draw at specified coordinates of the display, and/or
directly modify the underlying `ratatui::Buffer` at
`output.buffer`
rendering is intended to work with read-only access
to the application state. if you really need to update
values during rendering, use interior mutability.

View file

@ -10,7 +10,7 @@ pub(crate) use tengri_core::*;
#[cfg(feature = "dsl")] pub(crate) use ::tengri_dsl::*; #[cfg(feature = "dsl")] pub(crate) use ::tengri_dsl::*;
mod space; pub use self::space::*; mod space; pub use self::space::*;
mod ops; pub use self::ops::*; mod layout; pub use self::layout::*;
mod output; pub use self::output::*; mod output; pub use self::output::*;
#[cfg(test)] mod test; #[cfg(test)] mod test;

View file

@ -47,7 +47,7 @@ impl<E: Output, C: Content<E>> Render<E> for C {
/// Opaque pointer to a renderable living on the heap. /// Opaque pointer to a renderable living on the heap.
/// ///
/// Return this from [Content::content] to use dynamic dispatch. /// Return this from [Content::content] to use dynamic dispatch.
pub type RenderBox<E> = Box<RenderDyn<E>>; pub type RenderBox<E> = Box<dyn Render<E>>;
/// You can render from a box. /// You can render from a box.
impl<E: Output> Content<E> for RenderBox<E> { impl<E: Output> Content<E> for RenderBox<E> {
@ -55,11 +55,8 @@ impl<E: Output> Content<E> for RenderBox<E> {
//fn boxed <'b> (self) -> RenderBox<'b, E> where Self: Sized + 'b { self } //fn boxed <'b> (self) -> RenderBox<'b, E> where Self: Sized + 'b { self }
} }
/// Opaque pointer to a renderable.
pub type RenderDyn<E> = dyn Render<E>;
/// You can render from an opaque pointer. /// You can render from an opaque pointer.
impl<E: Output> Content<E> for &RenderDyn<E> where Self: Sized { impl<E: Output> Content<E> for &dyn Render<E> where Self: Sized {
fn content (&self) -> impl Render<E> + '_ { fn content (&self) -> impl Render<E> + '_ {
#[allow(suspicious_double_ref_op)] #[allow(suspicious_double_ref_op)]
self.deref() self.deref()

View file

@ -1,3 +1,10 @@
# tengri ***tengri*** is a metaframework for building interactive applications with rust. (aren't we all?)
an interface metaframework. currently supports ratatui. tengri is developed as part of [***tek***](https://codeberg.org/unspeaker/tek),
a music program for terminals.
tengri contains:
* [***dizzle***](./dsl), a framework for defining domain-specific languages.
* [***output***](./output), an abstract UI layout framework.
* [***input***](./input), an abstract UI event framework.
* [***tui***](./tui), an implementation of tengri over [***ratatui***](https://ratatui.rs/).