gstore 0.2.6

Global state management and easy-to-use widget macros for GTK applications written in Rust
Documentation
/// Defines a state and setter.
///
/// `use_state!` can be used to define a local (for a single gstore component) state variable and a
/// setter to update this value  
///
/// # Example
/// ```rust,no_run
/// #[macro_use]
/// extern crate gstore;
/// use gtk::prelude::*;
///
/// use_state! {
///     [count: u32, set_count] = 0
/// }
///
/// # pub fn main() {}
///
/// pub fn counter() -> gtk::ApplicationWindow {
///     glib::timeout_add_local(1000, move || {
///         // update the local state value each second...
///         set_count(count() + 1);
///         glib::Continue(true)
///     });
///     return application_window! {
///         widget {
///             children [
///                 label! {
///                     properties {
///                         // The value of the local state can be read with a getter function
///                         label: format!("Count: {}", count())
///                         expand: true
///                     }
///                 }
///             ]
///         }
///     }
/// }
/// ```
#[macro_export]
macro_rules! use_state {
    (
        $([$field:ident: $t:ty, $setter:ident] = $init:expr),*
    ) => {
        use std::ops::Deref;

        // --- render handling ---
        static mut _RENDER_CALLBACKS: gstore::once_cell::sync::Lazy<Vec<Box<dyn Fn()>>> =
            gstore::once_cell::sync::Lazy::new(|| vec![]);

        fn _register_rerender<F>(callback: F)
        where
            F: Fn() + 'static,
        {
            unsafe { _RENDER_CALLBACKS.push(Box::new(callback)) }
        }

        fn _rerender() {
            unsafe {
                for callback in _RENDER_CALLBACKS.deref() {
                    callback()
                }
            }
        }

        fn stateful<F>(callback: F)
        where
            F: Fn() + 'static,
        {
            _register_rerender(callback)
        }

        // --- state definition ---
        #[derive(Debug, Clone)]
        struct LocalState {$(
            $field: $t
        ),*}

        impl Default for LocalState {
            fn default() -> Self {
               LocalState {$(
                  $field: $init
               ),*}
            }
        }

        static mut _STATE: gstore::once_cell::sync::Lazy<LocalState> =
            gstore::once_cell::sync::Lazy::new(|| LocalState::default());

        // --- getters and setters ---
        $(
        fn $setter(v: $t) {
            unsafe {
                _STATE.$field = v;
            }
            _rerender()
        }
        fn $field() -> $t {
            unsafe {
                _STATE.$field.clone()
            }
        }
        )*

    };
}