From a82c0a557717ff8ddc8b8f2b5fe3f1b2299691c1 Mon Sep 17 00:00:00 2001 From: Ian Douglas Scott Date: Mon, 13 Sep 2021 13:48:17 -0700 Subject: [PATCH] Add button to close notification --- src/notification_list.rs | 11 +++++++++- src/notification_popover.rs | 13 ++++++------ src/notification_widget.rs | 40 ++++++++++++++++++++++++++++++------- src/notifications.rs | 18 +++++++++++++++++ 4 files changed, 67 insertions(+), 15 deletions(-) diff --git a/src/notification_list.rs b/src/notification_list.rs index b97b13c2..b8f8eff9 100644 --- a/src/notification_list.rs +++ b/src/notification_list.rs @@ -64,6 +64,9 @@ impl NotificationList { notifications.connect_notification_recieved(clone!(@weak obj => move |notification| { obj.handle_notification(¬ification); })); + notifications.connect_notification_closed(clone!(@weak obj => move |id| { + obj.remove_notification(id); + })); obj } @@ -74,7 +77,7 @@ impl NotificationList { fn handle_notification(&self, notification: &Notification) { let notification_widget = cascade! { - NotificationWidget::new(); + NotificationWidget::new(&*self.inner().notifications); ..set_notification(notification); }; @@ -88,6 +91,12 @@ impl NotificationList { self.inner().rows.borrow_mut().insert(notification.id, row); } + fn remove_notification(&self, id: NotificationId) { + if let Some(row) = self.inner().rows.borrow_mut().remove(&id) { + self.inner().listbox.remove(&row); + } + } + fn id_for_row(&self, row: >k4::ListBoxRow) -> Option { let rows = self.inner().rows.borrow(); Some(*rows.iter().find(|(_, i)| i == &row)?.0) diff --git a/src/notification_popover.rs b/src/notification_popover.rs index c8683d48..9c82a21f 100644 --- a/src/notification_popover.rs +++ b/src/notification_popover.rs @@ -31,19 +31,12 @@ impl ObjectImpl for NotificationPopoverInner { })); }); - let notification_widget = cascade! { - NotificationWidget::new(); - }; - cascade! { obj; ..set_autohide(false); ..set_has_arrow(false); ..set_offset(0, 12); - ..set_child(Some(¬ification_widget)); }; - - self.notification_widget.set(notification_widget); } } @@ -59,6 +52,12 @@ impl NotificationPopover { pub fn new(notifications: &Notifications) -> Self { let obj = glib::Object::new::(&[]).unwrap(); + let notification_widget = cascade! { + NotificationWidget::new(notifications); + }; + obj.set_child(Some(¬ification_widget)); + obj.inner().notification_widget.set(notification_widget); + // XXX disconnect? obj.inner().notifications.set(notifications.clone()); notifications.connect_notification_recieved(clone!(@weak obj => move |notification| { diff --git a/src/notification_widget.rs b/src/notification_widget.rs index 978520e7..30866931 100644 --- a/src/notification_widget.rs +++ b/src/notification_widget.rs @@ -1,14 +1,22 @@ use cascade::cascade; -use gtk4::{glib, pango, prelude::*, subclass::prelude::*}; +use gtk4::{ + glib::{self, clone}, + pango, + prelude::*, + subclass::prelude::*, +}; +use std::cell::Cell; use crate::deref_cell::DerefCell; -use crate::notifications::Notification; +use crate::notifications::{Notification, NotificationId, Notifications}; #[derive(Default)] pub struct NotificationWidgetInner { box_: DerefCell, summary_label: DerefCell, body_label: DerefCell, + notifications: DerefCell, + id: Cell>, } #[glib::object_subclass] @@ -37,10 +45,25 @@ impl ObjectImpl for NotificationWidgetInner { }; let box_ = cascade! { - gtk4::Box::new(gtk4::Orientation::Vertical, 0); + gtk4::Box::new(gtk4::Orientation::Horizontal, 0); ..set_parent(obj); - ..append(&summary_label); - ..append(&body_label); + ..append(&cascade! { + gtk4::Box::new(gtk4::Orientation::Vertical, 0); + ..append(&summary_label); + ..append(&body_label); + }); + ..append(&cascade! { + gtk4::Button::new(); + ..set_valign(gtk4::Align::Start); + ..set_child(Some(&cascade! { + gtk4::Image::from_icon_name(Some("window-close-symbolic")); + })); + ..connect_clicked(clone!(@weak obj => move |_| { + if let Some(id) = obj.inner().id.get() { + obj.inner().notifications.dismiss(id); + } + })); + }); }; self.box_.set(box_); @@ -61,8 +84,10 @@ glib::wrapper! { } impl NotificationWidget { - pub fn new() -> Self { - glib::Object::new(&[]).unwrap() + pub fn new(notifications: &Notifications) -> Self { + let obj = glib::Object::new::(&[]).unwrap(); + obj.inner().notifications.set(notifications.clone()); + obj } fn inner(&self) -> &NotificationWidgetInner { @@ -72,5 +97,6 @@ impl NotificationWidget { pub fn set_notification(&self, notification: &Notification) { self.inner().summary_label.set_label(¬ification.summary); self.inner().body_label.set_label(¬ification.body); + self.inner().id.set(Some(notification.id)); } } diff --git a/src/notifications.rs b/src/notifications.rs index 6e02628a..5a0a2000 100644 --- a/src/notifications.rs +++ b/src/notifications.rs @@ -297,6 +297,8 @@ impl Notifications { } fn close_notification(&self, id: NotificationId, reason: CloseReason) { + self.inner().notifications.borrow_mut().remove(&id); + self.emit_by_name("notification-closed", &[&id]).unwrap(); if let Some(connection) = self.inner().connection.borrow().as_ref() { @@ -312,6 +314,10 @@ impl Notifications { } } + pub fn dismiss(&self, id: NotificationId) { + self.close_notification(id, CloseReason::Dismiss); + } + fn bus_acquired(&self, connection: gio::DBusConnection, _name: &str) { *self.inner().connection.borrow_mut() = Some(connection); } @@ -396,4 +402,16 @@ impl Notifications { }) .unwrap() } + + pub fn connect_notification_closed( + &self, + cb: F, + ) -> SignalHandlerId { + self.connect_local("notification-closed", false, move |values| { + let id = values[1].get().unwrap(); + cb(id); + None + }) + .unwrap() + } }