gstore 0.2.11

Global state management and easy-to-use widget macros for GTK applications written in Rust
Documentation

gstore

pipeline status API

Global state management for GTK apps in redux style.

A State can be any kind of data structure an application is based on. For a 'counter' app it might be a struct with a single u32 field. Actions are enums which represent the possible features of the app affecting the state.

Usage

#[macro_use]
extern crate gstore;
use gtk::prelude::*;
use gstore::prelude::*;

// slice.rs
// -----------------------------------------------------------------
// define a slice

slice! {
    CountState { count: i64 = 0 }
    CountAction { Increment, Decrement }
}

// define a reducer on that slice
fn reduce_count(action: CountAction, state: CountState) -> CountState {
    match action {
        CountAction::Increment => CountState { count: state.count + 1, ..state },
        CountAction::Decrement => CountState { count: state.count - 1, ..state }
    }
}

// define a selector for your slice (the state is the Root state)
fn select_count(state: &crate::State) -> i64 { state.counting.count }

// define functions for convenient action dispatching
fn increment() -> Action {
    crate::Action::Counting(CountAction::Increment)
}

fn decrement() -> Action {
    crate::Action::Counting(CountAction::Decrement)
}

// store.rs
// -----------------------------------------------------------------
// combine slices in your store

store! {
    counting: Counting = crate::{CountState, CountAction, reduce_count}
}

fn main() {

    let logging_middleware = middleware(|store, next, action: Action| {
        println!("Handling action {:?}", action);
        next(store, action.clone());
        println!("Handled action {:?}", action);
    });

    let store: Store = Store::new(root_reducer, vec![logging_middleware]);
    
    gstore::gtk::run(store, |store| {
        let window = window(store.clone());
        store.dispatch(Action::Start);
        window
    })
}

// window.rs
// -----------------------------------------------------------------
// define window component

use_state! {
    [message: String, set_message] = "The current count:".to_string()
}

fn window(store: Store) -> gtk::ApplicationWindow {
    application_window! {
        properties {
            default_width: 400
            default_height: 400
        }
        children [
            label! {
                properties {
                    label: message()
                }
            }
        ]
    }
}

Documentation

Please check out the rust doc: https://docs.rs/gstore/latest/gstore.

Implementation

gstore works in the ui thread. Asynchronous tasks can be handled in middlewares. To listen to background threads gstore uses std::sync::mpsc::{Receiver, Sender} and polls every n (100) milliseconds for changes, thus the UI thread is never blocked. I think this is not a good approach. Please feel free to contribute

License

gstore is distributed under the terms of the MIT license. See LICENSE for details.

Acknowledgements

Dan Abramov eveyone who invented/contributes to Redux: https://redux.js.org/.

Thanks for inventing redux.