1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
//! Simple node-based graph editor for Rust. Register nodes, let the user mingle
//! with them, read the result.
//!
//! # Example
//!
//! The following example initializes the application with a single node type.
//! Eeach node will have one input and one output pin, and a "switch" widget
//! that can be set on or off by the user.
//!
//! First we need to define the config for our application. The config describes
//! all the node templates available for the user.
//!
//! ```
//! use gazpatcho::config::*;
//!
//! let config = Config {
//!     node_templates: vec![
//!         NodeTemplate {
//!             label: "Example node".to_owned(),
//!             class: "example_node".to_owned(),
//!             pins: vec![
//!                 Pin {
//!                     label: "Input".to_owned(),
//!                     class: "in".to_owned(),
//!                     direction: Input,
//!                 },
//!                 Pin {
//!                     label: "Output".to_owned(),
//!                     class: "out".to_owned(),
//!                     direction: Output,
//!                 },
//!             ],
//!             widgets: vec![Switch {
//!                 label: "Switch".to_owned(),
//!                 key: "switch".to_owned(),
//!             }],
//!         }
//!     ],
//! };
//! ```
//!
//! The we start the application, this will open a new window with the canvas.
//! We are passing the previously defined config and also a callback function.
//! This callback will be executed every time the user updates the graph
//! represented in the UI.
//!
//! ```no_run
//! # use gazpatcho::config::*;
//! # let config = Config { node_templates: vec![] };
//! gazpatcho::run("Application Name", config, |report| {
//!     // Act upon the current report
//!     dbg!(report);
//! });
//! ```
//!
//! The `dbg!` output of such a configuration would return something like:
//!
//! ```ignore
//! Report {
//!     nodes: [
//!         Node {
//!             id: "example_node:0",
//!             class: "example_node",
//!             data: {
//!                 "switch": Bool(
//!                     false,
//!                 ),
//!             },
//!         },
//!         Node {
//!             id: "example_node:1",
//!             class: "example_node",
//!             data: {
//!                 "switch": Bool(
//!                     true,
//!                 ),
//!             },
//!         },
//!     ],
//!     patches: [
//!         Patch {
//!             source: PinAddress {
//!                 node_id: "example_node:0",
//!                 pin_class: "out",
//!             },
//!             destination: PinAddress {
//!                 node_id: "example_node:1",
//!                 pin_class: "in",
//!             },
//!         },
//!     ],
//! }
//! ```
//!
//! To see the list of all available widgets and detailed documentation of the
//! state, read the [`config` documentation](config/index.html). To learn more
//! about the reported state, read the [`report`
//! documentation](file:///home/phoracek/code/zlosynth/gazpatcho/target/doc/gazpatcho/report/index.html).
//!
//! If you prefer to go directly for a code examples, take a look at the
//! [examples folder](https://github.com/zlosynth/gazpatcho/tree/main/examples).

#[macro_use]
extern crate imgui;

#[macro_use]
extern crate getset;

pub mod config;
pub mod report;

mod engine;
mod vec2;
mod widget;

use engine::{reducer, state, view};

/// Launch the user interface.
///
/// Config defines available node templates. Learn about all the available
/// configuration options in the [config documentation](config/index.html).
///
/// The report callback function will be executed every time there is a new
/// change in the graph modeled by the application. Learn more about its format
/// in the [documentation of the report](report/index.html).
///
/// See an example in the [crate documentation](index.html#example).
pub fn run<F>(title: &str, conf: config::Config, report_callback: F)
where
    F: Fn(report::Report) + 'static,
{
    let mut state = state::State::from(conf);
    engine::window::run(title, move |ui| {
        view::draw(&state, ui).into_iter().for_each(|action| {
            if reducer::reduce(&mut state, action).model_changed() {
                report_callback(report::Report::from(&state));
            }
        });
    });
}