= Relm

Asynchronous, GTK+-based, GUI library, inspired by Elm, written in Rust.

Relm only works on nightly since it depends on the feature conservative_impl_trait.

This library is in alpha stage: it has not been thoroughly tested and its API may change at any time.

image:https://img.shields.io/travis/antoyo/relm.svg[link="https://travis-ci.org/antoyo/relm"] //image:https://img.shields.io/coveralls/antoyo/relm.svg[link="https://coveralls.io/github/antoyo/relm"] image:https://img.shields.io/crates/v/relm.svg[link="https://crates.io/crates/relm"] image:https://img.shields.io/badge/rust-documentation-blue.svg[link="https://docs.rs/relm/0.1.0/relm/"] image:https://img.shields.io/crates/d/relm.svg[link="https://crates.io/crates/relm"] image:https://img.shields.io/crates/l/relm.svg[link="LICENSE"]

== Usage

First, add this to you Cargo.toml:

[source,bash]

relm = "0.1.0"

Next, add this to your crate:

[source,rust]

extern crate gtk;

[macro_use]

extern crate relm;

[macro_use]

extern crate relm_derive;

use relm::{Relm, RemoteRelm, Widget};

Then, create your model:

[source,rust]

[derive(Clone)]

struct Model { // …

}

The model contains the data related to a Widget. It may be updated by the Widget::update or the Widget::update_command function.

Create your message enum:

[source,rust]

[derive(Msg)]

enum Msg { // … Quit,

}

Messages are sent to both Widget::update and Widget::update_command to indicate that an event happened. The model can be updated when an event is received.

Create a struct to contain the GTK+ widgets:

[source,rust]

struct Widgets { // … window: Window,

}

Create a struct which represents a Widget (in this case, the main window of the application):

[source,rust]

struct Win { widgets: Widgets,

}

To make this struct a relm Widget that can be shown by the library, implement the Widget trait:

[source,rust]

impl Widget for Win { type Container = Window; type Model = Model;

// Return the container of this widget.
fn container(&self) -> &Self::Container {
    &self.widgets.window
}

// Create the widgets and return the struct with its initial model.
fn new(relm: RemoteRelm<Msg>) -> (Self, Model) {
    let model = Model {
    };
    // GTK+ widgets are used normally within a `Widget`.
    let window = Window::new(WindowType::Toplevel);
    // Connect the signal `delete_event` to send the `Quit` message.
    connect_no_inhibit!(relm, window, connect_delete_event(_, _), Quit);
    // There is also a `connect!()` macro for GTK+ events that does not need a value to be returned in the callback.
    window.show_all();
    let window = Win {
        widgets: Widgets {
            window: window,
        },
    };
    (window, model)
}

// The model may be updated when a message is received.
// Widgets may also be updated in this function.
fn update(&mut self, event: Msg, model: &mut Model) {
    match event {
        Quit => gtk::main_quit(),
    }
}

// The next methods are optional.

// Futures and streams can be connected to send a message when a value is ready.
// However, since the tokio event loop runs in another thread, they cannot be connected in the `update` function which is ran in the main thread.
// Thus, they must be added in the `update_command()` method which is ran in the tokio thread.
// fn update_command(relm: &Relm<Msg>, event: Msg, model: &mut Model) {
//     match event {
//         SomeEvent => {
//             let future = create_future();
//             relm.connect_exec_ignore_err(future, SomeEvent);
//         },
//     }
// }

// Futures and streams can be connected when the `Widget` is created in the `subscriptions()` method.
// fn subscriptions(relm: &Relm<Msg>) {
//     let stream = Interval::new(Duration::from_secs(1), relm.handle()).unwrap();
//     relm.connect_exec_ignore_err(stream, Tick);
// }

}

Finally, show this Widget by calling Relm::run():

[source,rust]

fn main() { Relm::run::().unwrap();

}

For more information about how you can use relm, you can take a look at the https://github.com/antoyo/relm/tree/master/examples[examples].