Struct Runtime

Source
pub struct Runtime<A> {
    pub runtime: RuntimeHandle<A>,
    pub tree: ElementTree<A>,
    pub root: Option<ElementId>,
}
Expand description

Per-window or per-root retained pipeline for reconciliation, layout, and paint.

A runtime owns one ElementTree namespace allocated from a clonable RuntimeHandle. It is UI-thread-oriented: component/widget callbacks run synchronously, while the handle supplies thread-safe queues and invalidation ingress. Dropping this value releases the tree scope and its scoped runtime state.

§Examples

use ailloli_ui_runtime::app::{Runtime, RuntimeHandle};
let runtime = Runtime::new(RuntimeHandle::<()>::new());
assert!(runtime.root.is_none());
assert!(runtime.tree.root().is_none());

Fields§

§runtime: RuntimeHandle<A>

Handle bound to this runtime’s retained-tree namespace.

§tree: ElementTree<A>

Mutable retained elements, geometry, dirty flags, and work diagnostics.

§root: Option<ElementId>

Current reconciled root, or None before the first reconciliation.

Implementations§

Source§

impl<A: 'static> Runtime<A>

Retained frame-stage operations for application payload type A.

Source

pub fn new(runtime: RuntimeHandle<A>) -> Self

Allocates a retained-tree scope from runtime and starts empty.

The stored handle shares application state and service registrations with the supplied handle, but receives the next allocated tree identity. Allocation starts at 0 and increases by one. No view is built and no invalidation is consumed.

§Panics

Panics if the shared u64 tree-identity counter is exhausted.

§Examples
use ailloli_ui_runtime::app::{Runtime, RuntimeHandle};
let base = RuntimeHandle::<()>::new();
let runtime = Runtime::new(base);
assert!(runtime.root.is_none());
assert_eq!(runtime.runtime.element_tree_id().get(), 0);
Source

pub fn work_diagnostics(&self) -> ElementTreeDiagnosticsSnapshot

Snapshots saturating work counters for this retained tree.

The returned value is owned and does not update as later build, layout, paint, or hit-test work occurs. An untouched runtime has zero totals and no per-element entries.

§Examples
use ailloli_ui_runtime::app::{Runtime, RuntimeHandle};
let runtime = Runtime::new(RuntimeHandle::<()>::new());
let snapshot = runtime.work_diagnostics();
assert_eq!(snapshot.totals.builds, 0);
assert!(snapshot.elements.is_empty());
Source

pub fn reconcile<V: IntoView<A>>(&mut self, root: V) -> ElementId

Converts and reconciles a declarative root, returning its retained ID.

This is the generic convenience form of Self::reconcile_view. It stores the root ID and removes popup owners whose retained elements no longer exist. Layout and paint are not run.

§Examples
use ailloli_ui_runtime::{app::{Runtime, RuntimeHandle}, component::View};
let mut runtime = Runtime::new(RuntimeHandle::<()>::new());
let id = runtime.reconcile(View::empty());
assert_eq!(runtime.root, Some(id));
Source

pub fn reconcile_view(&mut self, root_view: View<A>) -> ElementId

Reconciles a concrete View against the current retained root.

Compatible keyed/positional nodes are reused and changed nodes are marked dirty by the reconciler. The resulting ID becomes Self::root. Stale popup owners are pruned after reconciliation; layout and paint remain separate stages.

§Examples
use ailloli_ui_runtime::{app::{Runtime, RuntimeHandle}, component::View};
let mut runtime = Runtime::new(RuntimeHandle::<()>::new());
let first = runtime.reconcile_view(View::empty().key("root"));
let second = runtime.reconcile_view(View::empty().key("root"));
assert_eq!(first, second);
Source

pub fn layout( &mut self, constraints: Constraints, scale: Scale, text_system: &mut TextSystem, )

Prepares pending work, lays out the root, and commits absolute geometry.

Constraint dimensions and all output geometry are logical pixels; scale is physical pixels per logical pixel. Pending component invalidations are reconciled first. With no reconciled root, this still consumes/prepares pending work and then returns. Layout artifacts may borrow caches in text_system only for the duration of this call.

§Panics

Propagates panics from component/widget layout callbacks and from invalid scale or constraint operations those callbacks perform.

§Examples
use ailloli_ui_core::{Constraints, Scale};
use ailloli_ui_runtime::{app::{Runtime, RuntimeHandle}, component::View};
use ailloli_ui_text::TextSystem;
let mut runtime = Runtime::new(RuntimeHandle::<()>::new());
let root = runtime.reconcile_view(View::empty());
runtime.layout(Constraints::tight(80.0, 24.0), Scale::new(1.0), &mut TextSystem::new());
assert!(runtime.tree.get(root).unwrap().layout.is_some());
Source

pub fn prepare_frame(&mut self) -> FrameWorkPlan

Applies pending element-scoped invalidations and returns only the aggregate work visible to a presentation host.

Exact dirty roots remain encapsulated by the runtime. A host may skip layout when this plan only requests paint, while resize/DPI changes can still force layout independently. Calling this method drains the pending invalidation set and reconciles dirty components before returning the plan captured at entry.

§Examples
use ailloli_ui_core::ElementId;
use ailloli_ui_runtime::app::{Invalidation, Runtime, RuntimeHandle};
let mut runtime = Runtime::new(RuntimeHandle::<()>::new());
runtime.runtime.invalidate(ElementId(9), Invalidation::Paint);
let plan = runtime.prepare_frame();
assert!(plan.needs_paint());
assert!(runtime.runtime.frame_work_plan().is_empty());
Source

pub fn paint(&self, text_system: &mut TextSystem) -> Scene

Paints committed retained state with default input and frame time zero.

This is shorthand for paint_with_input(text_system, Default::default(), 0). With no root it returns an empty scene. It does not reconcile or run layout, so hosts must order stages appropriately.

§Examples
use ailloli_ui_runtime::app::{Runtime, RuntimeHandle};
use ailloli_ui_text::TextSystem;
let runtime = Runtime::new(RuntimeHandle::<()>::new());
assert!(runtime.paint(&mut TextSystem::new()).layers.is_empty());
Source

pub fn paint_with_input( &self, text_system: &mut TextSystem, input: InputSnapshot, frame_time_ms: u128, ) -> Scene

Paints committed state with an input snapshot and frame timestamp.

frame_time_ms is a host-defined millisecond timestamp exposed to paint callbacks; it is stored verbatim and need not be wall-clock time. Input state is copied into the paint context. No root produces an empty scene. This method does not reconcile or lay out dirty state.

§Examples
use ailloli_ui_runtime::{app::{Runtime, RuntimeHandle}, input::InputSnapshot};
use ailloli_ui_text::TextSystem;
let runtime = Runtime::new(RuntimeHandle::<()>::new());
let scene = runtime.paint_with_input(&mut TextSystem::new(), InputSnapshot::default(), 16);
assert!(scene.layers.is_empty());
Source

pub fn render_root( &mut self, root_view: View<A>, constraints: Constraints, scale: Scale, text_system: &mut TextSystem, ) -> Scene

Runs the canonical frame order: reconcile, layout, then paint.

Pending invalidations are prepared during the layout stage. Input state and frame time use their defaults, so interactive hosts needing current values should call the individual stages and Self::paint_with_input.

§Panics

Propagates panics from component and widget callbacks.

§Examples
use ailloli_ui_core::{Constraints, Scale};
use ailloli_ui_runtime::{app::{Runtime, RuntimeHandle}, component::View};
use ailloli_ui_text::TextSystem;
let mut runtime = Runtime::new(RuntimeHandle::<()>::new());
let scene = runtime.render_root(View::empty(), Constraints::tight(40.0, 20.0), Scale::new(1.0), &mut TextSystem::new());
assert!(runtime.root.is_some());
assert!(scene.layers.is_empty());
Source

pub fn reconcile_dirty_components(&mut self)

Applies and drains all pending invalidations for this tree scope.

Paint requests mark only their element. Layout requests dirty the path and, for component targets, their direct children. Build requests rebuild the nearest owning component; ancestor component rebuilds subsume selected descendants. Unknown build targets are conservatively layout-dirtied. Selected components are processed shallowest-first, then stale popup owners are pruned. Newly enqueued invalidations are left for a later call.

§Examples
use ailloli_ui_runtime::{app::{Invalidation, Runtime, RuntimeHandle}, component::View};
let mut runtime = Runtime::new(RuntimeHandle::<()>::new());
let root = runtime.reconcile_view(View::empty());
runtime.runtime.invalidate(root, Invalidation::Paint);
runtime.reconcile_dirty_components();
assert!(runtime.tree.get(root).unwrap().dirty.paint);

Trait Implementations§

Source§

impl<A> Drop for Runtime<A>

Releases this runtime’s allocated element-tree scope.

Source§

fn drop(&mut self)

Releases the retained-tree scope and all tree-owned runtime records.

Auto Trait Implementations§

§

impl<A> !Freeze for Runtime<A>

§

impl<A> !RefUnwindSafe for Runtime<A>

§

impl<A> !Send for Runtime<A>

§

impl<A> !Sync for Runtime<A>

§

impl<A> Unpin for Runtime<A>

§

impl<A> !UnwindSafe for Runtime<A>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> ErasedDestructor for T
where T: 'static,