polyhorn-core 0.4.0

Core types used in Polyhorn.
Documentation
use super::hooks::{UseAsync, UseContext, UseEffect, UseLayoutEffect, UseReference, UseState};
use super::{
    Context, ContextTree, Effect, EffectLink, Element, EventLoop, Instance, Key, LayoutEffect,
    Link, Memory, Platform, Reference, State, Weak, WeakLink,
};
use serde::{Deserialize, Serialize};
use std::future::Future;
use std::rc::Rc;

pub struct Manager<'a, P>
where
    P: Platform + ?Sized,
{
    compositor: &'a P::Compositor,
    bus: &'a EventLoop,
    memory: &'a mut Memory,
    context: &'a ContextTree,
    children: Element<P>,
    effects: Vec<Effect<P>>,
    layout_effects: Vec<LayoutEffect<P>>,
    instance: &'a Rc<Instance<P>>,
}

impl<'a, P> Manager<'a, P>
where
    P: Platform + ?Sized,
{
    pub fn new(
        compositor: &'a P::Compositor,
        bus: &'a EventLoop,
        memory: &'a mut Memory,
        context: &'a ContextTree,
        children: Element<P>,
        instance: &'a Rc<Instance<P>>,
    ) -> Manager<'a, P> {
        Manager {
            compositor,
            bus,
            memory,
            context,
            children,
            effects: vec![],
            layout_effects: vec![],
            instance,
        }
    }

    pub fn compositor(&self) -> &P::Compositor {
        self.compositor
    }

    pub fn children(&mut self) -> Element<P> {
        self.children.clone()
    }

    pub fn bind<F, I>(&self, closure: F) -> impl Fn(I)
    where
        F: Fn(&WeakLink<P>, I),
    {
        let weak = Weak::new(self.instance);

        move |input: I| {
            weak.with_link(|link| closure(link, input));
        }
    }

    pub(crate) fn into_effects(self) -> (Vec<Effect<P>>, Vec<LayoutEffect<P>>) {
        (self.effects, self.layout_effects)
    }
}

impl<'a, P> UseAsync for Manager<'a, P>
where
    P: Platform + ?Sized,
{
    fn use_async<F>(&mut self, key: Key, task: F)
    where
        F: Future<Output = ()> + 'static,
    {
        let bus = &mut self.bus;
        self.memory.future(key, || bus.queue(task))
    }
}

impl<'a, P> UseContext for Manager<'a, P>
where
    P: Platform + ?Sized,
{
    fn use_context<T>(&mut self) -> Option<Context<T>>
    where
        T: 'static,
    {
        self.context.get::<T>().map(|value| Context::new(&value))
    }
}

impl<'a, P> UseEffect<P> for Manager<'a, P>
where
    P: Platform + ?Sized,
{
    fn use_effect<F>(&mut self, key: Key, conditions: Option<Key>, effect: F)
    where
        F: FnOnce(&EffectLink<P>) + 'static,
    {
        if let Some(conditions) = conditions {
            if !self.memory.effect(key, conditions) {
                return;
            }
        }

        self.effects.push(Effect::new(self.instance, effect))
    }
}

impl<'a, P> UseLayoutEffect<P> for Manager<'a, P>
where
    P: Platform + ?Sized,
{
    fn use_layout_effect<F>(&mut self, key: Key, conditions: Option<Key>, effect: F)
    where
        F: FnOnce(&EffectLink<P>, &mut P::CommandBuffer) + 'static,
    {
        if let Some(conditions) = conditions {
            if !self.memory.effect(key, conditions) {
                return;
            }
        }

        let effect = LayoutEffect::new(self.instance, effect);
        self.layout_effects.push(effect)
    }
}

impl<'a, P> UseState for Manager<'a, P>
where
    P: Platform + ?Sized,
{
    fn use_state<S>(&mut self, key: Key, initial_value: S) -> State<S>
    where
        S: Serialize + for<'b> Deserialize<'b> + 'static,
    {
        let state_id = self.memory.state_id(key, move || initial_value);

        State::new(self.instance.id, state_id)
    }
}

impl<'a, P> UseReference for Manager<'a, P>
where
    P: Platform + ?Sized,
{
    fn use_reference<R, I>(&mut self, key: Key, initializer: I) -> Reference<R>
    where
        R: 'static,
        I: FnOnce() -> R,
    {
        let reference_id = self.memory.reference_id(key, initializer);

        Reference::new(self.instance.id, reference_id)
    }
}

impl<'a, P> Link for Manager<'a, P>
where
    P: Platform + ?Sized,
{
    type Platform = P;

    fn instance(&self) -> &Rc<Instance<Self::Platform>> {
        self.instance
    }

    fn memory(&self) -> &Memory {
        self.memory
    }
}