Struct Context

Source
pub struct Context<A> { /* private fields */ }
Expand description

Capabilities and hook-slot cursor for one synchronous component build.

A fresh context starts at signal slot zero. Components must call state/signal constructors in stable order and with a stable type per slot across builds; changing that order/type violates the type-erased crate::app::StateStore invariant and can panic. The context and its runtime handle are UI-thread local (Rc/RefCell), not Send or Sync.

§Examples

use ailloli_ui_core::ElementId;
use ailloli_ui_runtime::app::RuntimeHandle;
use ailloli_ui_runtime::component::Context;
let ctx = Context::<()>::new(ElementId(1), RuntimeHandle::new());
assert_eq!(ctx.element_id(), ElementId(1));

Implementations§

Source§

impl<A: 'static> Context<A>

Provides the operations defined for Context<A>.

Source

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

Creates a build context for element_id at hook slot zero.

The ID is stored verbatim and need not currently exist in a tree. The runtime clone determines the element-tree namespace used for state and invalidation.

§Examples
use ailloli_ui_core::ElementId;
use ailloli_ui_runtime::app::RuntimeHandle;
use ailloli_ui_runtime::component::Context;
let ctx = Context::<()>::new(ElementId(5), RuntimeHandle::new());
assert_eq!(ctx.element_id(), ElementId(5));
Source

pub fn element_id(&self) -> ElementId

Returns the retained component element targeted by this context.

§Examples
use ailloli_ui_core::ElementId;
use ailloli_ui_runtime::app::RuntimeHandle;
use ailloli_ui_runtime::component::Context;
assert_eq!(Context::<()>::new(ElementId(9), RuntimeHandle::new()).element_id(), ElementId(9));
Source

pub fn signal<T: 'static>(&mut self, initial: T) -> Signal<T>

Returns the signal in the next hook slot, creating it from initial once.

Writes request build invalidation. On later builds, an existing slot keeps its current value and ignores initial. Calls advance the slot cursor, so order and type must remain stable.

§Panics

Panics if an existing slot contains a different Rust type or if internal RefCell borrows conflict. Slot-index overflow follows build overflow settings and is practically unreachable.

§Examples
use ailloli_ui_core::ElementId;
use ailloli_ui_runtime::app::RuntimeHandle;
use ailloli_ui_runtime::component::Context;
let runtime = RuntimeHandle::<()>::new();
let mut ctx = Context::new(ElementId(1), runtime.clone());
let value = ctx.signal(3_u8);
value.set(4);
assert_eq!(value.read(), 4);
assert!(runtime.frame_work_plan().needs_build());
Source

pub fn signal_with<T: 'static>( &mut self, initial: impl FnOnce() -> T, ) -> Signal<T>

Lazily initializes the signal in the next build hook slot.

The factory runs only when that tree/element/slot has no stored signal; existing state skips it. Writes request build invalidation.

§Panics

Has the same stable-order/type and borrow requirements as Self::signal. Factory panics propagate without installing a value.

§Examples
use std::cell::Cell;
use ailloli_ui_core::ElementId;
use ailloli_ui_runtime::app::RuntimeHandle;
use ailloli_ui_runtime::component::Context;
let calls = Cell::new(0);
let mut ctx = Context::<()>::new(ElementId(1), RuntimeHandle::new());
let signal = ctx.signal_with(|| { calls.set(calls.get() + 1); 7 });
assert_eq!(signal.read(), 7);
assert_eq!(calls.get(), 1);
Source

pub fn signal_with_invalidation<T: 'static>( &mut self, initial: T, invalidation: Invalidation, ) -> Signal<T>

Creates a signal whose writes request the declared retained work.

Build matches the historical Self::signal behavior. Widget-local state that does not alter the declarative subtree can opt into Layout or Paint without rebuilding sibling components.

Existing state ignores initial, but the returned signal uses the invalidator installed when the slot was originally created. Reusing a slot with a different invalidation level does not replace that callback.

§Panics

Has the same stable-order/type and borrow requirements as Self::signal.

§Examples
use ailloli_ui_core::ElementId;
use ailloli_ui_runtime::app::{Invalidation, RuntimeHandle};
use ailloli_ui_runtime::component::Context;
let runtime = RuntimeHandle::<()>::new();
let mut ctx = Context::new(ElementId(2), runtime.clone());
ctx.signal_with_invalidation(false, Invalidation::Paint).set(true);
let plan = runtime.frame_work_plan();
assert!(plan.needs_paint() && !plan.needs_layout());
Source

pub fn signal_with_invalidation_factory<T: 'static>( &mut self, initial: impl FnOnce() -> T, invalidation: Invalidation, ) -> Signal<T>

Lazily initializes a signal with a chosen write-invalidation level.

The next slot index is reserved before the factory runs. Existing slots do not invoke initial and retain their originally installed invalidator.

§Panics

Panics on a stored type mismatch, conflicting interior borrow, or propagated factory panic. Hook-order changes can therefore fail during component reconciliation.

§Examples
use ailloli_ui_core::ElementId;
use ailloli_ui_runtime::app::{Invalidation, RuntimeHandle};
use ailloli_ui_runtime::component::Context;
let runtime = RuntimeHandle::<()>::new();
let mut ctx = Context::new(ElementId(2), runtime.clone());
let signal = ctx.signal_with_invalidation_factory(|| String::from("ready"), Invalidation::Layout);
signal.set(String::from("changed"));
assert!(runtime.frame_work_plan().needs_layout());
Source

pub fn state<T: 'static>(&mut self, initial: T) -> State<T>

Returns State backed by the next build-invalidating signal slot.

§Panics

Has the same stable-order/type and borrow requirements as Self::signal.

§Examples
use ailloli_ui_core::ElementId;
use ailloli_ui_runtime::app::RuntimeHandle;
use ailloli_ui_runtime::component::Context;
let mut ctx = Context::<()>::new(ElementId(1), RuntimeHandle::new());
let state = ctx.state(10);
state.update(|value| *value += 2);
assert_eq!(state.read(), 12);
Source

pub fn dispatch(&self, action: A)

Queues one application action in FIFO order.

§Examples
use ailloli_ui_core::ElementId;
use ailloli_ui_runtime::app::RuntimeHandle;
use ailloli_ui_runtime::component::Context;
let runtime = RuntimeHandle::<u8>::new();
Context::new(ElementId(1), runtime.clone()).dispatch(6);
assert_eq!(runtime.take_actions(), vec![6]);
Source

pub fn invalidate(&self, invalidation: Invalidation)

Marks this component element with explicit context-origin invalidation.

Repeated requests coalesce to the strongest work level and diagnostics preserve the request provenance.

§Examples
use ailloli_ui_core::ElementId;
use ailloli_ui_runtime::app::{Invalidation, RuntimeHandle};
use ailloli_ui_runtime::component::Context;
let runtime = RuntimeHandle::<()>::new();
Context::new(ElementId(4), runtime.clone()).invalidate(Invalidation::Layout);
assert!(runtime.frame_work_plan().needs_layout());
Source

pub fn request_repaint(&self)

Requests paint work for this component element.

§Examples
use ailloli_ui_core::ElementId;
use ailloli_ui_runtime::app::RuntimeHandle;
use ailloli_ui_runtime::component::Context;
let runtime = RuntimeHandle::<()>::new();
Context::new(ElementId(1), runtime.clone()).request_repaint();
assert!(runtime.frame_work_plan().needs_paint());
Source

pub fn request_layout(&self)

Requests layout and paint work for this component element.

§Examples
use ailloli_ui_core::ElementId;
use ailloli_ui_runtime::app::RuntimeHandle;
use ailloli_ui_runtime::component::Context;
let runtime = RuntimeHandle::<()>::new();
Context::new(ElementId(1), runtime.clone()).request_layout();
assert!(runtime.frame_work_plan().needs_layout());
Source

pub fn request_build(&self)

Requests build, layout, and paint work for this component element.

§Examples
use ailloli_ui_core::ElementId;
use ailloli_ui_runtime::app::RuntimeHandle;
use ailloli_ui_runtime::component::Context;
let runtime = RuntimeHandle::<()>::new();
Context::new(ElementId(1), runtime.clone()).request_build();
assert!(runtime.frame_work_plan().needs_build());
Source

pub fn invalidation_target(&self, invalidation: Invalidation) -> Rc<dyn Fn()>

Weak callback suitable for retained model subscriptions. The callback never keeps the runtime or its widget tree alive.

While the runtime exists, invocation records InvalidationSource::Model through the handle’s weak invalidator. After all strong handles are dropped, invocation is a harmless no-op.

§Examples
use ailloli_ui_core::ElementId;
use ailloli_ui_runtime::app::{Invalidation, RuntimeHandle};
use ailloli_ui_runtime::component::Context;
let runtime = RuntimeHandle::<()>::new();
let callback = Context::new(ElementId(3), runtime.clone()).invalidation_target(Invalidation::Paint);
callback();
assert_eq!(runtime.take_dirty_elements(), vec![ElementId(3)]);
Source

pub fn request_repaint_after(&self, delay: Duration)

Schedules paint invalidation no earlier than delay from now.

Timers are tree-scoped and the runtime deduplicates compatible requests by earliest due instant.

§Examples
use std::time::Duration;
use ailloli_ui_core::ElementId;
use ailloli_ui_runtime::app::RuntimeHandle;
use ailloli_ui_runtime::component::Context;
let runtime = RuntimeHandle::<()>::new();
Context::new(ElementId(1), runtime.clone()).request_repaint_after(Duration::from_millis(1));
assert!(runtime.next_scheduled_repaint_due().is_some());
Source

pub fn request_layout_after(&self, delay: Duration)

Schedules layout invalidation no earlier than delay from now.

§Examples
use std::time::Duration;
use ailloli_ui_core::ElementId;
use ailloli_ui_runtime::app::RuntimeHandle;
use ailloli_ui_runtime::component::Context;
let runtime = RuntimeHandle::<()>::new();
Context::new(ElementId(1), runtime.clone()).request_layout_after(Duration::from_millis(1));
assert!(runtime.next_scheduled_repaint_due().is_some());
Source

pub fn request_build_after(&self, delay: Duration)

Schedules build invalidation no earlier than delay from now.

§Examples
use std::time::Duration;
use ailloli_ui_core::ElementId;
use ailloli_ui_runtime::app::RuntimeHandle;
use ailloli_ui_runtime::component::Context;
let runtime = RuntimeHandle::<()>::new();
Context::new(ElementId(1), runtime.clone()).request_build_after(Duration::from_millis(1));
assert!(runtime.next_scheduled_repaint_due().is_some());
Source

pub fn runtime(&self) -> RuntimeHandle<A>

Clones the runtime handle while preserving this tree namespace.

§Examples
use ailloli_ui_core::ElementId;
use ailloli_ui_runtime::app::RuntimeHandle;
use ailloli_ui_runtime::component::Context;
let ctx = Context::<()>::new(ElementId(1), RuntimeHandle::new());
assert_eq!(ctx.runtime().element_tree_id(), ctx.runtime().element_tree_id());
Source

pub fn register_ui_service( &self, service: &Rc<dyn Fn() -> bool>, ) -> UiServiceRegistration<A>

Registers a polled UI service and returns its lifetime guard.

The callback is invoked by RuntimeHandle::service_ui_sources and returns whether it changed component-visible state. A true result requests Build for this exact component owner and mount generation; false queues no retained work. Dropping the registration removes only that tree-scoped service. Callback panics propagate from servicing.

§Examples
use std::rc::Rc;
use ailloli_ui_core::ElementId;
use ailloli_ui_runtime::app::RuntimeHandle;
use ailloli_ui_runtime::component::Context;
let runtime = RuntimeHandle::<()>::new();
let service: Rc<dyn Fn() -> bool> = Rc::new(|| true);
let registration = Context::new(ElementId(1), runtime.clone()).register_ui_service(&service);
assert!(runtime.service_ui_sources());
drop(registration);
assert!(!runtime.service_ui_sources());

Auto Trait Implementations§

§

impl<A> Freeze for Context<A>

§

impl<A> !RefUnwindSafe for Context<A>

§

impl<A> !Send for Context<A>

§

impl<A> !Sync for Context<A>

§

impl<A> Unpin for Context<A>

§

impl<A> !UnwindSafe for Context<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,