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
use gtk::prelude::{BoxExt, ButtonExt, GtkWindowExt, OrientableExt};
use rand::prelude::IteratorRandom;
use relm4::{gtk, send, AppUpdate, Model, RelmApp, Sender, WidgetPlus, Widgets};
const ICON_LIST: &[&str] = &[
"bookmark-new-symbolic",
"edit-copy-symbolic",
"edit-cut-symbolic",
"edit-find-symbolic",
"starred-symbolic",
"system-run-symbolic",
"emoji-objects-symbolic",
"emoji-nature-symbolic",
"display-brightness-symbolic",
];
fn random_icon_name() -> &'static str {
ICON_LIST
.iter()
.choose(&mut rand::thread_rng())
.expect("Could not choose a random icon")
}
enum AppMsg {
UpdateFirst,
UpdateSecond,
}
#[tracker::track]
struct AppModel {
first_icon: &'static str,
second_icon: &'static str,
identical: bool,
}
impl Model for AppModel {
type Msg = AppMsg;
type Widgets = AppWidgets;
type Components = ();
}
impl AppUpdate for AppModel {
fn update(&mut self, msg: AppMsg, _components: &(), _sender: Sender<AppMsg>) -> bool {
self.reset();
match msg {
AppMsg::UpdateFirst => {
self.set_first_icon(random_icon_name());
}
AppMsg::UpdateSecond => {
self.set_second_icon(random_icon_name());
}
}
self.set_identical(self.first_icon == self.second_icon);
true
}
}
#[relm4::widget]
impl Widgets<AppModel, ()> for AppWidgets {
view! {
main_window = gtk::ApplicationWindow {
set_class_active: track!(model.changed(AppModel::identical()), "identical", model.identical),
set_child = Some(>k::Box) {
set_orientation: gtk::Orientation::Horizontal,
set_spacing: 10,
set_margin_all: 10,
append = >k::Box {
set_orientation: gtk::Orientation::Vertical,
set_spacing: 10,
append = >k::Image {
set_pixel_size: 50,
set_icon_name: track!(Some(model.first_icon)),
},
append = >k::Button {
set_label: "New random image",
connect_clicked(sender) => move |_| {
send!(sender, AppMsg::UpdateFirst);
}
}
},
append = >k::Box {
set_orientation: gtk::Orientation::Vertical,
set_spacing: 10,
append = >k::Image {
set_pixel_size: 50,
set_icon_name: track!(model.changed(AppModel::second_icon()),
Some(model.second_icon)),
},
append = >k::Button {
set_label: "New random image",
connect_clicked(sender) => move |_| {
send!(sender, AppMsg::UpdateSecond);
}
}
},
}
}
}
fn post_init() {
relm4::set_global_css(b".identical { background: #00ad5c; }");
}
}
fn main() {
let model = AppModel {
first_icon: random_icon_name(),
second_icon: random_icon_name(),
identical: false,
tracker: 0,
};
let relm = RelmApp::new(model);
relm.run();
}