lgui-core 0.2.0

Platform-neutral runtime and UI primitives for LGUI
Documentation
use super::{
    AnimProperty, AnimationRegistry, ComponentId, ComponentState, ComponentStateStore,
    ComponentTree, CompositingLayerAnimation, CompositingLayerSpec, ContextRegistry,
    EffectRegistry, HookId, HookSlotKind, HookStateStore, InteractionFlags, UiId,
    UiInteractionState, UiRect, UiScale, UiScope, UiTaskSpawner, UiUpdateQueue,
};
use std::sync::Arc;

#[derive(Clone, Copy)]
pub struct UiRenderContext<'a> {
    interaction: &'a UiInteractionState,
    animations: &'a AnimationRegistry,
    component_states: &'a ComponentStateStore,
    component_tree: &'a ComponentTree,
    contexts: &'a ContextRegistry,
    hook_states: &'a HookStateStore,
    hook_updates: &'a Arc<UiUpdateQueue>,
    task_spawner: Option<&'a UiTaskSpawner>,
    effects: &'a EffectRegistry,
    viewport: UiRect,
    scale: UiScale,
}

impl<'a> UiRenderContext<'a> {
    pub fn new(
        interaction: &'a UiInteractionState,
        animations: &'a AnimationRegistry,
        component_states: &'a ComponentStateStore,
        component_tree: &'a ComponentTree,
        contexts: &'a ContextRegistry,
        hook_states: &'a HookStateStore,
        hook_updates: &'a Arc<UiUpdateQueue>,
        task_spawner: Option<&'a UiTaskSpawner>,
        effects: &'a EffectRegistry,
        viewport: UiRect,
        scale: UiScale,
    ) -> Self {
        Self {
            interaction,
            animations,
            component_states,
            component_tree,
            contexts,
            hook_states,
            hook_updates,
            task_spawner,
            effects,
            viewport,
            scale,
        }
    }

    pub fn viewport(&self) -> UiRect {
        self.viewport
    }

    pub fn scale(&self) -> UiScale {
        self.scale
    }

    pub fn interaction_flags(&self, id: &UiId) -> InteractionFlags {
        self.interaction.flags_for(id)
    }

    pub fn animation_value(&self, id: &UiId, property: AnimProperty) -> f32 {
        self.animations.value(id.clone(), property)
    }

    pub fn component_state_mut<T, R>(&self, id: &UiId, f: impl FnOnce(&mut T) -> R) -> R
    where
        T: ComponentState + Clone + Default + 'static,
    {
        self.component_states.with_mut(id, f)
    }

    pub(crate) fn component_state_mut_for_component<T, R>(
        &self,
        id: &UiId,
        owner: ComponentId,
        invalidation_id: UiId,
        f: impl FnOnce(&mut T) -> R,
    ) -> R
    where
        T: ComponentState + Clone + Default + 'static,
    {
        self.component_states
            .with_mut_for_component(id, owner, invalidation_id, f)
    }

    pub(crate) fn compositing_layer_animation_mut<T, R>(
        &self,
        id: &UiId,
        f: impl FnOnce(&mut T) -> R,
    ) -> (R, CompositingLayerSpec, bool)
    where
        T: CompositingLayerAnimation,
    {
        self.component_states
            .with_mut_for_compositing_layer(id, id.clone(), f)
    }

    pub fn preserve_component_state_scope(&self, scope: &UiScope) {
        self.component_states.preserve_scope(scope);
    }

    pub fn component_tree(&self) -> &ComponentTree {
        self.component_tree
    }

    pub fn contexts(&self) -> &ContextRegistry {
        self.contexts
    }

    pub fn hook_state<T>(&self, id: HookId, initial: impl FnOnce() -> T) -> T
    where
        T: Clone + 'static,
    {
        self.hook_states.value(id, initial)
    }

    pub fn hook_updates(&self) -> Arc<UiUpdateQueue> {
        Arc::clone(self.hook_updates)
    }

    pub fn task_spawner(&self) -> Option<UiTaskSpawner> {
        self.task_spawner.cloned()
    }

    pub fn effect<D, F, R>(&self, id: HookId, deps: D, effect: F)
    where
        D: Clone + PartialEq + 'static,
        F: FnOnce() -> R + 'static,
        R: super::IntoEffectCleanup,
    {
        self.effects.register(id, deps, effect);
    }

    #[doc(hidden)]
    pub fn element_effect<D, F, R>(&self, parent: ComponentId, owner: UiId, deps: D, effect: F)
    where
        D: Clone + PartialEq + 'static,
        F: FnOnce() -> R + 'static,
        R: super::IntoEffectCleanup,
    {
        let component = self.component_tree.element_effect_child(parent, &owner);
        self.component_tree.begin_component_execution(component);
        self.component_tree
            .record_hook(component, HookSlotKind::Effect);
        self.effects.register(
            HookId::new(component, 0, HookSlotKind::Effect),
            deps,
            effect,
        );
        self.component_tree.finish_component(component);
    }
}