Commit 63e9d221 authored by Erik Reider's avatar Erik Reider

Simplified finding notification widgets when replacing and removing

parent 42d06db3
......@@ -114,7 +114,7 @@ namespace SwayNotificationCenter.Widgets {
private void prepare_group_removal (NotificationGroup group) {
if (group.name_id.length > 0) {
noti_groups_name.unset (group.name_id, null);
noti_groups_name.unset (group.name_id);
}
if (expanded_group == group) {
expanded_group = null;
......@@ -175,8 +175,8 @@ namespace SwayNotificationCenter.Widgets {
}
private void remove_group_internal (NotificationGroup group) {
foreach (uint32 id in group.notification_ids) {
if (noti_groups_id.unset (id, null)) {
foreach (uint32 id in group.notification_ids.keys) {
if (noti_groups_id.unset (id)) {
n_notifications--;
}
}
......@@ -197,6 +197,7 @@ namespace SwayNotificationCenter.Widgets {
return;
}
if (group.state == NotificationGroupState.MANY) {
noti_groups_id.unset (id);
n_notifications--;
group.remove_notification.begin (id, (obj, result) => {
// Continue the removal logic even if the async result failed
......@@ -215,8 +216,10 @@ namespace SwayNotificationCenter.Widgets {
public void replace_notification (uint32 id, NotifyParams new_params) {
unowned NotificationGroup ?group = noti_groups_id.get (id);
if (group != null) {
noti_groups_id.unset (id, null);
noti_groups_id.unset (id);
if (group.replace_notification (id, new_params)) {
// Replace the ID, could be changed depending on the
// replacement method used
noti_groups_id.set (new_params.applied_id, group);
// Position the notification in the beginning of the list
list_box.invalidate_sort ();
......@@ -268,10 +271,10 @@ namespace SwayNotificationCenter.Widgets {
group.add_css_class ("not-expanded");
}
noti_groups_id.set (param.applied_id, group);
group.add_notification (noti);
noti_groups_id.set (param.applied_id, group);
n_notifications++;
list_box.invalidate_sort ();
scroll_to_start ();
......
......@@ -55,7 +55,7 @@ namespace SwayNotificationCenter {
}
internal void request_dismiss_notification_group (string group_name_id,
Gee.HashSet<uint32> ids,
Gee.Set<uint32> ids,
ClosedReasons reason) {
debug ("Dismissing notification group with ID:%s, reason:%s",
group_name_id, reason.to_string ());
......
......@@ -15,9 +15,10 @@ namespace SwayNotificationCenter {
private Adw.TimedAnimation animation;
public uint n_children { get; private set; }
public List<Gtk.Widget> widgets = new List<Gtk.Widget> ();
public List<unowned Gtk.Widget> visible_widgets = new List<unowned Gtk.Widget> ();
List<Gtk.Widget> widgets = new List<Gtk.Widget> ();
public delegate void on_expand_change (bool state);
private unowned Gtk.Viewport viewport;
......@@ -94,12 +95,42 @@ namespace SwayNotificationCenter {
bool widget_visible = widget.get_visible ();
widget.unparent ();
widgets.remove (widget);
if (get_visible () && widget_visible) {
if (widget_visible) {
queue_resize ();
}
n_children--;
}
public void remove_all () {
while (!widgets.is_empty ()) {
unowned List<Gtk.Widget> link = widgets.nth (0);
if (link.data != null && link.data is Gtk.Widget) {
remove (link.data);
} else {
widgets.delete_link (link);
}
}
warn_if_fail (widgets.is_empty ());
n_children = 0;
}
public delegate bool WidgetFilterDelegate (Gtk.Widget widget);
public unowned Gtk.Widget ?get_first_widget (WidgetFilterDelegate ? filter = null) {
for (unowned List<Gtk.Widget> ?link = widgets.first ();
link != null;
link = link.next) {
if (link.data != null && (filter == null || filter (link.data))) {
return link.data;
}
}
return null;
}
public inline bool is_empty () {
return widgets.is_empty ();
}
private delegate void compute_height_iter_cb (Gtk.Widget child,
WidgetAlloc widget_alloc,
int index,
......
......@@ -8,10 +8,10 @@ namespace SwayNotificationCenter {
public class NotificationGroup : Gtk.ListBoxRow {
public string name_id;
public Gee.HashSet<uint32> notification_ids {
public Gee.HashMap<uint32, unowned Notification> notification_ids {
get;
private set;
default = new Gee.HashSet<uint32> ();
default = new Gee.HashMap<uint32, unowned Notification> ();
}
public NotificationGroupState state {
......@@ -283,12 +283,11 @@ namespace SwayNotificationCenter {
return;
}
unowned Notification first = (Notification) group.widgets.first ().data;
unowned NotifyParams param = first.param;
unowned Notification ?latest = get_latest_notification ();
// Get the app icon
Icon ?icon = null;
if (param.desktop_app_info != null
&& (icon = param.desktop_app_info.get_icon ()) != null) {
if (latest != null && latest.param.desktop_app_info != null
&& (icon = latest.param.desktop_app_info.get_icon ()) != null) {
app_icon.set_from_gicon (icon);
} else {
app_icon.set_from_icon_name ("application-x-executable-symbolic");
......@@ -296,14 +295,12 @@ namespace SwayNotificationCenter {
}
private unowned Notification ?find_notification (uint32 id) {
foreach (unowned Gtk.Widget widget in group.widgets) {
unowned Notification notification = (Notification) widget;
if (notification != null && notification.param.applied_id == id) {
return notification;
}
}
unowned Notification ?notification = notification_ids.get (id);
if (notification == null || notification.param.applied_id != id) {
return null;
}
return notification;
}
public void set_expanded (bool state) {
if (dismissed) {
......@@ -324,8 +321,8 @@ namespace SwayNotificationCenter {
if (noti.param.urgency == UrgencyLevels.CRITICAL) {
urgent_notifications.add (noti.param.applied_id);
}
notification_ids.add (noti.param.applied_id);
group.add (noti);
notification_ids.set (noti.param.applied_id, noti);
update_state ();
set_icon ();
......@@ -336,8 +333,8 @@ namespace SwayNotificationCenter {
if (notification == null) {
return false;
}
notification_ids.remove (id);
notification_ids.add (new_params.applied_id);
notification_ids.unset (id);
notification_ids.set (new_params.applied_id, notification);
notification.replace_notification (new_params);
return true;
}
......@@ -352,7 +349,7 @@ namespace SwayNotificationCenter {
}
urgent_notifications.remove (notification.param.applied_id);
notification_ids.remove (notification.param.applied_id);
notification_ids.unset (notification.param.applied_id);
notification.remove_noti_timeout ();
// Only animate individual notifications when there are more than one,
......@@ -393,7 +390,7 @@ namespace SwayNotificationCenter {
}
}
if (group.widgets.is_empty ()) {
if (group.is_empty ()) {
debug ("Skiping removal of all notifications as the group is already empty");
return false;
}
......@@ -403,16 +400,7 @@ namespace SwayNotificationCenter {
return false;
}
while (!group.widgets.is_empty ()) {
unowned List<Gtk.Widget> link = group.widgets.nth (0);
unowned Notification ?notification = (Notification) link.data;
if (notification != null) {
notification.remove_noti_timeout ();
}
group.widgets.delete_link (link);
}
warn_if_fail (group.widgets.is_empty ());
group.remove_all ();
return true;
}
......@@ -421,19 +409,23 @@ namespace SwayNotificationCenter {
return;
}
dismissed = true;
noti_daemon.request_dismiss_notification_group (name_id, notification_ids,
noti_daemon.request_dismiss_notification_group (name_id, notification_ids.keys,
ClosedReasons.DISMISSED);
}
public unowned Notification ?get_latest_notification () {
return (Notification ?) group.widgets.first ().data;
return (Notification ?) group.get_first_widget ((widget) => {
unowned Notification ?notification = (Notification ?) widget;
return notification != null && !notification.dismissed;
});
}
public int64 get_time () {
if (group.widgets.is_empty ()) {
unowned Notification ?notification = get_latest_notification ();
if (notification_ids.is_empty || notification == null) {
return -1;
}
return ((Notification) group.widgets.first ().data).param.time;
return notification.param.time;
}
public bool get_is_urgent () {
......@@ -446,10 +438,9 @@ namespace SwayNotificationCenter {
public void update () {
set_icon ();
foreach (unowned Gtk.Widget widget in group.widgets) {
var noti = (Notification) widget;
if (noti != null) {
noti.set_time ();
foreach (unowned Notification ?notification in notification_ids.values) {
if (notification != null) {
notification.set_time ();
}
}
}
......
......@@ -7,6 +7,8 @@ namespace SwayNotificationCenter {
unowned AnimatedList list;
Gee.HashSet<uint32> inline_reply_notifications = new Gee.HashSet<uint32> ();
Gee.HashMap<uint32, unowned Notification> notification_ids
= new Gee.HashMap<uint32, unowned Notification> ();
private static string ?monitor_name = null;
......@@ -214,6 +216,18 @@ namespace SwayNotificationCenter {
surface.set_input_region (region);
}
private inline unowned Notification ?find_notification (uint32 id) {
unowned Notification ?notification = notification_ids.get (id);
if (notification == null || notification.param.applied_id != id) {
return null;
}
unowned AnimatedListItem ?item = (AnimatedListItem ?) notification.get_parent ();
if (item == null || item.destroying) {
return null;
}
return notification;
}
/**
* Hides all notifications. Only invokes the NotificationClosed signal when transient.
* The optional callback is used to remove select notifications where each
......@@ -221,6 +235,7 @@ namespace SwayNotificationCenter {
*/
public void remove_all_notifications (bool transition,
notification_filter_func ?filter_func) {
notification_ids.clear ();
inline_reply_notifications.clear ();
foreach (unowned AnimatedListItem item in list.children) {
if (item.destroying) {
......@@ -240,6 +255,7 @@ namespace SwayNotificationCenter {
return_if_fail (notification != null);
NotifyParams param = notification.param;
notification_ids.unset (param.applied_id);
// Disable transitions when not mapped
transition &= get_mapped ();
......@@ -285,36 +301,31 @@ namespace SwayNotificationCenter {
set_visible (true);
list.append.begin (noti);
notification_ids.set (param.applied_id, noti);
}
/** Removes the notification widget with ID. Doesn't dismiss */
public void remove_notification (uint32 id) {
foreach (unowned AnimatedListItem item in list.children) {
if (item.destroying) {
continue;
}
unowned Notification notification = (Notification) item.child;
if (notification != null && notification.param.applied_id == id) {
unowned Notification ?notification = find_notification (id);
if (notification != null) {
remove_notification_internal (notification, true);
break;
}
}
}
public void replace_notification (uint32 id, NotifyParams new_params) {
foreach (unowned AnimatedListItem item in list.children) {
if (item.destroying) {
continue;
}
var noti = (Notification) item.child;
if (noti != null && noti.param.applied_id == id) {
noti.replace_notification (new_params);
unowned Notification ?notification = find_notification (id);
if (notification != null) {
// Replace the ID, could be changed depending on the
// replacement method used
notification_ids.unset (id);
notification_ids.set (new_params.applied_id, notification);
notification.replace_notification (new_params);
// Position the notification in the beginning/end of the list
// and scroll to the new item
list.move_to_beginning (noti, true);
list.move_to_beginning (notification, true);
return;
}
}
// Display a new notification if the old one isn't visible
debug ("Could not find floating notification to replace: %u", id);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment