flemish 0.7.0

An Elmish architecture for fltk-rs
Documentation
use std::collections::HashMap;
use std::{cell::RefCell, rc::Rc};

use crate::vnode::View;
use crate::widgets::WidgetMap;

#[derive(Clone)]
pub struct VirtualDom<Message> {
    pub root: Rc<RefCell<View<Message>>>,
    pub widget_map: Rc<RefCell<WidgetMap>>,
    #[allow(clippy::type_complexity)]
    subscribers: Rc<RefCell<Vec<(usize, Rc<dyn Fn(&Message)>)>>>,
}

impl<Message> VirtualDom<Message>
where
    Message: Clone + 'static + Send + Sync,
{
    pub(crate) fn new(root: View<Message>) -> Self {
        let root_rc = Rc::new(RefCell::new(root));
        let widget_map = Rc::new(RefCell::new(HashMap::new()));

        let dom = Self {
            root: root_rc.clone(),
            widget_map: widget_map.clone(),
            subscribers: Rc::new(RefCell::new(Vec::new())),
        };

        {
            root_rc.borrow().mount(&dom);
        }

        dom
    }

    pub(crate) fn subscribe_owned<F: 'static + Fn(&Message)>(&self, owner: usize, callback: F) {
        self.subscribers
            .borrow_mut()
            .push((owner, Rc::new(callback)));
    }

    pub(crate) fn unsubscribe_owner(&self, owner: usize) {
        self.subscribers.borrow_mut().retain(|(id, _)| *id != owner);
    }

    pub(crate) fn dispatch(&self, message: Message) {
        for (_, subscriber) in self.subscribers.borrow().iter() {
            subscriber(&message);
        }
    }

    pub(crate) fn patch(&self, new: View<Message>) {
        let mut new = new;
        let mut old = self.root.borrow_mut();
        new.patch(&mut old, self);
        *old = new;
    }
}