Crate gstore[][src]

gstore

gstore is a library that provides global and local state management for GTK Apps as well as a bunch of macros to build GTK widgets.

gstore is inspired by react/redux. If you are familiar with these frameworks you might find a lot of their concepts used in gstore.

Contents

  1. Concepts
  2. Local State
  3. Actions

Concepts

gstore is an app framework above of GTK. GTK is a single-threaded UI library. gstore uses a background thread to handle global state mutations and connects it with the GTK main thread via user defined enums (called Actions) using std::sync::mpsc::channel.

Note: currently this leads to a major drawback: The GTK main thread has to check every n milliseconds for sent Actions. Please feel free to contact me if you have a better idea how to do this.

The diagram below aims to visualize the basic concept of gstore:

+-----------------------------------------------------------------+
|                                                                 |
| State                                                           |
|                                                                 |
+-----------------------------------------------------------------+
|                                                                 |
| Mutexed global state                                            |
|                                                                 |
+-----+------------------------------------------------+----------+
      ^                                                ^
      |                                                |
      | Read Access                                    | Read/Write Access
      |                                                |
      |                                                |
+-----+-----+                                 +--------+----------+
|           |                                 |                   |
| UI thread |                                 | Background thread |
|           |                                 |                   |
+-----------+    send Action on user input    +-------------------+
|           |                                 |                   |
| GTK main  +-------------------------------->+ runs reducers     |
| thread    |                                 |                   |
|           |        +-------------+          |                   |
|           |        |             |          |                   |
|           |        | enum Action |          |                   |
|           |        |             |          |                   |
|           |        +-------------+          |                   |
|           |                                 |                   |
|           |   receive Action when handled   |                   |
|           |                                 |                   |
|           +<--------------------------------+                   |
|           |                                 |                   |
+-----------+                                 +-------------------+

The background thread mutates the global state while the UI thread only reads the global state. State mutation means a new version of the state is by a stateless function. In redux this is called reducers. In other languages we know this kind function a fold.

In contrast to redux there are currently no additional restrictions of what to do in a reducers.

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

// slice
// -----------------------------------------------------------------
// 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
// -----------------------------------------------------------------
// 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
// -----------------------------------------------------------------
// define window component

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

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

Re-exports

pub use once_cell;

Modules

gtk
l10n
prelude
render_handling
store
use_state
widgets

Macros

action_row
application_window

Creates a new ApplicationWindow.

button

Creates a GTK button.

clamp
entry
gbox

Creates a GTK box.

header_bar

gstore macro for the GTK HeaderBar

image
label

gstore makro for the GTK label.

list_box
preferences_group
preferences_page
setup_render_handling
slice
spin_button
stack

Creates a GTK stack.

store
switch
title_bar

gstore macro for the libhandy TitleBar

use_select
use_state

Defines a state and setter.

view_switcher_bar
widget

Abstract GTK widget basis macro.