[notification-daemon] Add a notification box class that updates in place
- From: William Jon McCann <mccann src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [notification-daemon] Add a notification box class that updates in place
- Date: Fri, 29 Oct 2010 21:35:01 +0000 (UTC)
commit fe52631b4c0cdfd1ae19f1c1be10f01b381b245f
Author: William Jon McCann <jmccann redhat com>
Date: Fri Oct 29 17:34:11 2010 -0400
Add a notification box class that updates in place
https://bugzilla.gnome.org/show_bug.cgi?id=633457
src/Makefile.am | 2 +
src/nd-notification-box.c | 403 +++++++++++++++++++++++++++++++++++++++++++++
src/nd-notification-box.h | 58 +++++++
src/nd-queue.c | 314 ++---------------------------------
4 files changed, 477 insertions(+), 300 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index ad3cb8a..384129b 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -3,6 +3,8 @@ libexec_PROGRAMS = notification-daemon
notification_daemon_SOURCES = \
nd-notification.c \
nd-notification.h \
+ nd-notification-box.c \
+ nd-notification-box.h \
nd-bubble.c \
nd-bubble.h \
nd-stack.c \
diff --git a/src/nd-notification-box.c b/src/nd-notification-box.c
new file mode 100644
index 0000000..3261ad6
--- /dev/null
+++ b/src/nd-notification-box.c
@@ -0,0 +1,403 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2010 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <string.h>
+#include <strings.h>
+#include <glib.h>
+
+#include "nd-notification.h"
+#include "nd-notification-box.h"
+
+#define ND_NOTIFICATION_BOX_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), ND_TYPE_NOTIFICATION_BOX, NdNotificationBoxPrivate))
+
+#define IMAGE_SIZE 48
+#define BODY_X_OFFSET (IMAGE_SIZE + 8)
+#define WIDTH 400
+
+struct NdNotificationBoxPrivate
+{
+ NdNotification *notification;
+
+ GtkWidget *icon;
+ GtkWidget *close_button;
+ GtkWidget *summary_label;
+ GtkWidget *body_label;
+
+ GtkWidget *main_hbox;
+ GtkWidget *iconbox;
+ GtkWidget *content_hbox;
+ GtkWidget *actions_box;
+ GtkWidget *last_sep;
+};
+
+static void nd_notification_box_class_init (NdNotificationBoxClass *klass);
+static void nd_notification_box_init (NdNotificationBox *notification_box);
+static void nd_notification_box_finalize (GObject *object);
+
+G_DEFINE_TYPE (NdNotificationBox, nd_notification_box, GTK_TYPE_EVENT_BOX)
+
+NdNotification *
+nd_notification_box_get_notification (NdNotificationBox *notification_box)
+{
+ g_return_val_if_fail (ND_IS_NOTIFICATION_BOX (notification_box), NULL);
+
+ return notification_box->priv->notification;
+}
+
+static gboolean
+nd_notification_box_button_release_event (GtkWidget *widget,
+ GdkEventButton *event)
+{
+ NdNotificationBox *notification_box = ND_NOTIFICATION_BOX (widget);
+
+ nd_notification_action_invoked (notification_box->priv->notification, "default");
+
+ return FALSE;
+}
+
+static void
+nd_notification_box_class_init (NdNotificationBoxClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->finalize = nd_notification_box_finalize;
+ widget_class->button_release_event = nd_notification_box_button_release_event;
+
+ g_type_class_add_private (klass, sizeof (NdNotificationBoxPrivate));
+}
+
+static void
+on_close_button_clicked (GtkButton *button,
+ NdNotificationBox *notification_box)
+{
+ nd_notification_close (notification_box->priv->notification, ND_NOTIFICATION_CLOSED_USER);
+}
+
+static void
+on_action_clicked (GtkButton *button,
+ GdkEventButton *event,
+ NdNotificationBox *notification_box)
+{
+ const char *key = g_object_get_data (G_OBJECT (button), "_action_key");
+
+ nd_notification_action_invoked (notification_box->priv->notification,
+ key);
+}
+
+static GtkWidget *
+create_notification_action (NdNotificationBox *box,
+ NdNotification *notification,
+ const char *text,
+ const char *key)
+{
+ GtkWidget *label;
+ GtkWidget *button;
+ GtkWidget *hbox;
+ GdkPixbuf *pixbuf;
+ char *buf;
+
+ button = gtk_button_new ();
+ gtk_widget_show (button);
+ gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
+ gtk_container_set_border_width (GTK_CONTAINER (button), 0);
+
+ hbox = gtk_hbox_new (FALSE, 6);
+ gtk_widget_show (hbox);
+ gtk_container_add (GTK_CONTAINER (button), hbox);
+
+ /* Try to be smart and find a suitable icon. */
+ buf = g_strdup_printf ("stock_%s", key);
+ pixbuf = gtk_icon_theme_load_icon (gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (box))),
+ buf,
+ 16,
+ GTK_ICON_LOOKUP_USE_BUILTIN,
+ NULL);
+ g_free (buf);
+
+ if (pixbuf != NULL) {
+ GtkWidget *image = gtk_image_new_from_pixbuf (pixbuf);
+ gtk_widget_show (image);
+ gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, FALSE, 0);
+ gtk_misc_set_alignment (GTK_MISC (image), 0.5, 0.5);
+ }
+
+ label = gtk_label_new (NULL);
+ gtk_widget_show (label);
+ gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
+ gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
+ buf = g_strdup_printf ("<small>%s</small>", text);
+ gtk_label_set_markup (GTK_LABEL (label), buf);
+ g_free (buf);
+
+ g_object_set_data_full (G_OBJECT (button),
+ "_action_key", g_strdup (key), g_free);
+ g_signal_connect (G_OBJECT (button),
+ "button-release-event",
+ G_CALLBACK (on_action_clicked),
+ box);
+ return button;
+}
+
+static void
+remove_item (GtkWidget *item,
+ gpointer data)
+{
+ gtk_container_remove (GTK_CONTAINER (gtk_widget_get_parent (item)),
+ item);
+}
+
+static void
+update_notification_box (NdNotificationBox *notification_box)
+{
+ gboolean have_icon;
+ gboolean have_body;
+ gboolean have_actions;
+ GdkPixbuf *pixbuf;
+ char **actions;
+ int i;
+ char *str;
+ char *quoted;
+ GtkRequisition req;
+ int summary_width;
+
+ /* Add content */
+
+ have_icon = FALSE;
+ have_body = FALSE;
+ have_actions = FALSE;
+
+ /* image */
+ pixbuf = nd_notification_load_image (notification_box->priv->notification, IMAGE_SIZE);
+ if (pixbuf != NULL) {
+ gtk_image_set_from_pixbuf (GTK_IMAGE (notification_box->priv->icon), pixbuf);
+
+ g_object_unref (G_OBJECT (pixbuf));
+ have_icon = TRUE;
+ }
+
+ /* summary */
+ quoted = g_markup_escape_text (nd_notification_get_summary (notification_box->priv->notification), -1);
+ str = g_strdup_printf ("<b><big>%s</big></b>", quoted);
+ g_free (quoted);
+
+ gtk_label_set_markup (GTK_LABEL (notification_box->priv->summary_label), str);
+ g_free (str);
+
+ gtk_widget_size_request (notification_box->priv->close_button, &req);
+ /* -1: main_vbox border width
+ -10: vbox border width
+ -6: spacing for hbox */
+ summary_width = WIDTH - (1*2) - (10*2) - BODY_X_OFFSET - req.width - (6*2);
+
+ gtk_widget_set_size_request (notification_box->priv->summary_label,
+ summary_width,
+ -1);
+
+ /* body */
+ gtk_label_set_markup (GTK_LABEL (notification_box->priv->body_label), nd_notification_get_body (notification_box->priv->notification));
+
+ if (str != NULL && *str != '\0') {
+ gtk_widget_set_size_request (notification_box->priv->body_label,
+ summary_width,
+ -1);
+ have_body = TRUE;
+ }
+
+ /* actions */
+ gtk_container_foreach (GTK_CONTAINER (notification_box->priv->actions_box), remove_item, NULL);
+ actions = nd_notification_get_actions (notification_box->priv->notification);
+ for (i = 0; actions[i] != NULL; i += 2) {
+ char *l = actions[i + 1];
+
+ if (l == NULL) {
+ g_warning ("Label not found for action %s. "
+ "The protocol specifies that a label must "
+ "follow an action in the actions array",
+ actions[i]);
+
+ break;
+ }
+
+ if (strcasecmp (actions[i], "default") != 0) {
+ GtkWidget *button;
+
+ button = create_notification_action (notification_box,
+ notification_box->priv->notification,
+ l,
+ actions[i]);
+ gtk_box_pack_start (GTK_BOX (notification_box->priv->actions_box), button, FALSE, FALSE, 0);
+
+ have_actions = TRUE;
+ }
+ }
+
+ if (have_icon || have_body || have_actions) {
+ gtk_widget_show (notification_box->priv->content_hbox);
+ } else {
+ gtk_widget_hide (notification_box->priv->content_hbox);
+ }
+}
+
+static void
+nd_notification_box_init (NdNotificationBox *notification_box)
+{
+ GtkWidget *box;
+ GtkWidget *iconbox;
+ GtkWidget *image;
+ GtkWidget *vbox;
+ GtkWidget *alignment;
+ AtkObject *atkobj;
+ GtkRcStyle *rcstyle;
+
+ notification_box->priv = ND_NOTIFICATION_BOX_GET_PRIVATE (notification_box);
+ box = gtk_hbox_new (FALSE, 6);
+ gtk_container_add (GTK_CONTAINER (notification_box), box);
+ gtk_widget_show (box);
+
+ /* First row (icon, vbox, close) */
+ iconbox = gtk_alignment_new (0.5, 0, 0, 0);
+ gtk_widget_show (iconbox);
+ gtk_alignment_set_padding (GTK_ALIGNMENT (iconbox),
+ 5, 0, 0, 0);
+ gtk_box_pack_start (GTK_BOX (box),
+ iconbox,
+ FALSE, FALSE, 0);
+ gtk_widget_set_size_request (iconbox, BODY_X_OFFSET, -1);
+
+ notification_box->priv->icon = gtk_image_new ();
+ gtk_widget_show (notification_box->priv->icon);
+ gtk_container_add (GTK_CONTAINER (iconbox), notification_box->priv->icon);
+
+ vbox = gtk_vbox_new (FALSE, 6);
+ gtk_widget_show (vbox);
+ gtk_box_pack_start (GTK_BOX (box), vbox, TRUE, TRUE, 0);
+ gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
+
+ /* Add the close button */
+ alignment = gtk_alignment_new (0.5, 0, 0, 0);
+ gtk_widget_show (alignment);
+ gtk_box_pack_start (GTK_BOX (box), alignment, FALSE, FALSE, 0);
+
+ notification_box->priv->close_button = gtk_button_new ();
+ gtk_widget_show (notification_box->priv->close_button);
+ gtk_container_add (GTK_CONTAINER (alignment), notification_box->priv->close_button);
+ gtk_button_set_relief (GTK_BUTTON (notification_box->priv->close_button), GTK_RELIEF_NONE);
+ gtk_container_set_border_width (GTK_CONTAINER (notification_box->priv->close_button), 0);
+ g_signal_connect (G_OBJECT (notification_box->priv->close_button),
+ "clicked",
+ G_CALLBACK (on_close_button_clicked),
+ notification_box);
+
+ rcstyle = gtk_rc_style_new ();
+ rcstyle->xthickness = rcstyle->ythickness = 0;
+ gtk_widget_modify_style (notification_box->priv->close_button, rcstyle);
+ g_object_unref (rcstyle);
+
+ atkobj = gtk_widget_get_accessible (notification_box->priv->close_button);
+ atk_action_set_description (ATK_ACTION (atkobj), 0,
+ "Closes the notification.");
+ atk_object_set_name (atkobj, "");
+ atk_object_set_description (atkobj, "Closes the notification.");
+
+ image = gtk_image_new_from_stock (GTK_STOCK_CLOSE, GTK_ICON_SIZE_MENU);
+ gtk_widget_show (image);
+ gtk_container_add (GTK_CONTAINER (notification_box->priv->close_button), image);
+
+ /* center vbox */
+ notification_box->priv->summary_label = gtk_label_new (NULL);
+ gtk_widget_show (notification_box->priv->summary_label);
+ gtk_box_pack_start (GTK_BOX (vbox), notification_box->priv->summary_label, TRUE, TRUE, 0);
+ gtk_misc_set_alignment (GTK_MISC (notification_box->priv->summary_label), 0, 0);
+ gtk_label_set_line_wrap (GTK_LABEL (notification_box->priv->summary_label), TRUE);
+
+ atkobj = gtk_widget_get_accessible (notification_box->priv->summary_label);
+ atk_object_set_description (atkobj, "Notification summary text.");
+
+ notification_box->priv->content_hbox = gtk_hbox_new (FALSE, 6);
+ gtk_widget_show (notification_box->priv->content_hbox);
+ gtk_box_pack_start (GTK_BOX (vbox), notification_box->priv->content_hbox, FALSE, FALSE, 0);
+
+ vbox = gtk_vbox_new (FALSE, 6);
+
+ gtk_widget_show (vbox);
+ gtk_box_pack_start (GTK_BOX (notification_box->priv->content_hbox), vbox, TRUE, TRUE, 0);
+
+ notification_box->priv->body_label = gtk_label_new (NULL);
+ gtk_widget_show (notification_box->priv->body_label);
+ gtk_box_pack_start (GTK_BOX (vbox), notification_box->priv->body_label, TRUE, TRUE, 0);
+ gtk_misc_set_alignment (GTK_MISC (notification_box->priv->body_label), 0, 0);
+ gtk_label_set_line_wrap (GTK_LABEL (notification_box->priv->body_label), TRUE);
+
+ atkobj = gtk_widget_get_accessible (notification_box->priv->body_label);
+ atk_object_set_description (atkobj, "Notification body text.");
+
+ alignment = gtk_alignment_new (1, 0.5, 0, 0);
+ gtk_widget_show (alignment);
+ gtk_box_pack_start (GTK_BOX (vbox), alignment, FALSE, TRUE, 0);
+
+ notification_box->priv->actions_box = gtk_hbox_new (FALSE, 6);
+ gtk_widget_show (notification_box->priv->actions_box);
+ gtk_container_add (GTK_CONTAINER (alignment), notification_box->priv->actions_box);
+
+}
+
+static void
+on_notification_changed (NdNotification *notification,
+ NdNotificationBox *notification_box)
+{
+ update_notification_box (notification_box);
+}
+
+static void
+nd_notification_box_finalize (GObject *object)
+{
+ NdNotificationBox *notification_box;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (ND_IS_NOTIFICATION_BOX (object));
+
+ notification_box = ND_NOTIFICATION_BOX (object);
+
+ g_return_if_fail (notification_box->priv != NULL);
+
+ g_signal_handlers_disconnect_by_func (notification_box->priv->notification, G_CALLBACK (on_notification_changed), notification_box);
+
+ g_object_unref (notification_box->priv->notification);
+
+ G_OBJECT_CLASS (nd_notification_box_parent_class)->finalize (object);
+}
+
+NdNotificationBox *
+nd_notification_box_new_for_notification (NdNotification *notification)
+{
+ NdNotificationBox *notification_box;
+
+ notification_box = g_object_new (ND_TYPE_NOTIFICATION_BOX,
+ "visible-window", FALSE,
+ NULL);
+ notification_box->priv->notification = g_object_ref (notification);
+ g_signal_connect (notification, "changed", G_CALLBACK (on_notification_changed), notification_box);
+ update_notification_box (notification_box);
+
+ return notification_box;
+}
diff --git a/src/nd-notification-box.h b/src/nd-notification-box.h
new file mode 100644
index 0000000..2e59973
--- /dev/null
+++ b/src/nd-notification-box.h
@@ -0,0 +1,58 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2010 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+
+#ifndef __ND_NOTIFICATION_BOX_H
+#define __ND_NOTIFICATION_BOX_H
+
+#include <gtk/gtk.h>
+#include "nd-notification.h"
+
+G_BEGIN_DECLS
+
+#define ND_TYPE_NOTIFICATION_BOX (nd_notification_box_get_type ())
+#define ND_NOTIFICATION_BOX(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), ND_TYPE_NOTIFICATION_BOX, NdNotificationBox))
+#define ND_NOTIFICATION_BOX_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), ND_TYPE_NOTIFICATION_BOX, NdNotificationBoxClass))
+#define ND_IS_NOTIFICATION_BOX(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), ND_TYPE_NOTIFICATION_BOX))
+#define ND_IS_NOTIFICATION_BOX_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), ND_TYPE_NOTIFICATION_BOX))
+#define ND_NOTIFICATION_BOX_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), ND_TYPE_NOTIFICATION_BOX, NdNotificationBoxClass))
+
+typedef struct NdNotificationBoxPrivate NdNotificationBoxPrivate;
+
+typedef struct
+{
+ GtkEventBox parent;
+ NdNotificationBoxPrivate *priv;
+} NdNotificationBox;
+
+typedef struct
+{
+ GtkEventBoxClass parent_class;
+} NdNotificationBoxClass;
+
+GType nd_notification_box_get_type (void);
+
+NdNotificationBox * nd_notification_box_new_for_notification (NdNotification *notification);
+
+NdNotification * nd_notification_box_get_notification (NdNotificationBox *notification_box);
+
+G_END_DECLS
+
+#endif /* __ND_NOTIFICATION_BOX_H */
diff --git a/src/nd-queue.c b/src/nd-queue.c
index a3a0164..20eac19 100644
--- a/src/nd-queue.c
+++ b/src/nd-queue.c
@@ -32,12 +32,11 @@
#include "nd-queue.h"
#include "nd-notification.h"
+#include "nd-notification-box.h"
#include "nd-stack.h"
#define ND_QUEUE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), ND_TYPE_QUEUE, NdQueuePrivate))
-#define IMAGE_SIZE 48
-#define BODY_X_OFFSET (IMAGE_SIZE + 8)
#define WIDTH 400
typedef struct
@@ -70,13 +69,13 @@ enum {
static guint signals [LAST_SIGNAL] = { 0, };
-static void nd_queue_class_init (NdQueueClass *klass);
-static void nd_queue_init (NdQueue *queue);
-static void nd_queue_finalize (GObject *object);
-static void queue_update (NdQueue *queue);
-static void on_notification_close (NdNotification *notification,
- int reason,
- NdQueue *queue);
+static void nd_queue_class_init (NdQueueClass *klass);
+static void nd_queue_init (NdQueue *queue);
+static void nd_queue_finalize (GObject *object);
+static void queue_update (NdQueue *queue);
+static void on_notification_close (NdNotification *notification,
+ int reason,
+ NdQueue *queue);
static gpointer queue_object = NULL;
@@ -660,291 +659,6 @@ collate_notifications (NdNotification *a,
}
static void
-on_close_button_clicked (GtkButton *button,
- NdNotification *notification)
-{
- nd_notification_close (notification, ND_NOTIFICATION_CLOSED_USER);
-}
-
-static void
-on_action_clicked (GtkButton *button,
- GdkEventButton *event,
- NdNotification *notification)
-{
- const char *key = g_object_get_data (G_OBJECT (button), "_action_key");
-
- nd_notification_action_invoked (notification,
- key);
-}
-
-static GtkWidget *
-create_notification_action (NdQueue *queue,
- NdNotification *notification,
- const char *text,
- const char *key)
-{
- GtkWidget *label;
- GtkWidget *button;
- GtkWidget *hbox;
- GdkPixbuf *pixbuf;
- char *buf;
-
- button = gtk_button_new ();
- gtk_widget_show (button);
- gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
- gtk_container_set_border_width (GTK_CONTAINER (button), 0);
-
- hbox = gtk_hbox_new (FALSE, 6);
- gtk_widget_show (hbox);
- gtk_container_add (GTK_CONTAINER (button), hbox);
-
- /* Try to be smart and find a suitable icon. */
- buf = g_strdup_printf ("stock_%s", key);
- pixbuf = gtk_icon_theme_load_icon (gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (queue->priv->dock))),
- buf,
- 16,
- GTK_ICON_LOOKUP_USE_BUILTIN,
- NULL);
- g_free (buf);
-
- if (pixbuf != NULL) {
- GtkWidget *image = gtk_image_new_from_pixbuf (pixbuf);
- gtk_widget_show (image);
- gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, FALSE, 0);
- gtk_misc_set_alignment (GTK_MISC (image), 0.5, 0.5);
- }
-
- label = gtk_label_new (NULL);
- gtk_widget_show (label);
- gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
- gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
- buf = g_strdup_printf ("<small>%s</small>", text);
- gtk_label_set_markup (GTK_LABEL (label), buf);
- g_free (buf);
-
- g_object_set_data_full (G_OBJECT (button),
- "_action_key", g_strdup (key), g_free);
- g_signal_connect (G_OBJECT (button),
- "button-release-event",
- G_CALLBACK (on_action_clicked),
- notification);
- return button;
-}
-
-static gboolean
-on_button_release (GtkWidget *widget,
- GdkEventButton *event,
- NdNotification *notification)
-{
- g_debug ("CLICK");
- nd_notification_action_invoked (notification, "default");
-
- return FALSE;
-}
-
-static GtkWidget *
-create_notification_box (NdQueue *queue,
- NdNotification *n)
-{
- GtkWidget *event_box;
- GtkWidget *box;
- GtkWidget *iconbox;
- GtkWidget *icon;
- GtkWidget *image;
- GtkWidget *content_hbox;
- GtkWidget *actions_box;
- GtkWidget *vbox;
- GtkWidget *summary_label;
- GtkWidget *body_label;
- GtkWidget *alignment;
- GtkWidget *close_button;
- AtkObject *atkobj;
- GtkRcStyle *rcstyle;
- char *str;
- char *quoted;
- GtkRequisition req;
- int summary_width;
- gboolean have_icon;
- gboolean have_body;
- gboolean have_actions;
- GdkPixbuf *pixbuf;
- char **actions;
- int i;
-
- event_box = gtk_event_box_new ();
- gtk_event_box_set_visible_window (GTK_EVENT_BOX (event_box),
- FALSE);
- g_signal_connect (event_box, "button-release-event", G_CALLBACK (on_button_release), n);
-
- box = gtk_hbox_new (FALSE, 6);
- gtk_container_add (GTK_CONTAINER (event_box), box);
- gtk_widget_show (box);
-
- /* First row (icon, vbox, close) */
- iconbox = gtk_alignment_new (0.5, 0, 0, 0);
- gtk_widget_show (iconbox);
- gtk_alignment_set_padding (GTK_ALIGNMENT (iconbox),
- 5, 0, 0, 0);
- gtk_box_pack_start (GTK_BOX (box),
- iconbox,
- FALSE, FALSE, 0);
- gtk_widget_set_size_request (iconbox, BODY_X_OFFSET, -1);
-
- icon = gtk_image_new ();
- gtk_widget_show (icon);
- gtk_container_add (GTK_CONTAINER (iconbox), icon);
-
- vbox = gtk_vbox_new (FALSE, 6);
- gtk_widget_show (vbox);
- gtk_box_pack_start (GTK_BOX (box), vbox, TRUE, TRUE, 0);
- gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
-
- /* Add the close button */
- alignment = gtk_alignment_new (0.5, 0, 0, 0);
- gtk_widget_show (alignment);
- gtk_box_pack_start (GTK_BOX (box), alignment, FALSE, FALSE, 0);
-
- close_button = gtk_button_new ();
- gtk_widget_show (close_button);
- gtk_container_add (GTK_CONTAINER (alignment), close_button);
- gtk_button_set_relief (GTK_BUTTON (close_button), GTK_RELIEF_NONE);
- gtk_container_set_border_width (GTK_CONTAINER (close_button), 0);
- g_signal_connect (G_OBJECT (close_button),
- "clicked",
- G_CALLBACK (on_close_button_clicked),
- n);
-
- rcstyle = gtk_rc_style_new ();
- rcstyle->xthickness = rcstyle->ythickness = 0;
- gtk_widget_modify_style (close_button, rcstyle);
- g_object_unref (rcstyle);
-
- atkobj = gtk_widget_get_accessible (close_button);
- atk_action_set_description (ATK_ACTION (atkobj), 0,
- "Closes the notification.");
- atk_object_set_name (atkobj, "");
- atk_object_set_description (atkobj, "Closes the notification.");
-
- image = gtk_image_new_from_stock (GTK_STOCK_CLOSE, GTK_ICON_SIZE_MENU);
- gtk_widget_show (image);
- gtk_container_add (GTK_CONTAINER (close_button), image);
-
- /* center vbox */
- summary_label = gtk_label_new (NULL);
- gtk_widget_show (summary_label);
- gtk_box_pack_start (GTK_BOX (vbox), summary_label, TRUE, TRUE, 0);
- gtk_misc_set_alignment (GTK_MISC (summary_label), 0, 0);
- gtk_label_set_line_wrap (GTK_LABEL (summary_label), TRUE);
-
- atkobj = gtk_widget_get_accessible (summary_label);
- atk_object_set_description (atkobj, "Notification summary text.");
-
- content_hbox = gtk_hbox_new (FALSE, 6);
- gtk_widget_show (content_hbox);
- gtk_box_pack_start (GTK_BOX (vbox), content_hbox, FALSE, FALSE, 0);
-
- vbox = gtk_vbox_new (FALSE, 6);
-
- gtk_widget_show (vbox);
- gtk_box_pack_start (GTK_BOX (content_hbox), vbox, TRUE, TRUE, 0);
-
- body_label = gtk_label_new (NULL);
- gtk_widget_show (body_label);
- gtk_box_pack_start (GTK_BOX (vbox), body_label, TRUE, TRUE, 0);
- gtk_misc_set_alignment (GTK_MISC (body_label), 0, 0);
- gtk_label_set_line_wrap (GTK_LABEL (body_label), TRUE);
-
- atkobj = gtk_widget_get_accessible (body_label);
- atk_object_set_description (atkobj, "Notification body text.");
-
- alignment = gtk_alignment_new (1, 0.5, 0, 0);
- gtk_widget_show (alignment);
- gtk_box_pack_start (GTK_BOX (vbox), alignment, FALSE, TRUE, 0);
-
- actions_box = gtk_hbox_new (FALSE, 6);
- gtk_widget_show (actions_box);
- gtk_container_add (GTK_CONTAINER (alignment), actions_box);
-
- /* Add content */
-
- have_icon = FALSE;
- have_body = FALSE;
- have_actions = FALSE;
-
- /* image */
- pixbuf = nd_notification_load_image (n, IMAGE_SIZE);
- if (pixbuf != NULL) {
- gtk_image_set_from_pixbuf (GTK_IMAGE (icon), pixbuf);
-
- g_object_unref (G_OBJECT (pixbuf));
- have_icon = TRUE;
- }
-
- /* summary */
- quoted = g_markup_escape_text (nd_notification_get_summary (n), -1);
- str = g_strdup_printf ("<b><big>%s</big></b>", quoted);
- g_free (quoted);
-
- gtk_label_set_markup (GTK_LABEL (summary_label), str);
- g_free (str);
-
- gtk_widget_size_request (close_button, &req);
- /* -1: main_vbox border width
- -10: vbox border width
- -6: spacing for hbox */
- summary_width = WIDTH - (1*2) - (10*2) - BODY_X_OFFSET - req.width - (6*2);
-
- gtk_widget_set_size_request (summary_label,
- summary_width,
- -1);
-
- /* body */
- gtk_label_set_markup (GTK_LABEL (body_label), nd_notification_get_body (n));
-
- if (str != NULL && *str != '\0') {
- gtk_widget_set_size_request (body_label,
- summary_width,
- -1);
- have_body = TRUE;
- }
-
- /* actions */
- actions = nd_notification_get_actions (n);
- for (i = 0; actions[i] != NULL; i += 2) {
- char *l = actions[i + 1];
-
- if (l == NULL) {
- g_warning ("Label not found for action %s. "
- "The protocol specifies that a label must "
- "follow an action in the actions array",
- actions[i]);
-
- break;
- }
-
- if (strcasecmp (actions[i], "default") != 0) {
- GtkWidget *button;
-
- button = create_notification_action (queue,
- n,
- l,
- actions[i]);
- gtk_box_pack_start (GTK_BOX (actions_box), button, FALSE, FALSE, 0);
-
- have_actions = TRUE;
- }
- }
-
- if (have_icon || have_body || have_actions) {
- gtk_widget_show (content_hbox);
- } else {
- gtk_widget_hide (content_hbox);
- }
-
- return event_box;
-}
-
-static void
update_dock (NdQueue *queue)
{
GtkWidget *child;
@@ -974,13 +688,13 @@ update_dock (NdQueue *queue)
list = g_list_sort (list, (GCompareFunc)collate_notifications);
for (l = list; l != NULL; l = l->next) {
- NdNotification *n = l->data;
- GtkWidget *hbox;
- GtkWidget *sep;
+ NdNotification *n = l->data;
+ NdNotificationBox *box;
+ GtkWidget *sep;
- hbox = create_notification_box (queue, n);
- gtk_widget_show (hbox);
- gtk_box_pack_start (GTK_BOX (child), hbox, FALSE, FALSE, 0);
+ box = nd_notification_box_new_for_notification (n);
+ gtk_widget_show (GTK_WIDGET (box));
+ gtk_box_pack_start (GTK_BOX (child), GTK_WIDGET (box), FALSE, FALSE, 0);
sep = gtk_hseparator_new ();
gtk_widget_show (sep);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]