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>.
impl<A: 'static> Context<A>
Provides the operations defined for Context<A>.
Sourcepub fn new(element_id: ElementId, runtime: RuntimeHandle<A>) -> Self
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));Sourcepub fn element_id(&self) -> ElementId
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));Sourcepub fn signal<T: 'static>(&mut self, initial: T) -> Signal<T>
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());Sourcepub fn signal_with<T: 'static>(
&mut self,
initial: impl FnOnce() -> T,
) -> Signal<T>
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);Sourcepub fn signal_with_invalidation<T: 'static>(
&mut self,
initial: T,
invalidation: Invalidation,
) -> Signal<T>
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());Sourcepub fn signal_with_invalidation_factory<T: 'static>(
&mut self,
initial: impl FnOnce() -> T,
invalidation: Invalidation,
) -> Signal<T>
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());Sourcepub fn state<T: 'static>(&mut self, initial: T) -> State<T>
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);Sourcepub fn dispatch(&self, action: A)
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]);Sourcepub fn invalidate(&self, invalidation: Invalidation)
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());Sourcepub fn request_repaint(&self)
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());Sourcepub fn request_layout(&self)
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());Sourcepub fn request_build(&self)
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());Sourcepub fn invalidation_target(&self, invalidation: Invalidation) -> Rc<dyn Fn()>
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)]);Sourcepub fn request_repaint_after(&self, delay: Duration)
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());Sourcepub fn request_layout_after(&self, delay: Duration)
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());Sourcepub fn request_build_after(&self, delay: Duration)
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());Sourcepub fn runtime(&self) -> RuntimeHandle<A>
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());Sourcepub fn register_ui_service(
&self,
service: &Rc<dyn Fn() -> bool>,
) -> UiServiceRegistration<A>
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());