= 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
:
Next, add this to your crate:
extern crate gtk;
extern crate relm;
extern crate relm_derive;
Then, create your model:
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
:
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:
struct Widgets { // … window: Window,
Create a struct
which represents a Widget
(in this case, the main window of the application):
struct Win { widgets: Widgets,
To make this struct
a relm Widget
that can be shown by the library, implement the Widget
trait:
impl Widget
// 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()
:
fn main() {
Relm::run::
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].