azalea_shell/factory/notification/
mod.rs1use gtk::{gdk, glib, prelude::*};
2use relm4::{FactorySender, prelude::*};
3
4use crate::{component::image, service::dbus::notification};
5
6pub struct Model {
7 notification: notification::service::Notification,
8 image: relm4::Controller<image::Model>,
9 has_image: bool,
10 }
12
13#[derive(Debug)]
14pub enum Input {
15 Close,
16 }
18
19#[derive(Debug)]
20pub enum Output {
21 Close(u32),
22 }
24
25#[relm4::factory(pub)]
26impl FactoryComponent for Model {
27 type Index = u32;
28 type Init = notification::service::Notification;
29 type Input = Input;
30 type Output = Output;
31 type CommandOutput = ();
32 type ParentWidget = gtk::Box;
33
34 view! {
35 #[root]
36 gtk::Box {
37 gtk::Frame {
38 set_visible: self.has_image,
39 set_child: Some(self.image.widget()),
40 },
41
42 gtk::Box {
43 set_css_classes: &[
44 "azalea-padding",
45 ],
46 set_orientation: gtk::Orientation::Vertical,
47 set_spacing: 12,
48 set_vexpand: true,
49 set_hexpand: true,
50
51 gtk::Label {
52 set_css_classes: &[
53 "azalea-primary-fg",
54 ],
55 #[watch]
56 set_label: &self.notification.summary,
57
58 set_max_width_chars: 30,
59 set_wrap: true,
60 set_halign: gtk::Align::Start,
61 set_valign: gtk::Align::Start,
62 },
63
64 gtk::Label {
65 #[watch]
66 set_label: &self.notification.body,
67
68 set_max_width_chars: 30,
69 set_wrap: true,
70 set_halign: gtk::Align::Start,
71 set_valign: gtk::Align::Center,
72 },
73 },
74
75 gtk::Button {
76 set_css_classes: &[
77 "azalea-padding",
78 ],
79 set_halign: gtk::Align::End,
80 set_label: "X",
81 connect_clicked => Input::Close
82 },
83 }
84 }
85
86 fn init_model(notification: Self::Init, _index: &u32, _sender: FactorySender<Self>) -> Self {
87 let mut model = Self {
88 has_image: false,
89 image: image::Model::builder()
90 .launch(image::Init {
91 fallback: None,
92 width: None,
93 height: Some(100),
94 })
95 .detach(),
96 notification: notification.clone(),
97 };
98
99 match notification.image.clone() {
100 Some(image) => {
101 model.has_image = true;
102 match image {
103 notification::service::Image::Data {
104 width,
105 height,
106 rowstride,
107 has_alpha,
108 bits_per_sample,
109 channels: _,
110 data,
111 } => {
112 let pixbuf = gdk::gdk_pixbuf::Pixbuf::from_bytes(
113 &glib::Bytes::from_owned(data),
114 gtk::gdk_pixbuf::Colorspace::Rgb,
115 has_alpha,
116 bits_per_sample,
117 width,
118 height,
119 rowstride,
120 );
121
122 drop(model.image.sender().send(image::Input::LoadPixbuf(pixbuf)));
123 }
124 notification::service::Image::Path(path) => {
125 drop(model.image.sender().send(image::Input::LoadImage(path)));
126 }
127 }
128 }
129 None => {
130 if notification.app_icon != "" {
131 model.has_image = true;
132 println!("{}", notification.app_icon);
133 drop(
134 model
135 .image
136 .sender()
137 .send(image::Input::LoadImage(notification.app_icon)),
138 );
139 }
140 }
141 };
142
143 model
144 }
145
146 fn update(&mut self, message: Self::Input, sender: FactorySender<Self>) {
147 match message {
148 Input::Close => drop(sender.output(Output::Close(self.notification.id))),
149 }
150 }
151}