[goffice] Canvas: properly construct items; handle canvas changes for widgets.



commit 5ef9d14975d2a4c5715e1b866894999a9e8b2f76
Author: Morten Welinder <terra gnome org>
Date:   Wed Sep 16 13:19:53 2009 -0400

    Canvas: properly construct items; handle canvas changes for widgets.

 ChangeLog                   |   14 +++++++++
 goffice/canvas/goc-group.c  |   18 +++++++++--
 goffice/canvas/goc-item.c   |   60 ++++++++++++++++++++++++++++++---------
 goffice/canvas/goc-text.c   |    4 +-
 goffice/canvas/goc-widget.c |   66 +++++++++++++++++++++++++++++++++----------
 5 files changed, 127 insertions(+), 35 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 83035b7..ea9180d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,19 @@
 2009-09-16  Morten Welinder  <terra gnome org>
 
+	* goffice/canvas/goc-widget.c (goc_widget_init,
+	cb_canvas_changed): New functions.
+	(goc_widget_notify_scrolled): Do nothing if we have no parent.
+	(goc_widget_set_widget): Handle the no-canvas-yet case.
+
+	* goffice/canvas/goc-item.c (goc_item_class_init): Add canvas and
+	parent properties.
+	(goc_item_new): Construct the new item with all its properties.
+
+	* goffice/canvas/goc-group.c (goc_group_unrealize,
+	goc_group_realize): Chain.
+	(goc_group_add_child, goc_group_remove_child): Notify item::parent
+	and item::canvas.
+
 	* goffice/canvas/goc-item.c (goc_item_realize,
 	goc_item_unrealize): New handlers.
 	(_goc_item_realize, _goc_item_unrealize): Simplify.
diff --git a/goffice/canvas/goc-group.c b/goffice/canvas/goc-group.c
index d3eaf31..35fc63a 100644
--- a/goffice/canvas/goc-group.c
+++ b/goffice/canvas/goc-group.c
@@ -26,7 +26,7 @@
 #include <glib/gi18n-lib.h>
 #include <gsf/gsf-impl-utils.h>
 
-static GObjectClass *parent_klass;
+static GocItemClass *parent_klass;
 
 enum {
 	GROUP_PROP_0,
@@ -176,10 +176,13 @@ goc_group_realize (GocItem *item)
 {
 	GocGroup *group = GOC_GROUP (item);
 	GList *l;
+
 	for (l = g_list_first (group->children); l; l = g_list_next (l)) {
 		GocItem *child = GOC_ITEM (l->data);
 		_goc_item_realize (child);
 	}
+
+	parent_klass->realize (item);
 }
 
 static void
@@ -187,6 +190,9 @@ goc_group_unrealize (GocItem *item)
 {
 	GocGroup *group = GOC_GROUP (item);
 	GList *l;
+
+	parent_klass->unrealize (item);
+
 	for (l = g_list_first (group->children); l; l = g_list_next (l)) {
 		GocItem *child = GOC_ITEM (l->data);
 		_goc_item_unrealize (child);
@@ -211,7 +217,7 @@ goc_group_dispose (GObject *obj)
 {
 	GocGroup *group = GOC_GROUP (obj);
 	goc_group_clear (group);
-	parent_klass->dispose (obj);
+	((GObjectClass*)parent_klass)->dispose (obj);
 }
 
 static void
@@ -297,6 +303,8 @@ goc_group_add_child (GocGroup *group, GocItem *item)
 	group->children = g_list_append (group->children, item);
 	item->parent = group;
 	item->canvas = group->base.canvas;
+	g_object_notify (G_OBJECT (item), "parent");
+	g_object_notify (G_OBJECT (item), "canvas");
 	if (GOC_ITEM (group)->realized)
 		_goc_item_realize (item);
 	goc_item_parent_changed (item);
@@ -311,11 +319,13 @@ goc_group_remove_child (GocGroup *group, GocItem *item)
 	g_return_if_fail (item->parent == group);
 	if (item->canvas && item->canvas->last_item == item)
 		item->canvas->last_item = NULL;
+	if (GOC_ITEM (group)->realized)
+		_goc_item_unrealize (item);
 	group->children = g_list_remove (group->children, item);
 	item->parent = NULL;
 	item->canvas = NULL;
-	if (GOC_ITEM (group)->realized)
-		_goc_item_unrealize (item);
+	g_object_notify (G_OBJECT (item), "parent");
+	g_object_notify (G_OBJECT (item), "canvas");
 	goc_item_bounds_changed (GOC_ITEM (group));
 }
 
diff --git a/goffice/canvas/goc-item.c b/goffice/canvas/goc-item.c
index 0b0bfda..c5b886d 100644
--- a/goffice/canvas/goc-item.c
+++ b/goffice/canvas/goc-item.c
@@ -24,6 +24,13 @@
 #include <goffice/goffice.h>
 #include <gtk/gtk.h>
 #include <gsf/gsf-impl-utils.h>
+#include <glib/gi18n-lib.h>
+
+enum {
+	ITEM_PROP_0,
+	ITEM_PROP_CANVAS,
+	ITEM_PROP_PARENT
+};
 
 /**
  * GocItemClass:
@@ -142,11 +149,47 @@ goc_item_dispose (GObject *object)
 }
 
 static void
+goc_item_get_property (GObject *gobject, guint param_id,
+		       GValue *value, GParamSpec *pspec)
+{
+	GocItem *item = GOC_ITEM (gobject);
+
+	switch (param_id) {
+	case ITEM_PROP_CANVAS:
+		g_value_set_object (value, item->canvas);
+		break;
+
+	case ITEM_PROP_PARENT:
+		g_value_set_object (value, item->parent);
+		break;
+
+	default: G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, param_id, pspec);
+		return; /* NOTE : RETURN */
+	}
+}
+
+static void
 goc_item_class_init (GocItemClass *item_klass)
 {
 	GObjectClass *obj_klass = (GObjectClass *) item_klass;
 	item_parent_class = g_type_class_peek_parent (item_klass);
 
+	obj_klass->dispose = goc_item_dispose;
+	obj_klass->get_property = goc_item_get_property;
+
+	g_object_class_install_property (obj_klass, ITEM_PROP_CANVAS,
+		g_param_spec_object ("canvas",
+			_("Canvas"),
+			_("The canvas object on which the item resides"),
+			GOC_TYPE_CANVAS,
+			GSF_PARAM_STATIC | G_PARAM_READABLE));
+	g_object_class_install_property (obj_klass, ITEM_PROP_PARENT,
+		g_param_spec_object ("parent",
+			_("Parent"),
+			_("The group in which the item resides"),
+			GOC_TYPE_GROUP,
+			GSF_PARAM_STATIC | G_PARAM_READABLE));
+
 	item_klass->realize = goc_item_realize;
 	item_klass->unrealize = goc_item_unrealize;
 	item_klass->button_pressed = goc_item_button_pressed;
@@ -155,8 +198,6 @@ goc_item_class_init (GocItemClass *item_klass)
 	item_klass->motion = goc_item_motion;
 	item_klass->enter_notify = goc_item_enter_notify;
 	item_klass->leave_notify = goc_item_leave_notify;
-
-	obj_klass->dispose = goc_item_dispose;
 }
 
 static void
@@ -177,21 +218,12 @@ goc_item_new (GocGroup *group, GType type, const gchar *first_arg_name, ...)
 
 	g_return_val_if_fail (GOC_IS_GROUP (group), NULL);
 
-	item = GOC_ITEM (g_object_new (type, NULL));
-	g_return_val_if_fail ((item != NULL), NULL);
-
-	goc_group_add_child (group, item);
-
-	/* FIXME: Due to contruction-only arguments, this needs to be
-	   merged with the g_object_new above.  We cannot do this
-	   right now due to problems in GocWidget.  */
 	va_start (args, first_arg_name);
-	g_object_set_valist (G_OBJECT (item), first_arg_name, args);
+	item = GOC_ITEM (g_object_new_valist (type, first_arg_name, args));
 	va_end (args);
+	g_return_val_if_fail ((item != NULL), NULL);
 
-	/* This is probably a no-op.  goc_group_add_child did it.  */
-	if (GOC_ITEM (group)->realized)
-		_goc_item_realize (item);
+	goc_group_add_child (group, item);
 
 	return item;
 }
diff --git a/goffice/canvas/goc-text.c b/goffice/canvas/goc-text.c
index a3e2da5..87d6770 100644
--- a/goffice/canvas/goc-text.c
+++ b/goffice/canvas/goc-text.c
@@ -43,7 +43,7 @@ static GocItemClass *parent_class;
 
 static void
 goc_text_set_property (GObject *gobject, guint param_id,
-				    GValue const *value, GParamSpec *pspec)
+		       GValue const *value, GParamSpec *pspec)
 {
 	GocText *text = GOC_TEXT (gobject);
 
@@ -113,7 +113,7 @@ goc_text_set_property (GObject *gobject, guint param_id,
 
 static void
 goc_text_get_property (GObject *gobject, guint param_id,
-				    GValue *value, GParamSpec *pspec)
+		       GValue *value, GParamSpec *pspec)
 {
 	GocText *text = GOC_TEXT (gobject);
 
diff --git a/goffice/canvas/goc-widget.c b/goffice/canvas/goc-widget.c
index c29a446..a95968f 100644
--- a/goffice/canvas/goc-widget.c
+++ b/goffice/canvas/goc-widget.c
@@ -27,7 +27,17 @@
 
 #include <math.h>
 
-static GObjectClass *widget_parent_class;
+static GocItemClass *widget_parent_class;
+
+enum {
+	WIDGET_PROP_0,
+	WIDGET_PROP_WIDGET,
+	WIDGET_PROP_X,
+	WIDGET_PROP_Y,
+	WIDGET_PROP_W,
+	WIDGET_PROP_H
+};
+
 
 static gboolean
 enter_notify_cb (G_GNUC_UNUSED GtkWidget *w, GdkEventCrossing *event, GocWidget *item)
@@ -50,14 +60,28 @@ button_press_cb (G_GNUC_UNUSED GtkWidget *w, GdkEventButton *event, GocWidget *i
 			(event->y + item->y) / item->base.canvas->pixels_per_unit + item->base.canvas->scroll_y1);
 }
 
-enum {
-	WIDGET_PROP_0,
-	WIDGET_PROP_WIDGET,
-	WIDGET_PROP_X,
-	WIDGET_PROP_Y,
-	WIDGET_PROP_W,
-	WIDGET_PROP_H
-};
+static void
+cb_canvas_changed (GocWidget *item, G_GNUC_UNUSED GParamSpec *pspec,
+		   G_GNUC_UNUSED gpointer user)
+{
+	GtkWidget *parent, *w = item->widget;
+	GocItem *gitem = (GocItem *)item;
+
+	if (!w)
+		return;
+
+	parent = gtk_widget_get_parent (w);
+	if (parent == (GtkWidget *)gitem->canvas)
+		return;
+
+	g_object_ref (w);
+	if (parent)
+		gtk_container_remove (GTK_CONTAINER (parent), w);
+	if (gitem->canvas)
+		gtk_layout_put (GTK_LAYOUT (gitem->canvas), w,
+				item->x, item->y);
+	g_object_unref (w);
+}
 
 static void
 goc_widget_notify_scrolled (GocItem *item)
@@ -67,6 +91,9 @@ goc_widget_notify_scrolled (GocItem *item)
 	GocWidget *widget = GOC_WIDGET (item);
 
 	parent = item->parent;
+	if (!parent)
+		return;
+
 	if (!item->cached_bounds)
 		goc_item_update_bounds (GOC_ITEM (item)); /* don't care about const */
 	x0 = item->x0;
@@ -120,8 +147,9 @@ goc_widget_set_widget (GocWidget *item, GtkWidget *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);
+		if (GOC_ITEM (item)->canvas)
+			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",
@@ -133,7 +161,7 @@ goc_widget_set_widget (GocWidget *item, GtkWidget *widget)
 
 static void
 goc_widget_set_property (GObject *obj, guint param_id,
-				    GValue const *value, GParamSpec *pspec)
+			 GValue const *value, GParamSpec *pspec)
 {
 	GocWidget *item = GOC_WIDGET (obj);
 
@@ -171,7 +199,7 @@ goc_widget_set_property (GObject *obj, guint param_id,
 
 static void
 goc_widget_get_property (GObject *obj, guint param_id,
-				    GValue *value, GParamSpec *pspec)
+			 GValue *value, GParamSpec *pspec)
 {
 	GocWidget *item = GOC_WIDGET (obj);
 
@@ -250,7 +278,15 @@ goc_widget_dispose (GObject *object)
 {
 	GocWidget *item = GOC_WIDGET (object);
 	goc_widget_set_widget (item, NULL);
-	widget_parent_class->dispose (object);
+	((GObjectClass *)widget_parent_class)->dispose (object);
+}
+
+static void
+goc_widget_init (GocWidget *item)
+{
+	g_signal_connect (item, "notify::canvas",
+			  G_CALLBACK (cb_canvas_changed),
+			  NULL);
 }
 
 static void
@@ -303,7 +339,7 @@ goc_widget_class_init (GocItemClass *item_klass)
 }
 
 GSF_CLASS (GocWidget, goc_widget,
-	   goc_widget_class_init, NULL,
+	   goc_widget_class_init, goc_widget_init,
 	   GOC_TYPE_ITEM)
 
 void



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