[gnome-contacts] Make notification a pure GtkBin and move the content packing to the vala code
- From: Alexander Larsson <alexl src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-contacts] Make notification a pure GtkBin and move the content packing to the vala code
- Date: Tue, 20 Dec 2011 15:22:01 +0000 (UTC)
commit 570ceb747969b4b94d13a299b655a927aca20ffe
Author: Alexander Larsson <alexl redhat com>
Date: Tue Dec 20 16:20:18 2011 +0100
Make notification a pure GtkBin and move the content packing to the vala code
data/gnome-contacts.css | 3 +-
src/contacts-app.vala | 25 +-
src/gtk-notification.c | 865 ++++++++++++++++++++++++++---------------------
src/gtk-notification.h | 19 +-
vapi/custom.vapi | 6 +-
5 files changed, 508 insertions(+), 410 deletions(-)
---
diff --git a/data/gnome-contacts.css b/data/gnome-contacts.css
index e82ffd1..1945371 100644
--- a/data/gnome-contacts.css
+++ b/data/gnome-contacts.css
@@ -113,11 +113,12 @@ ContactsViewWidget {
color: #f57900;
}
-.contacts-notification {
+.notification {
border-style: solid;
border-color: #949486;
border-width: 0 1 1 1;
border-radius: 0 0 5 5;
+ padding: 8;
background-color: #d8d8d8;
background-image: -gtk-gradient (linear,
left top, left bottom,
diff --git a/src/contacts-app.vala b/src/contacts-app.vala
index f03fa12..b848734 100644
--- a/src/contacts-app.vala
+++ b/src/contacts-app.vala
@@ -136,21 +136,28 @@ public class Contacts.App : Gtk.Application {
contacts_pane = new ContactPane (contacts_store);
contacts_pane.set_hexpand (true);
contacts_pane.will_delete.connect ( (c) => {
+ var notification = new Gtk.Notification ();
+
+ var g = new Grid ();
+ g.set_column_spacing (8);
+ notification.add (g);
+
+
string msg = _("Contact deleted: \"%s\"").printf (c.display_name);
- var notification = new Gtk.Notification (msg, Stock.UNDO);
- notification.show ();
- ulong id;
- id = notification.destroy.connect ( () => {
- contacts_store.aggregator.remove_individual (c.individual);
+ var b = new Button.from_stock (Stock.UNDO);
+ g.add (new Label (msg));
+ g.add (b);
+
+ notification.show_all ();
+ var id = notification.timed_out.connect ( () => {
+ contacts_store.aggregator.remove_individual (c.individual);
});
- notification.actioned.connect ( () => {
- notification.disconnect (id);
- notification.destroy ();
+ b.clicked.connect ( () => {
+ notification.dismiss ();
c.show ();
list_pane.select_contact (c);
contacts_pane.show_contact (c);
});
-
overlay.add_overlay (notification);
});
grid.attach (contacts_pane, 1, 0, 1, 2);
diff --git a/src/gtk-notification.c b/src/gtk-notification.c
index abe1a80..72e53c3 100644
--- a/src/gtk-notification.c
+++ b/src/gtk-notification.c
@@ -1,4 +1,4 @@
-/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* gtk-notification.c
* Copyright (C) Erick PÃrez Castellanos 2011 <erick red gmail com>
@@ -26,540 +26,625 @@
* @see_also: #GtkStatusbar, #GtkMessageDialog, #GtkInfoBar
*
* #GtkNotification is a widget made for showing notifications to
- * the user, allowing them to execute 1 action over the notification,
- * or closing it.
+ * the user, allowing them to close the notification or wait for it
+ * to time out.
*
- * #GtkNotification provides one signal (#GtkNotification::actioned), for when the action button is activated.
- * Here the user will receive the signal, and then it's up to the user to destroy the widget,
- * or hide it.
- * The close button destroy the notification, so you can safely connect to the
- * #GtkWidget::destroy signal in order to know when the notification has been closed.
- *
- * #GtkNotification, the main difference here with some other widgets, is the timeout
- * inside GtkNotification widget. It mean, when the no action is taken over a period of time,
- * The widget will destroy itself.
+ * #GtkNotification provides one signal (#GtkNotification::timed-out), for when the notification
+ * times out.
*
*/
#define GTK_PARAM_READWRITE G_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB
#define SHADOW_OFFSET_X 2
#define SHADOW_OFFSET_Y 3
-#define INNER_BORDER 4
enum {
- PROP_0,
- PROP_MESSAGE,
- PROP_BUTTON_LABEL,
- PROP_TIMEOUT
+ PROP_0,
+ PROP_TIMEOUT
};
struct _GtkNotificationPrivate {
- GtkWidget *message;
- GtkWidget *action_button;
- GtkWidget *close_button;
-
- gchar *message_label;
- gchar *button_label;
- guint timeout;
+ GtkWidget *close_button;
- guint timeout_source_id;
+ guint timeout;
+ guint timeout_source_id;
};
enum {
- ACTIONED,
- LAST_SIGNAL
+ TIMED_OUT,
+ LAST_SIGNAL
};
static guint notification_signals[LAST_SIGNAL] = { 0 };
static gboolean gtk_notification_draw (GtkWidget *widget,
- cairo_t *cr);
+ cairo_t *cr);
static void gtk_notification_get_preferred_width (GtkWidget *widget,
- gint *minimum_size,
- gint *natural_size);
+ gint *minimum_size,
+ gint *natural_size);
static void gtk_notification_get_preferred_height_for_width (GtkWidget *widget,
- gint width,
- gint *minimum_height,
- gint *natural_height);
+ gint width,
+ gint *minimum_height,
+ gint *natural_height);
static void gtk_notification_get_preferred_height (GtkWidget *widget,
- gint *minimum_size,
- gint *natural_size);
+ gint *minimum_size,
+ gint *natural_size);
static void gtk_notification_get_preferred_width_for_height (GtkWidget *widget,
- gint height,
- gint *minimum_width,
- gint *natural_width);
+ gint height,
+ gint *minimum_width,
+ gint *natural_width);
static void gtk_notification_size_allocate (GtkWidget *widget,
- GtkAllocation *allocation);
+ GtkAllocation *allocation);
static void gtk_notification_update_message (GtkNotification *notification,
- const gchar *new_message);
+ const gchar *new_message);
static void gtk_notification_update_button (GtkNotification *notification,
- const gchar *new_button_label);
-static gboolean gtk_notification_auto_destroy (gpointer user_data);
+ const gchar *new_button_label);
+static gboolean gtk_notification_timeout_cb (gpointer user_data);
/* signals handlers */
static void gtk_notification_close_button_clicked_cb (GtkWidget *widget,
- gpointer user_data);
+ gpointer user_data);
static void gtk_notification_action_button_clicked_cb (GtkWidget *widget,
- gpointer user_data);
+ gpointer user_data);
+
-G_DEFINE_TYPE(GtkNotification, gtk_notification, GTK_TYPE_GRID);
+G_DEFINE_TYPE(GtkNotification, gtk_notification, GTK_TYPE_BIN);
static void
-gtk_notification_init(GtkNotification *notification)
+gtk_notification_init (GtkNotification *notification)
{
- GtkWidget *close_button_image;
-
- gtk_style_context_add_class (gtk_widget_get_style_context (GTK_WIDGET (notification)),
- "contacts-notification");
-
- //FIXME position should be set by properties
- gtk_widget_set_halign (GTK_WIDGET (notification), GTK_ALIGN_CENTER);
- gtk_widget_set_valign (GTK_WIDGET (notification), GTK_ALIGN_START);
-
- gtk_widget_push_composite_child ();
-
- notification->priv =
- G_TYPE_INSTANCE_GET_PRIVATE (notification,
- GTK_TYPE_NOTIFICATION,
- GtkNotificationPrivate);
-
- notification->priv->message = gtk_label_new (notification->priv->message_label);
- gtk_widget_show (notification->priv->message);
- notification->priv->action_button = gtk_button_new_with_label (notification->priv->button_label);
- gtk_widget_show (notification->priv->action_button);
- g_signal_connect (notification->priv->action_button,
- "clicked",
- G_CALLBACK (gtk_notification_action_button_clicked_cb),
- notification);
-
- notification->priv->close_button = gtk_button_new ();
- gtk_widget_show (notification->priv->close_button);
- g_object_set (notification->priv->close_button,
- "relief", GTK_RELIEF_NONE,
- "focus-on-click", FALSE,
- NULL);
- g_signal_connect (notification->priv->close_button,
- "clicked",
- G_CALLBACK (gtk_notification_close_button_clicked_cb),
- notification);
- close_button_image = gtk_image_new_from_icon_name ("window-close-symbolic", GTK_ICON_SIZE_BUTTON);
- gtk_button_set_image (GTK_BUTTON (notification->priv->close_button), close_button_image);
-
- gtk_container_add (GTK_CONTAINER (notification), notification->priv->message);
- gtk_container_add (GTK_CONTAINER (notification), notification->priv->action_button);
- gtk_container_add (GTK_CONTAINER (notification), notification->priv->close_button);
-
- gtk_widget_pop_composite_child ();
-
- notification->priv->timeout_source_id = 0;
+ GtkWidget *close_button_image;
+ GtkStyleContext *context;
+ GtkNotificationPrivate *priv;
+
+ context = gtk_widget_get_style_context (GTK_WIDGET (notification));
+ gtk_style_context_add_class (context, "notification");
+
+
+ gtk_widget_set_halign (GTK_WIDGET (notification), GTK_ALIGN_CENTER);
+ gtk_widget_set_valign (GTK_WIDGET (notification), GTK_ALIGN_START);
+
+ gtk_widget_push_composite_child ();
+
+ priv = notification->priv =
+ G_TYPE_INSTANCE_GET_PRIVATE (notification,
+ GTK_TYPE_NOTIFICATION,
+ GtkNotificationPrivate);
+
+ priv->close_button = gtk_button_new ();
+ gtk_widget_set_parent (priv->close_button, GTK_WIDGET (notification));
+ gtk_widget_show (priv->close_button);
+ g_object_set (priv->close_button,
+ "relief", GTK_RELIEF_NONE,
+ "focus-on-click", FALSE,
+ NULL);
+ g_signal_connect (priv->close_button,
+ "clicked",
+ G_CALLBACK (gtk_notification_close_button_clicked_cb),
+ notification);
+ close_button_image = gtk_image_new_from_icon_name ("window-close-symbolic", GTK_ICON_SIZE_BUTTON);
+ gtk_button_set_image (GTK_BUTTON (notification->priv->close_button), close_button_image);
+
+ gtk_widget_pop_composite_child ();
+
+ priv->timeout_source_id = 0;
}
static void
gtk_notification_finalize (GObject *object)
{
- g_return_if_fail (GTK_IS_NOTIFICATION (object));
- GtkNotification *notification = GTK_NOTIFICATION (object);
+ GtkNotification *notification;
- if (notification->priv->message_label)
- g_free (notification->priv->message_label);
+ g_return_if_fail (GTK_IS_NOTIFICATION (object));
- if (notification->priv->button_label)
- g_free (notification->priv->button_label);
+ notification = GTK_NOTIFICATION (object);
- if (notification->priv->timeout_source_id != 0)
- g_source_remove(notification->priv->timeout_source_id);
+ if (notification->priv->timeout_source_id != 0)
+ g_source_remove (notification->priv->timeout_source_id);
- G_OBJECT_CLASS (gtk_notification_parent_class)->finalize(object);
+ G_OBJECT_CLASS (gtk_notification_parent_class)->finalize(object);
}
static void
gtk_notification_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
{
- GtkNotification *notification = GTK_NOTIFICATION (object);
-
- g_return_if_fail (GTK_IS_NOTIFICATION (object));
-
- switch (prop_id) {
- case PROP_MESSAGE:
- gtk_notification_update_message (notification,
- g_value_get_string (value));
- break;
- case PROP_BUTTON_LABEL:
- gtk_notification_update_button (notification,
- g_value_get_string (value));
- break;
- case PROP_TIMEOUT:
- notification->priv->timeout = g_value_get_uint (value);
- g_object_notify (object, "timeout");
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
+ GtkNotification *notification = GTK_NOTIFICATION (object);
+
+ g_return_if_fail (GTK_IS_NOTIFICATION (object));
+
+ switch (prop_id) {
+ case PROP_TIMEOUT:
+ gtk_notification_set_timeout (notification,
+ g_value_get_uint (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
}
static void
gtk_notification_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
{
- g_return_if_fail (GTK_IS_NOTIFICATION (object));
- GtkNotification *notification = GTK_NOTIFICATION (object);
-
- switch (prop_id) {
- case PROP_MESSAGE:
- g_value_set_string (value, notification->priv->message_label);
- break;
- case PROP_BUTTON_LABEL:
- g_value_set_string (value, notification->priv->button_label);
- break;
- case PROP_TIMEOUT:
- g_value_set_uint (value, notification->priv->timeout);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
+ g_return_if_fail (GTK_IS_NOTIFICATION (object));
+ GtkNotification *notification = GTK_NOTIFICATION (object);
+
+ switch (prop_id) {
+ case PROP_TIMEOUT:
+ g_value_set_uint (value, notification->priv->timeout);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gtk_notification_forall (GtkContainer *container,
+ gboolean include_internals,
+ GtkCallback callback,
+ gpointer callback_data)
+{
+ GtkBin *bin = GTK_BIN (container);
+ GtkNotification *notification = GTK_NOTIFICATION (container);
+ GtkNotificationPrivate *priv = notification->priv;
+ GtkWidget *child;
+
+ child = gtk_bin_get_child (bin);
+ if (child)
+ (* callback) (child, callback_data);
+
+ if (include_internals)
+ (* callback) (priv->close_button, callback_data);
}
static void
gtk_notification_class_init (GtkNotificationClass *klass)
{
- GObjectClass* object_class = G_OBJECT_CLASS (klass);
- GtkWidgetClass* widget_class = GTK_WIDGET_CLASS(klass);
-
- object_class->finalize = gtk_notification_finalize;
- object_class->set_property = gtk_notification_set_property;
- object_class->get_property = gtk_notification_get_property;
-
- widget_class->get_preferred_width = gtk_notification_get_preferred_width;
- widget_class->get_preferred_height_for_width = gtk_notification_get_preferred_height_for_width;
- widget_class->get_preferred_height = gtk_notification_get_preferred_height;
- widget_class->get_preferred_width_for_height = gtk_notification_get_preferred_width_for_height;
- widget_class->size_allocate = gtk_notification_size_allocate;
-
- widget_class->draw = gtk_notification_draw;
-
- //FIXME these properties need tranlsations
- /**
- * GtkNotification:message:
- *
- * Message shown in the notification.
- *
- * Since: 0.1
- */
- g_object_class_install_property (object_class,
- PROP_MESSAGE,
- g_param_spec_string("message", "message", "Message shown on the notification", "",
- GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT));
-
- /**
- * GtkNotification:button-label:
- *
- * Action button label, could be one of #GtkStockItem.
- *
- * Since: 0.1
- */
- g_object_class_install_property (object_class,
- PROP_BUTTON_LABEL,
- g_param_spec_string("button-label",
- "button-label",
- "Label of the action button, if is a stock gtk indetifier, the button will get and icon too",
- "",
- GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT));
-
- /**
- * GtkNotification:timeout:
- *
- * The time it takes to hide the widget, in seconds.
- *
- * Since: 0.1
- */
- g_object_class_install_property (object_class,
- PROP_TIMEOUT,
- g_param_spec_uint("timeout", "timeout", "The time it takes to hide the widget, in seconds",
- 0, G_MAXUINT, 5,
- GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT));
-
- notification_signals[ACTIONED] = g_signal_new ("actioned",
- G_OBJECT_CLASS_TYPE (klass),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (GtkNotificationClass, actioned),
- NULL,
- NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE,
- 0);
-
- g_type_class_add_private (object_class, sizeof (GtkNotificationPrivate));
+ GObjectClass* object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass* widget_class = GTK_WIDGET_CLASS(klass);
+ GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
+
+ object_class->finalize = gtk_notification_finalize;
+ object_class->set_property = gtk_notification_set_property;
+ object_class->get_property = gtk_notification_get_property;
+
+ widget_class->get_preferred_width = gtk_notification_get_preferred_width;
+ widget_class->get_preferred_height_for_width = gtk_notification_get_preferred_height_for_width;
+ widget_class->get_preferred_height = gtk_notification_get_preferred_height;
+ widget_class->get_preferred_width_for_height = gtk_notification_get_preferred_width_for_height;
+ widget_class->size_allocate = gtk_notification_size_allocate;
+ widget_class->draw = gtk_notification_draw;
+
+ container_class->forall = gtk_notification_forall;
+ gtk_container_class_handle_border_width (container_class);
+
+
+ /**
+ * GtkNotification:timeout:
+ *
+ * The time it takes to hide the widget, in seconds.
+ *
+ * Since: 0.1
+ */
+ g_object_class_install_property (object_class,
+ PROP_TIMEOUT,
+ g_param_spec_uint("timeout", "timeout",
+ "The time it takes to hide the widget, in seconds",
+ 0, G_MAXUINT, 10,
+ GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
+ notification_signals[TIMED_OUT] = g_signal_new ("timed-out",
+ G_OBJECT_CLASS_TYPE (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GtkNotificationClass, timed_out),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE,
+ 0);
+
+ g_type_class_add_private (object_class, sizeof (GtkNotificationPrivate));
}
static void
draw_shadow_box (cairo_t *cr, GdkRectangle rect, int left_border, int right_border,
- int bottom_border, double inner_alpha)
+ int bottom_border, double inner_alpha)
{
- cairo_pattern_t *pattern;
- cairo_matrix_t matrix;
- double x0, x1, x2, x3;
- double y0, y1, y2, y3;
+ cairo_pattern_t *pattern;
+ cairo_matrix_t matrix;
+ double x0, x1, x2, x3;
+ double y0, y1, y2, y3;
+
+ cairo_save (cr);
- cairo_save (cr);
+ x0 = rect.x;
+ x1 = rect.x + left_border;
+ x2 = rect.x + rect.width - right_border;
+ x3 = rect.x + rect.width;
- x0 = rect.x;
- x1 = rect.x + left_border;
- x2 = rect.x + rect.width - right_border;
- x3 = rect.x + rect.width;
+ y0 = rect.y;
+ y2 = rect.y + rect.height - bottom_border;
+ y3 = rect.y + rect.height;
- y0 = rect.y;
- y2 = rect.y + rect.height - bottom_border;
- y3 = rect.y + rect.height;
+ /* Bottom border */
- /* Bottom border */
+ pattern = cairo_pattern_create_linear(0, y2, 0, y3);
- pattern = cairo_pattern_create_linear(0, y2, 0, y3);
+ cairo_pattern_add_color_stop_rgba(pattern, 0.0, 0, 0, 0, inner_alpha);
+ cairo_pattern_add_color_stop_rgba(pattern, 1.0, 0, 0, 0, 0.0);
- cairo_pattern_add_color_stop_rgba(pattern, 0.0, 0, 0, 0, inner_alpha);
- cairo_pattern_add_color_stop_rgba(pattern, 1.0, 0, 0, 0, 0.0);
+ cairo_set_source(cr, pattern);
+ cairo_pattern_destroy(pattern);
- cairo_set_source(cr, pattern);
- cairo_pattern_destroy(pattern);
+ cairo_rectangle(cr, x1, y2, x2 - x1, y3 - y2);
+ cairo_fill(cr);
- cairo_rectangle(cr, x1, y2, x2 - x1, y3 - y2);
- cairo_fill(cr);
+ /* Left border */
- /* Left border */
+ pattern = cairo_pattern_create_linear(x0, 0, x1, 0);
- pattern = cairo_pattern_create_linear(x0, 0, x1, 0);
+ cairo_pattern_add_color_stop_rgba(pattern, 0.0, 0, 0, 0, 0.0);
+ cairo_pattern_add_color_stop_rgba(pattern, 1.0, 0, 0, 0, inner_alpha);
- cairo_pattern_add_color_stop_rgba(pattern, 0.0, 0, 0, 0, 0.0);
- cairo_pattern_add_color_stop_rgba(pattern, 1.0, 0, 0, 0, inner_alpha);
+ cairo_set_source(cr, pattern);
+ cairo_pattern_destroy(pattern);
- cairo_set_source(cr, pattern);
- cairo_pattern_destroy(pattern);
+ cairo_rectangle(cr, x0, y0, x1 - x0, y2 - y0);
+ cairo_fill(cr);
- cairo_rectangle(cr, x0, y0, x1 - x0, y2 - y0);
- cairo_fill(cr);
+ /* Right border */
- /* Right border */
+ pattern = cairo_pattern_create_linear(x2, 0, x3, 0);
- pattern = cairo_pattern_create_linear(x2, 0, x3, 0);
+ cairo_pattern_add_color_stop_rgba(pattern, 0.0, 0, 0, 0, inner_alpha);
+ cairo_pattern_add_color_stop_rgba(pattern, 1.0, 0, 0, 0, 0.0);
- cairo_pattern_add_color_stop_rgba(pattern, 0.0, 0, 0, 0, inner_alpha);
- cairo_pattern_add_color_stop_rgba(pattern, 1.0, 0, 0, 0, 0.0);
+ cairo_set_source(cr, pattern);
+ cairo_pattern_destroy(pattern);
- cairo_set_source(cr, pattern);
- cairo_pattern_destroy(pattern);
+ cairo_rectangle(cr, x2, y0, x3 - x2, y2 - y0);
+ cairo_fill(cr);
- cairo_rectangle(cr, x2, y0, x3 - x2, y2 - y0);
- cairo_fill(cr);
+ /* SW corner */
- /* SW corner */
+ pattern = cairo_pattern_create_radial(0, 0, 0, 0.0, 0, 1.0);
+ cairo_pattern_add_color_stop_rgba(pattern, 0.0, 0, 0, 0, inner_alpha);
+ cairo_pattern_add_color_stop_rgba(pattern, 1.0, 0, 0, 0, 0.0);
- pattern = cairo_pattern_create_radial(0, 0, 0, 0.0, 0, 1.0);
- cairo_pattern_add_color_stop_rgba(pattern, 0.0, 0, 0, 0, inner_alpha);
- cairo_pattern_add_color_stop_rgba(pattern, 1.0, 0, 0, 0, 0.0);
+ cairo_matrix_init_scale (&matrix, 1.0 / left_border, 1.0 / bottom_border);
+ cairo_matrix_translate (&matrix, - x1, -y2);
+ cairo_pattern_set_matrix (pattern, &matrix);
- cairo_matrix_init_scale (&matrix, 1.0 / left_border, 1.0 / bottom_border);
- cairo_matrix_translate (&matrix, - x1, -y2);
- cairo_pattern_set_matrix (pattern, &matrix);
+ cairo_set_source(cr, pattern);
+ cairo_pattern_destroy(pattern);
- cairo_set_source(cr, pattern);
- cairo_pattern_destroy(pattern);
+ cairo_rectangle(cr, x0, y2, x1 - x0, y3 - y2);
+ cairo_fill(cr);
- cairo_rectangle(cr, x0, y2, x1 - x0, y3 - y2);
- cairo_fill(cr);
+ /* SE corner */
- /* SE corner */
+ pattern = cairo_pattern_create_radial(0, 0, 0, 0, 0, 1.0);
+ cairo_pattern_add_color_stop_rgba(pattern, 0.0, 0.0, 0, 0, inner_alpha);
+ cairo_pattern_add_color_stop_rgba(pattern, 1.0, 0.0, 0, 0, 0.0);
- pattern = cairo_pattern_create_radial(0, 0, 0, 0, 0, 1.0);
- cairo_pattern_add_color_stop_rgba(pattern, 0.0, 0.0, 0, 0, inner_alpha);
- cairo_pattern_add_color_stop_rgba(pattern, 1.0, 0.0, 0, 0, 0.0);
+ cairo_matrix_init_scale (&matrix, 1.0 / left_border, 1.0 / bottom_border);
+ cairo_matrix_translate (&matrix, - x2, -y2);
+ cairo_pattern_set_matrix (pattern, &matrix);
- cairo_matrix_init_scale (&matrix, 1.0 / left_border, 1.0 / bottom_border);
- cairo_matrix_translate (&matrix, - x2, -y2);
- cairo_pattern_set_matrix (pattern, &matrix);
+ cairo_set_source(cr, pattern);
+ cairo_pattern_destroy(pattern);
+
+ cairo_rectangle(cr, x2, y2, x3 - x2, y3 - y2);
+ cairo_fill(cr);
+
+ cairo_restore (cr);
+}
+
+static void
+get_padding_and_border (GtkNotification *notification,
+ GtkBorder *border)
+{
+ GtkStyleContext *context;
+ GtkStateFlags state;
+ GtkBorder tmp;
- cairo_set_source(cr, pattern);
- cairo_pattern_destroy(pattern);
+ context = gtk_widget_get_style_context (GTK_WIDGET (notification));
+ state = gtk_widget_get_state_flags (GTK_WIDGET (notification));
- cairo_rectangle(cr, x2, y2, x3 - x2, y3 - y2);
- cairo_fill(cr);
+ gtk_style_context_get_padding (context, state, border);
- cairo_restore (cr);
+ gtk_style_context_get_border (context, state, &tmp);
+ border->top += tmp.top;
+ border->right += tmp.right;
+ border->bottom += tmp.bottom;
+ border->left += tmp.left;
}
static gboolean
gtk_notification_draw (GtkWidget *widget, cairo_t *cr)
{
- GtkStyleContext *context;
- GdkRectangle rect;
- int border_radius;
- GtkStateFlags state;
- int inner_radius;
-
- gtk_widget_get_allocation (widget, &rect);
-
- context = gtk_widget_get_style_context(widget);
- state = gtk_style_context_get_state (context);
-
- inner_radius = 5;
- draw_shadow_box (cr, rect, SHADOW_OFFSET_X + inner_radius, SHADOW_OFFSET_X + inner_radius,
- SHADOW_OFFSET_Y + inner_radius, 0.8);
-
- gtk_style_context_save (context);
- gtk_render_background (context, cr,
- SHADOW_OFFSET_X, 0,
- gtk_widget_get_allocated_width (widget) - 2 *SHADOW_OFFSET_X,
- gtk_widget_get_allocated_height (widget) - SHADOW_OFFSET_Y);
- gtk_render_frame (context,cr,
- SHADOW_OFFSET_X, 0,
- gtk_widget_get_allocated_width (widget) - 2 *SHADOW_OFFSET_X,
- gtk_widget_get_allocated_height (widget) - SHADOW_OFFSET_Y);
-
- gtk_style_context_restore (context);
-
- if (GTK_WIDGET_CLASS (gtk_notification_parent_class)->draw)
- GTK_WIDGET_CLASS (gtk_notification_parent_class)->draw(widget, cr);
-
- /* starting timeout when drawing the first time */
- GtkNotification *notification = GTK_NOTIFICATION(widget);
- if (notification->priv->timeout_source_id == 0) {
- notification->priv->timeout_source_id = g_timeout_add(notification->priv->timeout * 1000,
- gtk_notification_auto_destroy,
- widget);
- }
- return FALSE;
+ GtkNotification *notification = GTK_NOTIFICATION (widget);
+ GtkStyleContext *context;
+ GdkRectangle rect;
+ int border_radius;
+ GtkStateFlags state;
+ int inner_radius;
+
+ gtk_widget_get_allocation (widget, &rect);
+
+ context = gtk_widget_get_style_context(widget);
+ state = gtk_style_context_get_state (context);
+
+ inner_radius = 5;
+ draw_shadow_box (cr, rect, SHADOW_OFFSET_X + inner_radius, SHADOW_OFFSET_X + inner_radius,
+ SHADOW_OFFSET_Y + inner_radius, 0.8);
+
+ gtk_style_context_save (context);
+ gtk_render_background (context, cr,
+ SHADOW_OFFSET_X, 0,
+ gtk_widget_get_allocated_width (widget) - 2 *SHADOW_OFFSET_X,
+ gtk_widget_get_allocated_height (widget) - SHADOW_OFFSET_Y);
+ gtk_render_frame (context,cr,
+ SHADOW_OFFSET_X, 0,
+ gtk_widget_get_allocated_width (widget) - 2 *SHADOW_OFFSET_X,
+ gtk_widget_get_allocated_height (widget) - SHADOW_OFFSET_Y);
+
+ gtk_style_context_restore (context);
+
+ if (GTK_WIDGET_CLASS (gtk_notification_parent_class)->draw)
+ GTK_WIDGET_CLASS (gtk_notification_parent_class)->draw(widget, cr);
+
+ /* starting timeout when drawing the first time */
+ if (notification->priv->timeout_source_id == 0)
+ notification->priv->timeout_source_id = g_timeout_add (notification->priv->timeout * 1000,
+ gtk_notification_timeout_cb,
+ widget);
+ return FALSE;
}
static void
gtk_notification_get_preferred_width (GtkWidget *widget, gint *minimum_size, gint *natural_size)
{
- gint parent_minimum_size, parent_natural_size;
-
- GTK_WIDGET_CLASS (gtk_notification_parent_class)->
- get_preferred_width (widget, &parent_minimum_size, &parent_natural_size);
-
- *minimum_size = parent_minimum_size + SHADOW_OFFSET_X * 2 + 2 * INNER_BORDER;
- *natural_size = parent_natural_size + SHADOW_OFFSET_X * 2 + 2 * INNER_BORDER;
+ GtkNotification *notification = GTK_NOTIFICATION (widget);
+ GtkNotificationPrivate *priv = notification->priv;
+ GtkBin *bin = GTK_BIN (widget);
+ gint child_min, child_nat;
+ GtkWidget *child;
+ GtkBorder padding;
+ gint minimum, natural;
+
+ get_padding_and_border (notification, &padding);
+
+ minimum = 0;
+ natural = 0;
+
+ child = gtk_bin_get_child (bin);
+ if (child && gtk_widget_get_visible (child))
+ {
+ gtk_widget_get_preferred_width (child,
+ &child_min, &child_nat);
+ minimum += child_min;
+ natural += child_nat;
+ }
+
+ gtk_widget_get_preferred_width (priv->close_button,
+ &child_min, &child_nat);
+ minimum += child_min;
+ natural += child_nat;
+
+
+ minimum += padding.left + padding.right + 2 * SHADOW_OFFSET_X;
+ natural += padding.left + padding.right + 2 * SHADOW_OFFSET_X;
+
+ if (minimum_size)
+ *minimum_size = minimum;
+
+ if (natural_size)
+ *natural_size = natural;
}
static void
-gtk_notification_get_preferred_height_for_width (GtkWidget *widget,
- gint width,
- gint *minimum_height,
- gint *natural_height)
+gtk_notification_get_preferred_width_for_height (GtkWidget *widget,
+ gint height,
+ gint *minimum_width,
+ gint *natural_width)
{
- gint parent_minimum_size, parent_natural_size;
-
- GTK_WIDGET_CLASS (gtk_notification_parent_class)->
- get_preferred_height_for_width (widget,
- width,
- &parent_minimum_size,
- &parent_natural_size);
-
- *minimum_height = parent_minimum_size + SHADOW_OFFSET_Y + 2 * INNER_BORDER;
- *natural_height = parent_natural_size + SHADOW_OFFSET_Y + 2 * INNER_BORDER;
+ GtkNotification *notification = GTK_NOTIFICATION (widget);
+ GtkNotificationPrivate *priv = notification->priv;
+ GtkBin *bin = GTK_BIN (widget);
+ gint child_min, child_nat, child_height;
+ GtkWidget *child;
+ GtkBorder padding;
+ gint minimum, natural;
+
+ get_padding_and_border (notification, &padding);
+
+ minimum = 0;
+ natural = 0;
+
+ child_height = height - SHADOW_OFFSET_Y - padding.top - padding.bottom;
+
+ child = gtk_bin_get_child (bin);
+ if (child && gtk_widget_get_visible (child))
+ {
+ gtk_widget_get_preferred_width_for_height (child, child_height,
+ &child_min, &child_nat);
+ minimum += child_min;
+ natural += child_nat;
+ }
+
+ gtk_widget_get_preferred_width_for_height (priv->close_button, child_height,
+ &child_min, &child_nat);
+ minimum += child_min;
+ natural += child_nat;
+
+ minimum += padding.left + padding.right + 2 * SHADOW_OFFSET_X;
+ natural += padding.left + padding.right + 2 * SHADOW_OFFSET_X;
+
+ if (minimum_width)
+ *minimum_width = minimum;
+
+ if (natural_width)
+ *natural_width = natural;
}
static void
-gtk_notification_get_preferred_height (GtkWidget *widget, gint *minimum_size, gint *natural_size)
+gtk_notification_get_preferred_height_for_width (GtkWidget *widget,
+ gint width,
+ gint *minimum_height,
+ gint *natural_height)
{
- gint parent_minimum_size, parent_natural_size;
-
- GTK_WIDGET_CLASS (gtk_notification_parent_class)->get_preferred_height (widget,
- &parent_minimum_size,
- &parent_natural_size);
-
- *minimum_size = parent_minimum_size + SHADOW_OFFSET_Y + 2 * INNER_BORDER;
- *natural_size = parent_natural_size + SHADOW_OFFSET_Y + 2 * INNER_BORDER;
+ GtkNotification *notification = GTK_NOTIFICATION (widget);
+ GtkNotificationPrivate *priv = notification->priv;
+ GtkBin *bin = GTK_BIN (widget);
+ gint child_min, child_nat, child_width, button_width;
+ GtkWidget *child;
+ GtkBorder padding;
+ gint minimum, natural;
+
+ get_padding_and_border (notification, &padding);
+
+ gtk_widget_get_preferred_height (priv->close_button,
+ &minimum, &natural);
+ gtk_widget_get_preferred_width (priv->close_button,
+ NULL, &button_width);
+
+ child = gtk_bin_get_child (bin);
+ if (child && gtk_widget_get_visible (child))
+ {
+ child_width = width - 2 * SHADOW_OFFSET_X - padding.left - padding.top - button_width;
+
+ gtk_widget_get_preferred_height_for_width (child, child_width,
+ &child_min, &child_nat);
+ minimum = MAX (minimum, child_min);
+ natural = MAX (natural, child_nat);
+ }
+
+ minimum += padding.top + padding.top + SHADOW_OFFSET_Y;
+ natural += padding.top + padding.top + SHADOW_OFFSET_Y;
+
+ if (minimum_height)
+ *minimum_height = minimum;
+
+ if (natural_height)
+ *natural_height = natural;
}
static void
-gtk_notification_get_preferred_width_for_height (GtkWidget *widget,
- gint height,
- gint *minimum_width,
- gint *natural_width) {
- gint parent_minimum_size, parent_natural_size;
-
- GTK_WIDGET_CLASS (gtk_notification_parent_class)->
- get_preferred_width_for_height(widget,
- height,
- &parent_minimum_size,
- &parent_natural_size);
-
- *minimum_width = parent_minimum_size + 2 * SHADOW_OFFSET_X + 2 * INNER_BORDER;
- *natural_width = parent_natural_size + 2 * SHADOW_OFFSET_X + 2 * INNER_BORDER;
+gtk_notification_get_preferred_height (GtkWidget *widget, gint *minimum_height, gint *natural_height)
+{
+ GtkNotification *notification = GTK_NOTIFICATION (widget);
+ GtkNotificationPrivate *priv = notification->priv;
+ GtkBin *bin = GTK_BIN (widget);
+ gint child_min, child_nat;
+ GtkWidget *child;
+ GtkBorder padding;
+ gint minimum, natural;
+
+ get_padding_and_border (notification, &padding);
+
+ gtk_widget_get_preferred_height (priv->close_button,
+ &minimum, &natural);
+
+ child = gtk_bin_get_child (bin);
+ if (child && gtk_widget_get_visible (child))
+ {
+ gtk_widget_get_preferred_height (child,
+ &child_min, &child_nat);
+ minimum = MAX (minimum, child_min);
+ natural = MAX (natural, child_nat);
+ }
+
+ minimum += padding.top + padding.top + SHADOW_OFFSET_Y;
+ natural += padding.top + padding.top + SHADOW_OFFSET_Y;
+
+ if (minimum_height)
+ *minimum_height = minimum;
+
+ if (natural_height)
+ *natural_height = natural;
}
static void
-gtk_notification_size_allocate (GtkWidget *widget, GtkAllocation *allocation)
+gtk_notification_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation)
{
- GtkAllocation parent_allocation;
+ GtkNotification *notification = GTK_NOTIFICATION (widget);
+ GtkNotificationPrivate *priv = notification->priv;
+ GtkBin *bin = GTK_BIN (widget);
+ GtkAllocation child_allocation;
+ GtkBorder padding;
+ GtkWidget *child;
+ int button_width;
- parent_allocation.x = allocation->x + SHADOW_OFFSET_X + INNER_BORDER;
- parent_allocation.y = allocation->y + INNER_BORDER;
- parent_allocation.width = allocation->width - 2 * SHADOW_OFFSET_X - 2 * INNER_BORDER;
- parent_allocation.height = allocation->height - SHADOW_OFFSET_Y - 2 *INNER_BORDER;
+ gtk_widget_set_allocation (widget, allocation);
- GTK_WIDGET_CLASS (gtk_notification_parent_class)->
- size_allocate (widget, &parent_allocation);
+ get_padding_and_border (notification, &padding);
- gtk_widget_set_allocation (widget, allocation);
+ child_allocation.x = allocation->x + SHADOW_OFFSET_X + padding.left;
+ child_allocation.y = allocation->y + padding.top;
+ child_allocation.height = MAX (1, allocation->height - SHADOW_OFFSET_Y - padding.top - padding.bottom);
+
+
+ gtk_widget_get_preferred_width_for_height (priv->close_button, child_allocation.height,
+ NULL, &button_width);
+
+ child_allocation.width = MAX (1, allocation->width - 2 * SHADOW_OFFSET_X - padding.left - padding.right - button_width);
+
+ child = gtk_bin_get_child (bin);
+ if (child && gtk_widget_get_visible (child))
+ gtk_widget_size_allocate (child, &child_allocation);
+
+ child_allocation.x += child_allocation.width;
+ child_allocation.width = button_width;
+
+ gtk_widget_size_allocate (priv->close_button, &child_allocation);
}
-static void
-gtk_notification_update_message (GtkNotification *notification, const gchar *new_message)
+static gboolean
+gtk_notification_timeout_cb (gpointer user_data)
{
- g_free (notification->priv->message_label);
- notification->priv->message_label = g_strdup (new_message);
- g_object_notify (G_OBJECT (notification), "message");
+ GtkNotification *notification = GTK_NOTIFICATION (user_data);
+
+ g_signal_emit (notification, notification_signals[TIMED_OUT], 0);
+ gtk_notification_dismiss (notification);
- gtk_label_set_text (GTK_LABEL (notification->priv->message),
- notification->priv->message_label);
+ return FALSE;
}
-static void
-gtk_notification_update_button (GtkNotification *notification, const gchar *new_button_label)
+void
+gtk_notification_set_timeout (GtkNotification *notification,
+ guint timeout_msec)
{
- g_free (notification->priv->button_label);
- notification->priv->button_label = g_strdup (new_button_label);
- g_object_notify (G_OBJECT (notification), "button-label");
-
- gtk_button_set_label (GTK_BUTTON (notification->priv->action_button),
- notification->priv->button_label);
- gtk_button_set_use_stock (GTK_BUTTON (notification->priv->action_button),
- TRUE);
+ notification->priv->timeout = timeout_msec;
+ g_object_notify (G_OBJECT (notification), "timeout");
}
-static gboolean
-gtk_notification_auto_destroy (gpointer user_data)
+void
+gtk_notification_dismiss (GtkNotification *notification)
{
- GtkWidget *notification = GTK_WIDGET(user_data);
- gtk_widget_destroy (notification);
- return FALSE;
+ gtk_widget_destroy (GTK_WIDGET (notification));
}
static void
gtk_notification_close_button_clicked_cb (GtkWidget *widget, gpointer user_data)
{
- GtkNotification *notification = GTK_NOTIFICATION(user_data);
- g_source_remove (notification->priv->timeout_source_id);
- notification->priv->timeout_source_id = 0;
+ GtkNotification *notification = GTK_NOTIFICATION(user_data);
+ g_source_remove (notification->priv->timeout_source_id);
+ notification->priv->timeout_source_id = 0;
- gtk_widget_destroy (GTK_WIDGET (notification));
+ gtk_widget_destroy (GTK_WIDGET (notification));
}
static void
gtk_notification_action_button_clicked_cb (GtkWidget *widget, gpointer user_data)
{
- g_signal_emit_by_name (user_data, "actioned", NULL);
+ g_signal_emit_by_name (user_data, "actioned", NULL);
}
GtkWidget *
-gtk_notification_new (gchar *message, gchar *action)
+gtk_notification_new (void)
{
- return g_object_new (GTK_TYPE_NOTIFICATION,
- "message", message,
- "button-label", action,
- "orientation", GTK_ORIENTATION_HORIZONTAL,
- "column-spacing", 8,
- NULL);
+ return g_object_new (GTK_TYPE_NOTIFICATION, NULL);
}
diff --git a/src/gtk-notification.h b/src/gtk-notification.h
index 5f6519c..9cff5e4 100644
--- a/src/gtk-notification.h
+++ b/src/gtk-notification.h
@@ -1,4 +1,4 @@
-/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* gtk-notification.c
* Copyright (C) Erick PÃrez Castellanos 2011 <erick red gmail com>
@@ -36,22 +36,25 @@ typedef struct _GtkNotificationClass GtkNotificationClass;
typedef struct _GtkNotification GtkNotification;
struct _GtkNotificationClass {
- GtkGridClass parent_class;
+ GtkBinClass parent_class;
- /* Signals */
- void (*actioned) (GtkNotification *self);
+ /* Signals */
+ void (*timed_out) (GtkNotification *self);
};
struct _GtkNotification {
- GtkGrid parent_instance;
+ GtkBin parent_instance;
- /*< private > */
- GtkNotificationPrivate *priv;
+ /*< private > */
+ GtkNotificationPrivate *priv;
};
GType gtk_notification_get_type (void) G_GNUC_CONST;
-GtkWidget * gtk_notification_new (gchar * message, gchar * action);
+GtkWidget *gtk_notification_new (void);
+void gtk_notification_set_timeout (GtkNotification *notification,
+ guint timeout_msec);
+void gtk_notification_dismiss (GtkNotification *notification);
G_END_DECLS
diff --git a/vapi/custom.vapi b/vapi/custom.vapi
index b124296..70b4854 100644
--- a/vapi/custom.vapi
+++ b/vapi/custom.vapi
@@ -41,6 +41,8 @@ namespace Contacts {
namespace Gtk {
public class Notification : Gtk.Box {
[CCode (has_construct_function = false, type = "GtkWidget*")]
- public Notification (string msg, string action);
- public virtual signal void actioned ();
+ public Notification ();
+ public void set_timeout (uint timeout_msec);
+ public void dismiss ();
+ public virtual signal void timed_out ();
}}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]