[gnome-contacts] Initial version of GtkNotification



commit 5b4091ab73512094edc3fced192982f5e309bb37
Author: Erick PÃrez Castellanos <erick red gmail com>
Date:   Mon Dec 19 15:30:07 2011 +0100

    Initial version of GtkNotification

 src/Makefile.am        |    2 +
 src/gtk-notification.c |  530 ++++++++++++++++++++++++++++++++++++++++++++++++
 src/gtk-notification.h |   58 ++++++
 vapi/custom.vapi       |    8 +
 4 files changed, 598 insertions(+), 0 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index 09feabc..0e81a3c 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -38,6 +38,7 @@ vala_sources = \
 	$(NULL)
 
 gnome_contacts_SOURCES = \
+	gtk-notification.c   \
 	contacts-esd-setup.c \
 	$(vala_sources) \
 	$(NULL)
@@ -47,5 +48,6 @@ gnome_contacts_LDADD = $(CONTACTS_LIBS) -lm
 CLEANFILES = $(vala_sources:.vala=.c) *.vapi *.stamp
 
 EXTRA_DIST = \
+	gtk-notification.h   \
 	contacts-esd-setup.h \
 	$(NULL)
diff --git a/src/gtk-notification.c b/src/gtk-notification.c
new file mode 100644
index 0000000..4b3eeea
--- /dev/null
+++ b/src/gtk-notification.c
@@ -0,0 +1,530 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+/*
+ * gtk-notification.c
+ * Copyright (C) Erick PÃrez Castellanos 2011 <erick red gmail com>
+ *
+ gtk-notification.c is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * gtk-notification.c 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.";
+ */
+
+#include "gtk-notification.h"
+
+/**
+ * SECTION:gtknotification
+ * @short_description: Report notification messages to the user
+ * @include: gtk/gtk.h
+ * @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.
+ *
+ * #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.
+ *
+ */
+
+#define GTK_PARAM_READWRITE G_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB
+#define SHADOW_OFFSET 10
+#define SHADOW_RADIUS 5
+
+#define GTK_STYLE_PROVIDER_PRIORITY_FORCE G_MAXUINT
+#define DEFAULT_CSS \
+  ".rounded-box {\n" \
+  "  border-radius: 0 0 5 5;\n" \
+  "}\n"
+
+enum {
+	PROP_0,
+	PROP_MESSAGE,
+	PROP_BUTTON_LABEL,
+	PROP_TIMEOUT
+};
+
+struct _GtkNotificationPrivate {
+	GtkWidget *message;
+	GtkWidget *action_button;
+	GtkWidget *close_button;
+
+	gchar * message_label;
+	gchar * button_label;
+	guint timeout;
+
+	guint timeout_source_id;
+};
+
+enum {
+	ACTIONED,
+	LAST_SIGNAL
+};
+
+static guint notification_signals[LAST_SIGNAL] = { 0 };
+
+static void draw_shadow_box(cairo_t *cr, GdkRectangle rect, double radius, double transparency);
+static gboolean gtk_notification_draw(GtkWidget *widget, cairo_t *cr);
+static void gtk_notification_get_preferred_width(GtkWidget *widget, 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);
+static void gtk_notification_get_preferred_height(GtkWidget *widget, 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);
+static void gtk_notification_size_allocate(GtkWidget *widget, GtkAllocation *allocation);
+static void gtk_notification_update_message(GtkNotification * notification, 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);
+
+/* signals handlers */
+static void gtk_notification_close_button_clicked_cb(GtkWidget * widget, gpointer user_data);
+static void gtk_notification_action_button_clicked_cb(GtkWidget * widget, gpointer user_data);
+
+G_DEFINE_TYPE(GtkNotification, gtk_notification, GTK_TYPE_BOX);
+
+static void gtk_notification_init(GtkNotification *notification) {
+	g_object_set(GTK_BOX(notification), "orientation", GTK_ORIENTATION_HORIZONTAL, "homogeneous", FALSE, "spacing", 2, NULL);
+
+	//setting fixed CSS to accomplish the border-radius seen in the mockups
+	GtkStyleProvider *provider = GTK_STYLE_PROVIDER (gtk_css_provider_new ());
+	gtk_style_context_add_provider_for_screen(gdk_screen_get_default(), provider, GTK_STYLE_PROVIDER_PRIORITY_FORCE);
+	gtk_css_provider_load_from_data(GTK_CSS_PROVIDER(provider), DEFAULT_CSS, -1, NULL);
+
+	gtk_style_context_add_class(gtk_widget_get_style_context(GTK_WIDGET(notification)), "rounded-box");
+
+	//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);
+	GtkWidget * close_button_image = gtk_image_new_from_stock(GTK_STOCK_CLOSE, GTK_ICON_SIZE_BUTTON);
+	gtk_button_set_image(GTK_BUTTON(notification->priv->close_button), close_button_image);
+
+	gtk_box_pack_start(GTK_BOX(notification), notification->priv->message, FALSE, FALSE, SHADOW_OFFSET);
+	gtk_box_pack_end(GTK_BOX(notification), notification->priv->close_button, FALSE, TRUE, 0);
+	gtk_box_pack_end(GTK_BOX(notification), notification->priv->action_button, FALSE, TRUE, 0);
+
+	gtk_widget_pop_composite_child();
+
+	notification->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);
+	if (notification->priv->message_label) {
+		g_free(notification->priv->message_label);
+	}
+	if (notification->priv->button_label) {
+		g_free(notification->priv->button_label);
+	}
+	if (notification->priv->timeout_source_id != 0) {
+		g_source_remove(notification->priv->timeout_source_id);
+	}
+
+	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) {
+	g_return_if_fail(GTK_IS_NOTIFICATION (object));
+	GtkNotification * notification = GTK_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;
+	}
+}
+
+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;
+	}
+}
+
+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));
+}
+
+static void draw_shadow_box(cairo_t *cr, GdkRectangle rect, double radius, double transparency) {
+	cairo_pattern_t *pattern;
+	double x0, x1, x2, x3;
+	double y0, y1, y2, y3;
+
+	x0 = rect.x;
+	x1 = rect.x + radius;
+	x2 = rect.x + rect.width - radius;
+	x3 = rect.x + rect.width;
+
+	y0 = rect.y;
+	y1 = rect.y + radius;
+	y2 = rect.y + rect.height - radius;
+	y3 = rect.y + rect.height;
+
+	/* Fill non-border part */
+	cairo_set_source_rgba(cr, 0, 0, 0, transparency);
+	cairo_rectangle(cr, x1, y1, x2 - x1, y2 - y1);
+	cairo_fill(cr);
+
+	/* Upper border */
+
+	pattern = cairo_pattern_create_linear(0, y0, 0, y1);
+
+	cairo_pattern_add_color_stop_rgba(pattern, 0.0, 0.0, 0, 0, 0.0);
+	cairo_pattern_add_color_stop_rgba(pattern, 1.0, 0.0, 0, 0, transparency);
+
+	cairo_set_source(cr, pattern);
+	cairo_pattern_destroy(pattern);
+
+	cairo_rectangle(cr, x1, y0, x2 - x1, y1 - y0);
+	cairo_fill(cr);
+
+	/* Bottom border */
+
+	pattern = cairo_pattern_create_linear(0, y2, 0, y3);
+
+	cairo_pattern_add_color_stop_rgba(pattern, 0.0, 0.0, 0, 0, transparency);
+	cairo_pattern_add_color_stop_rgba(pattern, 1.0, 0.0, 0, 0, 0.0);
+
+	cairo_set_source(cr, pattern);
+	cairo_pattern_destroy(pattern);
+
+	cairo_rectangle(cr, x1, y2, x2 - x1, y3 - y2);
+	cairo_fill(cr);
+
+	/* Left border */
+
+	pattern = cairo_pattern_create_linear(x0, 0, x1, 0);
+
+	cairo_pattern_add_color_stop_rgba(pattern, 0.0, 0.0, 0, 0, 0.0);
+	cairo_pattern_add_color_stop_rgba(pattern, 1.0, 0.0, 0, 0, transparency);
+
+	cairo_set_source(cr, pattern);
+	cairo_pattern_destroy(pattern);
+
+	cairo_rectangle(cr, x0, y1, x1 - x0, y2 - y1);
+	cairo_fill(cr);
+
+	/* Right border */
+
+	pattern = cairo_pattern_create_linear(x2, 0, x3, 0);
+
+	cairo_pattern_add_color_stop_rgba(pattern, 0.0, 0.0, 0, 0, transparency);
+	cairo_pattern_add_color_stop_rgba(pattern, 1.0, 0.0, 0, 0, 0.0);
+
+	cairo_set_source(cr, pattern);
+	cairo_pattern_destroy(pattern);
+
+	cairo_rectangle(cr, x2, y1, x3 - x2, y2 - y1);
+	cairo_fill(cr);
+
+	/* NW corner */
+
+	pattern = cairo_pattern_create_radial(x1, y1, 0, x1, y1, radius);
+
+	cairo_pattern_add_color_stop_rgba(pattern, 0.0, 0.0, 0, 0, transparency);
+	cairo_pattern_add_color_stop_rgba(pattern, 1.0, 0.0, 0, 0, 0.0);
+
+	cairo_set_source(cr, pattern);
+	cairo_pattern_destroy(pattern);
+
+	cairo_rectangle(cr, x0, y0, x1 - x0, y1 - y0);
+	cairo_fill(cr);
+
+	/* NE corner */
+
+	pattern = cairo_pattern_create_radial(x2, y1, 0, x2, y1, radius);
+
+	cairo_pattern_add_color_stop_rgba(pattern, 0.0, 0.0, 0, 0, transparency);
+	cairo_pattern_add_color_stop_rgba(pattern, 1.0, 0.0, 0, 0, 0.0);
+
+	cairo_set_source(cr, pattern);
+	cairo_pattern_destroy(pattern);
+
+	cairo_rectangle(cr, x2, y0, x3 - x2, y1 - y0);
+	cairo_fill(cr);
+
+	/* SW corner */
+
+	pattern = cairo_pattern_create_radial(x1, y2, 0, x1, y2, radius);
+
+	cairo_pattern_add_color_stop_rgba(pattern, 0.0, 0.0, 0, 0, transparency);
+	cairo_pattern_add_color_stop_rgba(pattern, 1.0, 0.0, 0, 0, 0.0);
+
+	cairo_set_source(cr, pattern);
+	cairo_pattern_destroy(pattern);
+
+	cairo_rectangle(cr, x0, y2, x1 - x0, y3 - y2);
+	cairo_fill(cr);
+
+	/* SE corner */
+
+	pattern = cairo_pattern_create_radial(x2, y2, 0, x2, y2, radius);
+
+	cairo_pattern_add_color_stop_rgba(pattern, 0.0, 0.0, 0, 0, transparency);
+	cairo_pattern_add_color_stop_rgba(pattern, 1.0, 0.0, 0, 0, 0.0);
+
+	cairo_set_source(cr, pattern);
+	cairo_pattern_destroy(pattern);
+
+	cairo_rectangle(cr, x2, y2, x3 - x2, y3 - y2);
+	cairo_fill(cr);
+}
+
+static gboolean gtk_notification_draw(GtkWidget *widget, cairo_t *cr) {
+	GdkRectangle rect;
+	gtk_widget_get_allocation(widget, &rect);
+	rect.x += SHADOW_OFFSET;
+	rect.y += SHADOW_OFFSET;
+	rect.width -= SHADOW_OFFSET;
+	rect.height -= SHADOW_OFFSET;
+
+	draw_shadow_box(cr, rect, SHADOW_RADIUS, 0.4);
+
+	GtkStyleContext * context = gtk_widget_get_style_context(widget);
+	gtk_style_context_save(context);
+	//FIXME I don't see the frame drawing at all
+	gtk_render_background(context,
+			cr,
+			0,
+			0,
+			gtk_widget_get_allocated_width(widget) - SHADOW_OFFSET,
+			gtk_widget_get_allocated_height(widget) - SHADOW_OFFSET);
+
+	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;
+}
+
+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 + (SHADOW_OFFSET / 2);
+	*natural_size = parent_natural_size + SHADOW_OFFSET + (SHADOW_OFFSET / 2);
+}
+
+static void 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_for_width(widget,
+			width,
+			&parent_minimum_size,
+			&parent_natural_size);
+
+	*minimum_height = parent_minimum_size + 2 * SHADOW_OFFSET;
+	*natural_height = parent_natural_size + 2 * SHADOW_OFFSET;
+}
+
+static void gtk_notification_get_preferred_height(GtkWidget *widget, gint *minimum_size, gint *natural_size) {
+	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 + 2 * SHADOW_OFFSET;
+	*natural_size = parent_natural_size + 2 * SHADOW_OFFSET;
+}
+
+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;
+	*natural_width = parent_natural_size + 2 * SHADOW_OFFSET;
+}
+
+static void gtk_notification_size_allocate(GtkWidget *widget, GtkAllocation *allocation) {
+	GtkAllocation parent_allocation;
+	parent_allocation.x = allocation->x + (SHADOW_OFFSET / 2);
+	parent_allocation.y = allocation->y  + (SHADOW_OFFSET / 2);
+	parent_allocation.width = allocation->width - 2 * SHADOW_OFFSET;
+	parent_allocation.height = allocation->height - 2 * SHADOW_OFFSET;
+
+	GTK_WIDGET_CLASS(gtk_notification_parent_class)->size_allocate(widget, &parent_allocation);
+
+	gtk_widget_set_allocation(widget, allocation);
+}
+
+static void gtk_notification_update_message(GtkNotification * notification, const gchar * new_message) {
+	g_free(notification->priv->message_label);
+	notification->priv->message_label = g_strdup(new_message);
+	g_object_notify(G_OBJECT(notification), "message");
+
+	gtk_label_set_text(GTK_LABEL(notification->priv->message), notification->priv->message_label);
+}
+
+static void gtk_notification_update_button(GtkNotification * notification, const gchar * new_button_label) {
+	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);
+}
+
+static gboolean gtk_notification_auto_destroy(gpointer user_data) {
+	GtkWidget * notification = GTK_WIDGET(user_data);
+	gtk_widget_destroy(notification);
+	return FALSE;
+}
+
+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;
+
+	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);
+}
+
+GtkWidget * gtk_notification_new(gchar * message, gchar * action) {
+	return g_object_new(GTK_TYPE_NOTIFICATION, "message", message, "button-label", action, NULL);
+}
diff --git a/src/gtk-notification.h b/src/gtk-notification.h
new file mode 100644
index 0000000..f9f9ce4
--- /dev/null
+++ b/src/gtk-notification.h
@@ -0,0 +1,58 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+/*
+ * gtk-notification.c
+ * Copyright (C) Erick PÃrez Castellanos 2011 <erick red gmail com>
+ *
+ gtk-notification.c is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * gtk-notification.c 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.";
+ */
+
+#ifndef _GTK_NOTIFICATION_H_
+#define _GTK_NOTIFICATION_H_
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_NOTIFICATION             (gtk_notification_get_type ())
+#define GTK_NOTIFICATION(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_NOTIFICATION, GtkNotification))
+#define GTK_NOTIFICATION_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_NOTIFICATION, GtkNotificationClass))
+#define GTK_IS_NOTIFICATION(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_NOTIFICATION))
+#define GTK_IS_NOTIFICATION_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_NOTIFICATION))
+#define GTK_NOTIFICATION_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_NOTIFICATION, GtkNotificationClass))
+
+typedef struct _GtkNotificationPrivate GtkNotificationPrivate;
+typedef struct _GtkNotificationClass GtkNotificationClass;
+typedef struct _GtkNotification GtkNotification;
+
+struct _GtkNotificationClass {
+	GtkBoxClass parent_class;
+
+	/* Signals */
+	void (*actioned) (GtkNotification *self);
+};
+
+struct _GtkNotification {
+	GtkBox parent_instance;
+
+	/*< private > */
+	GtkNotificationPrivate *priv;
+};
+
+GType gtk_notification_get_type (void) G_GNUC_CONST;
+
+GtkWidget * gtk_notification_new (gchar * message, gchar * action);
+
+G_END_DECLS
+
+#endif /* _GTK_NOTIFICATION_H_ */
diff --git a/vapi/custom.vapi b/vapi/custom.vapi
index 0ec822c..b124296 100644
--- a/vapi/custom.vapi
+++ b/vapi/custom.vapi
@@ -36,3 +36,11 @@ namespace Contacts {
 	[CCode (cname = "eds_personal_google_group_name")]
 	public static unowned string? eds_personal_google_group_name ();
 }
+
+[CCode (cprefix = "Gtk", lower_case_cprefix = "gtk_", cheader_filename = "gtk-notification.h")]
+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 ();
+	}}



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]