[goffice] Canvas: bullet-proof GocWidget.



commit 1d127e91e2982e4f10d84504819ad9bdcea383d8
Author: Morten Welinder <terra gnome org>
Date:   Mon Sep 14 21:58:12 2009 -0400

    Canvas: bullet-proof GocWidget.

 ChangeLog                   |    6 ++++
 goffice/canvas/goc-widget.c |   62 +++++++++++++++++++++++++++++++++++-------
 2 files changed, 57 insertions(+), 11 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index ec10108..c65d8ee 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,11 @@
 2009-09-14  Morten Welinder  <terra gnome org>
 
+	* goffice/canvas/goc-widget.c (goc_widget_set_widget): Split from
+	goc_widget_set_property.  Disconnect signals when changing widget.
+	Keep ref to widget.  Handle setting NULL widget.
+	(goc_widget_dispose): Set NULL widget.
+	(goc_widget_class_init): Hook up dispose method.
+
 	* goffice/canvas/goc-text.c (goc_text_class_init): Don't cast
 	klass pointer to parent's interface type and expect to get the
 	right thing!  Instead, make this implement the interface here and
diff --git a/goffice/canvas/goc-widget.c b/goffice/canvas/goc-widget.c
index b769e8d..c29a446 100644
--- a/goffice/canvas/goc-widget.c
+++ b/goffice/canvas/goc-widget.c
@@ -27,6 +27,8 @@
 
 #include <math.h>
 
+static GObjectClass *widget_parent_class;
+
 static gboolean
 enter_notify_cb (G_GNUC_UNUSED GtkWidget *w, GdkEventCrossing *event, GocWidget *item)
 {
@@ -93,6 +95,43 @@ goc_widget_notify_scrolled (GocItem *item)
 }
 
 static void
+goc_widget_set_widget (GocWidget *item, GtkWidget *widget)
+{
+	if (widget == item->widget)
+		return;
+
+	if (item->widget) {
+		GtkWidget *parent = gtk_widget_get_parent (item->widget);
+
+		g_signal_handlers_disconnect_by_func
+			(item->widget, G_CALLBACK (enter_notify_cb), item);
+		g_signal_handlers_disconnect_by_func
+			(item->widget, G_CALLBACK (button_press_cb), item);
+
+		if (parent)
+			gtk_container_remove (GTK_CONTAINER (parent),
+					      item->widget);
+
+		g_object_unref (item->widget);
+	}
+
+	item->widget = widget;
+
+	if (widget) {
+		g_object_ref (item->widget);
+		gtk_widget_show (widget);
+		gtk_layout_put (GTK_LAYOUT (GOC_ITEM (item)->canvas),
+				widget, item->x, item->y);
+		goc_widget_notify_scrolled (GOC_ITEM (item));
+		/* we need to propagate some signals to the parent item */
+		g_signal_connect (widget, "enter-notify-event",
+				  G_CALLBACK (enter_notify_cb), item);
+		g_signal_connect (widget, "button-press-event",
+				  G_CALLBACK (button_press_cb), item);
+	}
+}
+
+static void
 goc_widget_set_property (GObject *obj, guint param_id,
 				    GValue const *value, GParamSpec *pspec)
 {
@@ -101,17 +140,7 @@ goc_widget_set_property (GObject *obj, guint param_id,
 	switch (param_id) {
 	case WIDGET_PROP_WIDGET: {
 		GtkWidget *widget = GTK_WIDGET (g_value_get_object (value));
-		if (widget == item->widget)
-			return;
-		if (item->widget)
-			gtk_container_remove (GTK_CONTAINER (item->base.canvas), item->widget);
-		item->widget = widget;
-		gtk_widget_show (widget);
-		gtk_layout_put (GTK_LAYOUT (GOC_ITEM (item)->canvas), widget, item->x, item->y);
-		goc_widget_notify_scrolled (GOC_ITEM (item));
-		/* we need to propagate some signals to the parent item */
-		g_signal_connect (widget, "enter-notify-event", G_CALLBACK (enter_notify_cb), obj);
-		g_signal_connect (widget, "button-press-event", G_CALLBACK (button_press_cb), obj);
+		goc_widget_set_widget (item, widget);
 		return;
 	}
 	case WIDGET_PROP_X:
@@ -217,12 +246,23 @@ goc_widget_update_bounds (GocItem *item)
 }
 
 static void
+goc_widget_dispose (GObject *object)
+{
+	GocWidget *item = GOC_WIDGET (object);
+	goc_widget_set_widget (item, NULL);
+	widget_parent_class->dispose (object);
+}
+
+static void
 goc_widget_class_init (GocItemClass *item_klass)
 {
 	GObjectClass *obj_klass = (GObjectClass *) item_klass;
 
+	widget_parent_class = g_type_class_peek_parent (item_klass);
+
 	obj_klass->get_property = goc_widget_get_property;
 	obj_klass->set_property = goc_widget_set_property;
+	obj_klass->dispose = goc_widget_dispose;
 
 	g_object_class_install_property (obj_klass, WIDGET_PROP_WIDGET,
 		g_param_spec_object ("widget",



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