mxl_player_components/ui/message_dialog/
widget.rs1use super::{
2 messages::{MessageDialogInput, MessageDialogOutput, MessageDialogType, internal::PrivateMsg},
3 model::MessageDialog,
4};
5use crate::localization::helper::fl;
6use mxl_relm4_components::relm4::{self, adw::gtk::prelude::*, css as adw_css, prelude::*};
7
8#[relm4::component(pub)]
9impl Component for MessageDialog {
10 type Init = ();
11 type Input = MessageDialogInput;
12 type Output = MessageDialogOutput;
13 type CommandOutput = ();
14
15 view! {
16 #[name(dialog)]
17 adw::Window {
18 #[watch]
19 set_title: Some(model.title.as_str()),
20 set_modal: true,
21 set_hide_on_close: true,
22 set_destroy_with_parent: true,
23 set_height_request: 500,
24 set_width_request: 800,
25 #[watch]
26 set_visible: !model.hidden,
27
28 gtk::Box {
29 set_orientation: gtk::Orientation::Vertical,
30
31 adw::HeaderBar {
32 set_show_end_title_buttons: false,
33 },
34
35 gtk::Box {
36 set_orientation: gtk::Orientation::Vertical,
37 set_margin_all: 8,
38 set_spacing: 8,
39
40 gtk::ScrolledWindow {
41 set_vexpand: true,
42 set_hexpand: true,
43 set_vscrollbar_policy: gtk::PolicyType::Always,
44
45 gtk::TextView {
46 set_buffer: Some(&model.text_buffer),
47 set_vexpand: true,
48 set_hexpand: true,
49 set_editable: false,
50 set_wrap_mode: gtk::WrapMode::Word,
51 set_cursor_visible: false,
52 },
53 },
54
55 gtk::Box {
56 set_hexpand: true,
57 set_homogeneous: true,
58 set_spacing: 8,
59
60 gtk::Button {
61 #[watch]
62 set_label: &fl!("create-report"),
63 set_hexpand: true,
64 connect_clicked => MessageDialogInput::PrivateMessage(PrivateMsg::CreateReportButtonPressed),
65 },
66
67 gtk::Button {
68 #[watch]
69 set_label: match model.dialog_type {
70 MessageDialogType::Fatal => fl!("quit").to_owned(),
71 _ => fl!("close").to_owned(),
72 }.as_ref(),
73 add_css_class: adw_css::ERROR,
74 set_hexpand: true,
75 connect_clicked => MessageDialogInput::PrivateMessage(PrivateMsg::CloseButtonPressed),
76 },
77 },
78 },
79 },
80 }
81 }
82
83 fn init(_init: (), root: Self::Root, sender: ComponentSender<Self>) -> ComponentParts<Self> {
84 let model = MessageDialog {
85 hidden: true,
86 dialog_type: MessageDialogType::Error,
87 title: "".to_owned(),
88 text_buffer: gtk::TextBuffer::new(None),
89 };
90 let widgets = view_output!();
91
92 {
93 let controller = gtk::EventControllerKey::new();
94 controller.connect_key_pressed(move |_, key, _keycode, _modifiers| {
95 if key == gtk::gdk::Key::Escape {
96 sender.input(MessageDialogInput::PrivateMessage(PrivateMsg::CloseButtonPressed));
97 return gtk::glib::Propagation::Stop;
98 }
99 gtk::glib::Propagation::Proceed
100 });
101 root.add_controller(controller);
102 }
103
104 ComponentParts { model, widgets }
105 }
106
107 fn update(&mut self, msg: Self::Input, sender: ComponentSender<Self>, root: &Self::Root) {
108 match msg {
109 MessageDialogInput::PrivateMessage(msg) => match msg {
110 PrivateMsg::CreateReportButtonPressed => {
111 sender.output_sender().emit(MessageDialogOutput::CreateReport);
112 }
113 PrivateMsg::CloseButtonPressed => {
114 self.hidden = true;
115 root.close();
116 if self.dialog_type == MessageDialogType::Fatal {
117 sender.output_sender().emit(MessageDialogOutput::Quit);
118 }
119 }
120 },
121 MessageDialogInput::Message(message_type, title, text) => {
122 self.title = {
123 if let Some(title) = title {
124 title
125 } else {
126 match message_type {
127 MessageDialogType::Fatal => fl!("fatal-error-title").to_owned(),
128 MessageDialogType::Error => fl!("error-title").to_owned(),
129 MessageDialogType::Warning => fl!("warning-title").to_owned(),
130 }
131 }
132 };
133 self.dialog_type = message_type;
134 self.text_buffer.set_text(text.as_str());
135 self.hidden = false;
136 }
137 }
138 }
139}