extern crate gtk;
#[macro_use]
extern crate relm;
#[macro_use]
extern crate relm_derive;
use gtk::{
Button,
ButtonExt,
ContainerExt,
Inhibit,
Label,
WidgetExt,
Window,
WindowType,
};
use gtk::Orientation::{Horizontal, Vertical};
use relm::{Component, ContainerWidget, RemoteRelm, Widget};
use self::CounterMsg::*;
use self::Msg::*;
#[derive(Clone)]
struct Model {
counter: i32,
}
#[derive(Msg)]
enum CounterMsg {
Decrement,
Increment,
}
#[derive(Clone)]
struct Counter {
counter_label: Label,
vbox: gtk::Box,
}
impl Widget for Counter {
type Container = gtk::Box;
type Model = Model;
type Msg = CounterMsg;
fn container(&self) -> &Self::Container {
&self.vbox
}
fn model() -> Model {
Model {
counter: 0,
}
}
fn update(&mut self, event: CounterMsg, model: &mut Model) {
let label = &self.counter_label;
match event {
Decrement => {
model.counter -= 1;
label.set_text(&model.counter.to_string());
},
Increment => {
model.counter += 1;
label.set_text(&model.counter.to_string());
},
}
}
fn view(relm: RemoteRelm<CounterMsg>, _model: &Model) -> Self {
let vbox = gtk::Box::new(Vertical, 0);
let plus_button = Button::new_with_label("+");
vbox.add(&plus_button);
let counter_label = Label::new("0");
vbox.add(&counter_label);
let minus_button = Button::new_with_label("-");
vbox.add(&minus_button);
connect!(relm, plus_button, connect_clicked(_), Increment);
connect!(relm, minus_button, connect_clicked(_), Decrement);
Counter {
counter_label: counter_label,
vbox: vbox,
}
}
}
#[derive(Msg)]
enum Msg {
Add,
Quit,
Remove,
}
#[derive(Clone)]
struct Win {
counters: Vec<Component<Counter>>,
hbox: gtk::Box,
relm: RemoteRelm<Msg>,
window: Window,
}
impl Widget for Win {
type Container = Window;
type Model = ();
type Msg = Msg;
fn container(&self) -> &Self::Container {
&self.window
}
fn model() -> () {
()
}
fn update(&mut self, event: Msg, _model: &mut ()) {
match event {
Add => {
let widget = self.hbox.add_widget::<Counter, _>(&self.relm);
self.counters.push(widget);
},
Quit => gtk::main_quit(),
Remove => {
if let Some(counter) = self.counters.pop() {
self.hbox.remove_widget(counter);
}
},
}
}
fn view(relm: RemoteRelm<Msg>, _model: &()) -> Self {
let window = Window::new(WindowType::Toplevel);
let vbox = gtk::Box::new(Vertical, 0);
let add_button = Button::new_with_label("Add");
let remove_button = Button::new_with_label("Remove");
let hbox = gtk::Box::new(Horizontal, 0);
vbox.add(&hbox);
vbox.add(&add_button);
vbox.add(&remove_button);
window.add(&vbox);
window.show_all();
connect!(relm, add_button, connect_clicked(_), Add);
connect!(relm, remove_button, connect_clicked(_), Remove);
connect!(relm, window, connect_delete_event(_, _) (Some(Quit), Inhibit(false)));
Win {
counters: vec![],
hbox: hbox,
relm: relm,
window: window,
}
}
}
fn main() {
relm::run::<Win>().unwrap();
}