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
use gtk::prelude::{BoxExt, ButtonExt, Cast, GtkWindowExt, OrientableExt};
use relm4::{gtk, send, AppUpdate, Model, RelmApp, RelmComponent, Sender, WidgetPlus, Widgets};
use relm4_components::save_dialog::{
SaveDialogModel, SaveDialogMsg, SaveDialogParent, SaveDialogSettings,
};
use relm4_components::ParentWindow;
use std::path::PathBuf;
#[derive(Default)]
struct AppModel {
counter: u8,
}
enum AppMsg {
Increment,
Decrement,
SaveRequest,
SaveResponse(PathBuf),
}
impl Model for AppModel {
type Msg = AppMsg;
type Widgets = AppWidgets;
type Components = AppComponents;
}
impl AppUpdate for AppModel {
fn update(&mut self, msg: AppMsg, components: &AppComponents, _sender: Sender<AppMsg>) -> bool {
match msg {
AppMsg::Increment => {
self.counter = self.counter.wrapping_add(1);
}
AppMsg::Decrement => {
self.counter = self.counter.wrapping_sub(1);
}
AppMsg::SaveRequest => {
components
.dialog
.send(SaveDialogMsg::SaveAs(format!("Counter_{}", self.counter)))
.unwrap();
}
AppMsg::SaveResponse(path) => {
println!("File would have been saved at {:?}", path);
}
}
true
}
}
struct SaveDialogConfig {}
impl relm4_components::save_dialog::SaveDialogConfig for SaveDialogConfig {
type Model = AppModel;
fn dialog_config(_model: &Self::Model) -> SaveDialogSettings {
SaveDialogSettings {
accept_label: "Open",
cancel_label: "Cancel",
create_folders: true,
is_modal: true,
filters: Vec::new(),
}
}
}
impl SaveDialogParent for AppModel {
fn save_msg(path: PathBuf) -> Self::Msg {
AppMsg::SaveResponse(path)
}
}
impl ParentWindow for AppWidgets {
fn parent_window(&self) -> Option<gtk::Window> {
Some(self.main_window.clone().upcast::<gtk::Window>())
}
}
#[derive(relm4::Components)]
pub struct AppComponents {
dialog: RelmComponent<SaveDialogModel<SaveDialogConfig>, AppModel>,
}
#[relm4::widget]
impl Widgets<AppModel, ()> for AppWidgets {
view! {
main_window = gtk::ApplicationWindow {
set_title: Some("Simple app"),
set_default_width: 300,
set_default_height: 100,
set_child = Some(>k::Box) {
set_orientation: gtk::Orientation::Vertical,
set_margin_all: 5,
set_spacing: 5,
append = >k::Button {
set_label: "Increment",
connect_clicked(sender) => move |_| {
send!(sender, AppMsg::Increment);
},
},
append = >k::Button {
set_label: "Decrement",
connect_clicked(sender) => move |_| {
send!(sender, AppMsg::Decrement);
},
},
append = >k::Label {
set_margin_all: 5,
set_label: watch! { &format!("Counter: {}", model.counter) },
},
append = >k::Button {
set_label: "Save",
connect_clicked(sender) => move |_| {
send!(sender, AppMsg::SaveRequest);
},
},
},
}
}
}
fn main() {
let model = AppModel::default();
let app = RelmApp::new(model);
app.run();
}