TuiThread factors out poll/sleep/perf details
Some checks failed
/ build (push) Has been cancelled

This commit is contained in:
same mf who else 2026-03-06 12:59:07 +02:00
parent f1dda6af07
commit ecba0cc64f
5 changed files with 322 additions and 270 deletions

View file

@ -2,56 +2,51 @@ pub use self::logical::*; mod logical {
use crate::*;
/// Thunks can be natural error boundaries!
///
/// ```
/// let _ = tengri::ErrorBoundary::<tengri::Tui, &'static str>::new(Ok(Some("hello")));
/// let _ = tengri::ErrorBoundary::<tengri::Tui, &'static str>::new(Ok(None));
/// let _ = tengri::ErrorBoundary::<tengri::Tui, &'static str>::new(Err("draw fail".into()));
/// ```
pub struct ErrorBoundary<O: Out, T: Draw<O>>(
pub std::marker::PhantomData<O>,
pub Perhaps<T>
);
// TODO DOCUMENTME
pub struct Lazy<O, T, F>(
pub F,
pub PhantomData<(O, T)>
);
// TODO DOCUMENTME
pub struct Thunk<O: Out, F: Fn(&mut O)>(
pub Perhaps<T>,
pub PhantomData<O>,
pub F
);
// TODO DOCUMENTME
/// Late-evaluate a rendering.
///
/// ```
/// let _ = tengri::Thunk::<tengri::Tui, _>::new(|out|{});
/// ```
pub struct Thunk<O: Out, F: Fn(&mut O)>(
pub F,
pub PhantomData<O>,
);
/// Memoize a rendering.
///
/// ```
/// let _ = tengri::Memo::new((), ());
/// ```
#[derive(Debug, Default)] pub struct Memo<T, U> {
pub value: T,
pub view: Arc<RwLock<U>>
}
}
pub use self::temporal::*; mod temporal {
use crate::*;
/// Performance counter
#[derive(Debug)]
pub struct PerfModel {
pub enabled: bool,
pub clock: quanta::Clock,
// In nanoseconds. Time used by last iteration.
pub used: AtomicF64,
// In microseconds. Max prescribed time for iteration (frame, chunk...).
pub window: AtomicF64,
}
}
pub use self::spatial::*; mod spatial {
use crate::*;
// TODO DOCUMENTME
pub struct Bordered<S, W>(pub bool, pub S, pub W);
// TODO DOCUMENTME
pub struct Border<S>(pub bool, pub S);
/// A binary split or layer.
///
/// ```
/// let _ = tengri::Bsp::n((), ());
/// let _ = tengri::Bsp::s((), ());
/// let _ = tengri::Bsp::e((), ());
/// let _ = tengri::Bsp::w((), ());
/// let _ = tengri::Bsp::a((), ());
/// let _ = tengri::Bsp::b((), ());
/// ```
pub struct Bsp<Head, Tail>(
/// Direction of split
pub(crate) Direction,
@ -118,7 +113,7 @@ pub use self::spatial::*; mod spatial {
/// A widget that tracks its rendered width and height.
///
/// ```
/// let measure = tengri::Measure::<tengri::TuiOut>::default();
/// let measure = tengri::Measure::<tengri::Tui>::default();
/// ```
#[derive(Default)] pub struct Measure<O: Out> {
pub __: PhantomData<O>,
@ -129,7 +124,7 @@ pub use self::spatial::*; mod spatial {
/// Show an item only when a condition is true.
///
/// ```
/// fn test () -> impl tengri::Draw<tengri::TuiOut> {
/// fn test () -> impl tengri::Draw<tengri::Tui> {
/// tengri::when(true, "Yes")
/// }
/// ```
@ -141,7 +136,7 @@ pub use self::spatial::*; mod spatial {
/// Show one item if a condition is true and another if the condition is false.
///
/// ```
/// fn test () -> impl tengri::Draw<tengri::TuiOut> {
/// fn test () -> impl tengri::Draw<tengri::Tui> {
/// tengri::either(true, "Yes", "No")
/// }
/// ```
@ -212,7 +207,7 @@ pub use self::spatial::*; mod spatial {
/// ```
/// use ::tengri::*;
/// let area = XYWH(10u16, 10, 20, 20);
/// fn test (area: XYWH<u16>, item: &impl Draw<TuiOut>, expected: [u16;4]) {
/// fn test (area: XYWH<u16>, item: &impl Draw<Tui>, expected: [u16;4]) {
/// //assert_eq!(Lay::layout(item, area), expected);
/// //assert_eq!(Draw::layout(item, area), expected);
/// };
@ -242,13 +237,19 @@ pub use self::spatial::*; mod spatial {
// TODO DOCUMENTME
pub enum Pad<U, A> { X(U, A), Y(U, A), XY(U, U, A), }
// TODO DOCUMENTME
pub struct Bordered<S, W>(pub bool, pub S, pub W);
// TODO DOCUMENTME
pub struct Border<S>(pub bool, pub S);
/// TODO DOCUMENTME
///
/// ```
/// use tengri::{Bounded, XYWH};
/// let area = XYWH(0, 0, 0, 0);
/// let content = "";
/// let bounded: Bounded<tengri::TuiOut, _> = Bounded(area, content);
/// let bounded: Bounded<tengri::Tui, _> = Bounded(area, content);
/// ```
pub struct Bounded<O: Out, D>(pub XYWH<O::Unit>, pub D);
@ -314,24 +315,26 @@ pub use self::spatial::*; mod spatial {
/// # Ok(()) }
/// ```
pub struct Tui {
/// Exit flag
pub exited: Arc<AtomicBool>,
pub backend: CrosstermBackend<Box<dyn Write + Send + Sync>>,
pub buffer: Buffer,
pub area: [u16;4],
/// Error message
pub error: Option<Arc<str>>,
/// Performance counter
pub perf: PerfModel,
/// Ratatui backend
pub backend: RwLock<CrosstermBackend<Box<dyn Write + Send + Sync>>>,
/// Current tnput event
pub event: Option<TuiEvent>,
/// Current output buffer
pub buffer: RwLock<Buffer>,
/// FIXME unused?
pub area: XYWH<u16>,
}
/// The TUI input event source.
///
/// ```
/// use ::{tengri::{TuiIn, TuiEvent}, std::sync::Arc};
/// let tui_in = TuiIn { event: 'f'.into(), exited: Arc::new(false.into()) };
/// ```
#[derive(Debug, Clone)] pub struct TuiIn {
/// Input event
pub event: TuiEvent,
/// Exit flag
pub exited: Arc<AtomicBool>,
#[derive(Debug)] pub struct TuiThread {
pub exit: Arc<AtomicBool>,
pub perf: Arc<PerfModel>,
pub join: JoinHandle<()>,
}
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd)] pub struct TuiEvent(
@ -343,16 +346,6 @@ pub use self::spatial::*; mod spatial {
pub KeyModifiers
);
/// The TUI output render target.
///
/// ```
/// let tui_out = tengri::TuiOut::default();
/// ```
#[derive(Default)] pub struct TuiOut {
pub buffer: Buffer,
pub area: XYWH<u16>,
}
/// TUI buffer sized by `usize` instead of `u16`.
#[derive(Default)] pub struct BigBuffer {
pub width: usize,
@ -499,3 +492,19 @@ mod textual {
pub type BoxedJackEventHandler<'j> =
Box<dyn Fn(JackEvent) + Send + Sync + 'j>;
}
pub use self::temporal::*; mod temporal {
use crate::*;
/// Performance counter
#[derive(Debug)]
pub struct PerfModel {
pub clock: quanta::Clock,
/// Measurement has a small cost. Disable it here.
pub enabled: bool,
// In nanoseconds. Time used by last iteration.
pub used: AtomicF64,
// In microseconds. Max prescribed time for iteration (frame, chunk...).
pub window: AtomicF64,
}
}