From: Andrea Zagli <azagli@libero.it>
Date: Sun, 10 Jun 2007 08:54:39 +0000 (+0000)
Subject: Added CanvasItem.
X-Git-Url: https://saetta.ns0.it/gitweb?a=commitdiff_plain;h=9e506bc0017793c233ccc2237f8f758e503d9376;p=reptool%2Fgreptool

Added CanvasItem.
General code refactoring.
Objects Canvas and ObjectTree now communicate.


git-svn-id: svn+ssh://saetta.homelinux.org/svn/greptool/trunk@4 76169498-11ee-428b-941f-28d7a79d5cb2
---

diff --git a/src/Makefile.am b/src/Makefile.am
index f0d19eb..3c2d981 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -14,4 +14,5 @@ greptool_SOURCES = \
                    page_properties.c \
                    objects_tree.c \
                    canvas.c \
+                   canvasitem.c \
                    canvasline.c
diff --git a/src/canvas.c b/src/canvas.c
index 36c59b5..ac8f306 100644
--- a/src/canvas.c
+++ b/src/canvas.c
@@ -21,25 +21,28 @@
 
 #include "main.h"
 #include "canvas.h"
+#include "canvasline.h"
 
-static void canvas_class_init (CanvasClass *klass);
-static void canvas_init (Canvas *canvas);
+static void grpt_canvas_class_init (GRptCanvasClass *klass);
+static void grpt_canvas_init (GRptCanvas *canvas);
 
 
-#define CANVAS_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GRPT_TYPE_CANVAS, CanvasPrivate))
+#define GRPT_CANVAS_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GRPT_TYPE_CANVAS, GRptCanvasPrivate))
 
 
-typedef struct _CanvasPrivate CanvasPrivate;
-struct _CanvasPrivate
+typedef struct _GRptCanvasPrivate GRptCanvasPrivate;
+struct _GRptCanvasPrivate
 	{
 		RptReport *rpt_report;
 
 		GtkWidget *scrolledw;
-		GtkWidget *canvas;
+		GtkWidget *grpt_canvas;
 
 		GooCanvasItem *root;
 		GooCanvasItem *selection;
 
+		GList *body_objects;
+
 		gdouble sel_x_start;
 		gdouble sel_y_start;
 
@@ -47,52 +50,117 @@ struct _CanvasPrivate
 	};
 
 GType
-canvas_get_type (void)
+grpt_canvas_get_type (void)
 {
-	static GType canvas_type = 0;
+	static GType grpt_canvas_type = 0;
 
-	if (!canvas_type)
+	if (!grpt_canvas_type)
 		{
-			static const GTypeInfo canvas_info =
+			static const GTypeInfo grpt_canvas_info =
 			{
-				sizeof (CanvasClass),
+				sizeof (GRptCanvasClass),
 				NULL,	/* base_init */
 				NULL,	/* base_finalize */
-				(GClassInitFunc) canvas_class_init,
+				(GClassInitFunc) grpt_canvas_class_init,
 				NULL,	/* class_finalize */
 				NULL,	/* class_data */
-				sizeof (Canvas),
+				sizeof (GRptCanvas),
 				0,	/* n_preallocs */
-				(GInstanceInitFunc) canvas_init,
+				(GInstanceInitFunc) grpt_canvas_init,
 				NULL
 			};
 
-			canvas_type = g_type_register_static (G_TYPE_OBJECT, "Canvas",
-			                                      &canvas_info, 0);
+			grpt_canvas_type = g_type_register_static (G_TYPE_OBJECT, "GRptCanvas",
+			                                           &grpt_canvas_info, 0);
 		}
 
-	return canvas_type;
+	return grpt_canvas_type;
 }
 
 static void
-canvas_class_init (CanvasClass *klass)
+grpt_canvas_class_init (GRptCanvasClass *klass)
 {
 	GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
-	g_type_class_add_private (object_class, sizeof (CanvasPrivate));
+	g_type_class_add_private (object_class, sizeof (GRptCanvasPrivate));
+
+	klass->object_added_signal_id = g_signal_new ("object-added",
+	                                              G_TYPE_FROM_CLASS (object_class),
+	                                              G_SIGNAL_RUN_LAST,
+	                                              0,
+	                                              NULL,
+	                                              NULL,
+	                                              g_cclosure_marshal_VOID__POINTER,
+	                                              G_TYPE_NONE,
+	                                              1,
+	                                              G_TYPE_POINTER);
+	klass->object_removed_signal_id = g_signal_new ("object-removed",
+	                                                G_TYPE_FROM_CLASS (object_class),
+	                                                G_SIGNAL_RUN_LAST,
+	                                                0,
+	                                                NULL,
+	                                                NULL,
+	                                                g_cclosure_marshal_VOID__POINTER,
+	                                                G_TYPE_NONE,
+	                                                1,
+	                                                G_TYPE_POINTER);
+}
+
+static void
+grpt_canvas_init (GRptCanvas *grpt_canvas)
+{
 }
 
 static void
-canvas_init (Canvas *canvas)
+grpt_canvas_add_object (GRptCanvas *grpt_canvas, RptReportSection section,
+                   gdouble x, gdouble y, gdouble width, gdouble height)
 {
+	GRptCanvasPrivate *priv = GRPT_CANVAS_GET_PRIVATE (grpt_canvas);
+	GRptCanvasClass *klass = GRPT_CANVAS_GET_CLASS (grpt_canvas);
+
+	GRptCanvasItem *item;
+
+	switch (priv->tool)
+		{
+			case TOOL_LINE:
+				{
+					RptObject *rpt_object_line;
+					RptPoint position;
+					RptSize size;
+
+					position.x = x;
+					position.y = y;
+					rpt_object_line = rpt_obj_line_new (get_new_object_name (priv->tool), position);
+
+					size.width = width;
+					size.height = height;
+					g_object_set (G_OBJECT (rpt_object_line),
+					              "size", &size,
+					              NULL);
+
+					item = grpt_canvas_line_new (priv->root,
+							                x, y,
+									        width, height,
+					                        RPT_OBJ_LINE (rpt_object_line),
+					                        NULL);
+					grpt_canvas_item_set_section (item, RPTREPORT_SECTION_BODY);
+				}
+				break;
+		}
+
+	priv->body_objects = g_list_append (priv->body_objects, item);
+
+	g_signal_emit (grpt_canvas, klass->object_added_signal_id, 0,
+	               item);
 }
 
+/* SIGNALS */
 static gboolean
-canvas_on_button_press_event (GtkWidget *widget,
+grpt_canvas_on_button_press_event (GtkWidget *widget,
                               GdkEventButton *event,
                               gpointer user_data)
 {
-	CanvasPrivate *priv = CANVAS_GET_PRIVATE ((Canvas *)user_data);
+	GRptCanvasPrivate *priv = GRPT_CANVAS_GET_PRIVATE ((GRptCanvas *)user_data);
 
 	if (event->button == 1)
 		{
@@ -114,7 +182,7 @@ canvas_on_button_press_event (GtkWidget *widget,
 }
 
 static gboolean
-canvas_on_button_release_event (GtkWidget *widget,
+grpt_canvas_on_button_release_event (GtkWidget *widget,
                                 GdkEventButton *event,
                                 gpointer user_data)
 {
@@ -123,7 +191,7 @@ canvas_on_button_release_event (GtkWidget *widget,
 	gdouble width;
 	gdouble height;
 
-	CanvasPrivate *priv = CANVAS_GET_PRIVATE ((Canvas *)user_data);
+	GRptCanvasPrivate *priv = GRPT_CANVAS_GET_PRIVATE ((GRptCanvas *)user_data);
 
 	g_object_set (G_OBJECT (priv->selection),
 	              "visibility", GOO_CANVAS_ITEM_HIDDEN,
@@ -150,38 +218,13 @@ canvas_on_button_release_event (GtkWidget *widget,
 			height = event->y - y;
 		}
 
-	switch (priv->tool)
-		{
-			case TOOL_LINE:
-				{
-					RptObject *rpt_object_line;
-					RptPoint position;
-					RptSize size;
-
-					position.x = x;
-					position.y = y;
-					rpt_object_line = rpt_obj_line_new (get_new_object_name (priv->tool), position);
-
-					size.width = width;
-					size.height = height;
-					g_object_set (G_OBJECT (rpt_object_line),
-					              "size", &size,
-					              NULL);
-
-					canvas_line_new (priv->root,
-									 x, y,
-									 width, height,
-					                 RPT_OBJ_LINE (rpt_object_line),
-					                 NULL);
-				}
-				break;
-		}
+	grpt_canvas_add_object ((GRptCanvas *)user_data, RPTREPORT_SECTION_BODY, x, y, width, height);
 
 	return FALSE;
 }
 
 static gboolean
-canvas_on_motion_notify_event (GtkWidget *widget,
+grpt_canvas_on_motion_notify_event (GtkWidget *widget,
                                GdkEventMotion *event,
                                gpointer user_data)
 {
@@ -189,7 +232,7 @@ canvas_on_motion_notify_event (GtkWidget *widget,
 	gint y;
 	GdkModifierType state;
 
-	CanvasPrivate *priv = CANVAS_GET_PRIVATE ((Canvas *)user_data);
+	GRptCanvasPrivate *priv = GRPT_CANVAS_GET_PRIVATE ((GRptCanvas *)user_data);
 
 	if (event->is_hint)
 		{
@@ -245,16 +288,16 @@ canvas_on_motion_notify_event (GtkWidget *widget,
 	return FALSE;
 }
 
-Canvas
-*canvas_new (RptReport *rpt_report)
+GRptCanvas
+*grpt_canvas_new (RptReport *rpt_report)
 {
 	GtkWidget *viewport;
 	GtkWidget *fixed;
 	RptSize *size;
 
-	Canvas *canvas = GRPT_CANVAS (g_object_new (canvas_get_type (), NULL));
+	GRptCanvas *grpt_canvas = GRPT_CANVAS (g_object_new (grpt_canvas_get_type (), NULL));
 
-	CanvasPrivate *priv = CANVAS_GET_PRIVATE (canvas);
+	GRptCanvasPrivate *priv = GRPT_CANVAS_GET_PRIVATE (grpt_canvas);
 
 	priv->rpt_report = rpt_report;
 
@@ -269,54 +312,71 @@ Canvas
 	fixed = gtk_fixed_new ();
 	gtk_container_add (GTK_CONTAINER (viewport), fixed);
 
-	priv->canvas = goo_canvas_new ();
-	gtk_fixed_put (GTK_FIXED (fixed), priv->canvas, 0, 0);
+	priv->grpt_canvas = goo_canvas_new ();
+	gtk_fixed_put (GTK_FIXED (fixed), priv->grpt_canvas, 0, 0);
 
-	g_signal_connect (G_OBJECT (priv->canvas), "button-press-event",
-	                  G_CALLBACK (canvas_on_button_press_event), (gpointer)canvas);
-	g_signal_connect (G_OBJECT (priv->canvas), "button-release-event",
-	                  G_CALLBACK (canvas_on_button_release_event), (gpointer)canvas);
-	g_signal_connect (G_OBJECT (priv->canvas), "motion-notify-event",
-	                  G_CALLBACK (canvas_on_motion_notify_event), (gpointer)canvas);
+	g_signal_connect (G_OBJECT (priv->grpt_canvas), "button-press-event",
+	                  G_CALLBACK (grpt_canvas_on_button_press_event), (gpointer)grpt_canvas);
+	g_signal_connect (G_OBJECT (priv->grpt_canvas), "button-release-event",
+	                  G_CALLBACK (grpt_canvas_on_button_release_event), (gpointer)grpt_canvas);
+	g_signal_connect (G_OBJECT (priv->grpt_canvas), "motion-notify-event",
+	                  G_CALLBACK (grpt_canvas_on_motion_notify_event), (gpointer)grpt_canvas);
 
-	priv->root = goo_canvas_get_root_item (GOO_CANVAS (priv->canvas));
+	priv->root = goo_canvas_get_root_item (GOO_CANVAS (priv->grpt_canvas));
 
 	/* setting size */
 	size = rpt_report_get_page_size (priv->rpt_report);
 	size->height = rpt_report_get_section_height (priv->rpt_report, RPTREPORT_SECTION_BODY);
-	canvas_set_size (canvas, *size);
+	grpt_canvas_set_size (grpt_canvas, *size);
 
-	/* GooCanvasItem that represents the "selection" */
+	/* GooGRptCanvasItem that represents the "selection" */
 	priv->selection = goo_canvas_rect_new (priv->root, 0, 0, 0, 0,
 	                                       "stroke-color", "black",
 	                                       "visibility", GOO_CANVAS_ITEM_HIDDEN,
 	                                       NULL);
 
-	return canvas;
+	return grpt_canvas;
 }
 
 GtkWidget
-*canvas_get_widget (Canvas *canvas)
+*grpt_canvas_get_widget (GRptCanvas *grpt_canvas)
 {
-	CanvasPrivate *priv = CANVAS_GET_PRIVATE (canvas);
+	GRptCanvasPrivate *priv = GRPT_CANVAS_GET_PRIVATE (grpt_canvas);
 
 	return priv->scrolledw;
 }
 
 void
-canvas_set_size (Canvas *canvas, RptSize size)
+grpt_canvas_set_size (GRptCanvas *grpt_canvas, RptSize size)
 {
-	CanvasPrivate *priv = CANVAS_GET_PRIVATE (canvas);
+	GRptCanvasPrivate *priv = GRPT_CANVAS_GET_PRIVATE (grpt_canvas);
+
+	gtk_widget_set_size_request (priv->grpt_canvas, size.width, size.height);
+	goo_canvas_set_bounds (GOO_CANVAS (priv->grpt_canvas), 0, 0, size.width, size.height);
+}
+
+GList
+*grpt_canvas_section_get_objects (GRptCanvas *grpt_canvas, RptReportSection section)
+{
+	GList *objects = NULL;
+
+	GRptCanvasPrivate *priv = GRPT_CANVAS_GET_PRIVATE (grpt_canvas);
+
+	switch (section)
+		{
+			case RPTREPORT_SECTION_BODY:
+				objects = g_list_copy (priv->body_objects);
+				break;
+		}
 
-	gtk_widget_set_size_request (priv->canvas, size.width, size.height);
-	goo_canvas_set_bounds (GOO_CANVAS (priv->canvas), 0, 0, size.width, size.height);
+	return objects;
 }
 
 void
-canvas_free (Canvas *canvas)
+grpt_canvas_free (GRptCanvas *grpt_canvas)
 {
-	CanvasPrivate *priv = CANVAS_GET_PRIVATE (canvas);
+	GRptCanvasPrivate *priv = GRPT_CANVAS_GET_PRIVATE (grpt_canvas);
 
-	gtk_widget_destroy (priv->canvas);
+	gtk_widget_destroy (priv->grpt_canvas);
 	gtk_widget_destroy (priv->scrolledw);
 }
diff --git a/src/canvas.h b/src/canvas.h
index ca5e17c..b90d94f 100644
--- a/src/canvas.h
+++ b/src/canvas.h
@@ -22,40 +22,49 @@
 #include <glib-object.h>
 #include <libreptool.h>
 
+#include "canvasitem.h"
+
 
 G_BEGIN_DECLS
 
 
-#define GRPT_TYPE_CANVAS            (canvas_get_type ())
-#define GRPT_CANVAS(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GRPT_TYPE_CANVAS, Canvas))
-#define GRPT_CANVAS_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GRPT_TYPE_CANVAS, CanvasClass))
+#define GRPT_TYPE_CANVAS            (grpt_canvas_get_type ())
+#define GRPT_CANVAS(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GRPT_TYPE_CANVAS, GRptCanvas))
+#define GRPT_CANVAS_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GRPT_TYPE_CANVAS, GRptCanvasClass))
 #define GRPT_IS_CANVAS(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GRPT_TYPE_CANVAS))
 #define GRPT_IS_CANVAS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GRPT_TYPE_CANVAS))
-#define GRPT_CANVAS_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GRPT_TYPE_CANVAS, CanvasClass))
+#define GRPT_CANVAS_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GRPT_TYPE_CANVAS, GRptCanvasClass))
 
 
-typedef struct _Canvas Canvas;
-typedef struct _CanvasClass CanvasClass;
+typedef struct _GRptCanvas GRptCanvas;
+typedef struct _GRptCanvasClass GRptCanvasClass;
   
-struct _Canvas
-{
-	GObject parent;
-};
+struct _GRptCanvas
+	{
+		GObject parent;
+	};
+
+struct _GRptCanvasClass
+	{
+		GObjectClass parent_class;
+	
+		guint object_added_signal_id;
+		guint object_removed_signal_id;
+	};
+
+GType grpt_canvas_get_type (void) G_GNUC_CONST;
 
-struct _CanvasClass
-{
-	GObjectClass parent_class;
-};
+GRptCanvas *grpt_canvas_new (RptReport *rpt_report);
 
-GType canvas_get_type (void) G_GNUC_CONST;
+GtkWidget *grpt_canvas_get_widget (GRptCanvas *grpt_canvas);
 
-Canvas *canvas_new (RptReport *rpt_report);
+void grpt_canvas_set_size (GRptCanvas *grpt_canvas, RptSize size);
 
-GtkWidget *canvas_get_widget (Canvas *canvas);
+GList *grpt_canvas_section_get_objects (GRptCanvas *grpt_canvas, RptReportSection section);
 
-void canvas_set_size (Canvas *canvas, RptSize size);
+void grpt_canvas_select_object (GRptCanvas *grpt_canvas, GRptCanvasItem *grpt_canvas_item);
 
-void canvas_free (Canvas *canvas);
+void grpt_canvas_free (GRptCanvas *grpt_canvas);
 
 
 G_END_DECLS
diff --git a/src/canvasitem.c b/src/canvasitem.c
new file mode 100644
index 0000000..fff451a
--- /dev/null
+++ b/src/canvasitem.c
@@ -0,0 +1,179 @@
+/*
+ * Copyright (C) 2007 Andrea Zagli <azagli@inwind.it>
+ *
+ *  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 "canvasitem.h"
+
+
+static void grpt_canvas_item_class_init (GRptCanvasItemClass *klass);
+static void grpt_canvas_item_init (GRptCanvasItem *grpt_canvas_item);
+
+
+static void grpt_canvas_item_update (GooCanvasItemSimple *simple,
+                                     cairo_t *cr);
+static gboolean grpt_canvas_item_is_item_at (GooCanvasItemSimple *simple,
+                                             gdouble x,
+                                             gdouble y,
+                                             cairo_t *cr,
+                                             gboolean is_pointer_event);
+
+#define GRPT_CANVAS_ITEM_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GRPT_TYPE_CANVAS_ITEM, GRptCanvasItemPrivate))
+
+
+typedef struct _GRptCanvasItemPrivate GRptCanvasItemPrivate;
+struct _GRptCanvasItemPrivate
+	{
+		RptReportSection section;
+	};
+
+GType
+grpt_canvas_item_get_type (void)
+{
+	static GType grpt_canvas_item_type = 0;
+
+	if (!grpt_canvas_item_type)
+		{
+			static const GTypeInfo grpt_canvas_item_info =
+			{
+				sizeof (GRptCanvasItemClass),
+				NULL,	/* base_init */
+				NULL,	/* base_finalize */
+				(GClassInitFunc) grpt_canvas_item_class_init,
+				NULL,	/* class_finalize */
+				NULL,	/* class_data */
+				sizeof (GRptCanvasItem),
+				0,	/* n_preallocs */
+				(GInstanceInitFunc) grpt_canvas_item_init,
+				NULL
+			};
+
+			grpt_canvas_item_type = g_type_register_static (GOO_TYPE_CANVAS_ITEM_SIMPLE, "GRptCanvasItem",
+			                                                &grpt_canvas_item_info, 0);
+		}
+
+	return grpt_canvas_item_type;
+}
+
+static void
+grpt_canvas_item_class_init (GRptCanvasItemClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+	GooCanvasItemSimpleClass *simple_class = (GooCanvasItemSimpleClass *)klass;
+
+	g_type_class_add_private (object_class, sizeof (GRptCanvasItemPrivate));
+
+	simple_class->simple_update = grpt_canvas_item_update;
+	simple_class->simple_is_item_at = grpt_canvas_item_is_item_at;
+}
+
+static void
+grpt_canvas_item_init (GRptCanvasItem *grpt_canvas_item)
+{
+	grpt_canvas_item->x = 0.0;
+	grpt_canvas_item->y = 0.0;
+	grpt_canvas_item->width = 0.0;
+	grpt_canvas_item->height = 0.0;
+}
+
+GooCanvasItem
+*grpt_canvas_item_new (GooCanvasItem *parent, gdouble x, gdouble y, gdouble width, gdouble height, ...)
+{
+	GooCanvasItem *item;
+	GRptCanvasItem *grpt_canvas_item;
+	const char *first_property;
+	va_list var_args;
+	GRptCanvasItemPrivate *priv;
+
+	item = g_object_new (GRPT_TYPE_CANVAS_ITEM, NULL);
+
+	grpt_canvas_item = (GRptCanvasItem *)item;
+	grpt_canvas_item->x = x;
+	grpt_canvas_item->y = y;
+	grpt_canvas_item->width = width;
+	grpt_canvas_item->height = height;
+
+	va_start (var_args, height);
+	first_property = va_arg (var_args, char*);
+	if (first_property)
+		{
+			g_object_set_valist ((GObject *)item, first_property, var_args);
+		}
+	va_end (var_args);
+
+	if (parent)
+		{
+			goo_canvas_item_add_child (parent, item, -1);
+			g_object_unref (item);
+		}
+
+	return item;
+}
+
+RptObject
+*grpt_canvas_item_get_rpt_object (GRptCanvasItem *grpt_canvas_item)
+{
+	RptObject *rptobj = NULL;
+
+	if (GRPT_CANVAS_ITEM_GET_CLASS (grpt_canvas_item)->get_rpt_object)
+		{
+			rptobj = GRPT_CANVAS_ITEM_GET_CLASS (grpt_canvas_item)->get_rpt_object (grpt_canvas_item);
+		}
+
+	return rptobj;
+}
+
+RptReportSection
+grpt_canvas_item_get_section (GRptCanvasItem *grpt_canvas_item)
+{
+	GRptCanvasItemPrivate *priv = GRPT_CANVAS_ITEM_GET_PRIVATE (grpt_canvas_item);
+
+	return priv->section;
+}
+
+void
+grpt_canvas_item_set_section (GRptCanvasItem *grpt_canvas_item, RptReportSection section)
+{
+	GRptCanvasItemPrivate *priv = GRPT_CANVAS_ITEM_GET_PRIVATE (grpt_canvas_item);
+
+	priv->section = section;
+}
+
+static void
+grpt_canvas_item_update (GooCanvasItemSimple *simple, cairo_t *cr)
+{
+	GRptCanvasItem *grpt_canvas_item = (GRptCanvasItem *)simple;
+
+	/* Compute the new bounds. */
+	simple->bounds.x1 = grpt_canvas_item->x;
+	simple->bounds.y1 = grpt_canvas_item->y;
+	simple->bounds.x2 = grpt_canvas_item->x + grpt_canvas_item->width;
+	simple->bounds.y2 = grpt_canvas_item->y + grpt_canvas_item->height;
+}
+
+static gboolean
+grpt_canvas_item_is_item_at (GooCanvasItemSimple *simple, gdouble x, gdouble y, cairo_t *cr, gboolean is_pointer_event)
+{
+	GRptCanvasItem *grpt_canvas_item = (GRptCanvasItem *)simple;
+
+	if (x < grpt_canvas_item->x || x > grpt_canvas_item->x + grpt_canvas_item->width
+	    || y < grpt_canvas_item->y || y > grpt_canvas_item->y + grpt_canvas_item->height)
+		{
+			return FALSE;
+		}
+
+	return TRUE;
+}
diff --git a/src/canvasitem.h b/src/canvasitem.h
new file mode 100644
index 0000000..db330f4
--- /dev/null
+++ b/src/canvasitem.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2007 Andrea Zagli <azagli@inwind.it>
+ *
+ *  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 __GRPT_CANVAS_ITEM_H__
+#define __GRPT_CANVAS_ITEM_H__
+
+#include <gtk/gtk.h>
+#include <goocanvasitemsimple.h>
+#include <libreptool.h>
+
+
+G_BEGIN_DECLS
+
+
+#define GRPT_TYPE_CANVAS_ITEM            (grpt_canvas_item_get_type ())
+#define GRPT_CANVAS_ITEM(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GRPT_TYPE_CANVAS_ITEM, GRptCanvasItem))
+#define GRPT_CANVAS_ITEM_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GRPT_TYPE_CANVAS_ITEM, GRptCanvasItemClass))
+#define GRPT_IS_CANVAS_ITEM(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GRPT_TYPE_CANVAS_ITEM))
+#define GRPT_IS_CANVAS_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GRPT_TYPE_CANVAS_ITEM))
+#define GRPT_CANVAS_ITEM_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GRPT_TYPE_CANVAS_ITEM, GRptCanvasItemClass))
+
+
+typedef struct _GRptCanvasItem GRptCanvasItem;
+typedef struct _GRptCanvasItemClass GRptCanvasItemClass;
+  
+struct _GRptCanvasItem
+{
+	GooCanvasItemSimple parent;
+
+	gdouble x, y, width, height;
+};
+
+struct _GRptCanvasItemClass
+{
+	GooCanvasItemSimpleClass parent_class;
+
+	RptObject *(*get_rpt_object) (GRptCanvasItem *canvas_item);
+};
+
+GType grpt_canvas_item_get_type (void) G_GNUC_CONST;
+
+GooCanvasItem *grpt_canvas_item_new (GooCanvasItem *parent,
+                                     gdouble x,
+                                     gdouble y,
+                                     gdouble width,
+                                     gdouble height,
+                                     ...);
+
+RptObject *grpt_canvas_item_get_rpt_object (GRptCanvasItem *grpt_canvas_item);
+
+RptReportSection grpt_canvas_item_get_section (GRptCanvasItem *grpt_canvas_item);
+void grpt_canvas_item_set_section (GRptCanvasItem *grpt_canvas_item, RptReportSection section);
+
+
+G_END_DECLS
+
+
+#endif /* __GRPT_CANVAS_ITEM_H__ */
diff --git a/src/canvasline.c b/src/canvasline.c
index ae24f3b..867e827 100644
--- a/src/canvasline.c
+++ b/src/canvasline.c
@@ -19,98 +19,91 @@
 #include "canvasline.h"
 
 
-static void canvas_line_class_init (CanvasLineClass *klass);
-static void canvas_line_init (CanvasLine *canvas_line);
+static void grpt_canvas_line_class_init (GRptCanvasLineClass *klass);
+static void grpt_canvas_line_init (GRptCanvasLine *grpt_canvas_line);
 
 
-static void canvas_line_update (GooCanvasItemSimple *simple,
-                                cairo_t *cr);
-static void canvas_line_paint (GooCanvasItemSimple *simple,
-                               cairo_t *cr,
-							   const GooCanvasBounds *bounds);
-static gboolean canvas_line_is_item_at (GooCanvasItemSimple *simple,
-                                        gdouble x,
-										gdouble y,
-										cairo_t *cr,
-										gboolean is_pointer_event);
+static void grpt_canvas_line_paint (GooCanvasItemSimple *simple,
+                                    cairo_t *cr,
+							        const GooCanvasBounds *bounds);
 
-#define GRPT_CANVAS_LINE_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GRPT_TYPE_CANVAS_LINE, CanvasLinePrivate))
+static RptObject *grpt_canvas_line_get_rpt_object (GRptCanvasItem *grpt_canvas_item);
 
 
-typedef struct _CanvasLinePrivate CanvasLinePrivate;
-struct _CanvasLinePrivate
+#define GRPT_CANVAS_LINE_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GRPT_TYPE_CANVAS_LINE, GRptCanvasLinePrivate))
+
+
+typedef struct _GRptCanvasLinePrivate GRptCanvasLinePrivate;
+struct _GRptCanvasLinePrivate
 	{
 		RptObjLine *rpt_object_line;
 	};
 
 GType
-canvas_line_get_type (void)
+grpt_canvas_line_get_type (void)
 {
-	static GType canvas_line_type = 0;
+	static GType grpt_canvas_line_type = 0;
 
-	if (!canvas_line_type)
+	if (!grpt_canvas_line_type)
 		{
-			static const GTypeInfo canvas_line_info =
+			static const GTypeInfo grpt_canvas_line_info =
 			{
-				sizeof (CanvasLineClass),
+				sizeof (GRptCanvasLineClass),
 				NULL,	/* base_init */
 				NULL,	/* base_finalize */
-				(GClassInitFunc) canvas_line_class_init,
+				(GClassInitFunc) grpt_canvas_line_class_init,
 				NULL,	/* class_finalize */
 				NULL,	/* class_data */
-				sizeof (CanvasLine),
+				sizeof (GRptCanvasLine),
 				0,	/* n_preallocs */
-				(GInstanceInitFunc) canvas_line_init,
+				(GInstanceInitFunc) grpt_canvas_line_init,
 				NULL
 			};
 
-			canvas_line_type = g_type_register_static (GOO_TYPE_CANVAS_ITEM_SIMPLE, "CanvasLine",
-			                                           &canvas_line_info, 0);
+			grpt_canvas_line_type = g_type_register_static (GRPT_TYPE_CANVAS_ITEM, "GRptCanvasLine",
+			                                                &grpt_canvas_line_info, 0);
 		}
 
-	return canvas_line_type;
+	return grpt_canvas_line_type;
 }
 
 static void
-canvas_line_class_init (CanvasLineClass *klass)
+grpt_canvas_line_class_init (GRptCanvasLineClass *klass)
 {
 	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+	GRptCanvasItemClass *canvas_item_class = GRPT_CANVAS_ITEM_CLASS (klass);
 	GooCanvasItemSimpleClass *simple_class = (GooCanvasItemSimpleClass *)klass;
 
-	g_type_class_add_private (object_class, sizeof (CanvasLinePrivate));
+	g_type_class_add_private (object_class, sizeof (GRptCanvasLinePrivate));
+
+	simple_class->simple_paint = grpt_canvas_line_paint;
 
-	simple_class->simple_update = canvas_line_update;
-	simple_class->simple_paint = canvas_line_paint;
-	simple_class->simple_is_item_at = canvas_line_is_item_at;
+	canvas_item_class->get_rpt_object = grpt_canvas_line_get_rpt_object;
 }
 
 static void
-canvas_line_init (CanvasLine *canvas_line)
+grpt_canvas_line_init (GRptCanvasLine *grpt_canvas_line)
 {
-	canvas_line->x = 0.0;
-	canvas_line->y = 0.0;
-	canvas_line->width = 0.0;
-	canvas_line->height = 0.0;
 }
 
-GooCanvasItem
-*canvas_line_new (GooCanvasItem *parent, gdouble x, gdouble y, gdouble width, gdouble height, RptObjLine *rpt_object_line, ...)
+GRptCanvasItem
+*grpt_canvas_line_new (GooCanvasItem *parent, gdouble x, gdouble y, gdouble width, gdouble height, RptObjLine *rpt_object_line, ...)
 {
-	GooCanvasItem *item;
-	CanvasLine *canvas_line;
+	GRptCanvasItem *item;
+	GRptCanvasLine *grpt_canvas_line;
 	const char *first_property;
 	va_list var_args;
-	CanvasLinePrivate *priv;
+	GRptCanvasLinePrivate *priv;
 
 	item = g_object_new (GRPT_TYPE_CANVAS_LINE, NULL);
+	item->x = x;
+	item->y = y;
+	item->width = width;
+	item->height = height;
 
-	canvas_line = (CanvasLine *)item;
-	canvas_line->x = x;
-	canvas_line->y = y;
-	canvas_line->width = width;
-	canvas_line->height = height;
+	grpt_canvas_line = (GRptCanvasLine *)item;
 
-	priv = GRPT_CANVAS_LINE_GET_PRIVATE (canvas_line);
+	priv = GRPT_CANVAS_LINE_GET_PRIVATE (grpt_canvas_line);
 	priv->rpt_object_line = g_object_ref (rpt_object_line);
 
 	va_start (var_args, rpt_object_line);
@@ -123,7 +116,7 @@ GooCanvasItem
 
 	if (parent)
 		{
-			goo_canvas_item_add_child (parent, item, -1);
+			goo_canvas_item_add_child (parent, GOO_CANVAS_ITEM (item), -1);
 			g_object_unref (item);
 		}
 
@@ -131,33 +124,23 @@ GooCanvasItem
 }
 
 static void
-canvas_line_update (GooCanvasItemSimple *simple, cairo_t *cr)
-{
-	CanvasLine *canvas_line = (CanvasLine *)simple;
-
-	/* Compute the new bounds. */
-	simple->bounds.x1 = canvas_line->x;
-	simple->bounds.y1 = canvas_line->y;
-	simple->bounds.x2 = canvas_line->x + canvas_line->width;
-	simple->bounds.y2 = canvas_line->y + canvas_line->height;
-}
-
-static void
-canvas_line_paint (GooCanvasItemSimple *simple, cairo_t *cr, const GooCanvasBounds *bounds)
+grpt_canvas_line_paint (GooCanvasItemSimple *simple, cairo_t *cr, const GooCanvasBounds *bounds)
 {
 	RptPoint from_p;
 	RptPoint to_p;
 	RptRotation *rotation = NULL;
 	RptStroke *stroke = NULL;
 
-	CanvasLine *canvas_line = (CanvasLine *)simple;
+	GRptCanvasLine *grpt_canvas_line = (GRptCanvasLine *)simple;
+
+	GRptCanvasItem *grpt_canvas_item = (GRptCanvasItem *)simple;
 
-	CanvasLinePrivate *priv = GRPT_CANVAS_LINE_GET_PRIVATE (canvas_line);
+	GRptCanvasLinePrivate *priv = GRPT_CANVAS_LINE_GET_PRIVATE (grpt_canvas_line);
 
-	from_p.x = canvas_line->x;
-	from_p.y = canvas_line->y;
-	to_p.x = canvas_line->x + canvas_line->width;
-	to_p.y = canvas_line->y + canvas_line->height;
+	from_p.x = grpt_canvas_item->x;
+	from_p.y = grpt_canvas_item->y;
+	to_p.x = grpt_canvas_item->x + grpt_canvas_item->width;
+	to_p.y = grpt_canvas_item->y + grpt_canvas_item->height;
 
 	g_object_get (G_OBJECT (priv->rpt_object_line),
 	              "rotation", &rotation,
@@ -203,16 +186,10 @@ canvas_line_paint (GooCanvasItemSimple *simple, cairo_t *cr, const GooCanvasBoun
 		}
 }
 
-static gboolean
-canvas_line_is_item_at (GooCanvasItemSimple *simple, gdouble x, gdouble y, cairo_t *cr, gboolean is_pointer_event)
+static RptObject
+*grpt_canvas_line_get_rpt_object (GRptCanvasItem *grpt_canvas_item)
 {
-	CanvasLine *canvas_line = (CanvasLine *)simple;
-
-	if (x < canvas_line->x || x > canvas_line->x + canvas_line->width
-	    || y < canvas_line->y || y > canvas_line->y + canvas_line->height)
-		{
-			return FALSE;
-		}
+	GRptCanvasLinePrivate *priv = GRPT_CANVAS_LINE_GET_PRIVATE (GRPT_CANVAS_LINE (grpt_canvas_item));
 
-	return TRUE;
+	return RPT_OBJECT (priv->rpt_object_line);
 }
diff --git a/src/canvasline.h b/src/canvasline.h
index 07532e3..171c400 100644
--- a/src/canvasline.h
+++ b/src/canvasline.h
@@ -16,52 +16,51 @@
  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  */
 
-#ifndef __CANVAS_LINE_H__
-#define __CANVAS_LINE_H__
+#ifndef __GRPT_CANVAS_LINE_H__
+#define __GRPT_CANVAS_LINE_H__
 
 #include <gtk/gtk.h>
-#include <goocanvasitemsimple.h>
 #include <libreptool.h>
 
+#include "canvasitem.h"
+
 
 G_BEGIN_DECLS
 
 
-#define GRPT_TYPE_CANVAS_LINE            (canvas_line_get_type ())
-#define GRPT_CANVAS_LINE(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GRPT_TYPE_CANVAS_LINE, CanvasLine))
-#define GRPT_CANVAS_LINE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GRPT_TYPE_CANVAS_LINE, CanvasLineClass))
+#define GRPT_TYPE_CANVAS_LINE            (grpt_canvas_line_get_type ())
+#define GRPT_CANVAS_LINE(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GRPT_TYPE_CANVAS_LINE, GRptCanvasLine))
+#define GRPT_CANVAS_LINE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GRPT_TYPE_CANVAS_LINE, GRptCanvasLineClass))
 #define GRPT_IS_CANVAS_LINE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GRPT_TYPE_CANVAS_LINE))
 #define GRPT_IS_CANVAS_LINE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GRPT_TYPE_CANVAS_LINE))
-#define GRPT_CANVAS_LINE_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GRPT_TYPE_CANVAS_LINE, CanvasLineClass))
+#define GRPT_CANVAS_LINE_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GRPT_TYPE_CANVAS_LINE, GRptCanvasLineClass))
 
 
-typedef struct _CanvasLine CanvasLine;
-typedef struct _CanvasLineClass CanvasLineClass;
+typedef struct _GRptCanvasLine GRptCanvasLine;
+typedef struct _GRptCanvasLineClass GRptCanvasLineClass;
   
-struct _CanvasLine
+struct _GRptCanvasLine
 {
-	GooCanvasItemSimple parent;
-
-	gdouble x, y, width, height;
+	GRptCanvasItem parent;
 };
 
-struct _CanvasLineClass
+struct _GRptCanvasLineClass
 {
-	GooCanvasItemSimpleClass parent_class;
+	GRptCanvasItemClass parent_class;
 };
 
-GType canvas_line_get_type (void) G_GNUC_CONST;
+GType grpt_canvas_line_get_type (void) G_GNUC_CONST;
 
-GooCanvasItem *canvas_line_new (GooCanvasItem *parent,
-                                gdouble x,
-                                gdouble y,
-                                gdouble width,
-                                gdouble height,
-                                RptObjLine *rpt_object_line,
-                                ...);
+GRptCanvasItem *grpt_canvas_line_new (GooCanvasItem *parent,
+                                     gdouble x,
+                                     gdouble y,
+                                     gdouble width,
+                                     gdouble height,
+                                     RptObjLine *rpt_object_line,
+                                     ...);
 
 
 G_END_DECLS
 
 
-#endif /* __CANVAS_LINE_H__ */
+#endif /* __GRPT_CANVAS_LINE_H__ */
diff --git a/src/main.c b/src/main.c
index 41f945c..d0aceb3 100644
--- a/src/main.c
+++ b/src/main.c
@@ -19,6 +19,7 @@
 #include <gtk/gtk.h>
 #include <glade/glade.h>
 #include <libreptool.h>
+#include <goocanvas.h>
 
 #ifdef HAVE_CONFIG_H
 	#include <config.h>
@@ -26,6 +27,17 @@
 
 #include "main.h"
 #include "canvas.h"
+#include "canvasitem.h"
+#include "objects_tree.h"
+
+
+void report_on_canvas_object_added (GRptCanvas *grpt_canvas,
+                                    GRptCanvasItem *item,
+                                    gpointer user_data);
+void report_on_canvas_object_removed (GRptCanvas *grpt_canvas,
+                                      GRptCanvasItem *item,
+                                      gpointer user_data);
+
 
 static gchar *report_filename;
 static RptReport *rpt_report;
@@ -51,7 +63,9 @@ static GtkWidget *rtbtn_rect;
 static GtkWidget *rtbtn_ellipse;
 static GtkWidget *rtbtn_image;
 
-static Canvas *canvas;
+static GRptCanvas *grpt_canvas;
+
+static GRptObjectsTree *objects_tree;
 
 /* PRIVATE */
 static void
@@ -92,10 +106,10 @@ report_set_defaults ()
 static void
 report_close ()
 {
-	if (canvas != NULL)
+	if (grpt_canvas != NULL)
 		{
-			canvas_free (canvas);
-			canvas = NULL;
+			grpt_canvas_free (grpt_canvas);
+			grpt_canvas = NULL;
 		}
 	if (report_filename != NULL)
 		{
@@ -128,10 +142,13 @@ report_new ()
 
 	menu_toolbar_sensitivity ();
 
-	objects_tree_fill_tree (rpt_report);
-	canvas = canvas_new (rpt_report);
+	grpt_canvas = grpt_canvas_new (rpt_report);
+	grpt_objects_tree_set_canvas (objects_tree, grpt_canvas);
 
-	canvas_widget = canvas_get_widget (canvas);
+	g_signal_connect (grpt_canvas, "object-added", G_CALLBACK (report_on_canvas_object_added), NULL);
+	g_signal_connect (grpt_canvas, "object-removed", G_CALLBACK (report_on_canvas_object_removed), NULL);
+	
+	canvas_widget = grpt_canvas_get_widget (grpt_canvas);
 
 	gtk_container_add (GTK_CONTAINER (vbox), canvas_widget);
 	gtk_box_reorder_child (GTK_BOX (vbox), canvas_widget, 3);
@@ -159,10 +176,10 @@ report_open_from_file (const gchar *filename)
 
 	menu_toolbar_sensitivity ();
 
-	objects_tree_fill_tree (rpt_report);
-	canvas = canvas_new (rpt_report);
+	grpt_canvas = grpt_canvas_new (rpt_report);
+	grpt_objects_tree_set_canvas (objects_tree, grpt_canvas);
 
-	canvas_widget = canvas_get_widget (canvas);
+	canvas_widget = grpt_canvas_get_widget (grpt_canvas);
 
 	gtk_container_add (GTK_CONTAINER (vbox), canvas_widget);
 	gtk_box_reorder_child (GTK_BOX (vbox), canvas_widget, 3);
@@ -293,11 +310,12 @@ on_mnu_view_objects_tree_toggled (GtkCheckMenuItem *checkmenuitem,
 {
 	if (gtk_check_menu_item_get_active (checkmenuitem))
 		{
-			objects_tree (rpt_report);
+			objects_tree = grpt_objects_tree_new (grpt_canvas);
 		}
 	else
 		{
-			objects_tree_destroy ();
+			grpt_objects_tree_destroy (objects_tree);
+			objects_tree = NULL;
 		}
 }
 
@@ -340,6 +358,22 @@ on_tbtn_save_clicked (GtkToolButton *toolbutton,
 		}
 }
 
+void
+report_on_canvas_object_added (GRptCanvas *grpt_canvas,
+                               GRptCanvasItem *item,
+                               gpointer user_data)
+{
+	grpt_objects_tree_add_object_to_section (objects_tree, item, RPTREPORT_SECTION_BODY);
+}
+
+void
+report_on_canvas_object_removed (GRptCanvas *grpt_canvas,
+                                 GRptCanvasItem *item,
+                                 gpointer user_data)
+{
+	g_fprintf (stderr,"object removed\n");
+}
+
 /* PUBLIC */
 Tool
 get_current_tool ()
diff --git a/src/objects_tree.c b/src/objects_tree.c
index 576de23..363a885 100644
--- a/src/objects_tree.c
+++ b/src/objects_tree.c
@@ -18,30 +18,91 @@
 
 #include <gtk/gtk.h>
 #include <glade/glade.h>
-#include <libreptool.h>
+
+#include "objects_tree.h"
 
 enum
 {
 	OBJS_TREE_COL_NAME,
 	OBJS_TREE_COL_SECTION,
-	OBJS_TREE_COL_OBJECT,
+	OBJS_TREE_COL_GRPT_CANVAS_ITEM,
+	OBJS_TREE_COL_RPT_OBJECT,
 	OBJS_TREE_COLS
 };
 
-static RptReport *rpt_report_;
 
-static GtkWidget *w_tree;
-static GtkWidget *tr_objects_tree;
+static void grpt_objects_tree_class_init (GRptObjectsTreeClass *klass);
+static void grpt_objects_tree_init (GRptObjectsTree *grpt_objects_tree);
+
+
+#define GRPT_OBJECTS_TREE_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GRPT_TYPE_OBJECTS_TREE, GRptObjectsTreePrivate))
+
+
+typedef struct _GRptObjectsTreePrivate GRptObjectsTreePrivate;
+struct _GRptObjectsTreePrivate
+	{
+		GRptCanvas *canvas;
+
+		GtkWidget *w_tree;
+		GtkWidget *tr_objects;
+
+		GtkTreeStore *tr_store;
+		GtkTreeSelection *selection;
+
+		GtkTreeRowReference *trr_body;
+	};
+
+GType
+grpt_objects_tree_get_type (void)
+{
+	static GType grpt_objects_tree_type = 0;
+
+	if (!grpt_objects_tree_type)
+		{
+			static const GTypeInfo grpt_objects_tree_info =
+			{
+				sizeof (GRptObjectsTreeClass),
+				NULL,	/* base_init */
+				NULL,	/* base_finalize */
+				(GClassInitFunc) grpt_objects_tree_class_init,
+				NULL,	/* class_finalize */
+				NULL,	/* class_data */
+				sizeof (GRptObjectsTree),
+				0,	/* n_preallocs */
+				(GInstanceInitFunc) grpt_objects_tree_init,
+				NULL
+			};
+
+			grpt_objects_tree_type = g_type_register_static (G_TYPE_OBJECT, "GRptObjectsTree",
+			                                                 &grpt_objects_tree_info, 0);
+		}
+
+	return grpt_objects_tree_type;
+}
+
+static void
+grpt_objects_tree_class_init (GRptObjectsTreeClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
-static GtkTreeStore *tr_store;
-static GtkTreeSelection *selection;
+	g_type_class_add_private (object_class, sizeof (GRptObjectsTreePrivate));
+}
 
 static void
-objects_tree_fill_tree_section (RptReportSection section, GList *objects)
+grpt_objects_tree_init (GRptObjectsTree *grpt_objects_tree)
+{
+	GRptObjectsTreePrivate *priv = GRPT_OBJECTS_TREE_GET_PRIVATE (grpt_objects_tree);
+
+	priv->trr_body = NULL;
+}
+
+static void
+grpt_objects_tree_create_tree_section (GRptObjectsTree *grpt_objects_tree, RptReportSection section)
 {
 	GtkTreeIter iter;
-	gchar *name;
-	GList *list;
+	gchar *name = NULL;
+
+	GRptObjectsTreePrivate *priv = GRPT_OBJECTS_TREE_GET_PRIVATE (grpt_objects_tree);
 
 	switch (section)
 		{
@@ -62,119 +123,179 @@ objects_tree_fill_tree_section (RptReportSection section, GList *objects)
 				break;
 
 			case RPTREPORT_SECTION_BODY:
-				name = g_strdup ("Body");
+				if (priv->trr_body == NULL)
+					{
+						name = g_strdup ("Body");
+					}
 				break;
 		}
 
-	list = g_list_first (objects);
-	if (list != NULL)
+	if (name != NULL)
 		{
-			GtkTreeIter iter_child;
-			RptObject *obj;
-
-			gtk_tree_store_append (tr_store, &iter, NULL);
-			gtk_tree_store_set (tr_store, &iter,
+			gtk_tree_store_append (priv->tr_store, &iter, NULL);
+			gtk_tree_store_set (priv->tr_store, &iter,
 								OBJS_TREE_COL_NAME, name,
 								OBJS_TREE_COL_SECTION, section,
 								-1);
+		
+			priv->trr_body = gtk_tree_row_reference_new (GTK_TREE_MODEL (priv->tr_store),
+														 gtk_tree_model_get_path (GTK_TREE_MODEL (priv->tr_store),
+																				  &iter));
+		}
+}
 
-			while (list != NULL)
-				{
-					obj = (RptObject *)list->data;
+static void
+grpt_objects_tree_fill_tree_section (GRptObjectsTree *grpt_objects_tree, RptReportSection section, GList *objects)
+{
+	GList *list;
 
-					g_object_get (obj, "name", &name, NULL);
+	GRptObjectsTreePrivate *priv = GRPT_OBJECTS_TREE_GET_PRIVATE (grpt_objects_tree);
 
-					gtk_tree_store_append (tr_store, &iter_child, &iter);
-					gtk_tree_store_set (tr_store, &iter_child,
-										OBJS_TREE_COL_NAME, name,
-										OBJS_TREE_COL_SECTION, section,
-										OBJS_TREE_COL_OBJECT, obj,
-										-1);
+	list = g_list_first (objects);
+	if (list != NULL)
+		{
+			while (list != NULL)
+				{
+					grpt_objects_tree_add_object_to_section (grpt_objects_tree,
+					                                         (GRptCanvasItem *)list->data,
+					                                         section);
 
 					list = g_list_next (list);
 				}
 		}
 }
 
+GRptObjectsTree
+*grpt_objects_tree_new (GRptCanvas *canvas)
+{
+	GtkTreeViewColumn *column;
+	GtkCellRenderer *renderer;
+
+	GRptObjectsTree *obj_tree = GRPT_OBJECTS_TREE (g_object_new (grpt_objects_tree_get_type (), NULL));
+
+	GRptObjectsTreePrivate *priv = GRPT_OBJECTS_TREE_GET_PRIVATE (obj_tree);
+
+	GladeXML *gla = glade_xml_new (GLADEDIR "/greptool.glade", "w_objects_tree", NULL);
+	priv->w_tree = glade_xml_get_widget (gla, "w_objects_tree");
+	priv->tr_objects = glade_xml_get_widget (gla, "tr_objects_tree");
+
+	glade_xml_signal_autoconnect (gla);
+
+	priv->tr_store = gtk_tree_store_new (OBJS_TREE_COLS,
+	                               G_TYPE_STRING,
+	                               G_TYPE_INT,
+	                               G_TYPE_POINTER,
+	                               G_TYPE_POINTER);
+
+	gtk_tree_view_set_model (GTK_TREE_VIEW (priv->tr_objects), GTK_TREE_MODEL (priv->tr_store));
+
+	renderer = gtk_cell_renderer_text_new ();
+	column = gtk_tree_view_column_new_with_attributes ("Objects",
+	                                                   renderer,
+	                                                   "text", OBJS_TREE_COL_NAME,
+	                                                   NULL);
+	gtk_tree_view_append_column (GTK_TREE_VIEW (priv->tr_objects), column);
+
+	priv->selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->tr_objects));
+
+	grpt_objects_tree_set_canvas (obj_tree, canvas);
+
+	gtk_widget_show_all (priv->w_tree);
+
+	return obj_tree;
+}
+
 void
-objects_tree_fill_tree (RptReport *rpt_report)
+grpt_objects_tree_set_canvas (GRptObjectsTree *grpt_objects_tree, GRptCanvas *canvas)
 {
 	GList *objects;
 
-	if (w_tree == NULL) return;
+	if (!GRPT_IS_OBJECTS_TREE (grpt_objects_tree)) return;
+	if (!GRPT_IS_CANVAS (canvas)) return;
 
-	if (rpt_report != NULL)
-		{
-			rpt_report_ = rpt_report;
-		}
+	GRptObjectsTreePrivate *priv = GRPT_OBJECTS_TREE_GET_PRIVATE (grpt_objects_tree);
+
+	if (priv->w_tree == NULL) return;
 
-	gtk_tree_store_clear (tr_store);
+	priv->canvas = canvas;
 
-	objects = rpt_report_section_get_objects (rpt_report_, RPTREPORT_SECTION_REPORT_HEADER);
+	gtk_tree_store_clear (priv->tr_store);
+
+	objects = grpt_canvas_section_get_objects (priv->canvas, RPTREPORT_SECTION_REPORT_HEADER);
 	if (objects != NULL)
 		{
-			objects_tree_fill_tree_section (RPTREPORT_SECTION_REPORT_HEADER, objects);
+			grpt_objects_tree_fill_tree_section (grpt_objects_tree, RPTREPORT_SECTION_REPORT_HEADER, objects);
 		}
-	objects = rpt_report_section_get_objects (rpt_report_, RPTREPORT_SECTION_PAGE_HEADER);
+	objects = grpt_canvas_section_get_objects (priv->canvas, RPTREPORT_SECTION_PAGE_HEADER);
 	if (objects != NULL)
 		{
-			objects_tree_fill_tree_section (RPTREPORT_SECTION_PAGE_HEADER, objects);
+			grpt_objects_tree_fill_tree_section (grpt_objects_tree, RPTREPORT_SECTION_PAGE_HEADER, objects);
 		}
-	objects = rpt_report_section_get_objects (rpt_report_, RPTREPORT_SECTION_BODY);
+	objects = grpt_canvas_section_get_objects (priv->canvas, RPTREPORT_SECTION_BODY);
 	if (objects != NULL)
 		{
-			objects_tree_fill_tree_section (RPTREPORT_SECTION_BODY, objects);
+			grpt_objects_tree_fill_tree_section (grpt_objects_tree, RPTREPORT_SECTION_BODY, objects);
 		}
-	objects = rpt_report_section_get_objects (rpt_report_, RPTREPORT_SECTION_REPORT_FOOTER);
+	objects = grpt_canvas_section_get_objects (priv->canvas, RPTREPORT_SECTION_REPORT_FOOTER);
 	if (objects != NULL)
 		{
-			objects_tree_fill_tree_section (RPTREPORT_SECTION_REPORT_FOOTER, objects);
+			grpt_objects_tree_fill_tree_section (grpt_objects_tree, RPTREPORT_SECTION_REPORT_FOOTER, objects);
 		}
-	objects = rpt_report_section_get_objects (rpt_report_, RPTREPORT_SECTION_PAGE_FOOTER);
+	objects = grpt_canvas_section_get_objects (priv->canvas, RPTREPORT_SECTION_PAGE_FOOTER);
 	if (objects != NULL)
 		{
-			objects_tree_fill_tree_section (RPTREPORT_SECTION_PAGE_FOOTER, objects);
+			grpt_objects_tree_fill_tree_section (grpt_objects_tree, RPTREPORT_SECTION_PAGE_FOOTER, objects);
 		}
 }
 
 void
-objects_tree (RptReport *rpt_report)
+grpt_objects_tree_destroy (GRptObjectsTree *grpt_objects_tree)
 {
-	GtkTreeViewColumn *column;
-	GtkCellRenderer *renderer;
+	GRptObjectsTreePrivate *priv = GRPT_OBJECTS_TREE_GET_PRIVATE (grpt_objects_tree);
 
-	GladeXML *gla = glade_xml_new (GLADEDIR "/greptool.glade", "w_objects_tree", NULL);
-	w_tree = glade_xml_get_widget (gla, "w_objects_tree");
-	tr_objects_tree = glade_xml_get_widget (gla, "tr_objects_tree");
+	gtk_widget_destroy (priv->w_tree);
+	priv->w_tree = NULL;
+}
 
-	rpt_report_ = rpt_report;
+void
+grpt_objects_tree_add_object_to_section (GRptObjectsTree *grpt_objects_tree,
+                                         GRptCanvasItem *grpt_canvas_item,
+                                         RptReportSection section)
+{
+	GtkTreeRowReference *trr;
+	GtkTreePath *path;
+	GtkTreeIter iter;
 
-	glade_xml_signal_autoconnect (gla);
+	if (!GRPT_IS_OBJECTS_TREE (grpt_objects_tree)) return;
 
-	tr_store = gtk_tree_store_new (OBJS_TREE_COLS,
-	                               G_TYPE_STRING,
-	                               G_TYPE_INT,
-	                               G_TYPE_POINTER);
+	GRptObjectsTreePrivate *priv = GRPT_OBJECTS_TREE_GET_PRIVATE (grpt_objects_tree);
 
-	gtk_tree_view_set_model (GTK_TREE_VIEW (tr_objects_tree), GTK_TREE_MODEL (tr_store));
+	grpt_objects_tree_create_tree_section (grpt_objects_tree, section);
 
-	renderer = gtk_cell_renderer_text_new ();
-	column = gtk_tree_view_column_new_with_attributes ("Objects",
-	                                                   renderer,
-	                                                   "text", OBJS_TREE_COL_NAME,
-	                                                   NULL);
-	gtk_tree_view_append_column (GTK_TREE_VIEW (tr_objects_tree), column);
+	switch (section)
+		{
+			case RPTREPORT_SECTION_BODY:
+				trr = priv->trr_body;
+				break;
+		}
 
-	selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tr_objects_tree));
+	path = gtk_tree_row_reference_get_path (trr);
+	if (gtk_tree_model_get_iter (GTK_TREE_MODEL (priv->tr_store), &iter, path))
+		{
+			GtkTreeIter iter_child;
+			RptObject *obj;
+			gchar *name;
 
-	objects_tree_fill_tree (NULL);
+			obj = grpt_canvas_item_get_rpt_object (grpt_canvas_item);
 
-	gtk_widget_show_all (w_tree);
-}
+			g_object_get (obj, "name", &name, NULL);
 
-void
-objects_tree_destroy ()
-{
-	gtk_widget_destroy (w_tree);
-	w_tree = NULL;
+			gtk_tree_store_append (priv->tr_store, &iter_child, &iter);
+			gtk_tree_store_set (priv->tr_store, &iter_child,
+								OBJS_TREE_COL_NAME, name,
+								OBJS_TREE_COL_SECTION, section,
+								OBJS_TREE_COL_GRPT_CANVAS_ITEM, grpt_canvas_item,
+								OBJS_TREE_COL_RPT_OBJECT, obj,
+								-1);
+		}
 }