[dia/dia-next: 56/59] Tools as GObjects



commit dd69cf1a8d1970857abb1c0864910eb06e311c9e
Author: Zander Brown <zbrown gnome org>
Date:   Tue Jan 8 19:49:27 2019 +0000

    Tools as GObjects
    
    Makes the code a little cleaner, may come in useful later

 app/app_procs.c           | 131 ++++++++---------
 app/disp_callbacks.c      |  84 +++++------
 app/menus.c               |  24 +--
 app/toolbox.c             |  29 ++--
 app/toolbox.h             |   8 +-
 app/tools/create_object.c | 359 ++++++++++++++++++++++++++++-----------------
 app/tools/create_object.h |  15 +-
 app/tools/magnify.c       | 102 +++++++------
 app/tools/magnify.h       |   9 +-
 app/tools/modify_tool.c   | 361 ++++++++++++++++++++++++----------------------
 app/tools/modify_tool.h   |   6 +-
 app/tools/scroll_tool.c   | 160 +++++++++++---------
 app/tools/scroll_tool.h   |  10 +-
 app/tools/textedit_tool.c | 119 ++++++++-------
 app/tools/textedit_tool.h |  10 +-
 app/tools/tool.c          | 269 ++++++++++++++++++++++++----------
 app/tools/tool.h          |  64 ++++----
 lib/diatypes.h            |   4 -
 18 files changed, 1008 insertions(+), 756 deletions(-)
---
diff --git a/app/app_procs.c b/app/app_procs.c
index 82b2b6e1..134122e1 100644
--- a/app/app_procs.c
+++ b/app/app_procs.c
@@ -668,69 +668,70 @@ app_init (int argc, char **argv)
 
     if (!g_option_context_parse (context, &argc, &argv, &error)) {
       if (error) { /* IMO !error here is a bug upstream, triggered e.g. with --gdk-debug=updates */
-       g_print ("%s", error->message);
-       g_error_free (error);
+        g_print ("%s", error->message);
+        g_error_free (error);
       } else {
-       g_print (_("Invalid option?"));
+        g_print (_("Invalid option?"));
       }
 
       g_option_context_free(context);
       exit(1);
     }
+
     /* second level check of command line options, existance of input files etc. */
     if (filenames) {
       while (filenames[i] != NULL) {
-       gchar *filename; 
-       gchar *testpath;          
-
-       if (g_str_has_prefix (filenames[i], "file://")) {
-         filename = g_filename_from_uri (filenames[i], NULL, NULL);
-         if (!g_utf8_validate(filename, -1, NULL)) {
-           gchar *tfn = filename;
-           filename = g_filename_to_utf8(filename, -1, NULL, NULL, NULL);
-           g_free(tfn);
-         }
-       } else
-         filename = g_filename_to_utf8 (filenames[i], -1, NULL, NULL, NULL);
-
-       if (!filename) {
-         g_print (_("Filename conversion failed: %s\n"), filenames[i]);
-         continue;
-       }
-
-       if (g_path_is_absolute(filename))
-         testpath = filename;
-       else
-         testpath = g_build_filename(input_directory ? input_directory : ".", filename, NULL);
-
-       /* we still have a problem here, if GLib's file name encoding would not be utf-8 */
-       if (g_file_test (testpath, G_FILE_TEST_IS_REGULAR))
-         files = g_slist_append(files, filename);
-       else {
-         g_print (_("Missing input: %s\n"), filename);
-         g_free (filename);
-       }
-       if (filename != testpath)
-         g_free (testpath);
-       ++i;
+        gchar *filename;
+        gchar *testpath;
+        
+        if (g_str_has_prefix (filenames[i], "file://")) {
+          filename = g_filename_from_uri (filenames[i], NULL, NULL);
+          if (!g_utf8_validate(filename, -1, NULL)) {
+            gchar *tfn = filename;
+            filename = g_filename_to_utf8(filename, -1, NULL, NULL, NULL);
+            g_free(tfn);
+          }
+        } else {
+          filename = g_filename_to_utf8 (filenames[i], -1, NULL, NULL, NULL);
+        }
+        if (!filename) {
+          g_print (_("Filename conversion failed: %s\n"), filenames[i]);
+          continue;
+        }
+        
+        if (g_path_is_absolute(filename))
+          testpath = filename;
+        else
+          testpath = g_build_filename(input_directory ? input_directory : ".", filename, NULL);
+          
+        /* we still have a problem here, if GLib's file name encoding would not be utf-8 */
+        if (g_file_test (testpath, G_FILE_TEST_IS_REGULAR)) {
+          files = g_slist_append(files, filename);
+        } else {
+          g_print (_("Missing input: %s\n"), filename);
+          g_free (filename);
+        }
+        
+        if (filename != testpath)
+          g_free (testpath);
+        ++i;
       }
     }
+
     /* given some files to output (or something;)), we are not starting up the UI */
     if (export_file_name || export_file_format || size || credits || version || list_filters)
       dia_is_interactive = FALSE;
-
   }
 
   if (argv && dia_is_interactive) {
-    gtk_init(&argc, &argv);
-  }
-  else {
+    gtk_init (&argc, &argv);
+  } else {
     /*
      * On Windows there is no command line without display so that gtk_init is harmless. 
      * On X11 we need gtk_init_check() to avoid exit() just because there is no display 
      * running outside of X11.
      */
-    if (!gtk_init_check(&argc, &argv))
+    if (!gtk_init_check (&argc, &argv))
       dia_log_message ("Running without display");
   }
 
@@ -739,14 +740,14 @@ app_init (int argc, char **argv)
     gchar *ver_locale;
 #if (defined __TIME__) && (defined __DATE__)
     /* TRANSLATOR: 2nd and 3rd %s are time and date respectively. */
-    ver_utf8 = g_strdup_printf(_("Dia version %s, compiled %s %s\n"), VERSION, __TIME__, __DATE__);
+    ver_utf8 = g_strdup_printf (_("Dia version %s, compiled %s %s\n"), VERSION, __TIME__, __DATE__);
 #else
-    ver_utf8 = g_strdup_printf(_("Dia version %s\n"), VERSION);
+    ver_utf8 = g_strdup_printf (_("Dia version %s\n"), VERSION);
 #endif
-    ver_locale = g_locale_from_utf8(ver_utf8, -1, NULL, NULL, NULL);
-    printf("%s\n", ver_locale);
-    g_free(ver_locale);
-    g_free(ver_utf8);
+    ver_locale = g_locale_from_utf8 (ver_utf8, -1, NULL, NULL, NULL);
+    g_printf ("%s\n", ver_locale);
+    g_free (ver_locale);
+    g_free (ver_utf8);
     if (verbose)
       dump_dependencies();
     exit(0);
@@ -755,9 +756,9 @@ app_init (int argc, char **argv)
   if (!dia_is_interactive)
     log_to_stderr = TRUE;
 
-  libdia_init (   (dia_is_interactive ? DIA_INTERACTIVE : 0)
-              | (log_to_stderr ? DIA_MESSAGE_STDERR : 0)
-              | (verbose ? DIA_VERBOSE : 0) );
+  libdia_init (  (dia_is_interactive ? DIA_INTERACTIVE : 0)
+               | (log_to_stderr ? DIA_MESSAGE_STDERR : 0)
+               | (verbose ? DIA_VERBOSE : 0) );
 
   if (credits) {
     print_credits();
@@ -768,22 +769,22 @@ app_init (int argc, char **argv)
     create_user_dirs();
 
     if (!nosplash)
-      app_splash_init("");
+      app_splash_init ("");
 
     /* Init cursors: */
-    default_cursor = gdk_cursor_new(GDK_LEFT_PTR);
-    ddisplay_set_all_cursor(default_cursor);
+    default_cursor = gdk_cursor_new (GDK_LEFT_PTR);
+    ddisplay_set_all_cursor (default_cursor);
   }
 
-  dia_register_plugins();
-  dia_register_builtin_plugin(internal_plugin_init);
+  dia_register_plugins ();
+  dia_register_builtin_plugin (internal_plugin_init);
 
   if (list_filters) {
     print_filters_list (verbose);
     exit (0);
   }
 
-  load_all_sheets();     /* new mechanism */
+  load_all_sheets ();     /* new mechanism */
 
   dia_log_message ("object defaults");
   {
@@ -793,11 +794,11 @@ app_init (int argc, char **argv)
   }
   debug_break();
 
-  if (object_get_type("Standard - Box") == NULL) {
-    message_error(_("Couldn't find standard objects when looking for "
-                 "object-libs; exiting...\n"));
-    g_critical( _("Couldn't find standard objects when looking for "
-           "object-libs in '%s'; exiting...\n"), dia_get_lib_directory("dia"));
+  if (object_get_type ("Standard - Box") == NULL) {
+    message_error (_("Couldn't find standard objects when looking for "
+                    "object-libs; exiting...\n"));
+    g_critical (_("Couldn't find standard objects when looking for "
+                  "object-libs in '%s'; exiting...\n"), dia_get_lib_directory("dia"));
     exit(1);
   }
 
@@ -809,7 +810,7 @@ app_init (int argc, char **argv)
   if (dia_is_interactive) {
 
     /* further initialization *before* reading files */  
-    active_tool = create_modify_tool();
+    active_tool = g_object_new (DIA_TYPE_MODIFY_TOOL, NULL);
 
     dia_log_message ("ui creation");
     if (use_integrated_ui) {
@@ -838,9 +839,9 @@ app_init (int argc, char **argv)
   }
 
   dia_log_message ("diagrams");
-  made_conversions = handle_all_diagrams(files, export_file_name,
-                                        export_file_format, size, show_layers,
-                                        input_directory, output_directory);
+  made_conversions = handle_all_diagrams (files, export_file_name,
+                                          export_file_format, size, show_layers,
+                                          input_directory, output_directory);
 
   if (dia_is_interactive && files == NULL && !nonew) {
     if (use_integrated_ui) {
diff --git a/app/disp_callbacks.c b/app/disp_callbacks.c
index b18dd7e2..50c69216 100644
--- a/app/disp_callbacks.c
+++ b/app/disp_callbacks.c
@@ -40,6 +40,7 @@
 #include "diamenu.h"
 #include "preferences.h"
 #include "tools/scroll_tool.h"
+#include "tools/textedit_tool.h"
 #include "commands.h"
 #include "textedit.h"
 #include "lib/parent.h"
@@ -689,8 +690,7 @@ hold_remove_handler(void)
 static gboolean 
 hold_timeout_handler(gpointer data) 
 {
-  if (active_tool->button_hold_func)
-    (*active_tool->button_hold_func) (active_tool, (GdkEventButton *)(hold_data.event), hold_data.ddisp);
+  dia_tool_button_hold (active_tool, (GdkEventButton *)(hold_data.event), hold_data.ddisp);
   hold_remove_handler();
   return FALSE;
 }
@@ -785,8 +785,7 @@ ddisplay_canvas_events (GtkWidget *canvas,
             case 1:
               if (transient_tool)
                 break;
-              if (active_tool->double_click_func)
-                (*active_tool->double_click_func) (active_tool, bevent, ddisp);
+              dia_tool_double_click (active_tool, bevent, ddisp);
               break;
 
             case 2:
@@ -812,10 +811,9 @@ ddisplay_canvas_events (GtkWidget *canvas,
               if (transient_tool)
                 break;
                   /* get the focus again, may be lost by zoom combo */
-             moving = TRUE;
-              gtk_widget_grab_focus(canvas);
-              if (active_tool->button_press_func)
-                (*active_tool->button_press_func) (active_tool, bevent, ddisp);
+              moving = TRUE;
+              gtk_widget_grab_focus (canvas);
+              dia_tool_button_press (active_tool, bevent, ddisp);
 
              /* Detect user holding down the button.
               * Set timeout for 1sec. If timeout is called, user must still
@@ -827,12 +825,11 @@ ddisplay_canvas_events (GtkWidget *canvas,
             case 2:
               if (ddisp->menu_bar == NULL && !is_integrated_ui()) {
                 popup_object_menu(ddisp, event);
+              } else if (!transient_tool) {
+                gtk_widget_grab_focus(canvas);
+                transient_tool = g_object_new (DIA_TYPE_SCROLL_TOOL, NULL);
+                dia_tool_button_press (transient_tool, bevent, ddisp);
               }
-             else if (!transient_tool) {
-               gtk_widget_grab_focus(canvas);
-               transient_tool = create_scroll_tool();
-               (*transient_tool->button_press_func) (transient_tool, bevent, ddisp);
-             }
               break;
 
             case 3:
@@ -860,33 +857,28 @@ ddisplay_canvas_events (GtkWidget *canvas,
         display_set_active(ddisp);
         bevent = (GdkEventButton *) event;
 
-        switch (bevent->button)
-        {
-            case 1:
-             if (moving)
-               moving = FALSE;               
-              if (active_tool->button_release_func)
-                (*active_tool->button_release_func) (active_tool,
-                                                     bevent, ddisp);
-             /* Button Press and Hold - remove handler then deallocate memory */
-             hold_remove_handler();
-              break;
-
-            case 2:
-             if (transient_tool) {
-               (*transient_tool->button_release_func) (transient_tool,
-                                                    bevent, ddisp);
-                                                               
-               tool_free(transient_tool);
-               transient_tool = NULL;
-             }
-              break;
-
-            case 3:
-              break;
-
-            default:
-              break;
+        switch (bevent->button) {
+          case 1:
+            if (moving)
+              moving = FALSE;
+            dia_tool_button_release (active_tool, bevent, ddisp);
+            /* Button Press and Hold - remove handler then deallocate memory */
+            hold_remove_handler();
+            break;
+
+          case 2:
+            if (transient_tool) {
+              dia_tool_button_release (transient_tool, bevent, ddisp);
+              dia_tool_deactivate (transient_tool);
+              transient_tool = NULL;
+            }
+            break;
+
+          case 3:
+            break;
+
+          default:
+            break;
         }
         break;
 
@@ -903,10 +895,10 @@ ddisplay_canvas_events (GtkWidget *canvas,
           mevent->state = tmask;
           mevent->is_hint = FALSE;
         }
-        if (transient_tool && (*transient_tool->motion_func)) 
-          (*transient_tool->motion_func) (transient_tool, mevent, ddisp);
-        else if (active_tool->motion_func)
-          (*active_tool->motion_func) (active_tool, mevent, ddisp);
+        if (transient_tool) 
+          dia_tool_motion (transient_tool, mevent, ddisp);
+        else
+          dia_tool_motion (active_tool, mevent, ddisp);
         break;
 
       case GDK_KEY_PRESS:
@@ -1022,7 +1014,7 @@ ddisplay_canvas_events (GtkWidget *canvas,
                 break;
               case GDK_KEY_Shift_L:
               case GDK_KEY_Shift_R:
-                if (active_tool->type == MAGNIFY_TOOL)
+                if (DIA_IS_MAGNIFY_TOOL (active_tool))
                   set_zoom_out(active_tool);
                 break;
               case GDK_KEY_Escape:
@@ -1059,7 +1051,7 @@ ddisplay_canvas_events (GtkWidget *canvas,
           switch(kevent->keyval) {
               case GDK_KEY_Shift_L:
               case GDK_KEY_Shift_R:
-                if (active_tool->type == MAGNIFY_TOOL)
+                if (DIA_IS_MAGNIFY_TOOL (active_tool))
                   set_zoom_in(active_tool);
                 break;
               default:
diff --git a/app/menus.c b/app/menus.c
index 40d9cca5..4e0e8fbf 100644
--- a/app/menus.c
+++ b/app/menus.c
@@ -626,7 +626,6 @@ create_integrated_ui_toolbar (void)
 static GtkActionGroup *
 create_or_ref_tool_actions (void)
 {
-  GtkIconFactory *icon_factory;
   GtkActionGroup *actions;
   GtkAction      *action;
   int           i;
@@ -638,36 +637,23 @@ create_or_ref_tool_actions (void)
   gtk_action_group_set_translation_domain (actions, NULL);
   gtk_action_group_set_translate_func (actions, _dia_translate, NULL, NULL);
 
-  gtk_action_group_add_actions (actions, tool_entries, 
-                               G_N_ELEMENTS (tool_entries), NULL);
-
-  icon_factory = gtk_icon_factory_new ();
+  gtk_action_group_add_actions (actions,
+                                tool_entries,
+                                G_N_ELEMENTS (tool_entries), NULL);
 
   for (i = 0; i < num_tools; i++) {
     action = gtk_action_group_get_action (actions, tool_data[i].action_name);
     if (action != NULL) {
       g_signal_connect (G_OBJECT (action), "activate",
-                       G_CALLBACK (tool_menu_select),
-                       &tool_data[i].callback_data);
+                        G_CALLBACK (tool_menu_select),
+                        &tool_data[i].callback_data);
 
       gtk_action_set_tooltip (action, tool_data[i].tool_desc);
-
-      {
-        GdkPixbuf *pb = tool_get_pixbuf (&tool_data[i]);
-       GtkIconSet *is = gtk_icon_set_new_from_pixbuf (pb);
-
-       /* not sure if the action name is unique enough */
-       gtk_icon_factory_add (icon_factory, tool_data[i].action_name, is);
-       gtk_action_set_stock_id (action, tool_data[i].action_name);
-
-       g_object_unref (pb);
-      }
     }
     else {
       g_warning ("couldn't find tool menu item %s", tool_data[i].action_name);
     }
   }
-  gtk_icon_factory_add_default (icon_factory);
   return actions;
 }
 
diff --git a/app/toolbox.c b/app/toolbox.c
index 4306d699..62eaf047 100644
--- a/app/toolbox.c
+++ b/app/toolbox.c
@@ -38,6 +38,12 @@
 
 #include "pixmaps/missing.xpm"
 
+#include "tools/textedit_tool.h"
+#include "tools/create_object.h"
+#include "tools/magnify.h"
+#include "tools/modify_tool.h"
+#include "tools/scroll_tool.h"
+
 #include <gdk-pixbuf/gdk-pixbuf.h>
 #include "dia-app-icons.h"
 
@@ -329,7 +335,7 @@ fill_sheet_wbox (DiaToolbox *self, DiaSheet *sheet)
   }
   /* If the selection is in the old sheet, steal it */
   if (active_tool != NULL &&
-      active_tool->type == CREATE_OBJECT_TOOL &&
+      DIA_IS_CREATE_TOOL (active_tool) &&
       first_button != NULL)
     g_signal_emit_by_name(G_OBJECT(first_button), "toggled",
                          GTK_BUTTON(first_button), NULL);
@@ -455,7 +461,7 @@ change_end_arrow_style (DiaArrowChooser *chooser, gpointer user_data)
 }
 
 static void
-change_line_style(DiaLineStyleSelector *selector, gpointer user_data)
+change_line_style(DiaLineChooser *selector, gpointer user_data)
 {
   LineStyle lstyle;
   real dash_length;
@@ -551,14 +557,18 @@ tool_get_pixbuf (ToolButton *tb)
     
     type = object_get_type((char *)tb->callback_data.extra_data);
     if (type == NULL)
-      icon_data = tool_data[0].icon_data;
+      icon_data = NULL;
     else
       icon_data = type->pixmap;
   } else {
     icon_data = tb->icon_data;
   }
   
-  if (strncmp((char*)icon_data, "GdkP", 4) == 0) {
+  if (icon_data == NULL) {
+    pixbuf = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (),
+                                       "image-missing", 22,
+                                       0, NULL);
+  } else if (strncmp((char*)icon_data, "GdkP", 4) == 0) {
     pixbuf = gdk_pixbuf_new_from_inline(-1, (guint8*)icon_data, TRUE, NULL);
   } else {
     const char **pixmap_data = icon_data;
@@ -609,17 +619,6 @@ create_tools (DiaToolbox *self)
     tool_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (button));
     gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (button), FALSE);
 
-/*
-
-  0     1     2     3 
-  0, 0  0, 1  0, 2  0, 3
-  4     5     6     7 
-  1, 0  1, 1  1, 2  1, 3
-  8     9     10    11
-  2, 0  2, 1  2, 2  2, 3
-
-*/
-
     gtk_grid_attach (GTK_GRID (self->tools), button, i % COLUMNS, i / COLUMNS, 1, 1);
 
     if (tool_data[i].callback_data.type == MODIFY_TOOL) {
diff --git a/app/toolbox.h b/app/toolbox.h
index 55b418bd..3ca8bfbb 100644
--- a/app/toolbox.h
+++ b/app/toolbox.h
@@ -1,4 +1,5 @@
 #include "tools/tool.h"
+#include "tools/create_object.h"
 
 G_BEGIN_DECLS
 
@@ -19,7 +20,7 @@ typedef struct _ToolButtonData ToolButtonData;
 
 struct _ToolButtonData
 {
-  ToolType type;
+  GType    type;
   gpointer extra_data;
   gpointer user_data; /* Used by create_object_tool */
   GtkWidget *widget;
@@ -39,12 +40,11 @@ extern ToolButton tool_data[];
 extern gchar *interface_current_sheet_name;
 
 void tool_select_update (GtkWidget *w, gpointer   data);
-GdkPixbuf *tool_get_pixbuf (ToolButton *tb);
 
 void toolbox_setup_drag_dest (GtkWidget *canvas);
 void canvas_setup_drag_dest (GtkWidget *canvas);
 
-GtkWidget *dia_toolbox_new           ();
+GtkWidget *dia_toolbox_new           (void);
 void       dia_toolbox_update_sheets (DiaToolbox *self);
 
-G_END_DECLS
\ No newline at end of file
+G_END_DECLS
diff --git a/app/tools/create_object.c b/app/tools/create_object.c
index 6804123b..1c38b334 100644
--- a/app/tools/create_object.c
+++ b/app/tools/create_object.c
@@ -32,54 +32,171 @@
 #include "intl.h"
 #include "menus.h"
 
-static void create_object_button_press(CreateObjectTool *tool, GdkEventButton *event,
-                                    DDisplay *ddisp);
-static void create_object_button_release(CreateObjectTool *tool, GdkEventButton *event,
-                                      DDisplay *ddisp);
-static void create_object_motion(CreateObjectTool *tool, GdkEventMotion *event,
-                                DDisplay *ddisp);
-static void create_object_double_click(CreateObjectTool *tool, GdkEventMotion *event,
-                                      DDisplay *ddisp);
+static void create_button_press   (DiaTool        *tool,
+                                   GdkEventButton *event,
+                                   DDisplayBox    *ddisp);
+static void create_button_release (DiaTool        *tool,
+                                   GdkEventButton *event,
+                                   DDisplayBox    *ddisp);
+static void create_motion         (DiaTool        *tool,
+                                   GdkEventMotion *event,
+                                   DDisplayBox    *ddisp);
+static void create_double_click   (DiaTool        *tool,
+                                   GdkEventButton *event,
+                                   DDisplayBox    *ddisp);
+
+G_DEFINE_TYPE (DiaCreateTool, dia_create_tool, DIA_TYPE_TOOL)
+
+enum {
+  PROP_INVERT_PERSISTENCE = 1,
+  N_PROPS
+};
+static GParamSpec* properties[N_PROPS];
 
+static void
+activate (DiaTool *tool)
+{
+  DiaCreateTool *self = DIA_CREATE_TOOL (tool);
+
+  self->moving = FALSE;
+
+  ddisplay_set_all_cursor (get_cursor (CURSOR_CREATE));
+}
+
+static void
+deactivate (DiaTool *tool)
+{
+  DiaCreateTool *real_tool = DIA_CREATE_TOOL (tool);
+
+  if (real_tool->moving) { /* should not get here, but see bug #619246 */
+    gdk_pointer_ungrab (GDK_CURRENT_TIME);
+    ddisplay_set_all_cursor (default_cursor);
+  }
+}
+
+static void
+dia_create_tool_set_property (GObject      *object,
+                              guint         property_id,
+                              const GValue *value,
+                              GParamSpec   *pspec)
+{
+  DiaCreateTool *self = DIA_CREATE_TOOL (object);
+
+  switch (property_id) {
+    case PROP_INVERT_PERSISTENCE:
+      self->invert_persistence = g_value_get_boolean (value);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+      break;
+  }
+}
+
+static void
+dia_create_tool_get_property (GObject    *object,
+                              guint       property_id,
+                              GValue     *value,
+                              GParamSpec *pspec)
+{
+  DiaCreateTool *self = DIA_CREATE_TOOL (object);
+
+  switch (property_id) {
+    case PROP_INVERT_PERSISTENCE:
+      g_value_set_boolean (value, self->invert_persistence);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+      break;
+  }
+}
+
+static void
+dia_create_tool_class_init (DiaCreateToolClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  DiaToolClass *tool_class = DIA_TOOL_CLASS (klass);
+
+  object_class->set_property = dia_create_tool_set_property;
+  object_class->get_property = dia_create_tool_get_property;
+
+  properties[PROP_INVERT_PERSISTENCE] = g_param_spec_boolean ("invert-persistence",
+                                                              NULL, NULL,
+                                                              FALSE,
+                                                              G_PARAM_READWRITE);
+
+  g_object_class_install_properties (object_class,
+                                     N_PROPS,
+                                     properties);
+
+  tool_class->activate = activate;
+  tool_class->deactivate = deactivate;
+
+  tool_class->button_press = create_button_press;
+  tool_class->button_release = create_button_release;
+  tool_class->motion = create_motion;
+  tool_class->double_click = create_double_click;
+}
+
+static void
+dia_create_tool_init (DiaCreateTool *self)
+{
+}
+
+DiaTool *
+dia_create_tool_new (DiaObjectType *objtype,
+                     gboolean       invert_persistence,
+                     void          *user_data)
+{
+  DiaCreateTool *self = g_object_new (DIA_TYPE_CREATE_TOOL,
+                                      "invert-persistence", invert_persistence);
+
+  /* TODO: As properties */
+  self->objtype = objtype;
+  self->user_data = user_data;
+
+  return DIA_TOOL (self);
+}
 
 static void
-create_object_button_press(CreateObjectTool *tool, GdkEventButton *event,
-                          DDisplay *ddisp)
+create_button_press (DiaTool        *tool,
+                     GdkEventButton *event,
+                     DDisplayBox    *ddisp)
 {
+  DiaCreateTool *self = DIA_CREATE_TOOL (tool);
   Point clickedpoint, origpoint;
   Handle *handle1;
   Handle *handle2;
   DiaObject *obj;
 
-  ddisplay_untransform_coords(ddisp,
-                             (int)event->x, (int)event->y,
-                             &clickedpoint.x, &clickedpoint.y);
+  ddisplay_untransform_coords (ddisp->ddisp,
+                               (int)event->x, (int)event->y,
+                               &clickedpoint.x, &clickedpoint.y);
 
   origpoint = clickedpoint;
 
-  snap_to_grid(ddisp, &clickedpoint.x, &clickedpoint.y);
+  snap_to_grid (ddisp->ddisp, &clickedpoint.x, &clickedpoint.y);
 
-  obj = dia_object_default_create (tool->objtype, &clickedpoint,
-                                   tool->user_data,
+  obj = dia_object_default_create (self->objtype, &clickedpoint,
+                                   self->user_data,
                                    &handle1, &handle2);
 
-  tool->obj = obj; /* ensure that tool->obj is initialised in case we
+  self->obj = obj; /* ensure that tool->obj is initialised in case we
                      return early. */
   if (!obj) {
-    tool->moving = FALSE;
-    tool->handle = NULL;
-    message_error(_("'%s' creation failed"), tool->objtype ? tool->objtype->name : "NULL");
+    self->moving = FALSE;
+    self->handle = NULL;
+    message_error(_("'%s' creation failed"), self->objtype ? self->objtype->name : "NULL");
     return;
   }
 
-  diagram_add_object(ddisp->diagram, obj);
+  diagram_add_object (ddisp->ddisp->diagram, obj);
 
   /* Try a connect */
   if (handle1 != NULL &&
       handle1->connect_type != HANDLE_NONCONNECTABLE) {
     ConnectionPoint *connectionpoint;
-    connectionpoint =
-      object_find_connectpoint_display(ddisp, &origpoint, obj, TRUE);
+    connectionpoint = object_find_connectpoint_display (ddisp->ddisp,
+                                                        &origpoint, obj, TRUE);
     if (connectionpoint != NULL) {
       (obj->ops->move)(obj, &origpoint);
     }
@@ -87,48 +204,51 @@ create_object_button_press(CreateObjectTool *tool, GdkEventButton *event,
   
   if (!(event->state & GDK_SHIFT_MASK)) {
     /* Not Multi-select => remove current selection */
-    diagram_remove_all_selected(ddisp->diagram, TRUE);
+    diagram_remove_all_selected (ddisp->ddisp->diagram, TRUE);
   }
-  diagram_select(ddisp->diagram, obj);
+  diagram_select (ddisp->ddisp->diagram, obj);
 
   /* Connect first handle if possible: */
   if ((handle1!= NULL) &&
       (handle1->connect_type != HANDLE_NONCONNECTABLE)) {
-    object_connect_display(ddisp, obj, handle1, TRUE);
+    object_connect_display (ddisp->ddisp, obj, handle1, TRUE);
   }
 
-  object_add_updates(obj, ddisp->diagram);
-  ddisplay_do_update_menu_sensitivity(ddisp);
-  diagram_flush(ddisp->diagram);
+  object_add_updates (obj, ddisp->ddisp->diagram);
+  ddisplay_do_update_menu_sensitivity (ddisp->ddisp);
+  diagram_flush (ddisp->ddisp->diagram);
   
   if (handle2 != NULL) {
-    tool->handle = handle2;
-    tool->moving = TRUE;
-    tool->last_to = handle2->pos;
+    self->handle = handle2;
+    self->moving = TRUE;
+    self->last_to = handle2->pos;
     
-    gdk_pointer_grab (gtk_widget_get_window(ddisp->canvas), FALSE,
+    gdk_pointer_grab (gtk_widget_get_window (ddisp->ddisp->canvas), FALSE,
                      GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON1_MOTION_MASK | GDK_BUTTON_RELEASE_MASK,
                      NULL, NULL, event->time);
-    ddisplay_set_all_cursor(get_cursor(CURSOR_SCROLL));
+    ddisplay_set_all_cursor (get_cursor (CURSOR_SCROLL));
   } else {
-    diagram_update_extents(ddisp->diagram);
-    tool->moving = FALSE;
+    diagram_update_extents (ddisp->ddisp->diagram);
+    self->moving = FALSE;
   }
 
 }
 
 static void
-create_object_double_click(CreateObjectTool *tool, GdkEventMotion *event,
-                          DDisplay *ddisp)
+create_double_click (DiaTool        *tool,
+                     GdkEventButton *event,
+                     DDisplayBox    *ddisp)
 {
 }
 
 static void
-create_object_button_release(CreateObjectTool *tool, GdkEventButton *event,
-                            DDisplay *ddisp)
+create_button_release (DiaTool        *tool,
+                       GdkEventButton *event,
+                       DDisplayBox    *ddisp)
 {
+  DiaCreateTool *self = DIA_CREATE_TOOL (tool);
   GList *list = NULL;
-  DiaObject *obj = tool->obj;
+  DiaObject *obj = self->obj;
   gboolean reset;
 
   GList *parent_candidates;
@@ -137,27 +257,28 @@ create_object_button_release(CreateObjectTool *tool, GdkEventButton *event,
   if (!obj) /* not sure if this isn't enough */
     return; /* could be a legal invariant */
 
-  if (tool->moving) {
+  if (self->moving) {
     gdk_pointer_ungrab (event->time);
 
-    object_add_updates(tool->obj, ddisp->diagram);
-    tool->obj->ops->move_handle(tool->obj, tool->handle, &tool->last_to,
-                               NULL, HANDLE_MOVE_CREATE_FINAL, 0);
-    object_add_updates(tool->obj, ddisp->diagram);
-
+    object_add_updates (self->obj, ddisp->ddisp->diagram);
+    self->obj->ops->move_handle (self->obj,
+                                 self->handle,
+                                 &self->last_to,
+                                 NULL,
+                                 HANDLE_MOVE_CREATE_FINAL,
+                                 0);
+    object_add_updates (self->obj, ddisp->ddisp->diagram);
   }
 
-  parent_candidates = 
-    layer_find_objects_containing_rectangle(obj->parent_layer, 
-                                           &obj->bounding_box);
+  parent_candidates = layer_find_objects_containing_rectangle (obj->parent_layer,
+                                                               &obj->bounding_box);
 
   /* whole object must be within another object to parent it */
   for (; parent_candidates != NULL; parent_candidates = g_list_next(parent_candidates)) {
     DiaObject *parent_obj = (DiaObject *) parent_candidates->data;
-    if (obj != parent_obj 
-       && object_within_parent(obj, parent_obj)) {
-      Change *change = undo_parenting(ddisp->diagram, parent_obj, obj, TRUE);
-      (change->apply)(change, ddisp->diagram);
+    if (obj != parent_obj && object_within_parent (obj, parent_obj)) {
+      Change *change = undo_parenting (ddisp->ddisp->diagram, parent_obj, obj, TRUE);
+      (change->apply)(change, ddisp->ddisp->diagram);
       break;
     /*
     obj->parent = parent_obj;
@@ -167,143 +288,109 @@ create_object_button_release(CreateObjectTool *tool, GdkEventButton *event,
   }
   g_list_free(parent_candidates);
 
-  list = g_list_prepend(list, tool->obj);
+  list = g_list_prepend (list, self->obj);
 
-  undo_insert_objects(ddisp->diagram, list, 1); 
+  undo_insert_objects (ddisp->ddisp->diagram, list, 1); 
 
-  if (tool->moving) {
-    if (tool->handle->connect_type != HANDLE_NONCONNECTABLE) {
-      object_connect_display(ddisp, tool->obj, tool->handle, TRUE);
-      diagram_update_connections_selection(ddisp->diagram);
-      diagram_flush(ddisp->diagram);
+  if (self->moving) {
+    if (self->handle->connect_type != HANDLE_NONCONNECTABLE) {
+      object_connect_display (ddisp->ddisp, self->obj, self->handle, TRUE);
+      diagram_update_connections_selection (ddisp->ddisp->diagram);
+      diagram_flush (ddisp->ddisp->diagram);
     }
-    tool->moving = FALSE;
-    tool->handle = NULL;
-    tool->obj = NULL;    
+    self->moving = FALSE;
+    self->handle = NULL;
+    self->obj = NULL;
   }
   
   {
     /* remove position from status bar */
-    GtkStatusbar *statusbar = GTK_STATUSBAR (ddisp->modified_status);
+    GtkStatusbar *statusbar = GTK_STATUSBAR (ddisp->ddisp->modified_status);
     guint context_id = gtk_statusbar_get_context_id (statusbar, "ObjectPos");
     gtk_statusbar_pop (statusbar, context_id);
   }
   
-  highlight_reset_all(ddisp->diagram);
-  reset = prefs.reset_tools_after_create != tool->invert_persistence;
+  highlight_reset_all (ddisp->ddisp->diagram);
+  reset = prefs.reset_tools_after_create != self->invert_persistence;
   /* kind of backward: first starting editing to see if it is possible at all, than GUI reflection */
-  if (textedit_activate_object(ddisp, obj, NULL) && reset) {
+  if (textedit_activate_object (ddisp->ddisp, obj, NULL) && reset) {
     gtk_action_activate (menus_get_action ("ToolsTextedit"));
     reset = FALSE; /* don't switch off textedit below */
   }
-  diagram_update_extents(ddisp->diagram);
-  diagram_modified(ddisp->diagram);
+  diagram_update_extents (ddisp->ddisp->diagram);
+  diagram_modified (ddisp->ddisp->diagram);
 
-  undo_set_transactionpoint(ddisp->diagram->undo);
+  undo_set_transactionpoint (ddisp->ddisp->diagram->undo);
   
   if (reset)
-      tool_reset();
-  ddisplay_set_all_cursor(default_cursor);
-  ddisplay_do_update_menu_sensitivity(ddisp);
+    tool_reset();
+  ddisplay_set_all_cursor (default_cursor);
+  ddisplay_do_update_menu_sensitivity (ddisp->ddisp);
 }
 
 static void
-create_object_motion(CreateObjectTool *tool, GdkEventMotion *event,
-                  DDisplay *ddisp)
+create_motion (DiaTool        *tool,
+               GdkEventMotion *event,
+               DDisplayBox    *ddisp)
 {
+  DiaCreateTool *self = DIA_CREATE_TOOL (tool);
   Point to;
   ConnectionPoint *connectionpoint = NULL;
   gchar *postext;
   GtkStatusbar *statusbar;
   guint context_id;
 
-  if (!tool->moving)
+  if (!self->moving)
     return;
   
-  ddisplay_untransform_coords(ddisp, event->x, event->y, &to.x, &to.y);
+  ddisplay_untransform_coords (ddisp->ddisp, event->x, event->y, &to.x, &to.y);
 
   /* make sure the new object is restricted to its parent */
-  parent_handle_move_out_check(tool->obj, &to);
+  parent_handle_move_out_check(self->obj, &to);
 
   /* Move to ConnectionPoint if near: */
-  if (tool->handle != NULL &&
-      tool->handle->connect_type != HANDLE_NONCONNECTABLE) {
-    connectionpoint =
-      object_find_connectpoint_display(ddisp, &to, tool->obj, TRUE);
+  if (self->handle != NULL &&
+      self->handle->connect_type != HANDLE_NONCONNECTABLE) {
+    connectionpoint = object_find_connectpoint_display (ddisp->ddisp,
+                                                        &to, self->obj, TRUE);
     
     if (connectionpoint != NULL) {
       to = connectionpoint->pos;
-      highlight_object(connectionpoint->object, DIA_HIGHLIGHT_CONNECTIONPOINT, ddisp->diagram);
+      highlight_object(connectionpoint->object, DIA_HIGHLIGHT_CONNECTIONPOINT, ddisp->ddisp->diagram);
       ddisplay_set_all_cursor(get_cursor(CURSOR_CONNECT));
     }
   }
   
   if (connectionpoint == NULL) {
     /* No connectionopoint near, then snap to grid (if enabled) */
-    snap_to_grid(ddisp, &to.x, &to.y);
-    highlight_reset_all(ddisp->diagram);
-    ddisplay_set_all_cursor(get_cursor(CURSOR_SCROLL));
+    snap_to_grid (ddisp->ddisp, &to.x, &to.y);
+    highlight_reset_all (ddisp->ddisp->diagram);
+    ddisplay_set_all_cursor (get_cursor (CURSOR_SCROLL));
   }
       
-  object_add_updates(tool->obj, ddisp->diagram);
-  tool->obj->ops->move_handle(tool->obj, tool->handle, &to, connectionpoint,
-                             HANDLE_MOVE_CREATE, 0);
-  object_add_updates(tool->obj, ddisp->diagram);
+  object_add_updates (self->obj, ddisp->ddisp->diagram);
+  self->obj->ops->move_handle (self->obj, self->handle, &to, connectionpoint,
+                               HANDLE_MOVE_CREATE, 0);
+  object_add_updates (self->obj, ddisp->ddisp->diagram);
 
   /* Put current mouse position in status bar */
-  statusbar = GTK_STATUSBAR (ddisp->modified_status);
+  statusbar = GTK_STATUSBAR (ddisp->ddisp->modified_status);
   context_id = gtk_statusbar_get_context_id (statusbar, "ObjectPos");
     
-  postext = g_strdup_printf("%.3f, %.3f - %.3f, %.3f",
-                           tool->obj->bounding_box.left,
-                           tool->obj->bounding_box.top,
-                           tool->obj->bounding_box.right,
-                           tool->obj->bounding_box.bottom);
-                              
+  postext = g_strdup_printf ("%.3f, %.3f - %.3f, %.3f",
+                             self->obj->bounding_box.left,
+                             self->obj->bounding_box.top,
+                             self->obj->bounding_box.right,
+                             self->obj->bounding_box.bottom);
+
   gtk_statusbar_pop (statusbar, context_id); 
   gtk_statusbar_push (statusbar, context_id, postext);
 
   g_free(postext);
   
-  diagram_flush(ddisp->diagram);
+  diagram_flush (ddisp->ddisp->diagram);
 
-  tool->last_to = to;
+  self->last_to = to;
   
   return;
 }
-
-
-
-Tool *
-create_create_object_tool(DiaObjectType *objtype, void *user_data,
-                         int invert_persistence)
-{
-  CreateObjectTool *tool;
-
-  tool = g_new0(CreateObjectTool, 1);
-  tool->tool.type = CREATE_OBJECT_TOOL;
-  tool->tool.button_press_func = (ButtonPressFunc) &create_object_button_press;
-  tool->tool.button_release_func = (ButtonReleaseFunc) &create_object_button_release;
-  tool->tool.motion_func = (MotionFunc) &create_object_motion;
-  tool->tool.double_click_func = (DoubleClickFunc) &create_object_double_click;
-    
-  tool->objtype = objtype;
-  tool->user_data = user_data;
-  tool->moving = FALSE;
-  tool->invert_persistence = invert_persistence;
-
-  ddisplay_set_all_cursor(get_cursor(CURSOR_CREATE));
-  
-  return (Tool *) tool;
-}
-
-void free_create_object_tool(Tool *tool)
-{
-  CreateObjectTool *real_tool = (CreateObjectTool *)tool;
-
-  if (real_tool->moving) { /* should not get here, but see bug #619246 */
-    gdk_pointer_ungrab (GDK_CURRENT_TIME);
-    ddisplay_set_all_cursor(default_cursor);
-  }
-  g_free(tool);
-}
diff --git a/app/tools/create_object.h b/app/tools/create_object.h
index 9e3500ff..10dcf1b2 100644
--- a/app/tools/create_object.h
+++ b/app/tools/create_object.h
@@ -21,10 +21,12 @@
 #include "geometry.h"
 #include "tool.h"
 
-typedef struct _CreateObjectTool CreateObjectTool;
 
-struct _CreateObjectTool {
-  Tool tool;
+#define DIA_TYPE_CREATE_TOOL (dia_create_tool_get_type ())
+G_DECLARE_FINAL_TYPE (DiaCreateTool, dia_create_tool, DIA, CREATE_TOOL, DiaTool)
+
+struct _DiaCreateTool {
+  DiaTool tool;
 
   DiaObjectType *objtype;
   void *user_data;
@@ -36,8 +38,9 @@ struct _CreateObjectTool {
   int invert_persistence;
 };
 
-
-Tool *create_create_object_tool(DiaObjectType *objtype, void *user_date, int invert_persistence);
-void free_create_object_tool(Tool *tool);
+DiaTool *
+dia_create_tool_new (DiaObjectType *objtype,
+                     gboolean       invert_persistence,
+                     void          *user_data);
 
 #endif /* CREATE_OBJECT_H */
diff --git a/app/tools/magnify.c b/app/tools/magnify.c
index 3eacd50f..2295df5d 100644
--- a/app/tools/magnify.c
+++ b/app/tools/magnify.c
@@ -22,8 +22,9 @@
 #include "magnify.h"
 #include "cursor.h"
 
-struct _MagnifyTool {
-  Tool tool;
+struct _DiaMagnifyTool {
+  DiaTool tool;
+
   int box_active;
   int moved;
   int x, y;
@@ -32,23 +33,29 @@ struct _MagnifyTool {
   gboolean zoom_out;
 };
 
+G_DEFINE_TYPE (DiaMagnifyTool, dia_magnify_tool, DIA_TYPE_TOOL)
+
 static void
-magnify_button_press(MagnifyTool *tool, GdkEventButton *event,
-                    DDisplay *ddisp)
+magnify_button_press (DiaTool        *self,
+                      GdkEventButton *event,
+                      DDisplayBox    *ddisp)
 {
+  DiaMagnifyTool *tool = DIA_MAGNIFY_TOOL (self);
   tool->x = tool->oldx = event->x;
   tool->y = tool->oldy = event->y;
   tool->box_active = TRUE;
   tool->moved = FALSE;
-  gdk_pointer_grab (gtk_widget_get_window(ddisp->canvas), FALSE,
+  gdk_pointer_grab (gtk_widget_get_window(ddisp->ddisp->canvas), FALSE,
                    GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON1_MOTION_MASK | GDK_BUTTON_RELEASE_MASK,
                    NULL, NULL, event->time);
 }
 
 static void
-magnify_button_release(MagnifyTool *tool, GdkEventButton *event,
-                      DDisplay *ddisp)
+magnify_button_release (DiaTool        *self,
+                        GdkEventButton *event,
+                        DDisplayBox    *ddisp)
 {
+  DiaMagnifyTool *tool = DIA_MAGNIFY_TOOL (self);
   Rectangle *visible;
   Point p1, p2, tl;
   real diff;
@@ -57,15 +64,15 @@ magnify_button_release(MagnifyTool *tool, GdkEventButton *event,
 
   tool->box_active = FALSE;
 
-  dia_interactive_renderer_set_selection (ddisp->renderer,
+  dia_interactive_renderer_set_selection (ddisp->ddisp->renderer,
                                           FALSE, 0, 0, 0, 0);
-  ddisplay_flush (ddisp);
+  ddisplay_flush (ddisp->ddisp);
 
 
-  visible = &ddisp->visible;
+  visible = &ddisp->ddisp->visible;
   
-  ddisplay_untransform_coords(ddisp, tool->x, tool->y, &p1.x, &p1.y);
-  ddisplay_untransform_coords(ddisp, event->x, event->y, &p2.x, &p2.y);
+  ddisplay_untransform_coords (ddisp->ddisp, tool->x, tool->y, &p1.x, &p1.y);
+  ddisplay_untransform_coords (ddisp->ddisp, event->x, event->y, &p2.x, &p2.y);
 
   tl.x = MIN(p1.x, p2.x);
   tl.y = MIN(p1.y, p2.y);
@@ -75,8 +82,8 @@ magnify_button_release(MagnifyTool *tool, GdkEventButton *event,
 
   if (tool->moved) {
     if (idiff <= 4) {
-      ddisplay_add_update_all(ddisp);
-      ddisplay_flush(ddisp);
+      ddisplay_add_update_all (ddisp->ddisp);
+      ddisplay_flush (ddisp->ddisp);
     } else if (!(event->state & GDK_CONTROL_MASK)) {
       /* the whole zoom rect should be visible, not just it's square equivalent */
       real fh = fabs(p2.y - p1.y) / (visible->bottom - visible->top);
@@ -84,18 +91,18 @@ magnify_button_release(MagnifyTool *tool, GdkEventButton *event,
       factor = 1.0 / MAX(fh, fw);
       tl.x += (visible->right - visible->left)/(2.0*factor);
       tl.y += (visible->bottom - visible->top)/(2.0*factor);
-      ddisplay_zoom(ddisp, &tl, factor);
+      ddisplay_zoom (ddisp->ddisp, &tl, factor);
     } else {
       factor = diff / (visible->right - visible->left);
       tl.x = tl.x * factor + tl.x;
       tl.y = tl.y * factor + tl.y;
-      ddisplay_zoom(ddisp, &tl, factor);
+      ddisplay_zoom (ddisp->ddisp, &tl, factor);
     }
   } else {
     if (event->state & GDK_SHIFT_MASK)
-      ddisplay_zoom(ddisp, &tl, 0.5);
+      ddisplay_zoom (ddisp->ddisp, &tl, 0.5);
     else
-      ddisplay_zoom(ddisp, &tl, 2.0);
+      ddisplay_zoom (ddisp->ddisp, &tl, 2.0);
   }
 
   gdk_pointer_ungrab (event->time);
@@ -104,9 +111,11 @@ magnify_button_release(MagnifyTool *tool, GdkEventButton *event,
 typedef struct intPoint { int x,y; } intPoint;
 
 static void
-magnify_motion(MagnifyTool *tool, GdkEventMotion *event,
-              DDisplay *ddisp)
+magnify_motion (DiaMagnifyTool *self,
+                GdkEventMotion *event,
+                DDisplayBox    *ddisp)
 {
+  DiaMagnifyTool *tool = DIA_MAGNIFY_TOOL (self);
   intPoint tl, br;
 
   if (tool->box_active) {
@@ -115,50 +124,55 @@ magnify_motion(MagnifyTool *tool, GdkEventMotion *event,
     tl.x = MIN (tool->x, event->x); tl.y = MIN (tool->y, event->y);
     br.x = MAX (tool->x, event->x); br.y = MAX (tool->y, event->y);
 
-    dia_interactive_renderer_set_selection (ddisp->renderer,
+    dia_interactive_renderer_set_selection (ddisp->ddisp->renderer,
                                             TRUE,
                                             tl.x, tl.y, br.x - tl.x, br.y - tl.y);
-    ddisplay_flush (ddisp);
+    ddisplay_flush (ddisp->ddisp);
   }
 }
 
 void
-set_zoom_out(Tool *tool)
+set_zoom_out (DiaTool *tool)
 {
-  ((MagnifyTool *)tool)->zoom_out = TRUE;
+  ((DiaMagnifyTool *)tool)->zoom_out = TRUE;
   ddisplay_set_all_cursor(get_cursor(CURSOR_ZOOM_OUT));
 }
 
 void
-set_zoom_in(Tool *tool)
+set_zoom_in (DiaTool *tool)
 {
-  ((MagnifyTool *)tool)->zoom_out = FALSE;
+  ((DiaMagnifyTool *)tool)->zoom_out = FALSE;
   ddisplay_set_all_cursor(get_cursor(CURSOR_ZOOM_IN));
 }
 
-Tool *
-create_magnify_tool(void)
+static void
+activate (DiaTool *self)
 {
-  MagnifyTool *tool;
-
-  tool = g_new0(MagnifyTool, 1);
-  tool->tool.type = MAGNIFY_TOOL;
-  tool->tool.button_press_func = (ButtonPressFunc) &magnify_button_press;
-  tool->tool.button_release_func = (ButtonPressFunc) &magnify_button_release;
-  tool->tool.motion_func = (MotionFunc) &magnify_motion;
-  tool->tool.double_click_func = NULL;
-
-  tool->box_active = FALSE;
-  tool->zoom_out = FALSE;
+  DIA_MAGNIFY_TOOL (self)->box_active = FALSE;
+  DIA_MAGNIFY_TOOL (self)->zoom_out = FALSE;
 
   ddisplay_set_all_cursor(get_cursor(CURSOR_ZOOM_IN));
-  
-  return (Tool *) tool;
 }
 
-void
-free_magnify_tool(Tool *tool)
+static void
+deactivate (DiaTool *tool)
 {
-  g_free(tool);
   ddisplay_set_all_cursor(default_cursor);
 }
+
+static void
+dia_magnify_tool_class_init (DiaMagnifyToolClass *klass)
+{
+  DiaToolClass *tool_class = DIA_TOOL_CLASS (klass);
+
+  tool_class->activate = activate;
+  tool_class->deactivate = deactivate;
+  tool_class->button_press = magnify_button_press;
+  tool_class->button_release = magnify_button_release;
+  tool_class->motion = magnify_motion;
+}
+
+static void
+dia_magnify_tool_init (DiaMagnifyTool *self)
+{
+}
diff --git a/app/tools/magnify.h b/app/tools/magnify.h
index 6e218a00..0cb3a26c 100644
--- a/app/tools/magnify.h
+++ b/app/tools/magnify.h
@@ -20,11 +20,10 @@
 
 #include "tool.h"
 
-typedef struct _MagnifyTool MagnifyTool;
+#define DIA_TYPE_MAGNIFY_TOOL (dia_magnify_tool_get_type ())
+G_DECLARE_FINAL_TYPE (DiaMagnifyTool, dia_magnify_tool, DIA, MAGNIFY_TOOL, DiaTool)
 
-Tool *create_magnify_tool(void);
-void free_magnify_tool(Tool *tool);
-void set_zoom_out(Tool *tool);
-void set_zoom_in(Tool *tool);
+void set_zoom_out (DiaTool *tool);
+void set_zoom_in (DiaTool *tool);
 
 #endif /* MAGNIFY_H */
diff --git a/app/tools/modify_tool.c b/app/tools/modify_tool.c
index e3c49a2f..a82a93ed 100644
--- a/app/tools/modify_tool.c
+++ b/app/tools/modify_tool.c
@@ -40,25 +40,8 @@
 #include "prop_text.h"
 #include "object.h"
 
-
-static DiaObject *click_select_object(DDisplay *ddisp, Point *clickedpoint,
-                                  GdkEventButton *event);
-static int do_if_clicked_handle(DDisplay *ddisp, ModifyTool *tool,
-                               Point *clickedpoint,
-                               GdkEventButton *event);
-static void modify_button_press(ModifyTool *tool, GdkEventButton *event,
-                                DDisplay *ddisp);
-static void modify_button_hold(ModifyTool *tool, GdkEventButton *event,
-                                DDisplay *ddisp);
-static void modify_button_release(ModifyTool *tool, GdkEventButton *event,
-                                 DDisplay *ddisp);
-static void modify_motion(ModifyTool *tool, GdkEventMotion *event,
-                         DDisplay *ddisp);
-static void modify_double_click(ModifyTool *tool, GdkEventButton *event,
-                               DDisplay *ddisp);
-
-struct _ModifyTool {
-  Tool tool;
+struct _DiaModifyTool {
+  DiaTool tool;
 
   enum ModifyToolState state;
   int break_connections;
@@ -78,26 +61,57 @@ struct _ModifyTool {
   Point *orig_pos;
 };
 
+G_DEFINE_TYPE (DiaModifyTool, dia_modify_tool, DIA_TYPE_TOOL)
+
+static DiaObject *click_select_object(DDisplayBox  *ddisp, Point *clickedpoint,
+                                  GdkEventButton *event);
+static int  do_if_clicked_handle  (DDisplayBox    *ddisp,
+                                   DiaModifyTool  *tool,
+                                   Point          *clickedpoint,
+                                   GdkEventButton *event);
+static void modify_button_press   (DiaTool        *tool,
+                                   GdkEventButton *event,
+                                   DDisplayBox    *ddisp);
+static void modify_button_hold    (DiaTool        *tool,
+                                   GdkEventButton *event,
+                                   DDisplayBox    *ddisp);
+static void modify_button_release (DiaTool        *tool,
+                                   GdkEventButton *event,
+                                   DDisplayBox    *ddisp);
+static void modify_motion         (DiaTool        *tool,
+                                   GdkEventMotion *event,
+                                   DDisplayBox    *ddisp);
+static void modify_double_click   (DiaTool        *tool,
+                                   GdkEventButton *event,
+                                   DDisplayBox    *ddisp);
 
-Tool *
-create_modify_tool(void)
+static void
+activate (DiaTool *self)
 {
-  ModifyTool *tool;
-
-  tool = g_new0(ModifyTool, 1);
-  tool->tool.type = MODIFY_TOOL;
-  tool->tool.button_press_func = (ButtonPressFunc) &modify_button_press;
-  tool->tool.button_hold_func = (ButtonHoldFunc) &modify_button_hold;
-  tool->tool.button_release_func = (ButtonReleaseFunc) &modify_button_release;
-  tool->tool.motion_func = (MotionFunc) &modify_motion;
-  tool->tool.double_click_func = (DoubleClickFunc) &modify_double_click;
-  tool->state = STATE_NONE;
-  tool->break_connections = FALSE;
-  tool->auto_scrolled = FALSE;
+  DIA_MODIFY_TOOL (self)->state = STATE_NONE;
+  DIA_MODIFY_TOOL (self)->break_connections = FALSE;
+  DIA_MODIFY_TOOL (self)->auto_scrolled = FALSE;
 
-  tool->orig_pos = NULL;
-  
-  return (Tool *)tool;
+  DIA_MODIFY_TOOL (self)->orig_pos = NULL;
+}
+
+static void
+dia_modify_tool_class_init (DiaModifyToolClass *klass)
+{
+  DiaToolClass *tool_class = DIA_TOOL_CLASS (klass);
+
+  tool_class->activate = activate;
+
+  tool_class->button_press = modify_button_press;
+  tool_class->button_hold = modify_button_hold;
+  tool_class->button_release = modify_button_release;
+  tool_class->motion = modify_motion;
+  tool_class->double_click = modify_double_click;
+}
+
+static void
+dia_modify_tool_init (DiaModifyTool *self)
+{
 }
 
 static ModifierKeys 
@@ -144,27 +158,19 @@ gdk_event_to_dia_ModifierKeys(guint event_state)
   return mod;
 }
 
-        
-void
-free_modify_tool(Tool *tool)
-{
-  ModifyTool *mtool = (ModifyTool *)tool;
-  g_free(mtool);
-}
-
 static DiaObject *
-click_select_object(DDisplay *ddisp, Point *clickedpoint,
+click_select_object(DDisplayBox  *ddisp, Point *clickedpoint,
                    GdkEventButton *event)
 {
   Diagram *diagram;
   real click_distance;
   DiaObject *obj;
   
-  diagram = ddisp->diagram;
+  diagram = ddisp->ddisp->diagram;
   
   /* Find the closest object to select it: */
 
-  click_distance = ddisplay_untransform_length(ddisp, 3.0);
+  click_distance = ddisplay_untransform_length (ddisp->ddisp, 3.0);
   
   obj = diagram_find_clicked_object(diagram, clickedpoint,
                                    click_distance);
@@ -189,7 +195,7 @@ click_select_object(DDisplay *ddisp, Point *clickedpoint,
         textedit_activate_object(ddisp, obj, clickedpoint);
       */
 
-      ddisplay_do_update_menu_sensitivity(ddisp);
+      ddisplay_do_update_menu_sensitivity (ddisp->ddisp);
       object_add_updates_list(diagram->data->selected, diagram);
       diagram_flush(diagram);
 
@@ -205,9 +211,9 @@ click_select_object(DDisplay *ddisp, Point *clickedpoint,
       
       if (event->state & GDK_SHIFT_MASK) { /* Multi-select */
        /* Remove the selected selected */
-       ddisplay_do_update_menu_sensitivity(ddisp);
+       ddisplay_do_update_menu_sensitivity (ddisp->ddisp);
        diagram_unselect_object(diagram, (DiaObject *)already->data);
-       diagram_flush(ddisp->diagram);
+       diagram_flush(ddisp->ddisp->diagram);
       } else {
        return obj;
       }
@@ -226,21 +232,22 @@ time_micro()
   return tv.tv_sec*G_USEC_PER_SEC+tv.tv_usec;
 }
 
-static int do_if_clicked_handle(DDisplay *ddisp, ModifyTool *tool,
+static int do_if_clicked_handle(DDisplayBox  *ddisp, DiaModifyTool *tool,
                                Point *clickedpoint, GdkEventButton *event)
 {
   DiaObject *obj;
   Handle *handle;
   
   handle = NULL;
-  diagram_find_closest_handle(ddisp->diagram, &handle, &obj, clickedpoint);
-  if  (handle_is_clicked(ddisp, handle, clickedpoint)) {
+  diagram_find_closest_handle(ddisp->ddisp->diagram, &handle, &obj, clickedpoint);
+  if (handle_is_clicked (ddisp->ddisp, handle, clickedpoint)) {
     tool->state = STATE_MOVE_HANDLE;
     tool->break_connections = TRUE;
     tool->last_to = handle->pos;
     tool->handle = handle;
     tool->object = obj;
-    gdk_pointer_grab (gtk_widget_get_window(ddisp->canvas), FALSE,
+    gdk_pointer_grab (gtk_widget_get_window(ddisp->ddisp->canvas),
+                      FALSE,
                       GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON1_MOTION_MASK | GDK_BUTTON_RELEASE_MASK,
                       NULL, NULL, event->time);
     tool->start_at = handle->pos;
@@ -252,20 +259,22 @@ static int do_if_clicked_handle(DDisplay *ddisp, ModifyTool *tool,
 }
 
 static void
-modify_button_press(ModifyTool *tool, GdkEventButton *event,
-                    DDisplay *ddisp)
+modify_button_press (DiaTool        *self,
+                     GdkEventButton *event,
+                     DDisplayBox    *ddisp)
 {
+  DiaModifyTool *tool = DIA_MODIFY_TOOL (self);
   Point clickedpoint;
   DiaObject *clicked_obj;
   gboolean some_selected;
 
-  ddisplay_untransform_coords(ddisp,
-                             (int)event->x, (int)event->y,
-                             &clickedpoint.x, &clickedpoint.y);
+  ddisplay_untransform_coords (ddisp->ddisp,
+                               (int) event->x, (int) event->y,
+                               &clickedpoint.x, &clickedpoint.y);
 
   /* don't got to single handle movement if there is more than one object selected */
-  some_selected = g_list_length (ddisp->diagram->data->selected) > 1;
-  if (!some_selected && do_if_clicked_handle(ddisp, tool, &clickedpoint, event))
+  some_selected = g_list_length (ddisp->ddisp->diagram->data->selected) > 1;
+  if (!some_selected && do_if_clicked_handle (ddisp, tool, &clickedpoint, event))
     return;
   
   clicked_obj = click_select_object(ddisp, &clickedpoint, event);
@@ -279,7 +288,7 @@ modify_button_press(ModifyTool *tool, GdkEventButton *event,
     point_sub(&tool->move_compensate, &clickedpoint);
     tool->break_connections = TRUE; /* unconnect when not grabbing handles, just setting to
                                      * FALSE is not enough. Need to refine the move op, too. */
-    gdk_pointer_grab (gtk_widget_get_window(ddisp->canvas), FALSE,
+    gdk_pointer_grab (gtk_widget_get_window(ddisp->ddisp->canvas), FALSE,
                       GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON1_MOTION_MASK | GDK_BUTTON_RELEASE_MASK,
                       NULL, NULL, event->time);
     tool->start_at = clickedpoint;
@@ -292,15 +301,15 @@ modify_button_press(ModifyTool *tool, GdkEventButton *event,
     tool->x1 = tool->x2 = (int) event->x;
     tool->y1 = tool->y2 = (int) event->y;
 
-    dia_interactive_renderer_set_selection (ddisp->renderer,
+    dia_interactive_renderer_set_selection (ddisp->ddisp->renderer,
                                             TRUE,
                                             tool->x1,
                                             tool->y1,
                                             tool->x2 - tool->x1,
                                             tool->y2 - tool->y1);
-    ddisplay_flush (ddisp);
+    ddisplay_flush (ddisp->ddisp);
     
-    gdk_pointer_grab (gtk_widget_get_window (ddisp->canvas), FALSE,
+    gdk_pointer_grab (gtk_widget_get_window (ddisp->ddisp->canvas), FALSE,
                       GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON1_MOTION_MASK | GDK_BUTTON_RELEASE_MASK,
                       NULL, NULL, event->time);
   }
@@ -308,28 +317,30 @@ modify_button_press(ModifyTool *tool, GdkEventButton *event,
 
 
 static void
-modify_button_hold(ModifyTool *tool, GdkEventButton *event,
-               DDisplay *ddisp)
+modify_button_hold (DiaTool        *self,
+                    GdkEventButton *event,
+                    DDisplayBox    *ddisp)
 {
+  DiaModifyTool *tool = DIA_MODIFY_TOOL (self);
   Point clickedpoint;
 
   switch (tool->state) {
   case STATE_MOVE_OBJECT: 
     /* A button hold is as if user was moving object - if it is
      * a text object and can be edited, then the move is cancelled */
-    ddisplay_untransform_coords(ddisp,
-                               (int)event->x, (int)event->y,
-                               &clickedpoint.x, &clickedpoint.y);
+    ddisplay_untransform_coords (ddisp->ddisp,
+                                 (int)event->x, (int)event->y,
+                                 &clickedpoint.x, &clickedpoint.y);
 
     if (tool->object != NULL &&
-       diagram_is_selected(ddisp->diagram, tool->object)) {
-      if (textedit_activate_object(ddisp, tool->object, &clickedpoint)) {
-       /* Return tool to normal state - object is text and is in edit */
-       gdk_pointer_ungrab (event->time);
-       tool->orig_pos = NULL;
-       tool->state = STATE_NONE;
-       /* Activate Text Edit */
-       gtk_action_activate (menus_get_action ("ToolsTextedit"));
+        diagram_is_selected (ddisp->ddisp->diagram, tool->object)) {
+      if (textedit_activate_object (ddisp->ddisp, tool->object, &clickedpoint)) {
+        /* Return tool to normal state - object is text and is in edit */
+        gdk_pointer_ungrab (event->time);
+        tool->orig_pos = NULL;
+        tool->state = STATE_NONE;
+        /* Activate Text Edit */
+        gtk_action_activate (menus_get_action ("ToolsTextedit"));
       }
     } 
     break;
@@ -345,27 +356,28 @@ modify_button_hold(ModifyTool *tool, GdkEventButton *event,
 }
 
 static void
-modify_double_click(ModifyTool *tool, GdkEventButton *event,
-                   DDisplay *ddisp)
+modify_double_click (DiaTool        *self,
+                     GdkEventButton *event,
+                     DDisplayBox    *ddisp)
 {
   Point clickedpoint;
   DiaObject *clicked_obj;
   
-  ddisplay_untransform_coords(ddisp,
-                             (int)event->x, (int)event->y,
-                             &clickedpoint.x, &clickedpoint.y);
+  ddisplay_untransform_coords (ddisp->ddisp,
+                               (int) event->x, (int) event->y,
+                               &clickedpoint.x, &clickedpoint.y);
 
   clicked_obj = click_select_object(ddisp, &clickedpoint, event);
   
   if ( clicked_obj != NULL ) {
-    object_list_properties_show(ddisp->diagram, ddisp->diagram->data->selected);
+    object_list_properties_show(ddisp->ddisp->diagram, ddisp->ddisp->diagram->data->selected);
   } else { /* No object selected */
     /*printf("didn't select object\n");*/
     if (!(event->state & GDK_SHIFT_MASK)) {
       /* Not Multi-select => Remove all selected */
-      ddisplay_do_update_menu_sensitivity(ddisp);
-      diagram_remove_all_selected(ddisp->diagram, TRUE);
-      diagram_flush(ddisp->diagram);
+      ddisplay_do_update_menu_sensitivity (ddisp->ddisp);
+      diagram_remove_all_selected(ddisp->ddisp->diagram, TRUE);
+      diagram_flush(ddisp->ddisp->diagram);
     }
   }
 }
@@ -384,7 +396,7 @@ modify_double_click(ModifyTool *tool, GdkEventButton *event,
  */
 
 static gboolean
-modify_move_already(ModifyTool *tool, DDisplay *ddisp, Point *to)
+modify_move_already (DiaModifyTool *tool, DDisplay *ddisp, Point *to)
 {
   static gboolean settings_taken = FALSE;
   static int double_click_time = 250;
@@ -415,43 +427,44 @@ modify_move_already(ModifyTool *tool, DDisplay *ddisp, Point *to)
       return TRUE;
     }
   }
-  if (ddisplay_transform_length(ddisp, dist) > MIN_PIXELS) {
-    return (ddisplay_transform_length(ddisp, dist) > MIN_PIXELS);
+  if (ddisplay_transform_length (ddisp, dist) > MIN_PIXELS) {
+    return (ddisplay_transform_length (ddisp, dist) > MIN_PIXELS);
   } else {
     return FALSE;
   }
 }
 
 static void
-modify_motion (ModifyTool     *tool,
+modify_motion (DiaTool        *self,
                GdkEventMotion *event,
-               DDisplay       *ddisp)
+               DDisplayBox    *ddisp)
 {
+  DiaModifyTool *tool = DIA_MODIFY_TOOL (self);
   Point to;
   Point now, delta, full_delta;
   gboolean auto_scroll, vertical = FALSE;
   ConnectionPoint *connectionpoint = NULL;
   ObjectChange *objchange = NULL;
 
-  ddisplay_untransform_coords(ddisp, event->x, event->y, &to.x, &to.y);
+  ddisplay_untransform_coords (ddisp->ddisp, event->x, event->y, &to.x, &to.y);
 
   if (tool->state==STATE_NONE) {
     DiaObject *obj = NULL;
     Handle *handle = NULL;
 
-    diagram_find_closest_handle (ddisp->diagram, &handle, &obj, &to);
+    diagram_find_closest_handle (ddisp->ddisp->diagram, &handle, &obj, &to);
     if  (handle && handle->type != HANDLE_NON_MOVABLE
       && handle->id >= HANDLE_RESIZE_NW && handle->id <= HANDLE_RESIZE_SE
-      && handle_is_clicked(ddisp, handle, &to)
-      && g_list_length (ddisp->diagram->data->selected) == 1)
+      && handle_is_clicked (ddisp->ddisp, handle, &to)
+      && g_list_length (ddisp->ddisp->diagram->data->selected) == 1)
       ddisplay_set_all_cursor(get_cursor(CURSOR_DIRECTION_0 + handle->id));
     else
       ddisplay_set_all_cursor(get_cursor(CURSOR_POINT));
     return; /* Fast path... */
   }
-  auto_scroll = ddisplay_autoscroll(ddisp, event->x, event->y);
+  auto_scroll = ddisplay_autoscroll (ddisp->ddisp, event->x, event->y);
   
-  if (!modify_move_already(tool, ddisp, &to)) return;
+  if (!modify_move_already (tool, ddisp->ddisp, &to)) return;
 
   switch (tool->state) {
   case STATE_MOVE_OBJECT:
@@ -462,7 +475,7 @@ modify_motion (ModifyTool     *tool,
       DiaObject *obj;
 
       /* consider non-selected children affected */
-      pla = list = parent_list_affected(ddisp->diagram->data->selected);
+      pla = list = parent_list_affected(ddisp->ddisp->diagram->data->selected);
       tool->orig_pos = g_new(Point, g_list_length(list));
       i=0;
       while (list != NULL) {
@@ -474,7 +487,7 @@ modify_motion (ModifyTool     *tool,
     }
     
     if (tool->break_connections)
-      diagram_unconnect_selected(ddisp->diagram); /* Pushes UNDO info */
+      diagram_unconnect_selected(ddisp->ddisp->diagram); /* Pushes UNDO info */
 
     if (gdk_event_to_dia_ModifierKeys (event->state) & MODIFIER_CONTROL) {
       full_delta = to;
@@ -483,7 +496,7 @@ modify_motion (ModifyTool     *tool,
     }
 
     point_add(&to, &tool->move_compensate);
-    snap_to_grid(ddisp, &to.x, &to.y);
+    snap_to_grid (ddisp->ddisp, &to.x, &to.y);
   
     now = tool->object->position;
     
@@ -499,19 +512,19 @@ modify_motion (ModifyTool     *tool,
       }
     }
 
-    object_add_updates_list(ddisp->diagram->data->selected, ddisp->diagram);
-    objchange = object_list_move_delta(ddisp->diagram->data->selected, &delta);
+    object_add_updates_list(ddisp->ddisp->diagram->data->selected, ddisp->ddisp->diagram);
+    objchange = object_list_move_delta(ddisp->ddisp->diagram->data->selected, &delta);
     if (objchange != NULL) {
-      undo_object_change(ddisp->diagram, tool->object, objchange);
+      undo_object_change(ddisp->ddisp->diagram, tool->object, objchange);
     }
-    object_add_updates_list(ddisp->diagram->data->selected, ddisp->diagram);
+    object_add_updates_list(ddisp->ddisp->diagram->data->selected, ddisp->ddisp->diagram);
 
-    object_add_updates(tool->object, ddisp->diagram);
+    object_add_updates(tool->object, ddisp->ddisp->diagram);
 
     /* Put current mouse position in status bar */
     {
       gchar *postext;
-      GtkStatusbar *statusbar = GTK_STATUSBAR (ddisp->modified_status);
+      GtkStatusbar *statusbar = GTK_STATUSBAR (ddisp->ddisp->modified_status);
       guint context_id = gtk_statusbar_get_context_id (statusbar, "ObjectPos");
       gtk_statusbar_pop (statusbar, context_id); 
       postext = g_strdup_printf("%.3f, %.3f - %.3f, %.3f",
@@ -526,8 +539,8 @@ modify_motion (ModifyTool     *tool,
       g_free(postext);
     }
 
-    diagram_update_connections_selection(ddisp->diagram);
-    diagram_flush(ddisp->diagram);
+    diagram_update_connections_selection(ddisp->ddisp->diagram);
+    diagram_flush(ddisp->ddisp->diagram);
     break;
   case STATE_MOVE_HANDLE:
     full_delta = to;
@@ -543,10 +556,10 @@ modify_motion (ModifyTool     *tool,
     if (gdk_event_to_dia_ModifierKeys (event->state) & MODIFIER_CONTROL)
       vertical = (fabs(full_delta.x) < fabs(full_delta.y));
 
-    highlight_reset_all(ddisp->diagram);
+    highlight_reset_all(ddisp->ddisp->diagram);
     if ((tool->handle->connect_type != HANDLE_NONCONNECTABLE)) {
       /* Move to ConnectionPoint if near: */
-      connectionpoint = object_find_connectpoint_display (ddisp,
+      connectionpoint = object_find_connectpoint_display (ddisp->ddisp,
                                                           &to,
                                                           tool->object, TRUE);
       if (connectionpoint != NULL) {
@@ -557,24 +570,24 @@ modify_motion (ModifyTool     *tool,
         } else {
           type = DIA_HIGHLIGHT_CONNECTIONPOINT;
         }
-        highlight_object(connectionpoint->object, type, ddisp->diagram);
+        highlight_object(connectionpoint->object, type, ddisp->ddisp->diagram);
         ddisplay_set_all_cursor(get_cursor(CURSOR_CONNECT));
       }
     }
     if (connectionpoint == NULL) {
       /* No connectionopoint near, then snap to grid (if enabled) */
-      snap_to_grid(ddisp, &to.x, &to.y);
+      snap_to_grid (ddisp->ddisp, &to.x, &to.y);
       ddisplay_set_all_cursor(get_cursor(CURSOR_SCROLL));
     }
 
     if (tool->break_connections) {
       /* break connections to the handle currently selected. */
       if (tool->handle->connected_to!=NULL) {
-        Change *change = undo_unconnect (ddisp->diagram,
+        Change *change = undo_unconnect (ddisp->ddisp->diagram,
                                          tool->object,
                                          tool->handle);
 
-        (change->apply)(change, ddisp->diagram);
+        (change->apply)(change, ddisp->ddisp->diagram);
       }
     }
 
@@ -595,7 +608,7 @@ modify_motion (ModifyTool     *tool,
     /* Put current mouse position in status bar */
     {
       gchar *postext;
-      GtkStatusbar *statusbar = GTK_STATUSBAR (ddisp->modified_status);
+      GtkStatusbar *statusbar = GTK_STATUSBAR (ddisp->ddisp->modified_status);
       guint context_id = gtk_statusbar_get_context_id (statusbar, "ObjectPos");
     
       if (tool->object) { /* play safe */
@@ -612,7 +625,7 @@ modify_motion (ModifyTool     *tool,
       g_free(postext);
     }
     
-    object_add_updates(tool->object, ddisp->diagram);
+    object_add_updates(tool->object, ddisp->ddisp->diagram);
 
     /* Handle undo */
     if (tool->object)
@@ -620,32 +633,32 @@ modify_motion (ModifyTool     *tool,
                                                 &to, connectionpoint,
                                                 HANDLE_MOVE_USER, 
gdk_event_to_dia_ModifierKeys(event->state));
     if (objchange != NULL) {
-      undo_object_change(ddisp->diagram, tool->object, objchange);
+      undo_object_change(ddisp->ddisp->diagram, tool->object, objchange);
     }
-    object_add_updates(tool->object, ddisp->diagram);
+    object_add_updates(tool->object, ddisp->ddisp->diagram);
   
-    diagram_update_connections_selection(ddisp->diagram);
-    diagram_flush(ddisp->diagram);
+    diagram_update_connections_selection(ddisp->ddisp->diagram);
+    diagram_flush(ddisp->ddisp->diagram);
     break;
   case STATE_BOX_SELECT:
     tool->end_box = to;
 
-    ddisplay_transform_coords(ddisp,
-                             MIN(tool->start_box.x, tool->end_box.x),
-                             MIN(tool->start_box.y, tool->end_box.y),
-                             &tool->x1, &tool->y1);
-    ddisplay_transform_coords(ddisp,
-                             MAX(tool->start_box.x, tool->end_box.x),
-                             MAX(tool->start_box.y, tool->end_box.y),
-                             &tool->x2, &tool->y2);
+    ddisplay_transform_coords (ddisp->ddisp,
+                               MIN (tool->start_box.x, tool->end_box.x),
+                               MIN (tool->start_box.y, tool->end_box.y),
+                               &tool->x1, &tool->y1);
+    ddisplay_transform_coords (ddisp->ddisp,
+                               MAX(tool->start_box.x, tool->end_box.x),
+                               MAX(tool->start_box.y, tool->end_box.y),
+                               &tool->x2, &tool->y2);
 
-    dia_interactive_renderer_set_selection (ddisp->renderer,
+    dia_interactive_renderer_set_selection (ddisp->ddisp->renderer,
                                             TRUE,
                                             tool->x1,
                                             tool->y1,
                                             tool->x2 - tool->x1,
                                             tool->y2 - tool->y1);
-    ddisplay_flush (ddisp);
+    ddisplay_flush (ddisp->ddisp);
 
     break;
   case STATE_NONE:
@@ -661,7 +674,7 @@ modify_motion (ModifyTool     *tool,
 /** Find the list of objects selected by current rubberbanding. 
  * The list should be freed after use. */
 static GList *
-find_selected_objects(DDisplay *ddisp, ModifyTool *tool)
+find_selected_objects(DDisplayBox  *ddisp, DiaModifyTool *tool)
 {
   Rectangle r;
   r.left = MIN(tool->start_box.x, tool->end_box.x);
@@ -672,17 +685,19 @@ find_selected_objects(DDisplay *ddisp, ModifyTool *tool)
   if (prefs.reverse_rubberbanding_intersects && 
       tool->start_box.x > tool->end_box.x) {
     return
-      layer_find_objects_intersecting_rectangle(ddisp->diagram->data->active_layer, &r);
+      layer_find_objects_intersecting_rectangle(ddisp->ddisp->diagram->data->active_layer, &r);
   } else {
     return
-      layer_find_objects_in_rectangle(ddisp->diagram->data->active_layer, &r);
+      layer_find_objects_in_rectangle(ddisp->ddisp->diagram->data->active_layer, &r);
   }
 }
 
 static void
-modify_button_release(ModifyTool *tool, GdkEventButton *event,
-                     DDisplay *ddisp)
+modify_button_release (DiaTool        *self,
+                       GdkEventButton *event,
+                       DDisplayBox    *ddisp)
 {
+  DiaModifyTool *tool = DIA_MODIFY_TOOL (self);
   Point *dest_pos, to;
   GList *list;
   int i;
@@ -693,7 +708,7 @@ modify_button_release(ModifyTool *tool, GdkEventButton *event,
 
   /* remove position from status bar */
   {
-    GtkStatusbar *statusbar = GTK_STATUSBAR (ddisp->modified_status);
+    GtkStatusbar *statusbar = GTK_STATUSBAR (ddisp->ddisp->modified_status);
     guint context_id = gtk_statusbar_get_context_id (statusbar, "ObjectPos");
     gtk_statusbar_pop (statusbar, context_id);
   }
@@ -702,18 +717,18 @@ modify_button_release(ModifyTool *tool, GdkEventButton *event,
     /* Return to normal state */
     gdk_pointer_ungrab (event->time);
 
-    ddisplay_untransform_coords(ddisp, event->x, event->y, &to.x, &to.y);
-    if (!modify_move_already(tool, ddisp, &to)) {
+    ddisplay_untransform_coords (ddisp->ddisp, event->x, event->y, &to.x, &to.y);
+    if (!modify_move_already (tool, ddisp->ddisp, &to)) {
       tool->orig_pos = NULL;
       tool->state = STATE_NONE;
       return;
     }
 
-    diagram_update_connections_selection(ddisp->diagram);
+    diagram_update_connections_selection(ddisp->ddisp->diagram);
 
     if (tool->orig_pos != NULL) {
       /* consider the non-selected children affected */
-      list = parent_list_affected(ddisp->diagram->data->selected);
+      list = parent_list_affected (ddisp->ddisp->diagram->data->selected);
       dest_pos = g_new(Point, g_list_length(list));
       i=0;
       while (list != NULL) {
@@ -722,16 +737,16 @@ modify_button_release(ModifyTool *tool, GdkEventButton *event,
        list = g_list_next(list); i++;
       }
 
-      undo_move_objects(ddisp->diagram, tool->orig_pos, dest_pos,
-                       parent_list_affected(ddisp->diagram->data->selected));
+      undo_move_objects(ddisp->ddisp->diagram, tool->orig_pos, dest_pos,
+                       parent_list_affected(ddisp->ddisp->diagram->data->selected));
     }
     
-    ddisplay_connect_selected(ddisp); /* pushes UNDO info */
-    diagram_update_extents(ddisp->diagram);
-    diagram_modified(ddisp->diagram);
-    diagram_flush(ddisp->diagram);
+    ddisplay_connect_selected (ddisp->ddisp); /* pushes UNDO info */
+    diagram_update_extents(ddisp->ddisp->diagram);
+    diagram_modified(ddisp->ddisp->diagram);
+    diagram_flush(ddisp->ddisp->diagram);
 
-    undo_set_transactionpoint(ddisp->diagram->undo);
+    undo_set_transactionpoint(ddisp->ddisp->diagram->undo);
 
     tool->orig_pos = NULL;
     tool->state = STATE_NONE;
@@ -741,34 +756,34 @@ modify_button_release(ModifyTool *tool, GdkEventButton *event,
     tool->state = STATE_NONE;
 
     if (tool->orig_pos != NULL) {
-      undo_move_handle(ddisp->diagram, tool->handle, tool->object,
+      undo_move_handle(ddisp->ddisp->diagram, tool->handle, tool->object,
                       *tool->orig_pos, tool->last_to, gdk_event_to_dia_ModifierKeys(event->state));
     }
     
     /* Final move: */
-    object_add_updates(tool->object, ddisp->diagram);
+    object_add_updates(tool->object, ddisp->ddisp->diagram);
     objchange = tool->object->ops->move_handle(tool->object, tool->handle,
                                               &tool->last_to, NULL,
                                               
HANDLE_MOVE_USER_FINAL,gdk_event_to_dia_ModifierKeys(event->state));
     if (objchange != NULL) {
-      undo_object_change(ddisp->diagram, tool->object, objchange);
+      undo_object_change(ddisp->ddisp->diagram, tool->object, objchange);
     }
 
-    object_add_updates(tool->object, ddisp->diagram);
+    object_add_updates(tool->object, ddisp->ddisp->diagram);
 
     /* Connect if possible: */
     if (tool->handle->connect_type != HANDLE_NONCONNECTABLE) {
-      object_connect_display(ddisp, tool->object, tool->handle, TRUE); /* pushes UNDO info */
-      diagram_update_connections_selection(ddisp->diagram);
+      object_connect_display (ddisp->ddisp, tool->object, tool->handle, TRUE); /* pushes UNDO info */
+      diagram_update_connections_selection (ddisp->ddisp->diagram);
     }
     
-    highlight_reset_all(ddisp->diagram);
-    diagram_flush(ddisp->diagram);
+    highlight_reset_all(ddisp->ddisp->diagram);
+    diagram_flush(ddisp->ddisp->diagram);
     
-    diagram_modified(ddisp->diagram);
-    diagram_update_extents(ddisp->diagram);
+    diagram_modified(ddisp->ddisp->diagram);
+    diagram_update_extents(ddisp->ddisp->diagram);
 
-    undo_set_transactionpoint(ddisp->diagram->undo);
+    undo_set_transactionpoint(ddisp->ddisp->diagram->undo);
 
     if (tool->orig_pos != NULL) {
       g_free(tool->orig_pos);
@@ -780,7 +795,7 @@ modify_button_release(ModifyTool *tool, GdkEventButton *event,
     
     gdk_pointer_ungrab (event->time);
     /* Remove last box: */
-    dia_interactive_renderer_set_selection (ddisp->renderer,
+    dia_interactive_renderer_set_selection (ddisp->ddisp->renderer,
                                             FALSE, 0, 0, 0, 0);
 
     {
@@ -791,7 +806,7 @@ modify_button_release(ModifyTool *tool, GdkEventButton *event,
       if (selection_style == SELECT_REPLACE &&
           !(event->state & GDK_SHIFT_MASK)) {
         /* Not Multi-select => Remove all selected */
-        diagram_remove_all_selected(ddisp->diagram, TRUE);
+        diagram_remove_all_selected(ddisp->ddisp->diagram, TRUE);
       }
 
       if (selection_style == SELECT_INTERSECTION) {
@@ -800,18 +815,18 @@ modify_button_release(ModifyTool *tool, GdkEventButton *event,
         while (list != NULL) {
           DiaObject *obj = (DiaObject *)list->data;
           
-          if (diagram_is_selected(ddisp->diagram, obj)) {
+          if (diagram_is_selected(ddisp->ddisp->diagram, obj)) {
             intersection = g_list_append(intersection, obj);
           }
           
           list = g_list_next(list);
         }
         list = intersection;
-        diagram_remove_all_selected(ddisp->diagram, TRUE);
+        diagram_remove_all_selected(ddisp->ddisp->diagram, TRUE);
         while (list != NULL) {
           DiaObject *obj = (DiaObject *)list->data;
 
-          diagram_select(ddisp->diagram, obj);
+          diagram_select(ddisp->ddisp->diagram, obj);
 
           list = g_list_next(list);
         }
@@ -821,16 +836,16 @@ modify_button_release(ModifyTool *tool, GdkEventButton *event,
           DiaObject *obj = (DiaObject *)list->data;
           
           if (selection_style == SELECT_REMOVE) {
-            if (diagram_is_selected(ddisp->diagram, obj))
-              diagram_unselect_object(ddisp->diagram, obj);
+            if (diagram_is_selected(ddisp->ddisp->diagram, obj))
+              diagram_unselect_object(ddisp->ddisp->diagram, obj);
           } else if (selection_style == SELECT_INVERT) { 
-            if (diagram_is_selected(ddisp->diagram, obj))
-              diagram_unselect_object(ddisp->diagram, obj);
+            if (diagram_is_selected(ddisp->ddisp->diagram, obj))
+              diagram_unselect_object(ddisp->ddisp->diagram, obj);
             else
-              diagram_select(ddisp->diagram, obj);
+              diagram_select(ddisp->ddisp->diagram, obj);
           } else {
-            if (!diagram_is_selected(ddisp->diagram, obj))
-              diagram_select(ddisp->diagram, obj);
+            if (!diagram_is_selected(ddisp->ddisp->diagram, obj))
+              diagram_select(ddisp->ddisp->diagram, obj);
           }
           
           list = g_list_next(list);
@@ -841,8 +856,8 @@ modify_button_release(ModifyTool *tool, GdkEventButton *event,
       
     }
     
-    ddisplay_do_update_menu_sensitivity(ddisp);
-    ddisplay_flush(ddisp);
+    ddisplay_do_update_menu_sensitivity (ddisp->ddisp);
+    ddisplay_flush (ddisp->ddisp);
 
     tool->state = STATE_NONE;
     break;
diff --git a/app/tools/modify_tool.h b/app/tools/modify_tool.h
index 7b854427..9822e33b 100644
--- a/app/tools/modify_tool.h
+++ b/app/tools/modify_tool.h
@@ -21,7 +21,8 @@
 #include "geometry.h"
 #include "tool.h"
 
-typedef struct _ModifyTool ModifyTool;
+#define DIA_TYPE_MODIFY_TOOL (dia_modify_tool_get_type ())
+G_DECLARE_FINAL_TYPE (DiaModifyTool, dia_modify_tool, DIA, MODIFY_TOOL, DiaTool)
 
 enum ModifyToolState {
   STATE_NONE,
@@ -30,7 +31,4 @@ enum ModifyToolState {
   STATE_BOX_SELECT
 };
 
-Tool *create_modify_tool(void);
-void free_modify_tool(Tool *tool);
-
 #endif /* MODIFY_TOOL_H */
diff --git a/app/tools/scroll_tool.c b/app/tools/scroll_tool.c
index e9ce9ff6..e6ebb514 100644
--- a/app/tools/scroll_tool.c
+++ b/app/tools/scroll_tool.c
@@ -24,132 +24,148 @@
 #include "message.h"
 #include "cursor.h"
 
-static void scroll_button_press(ScrollTool *tool, GdkEventButton *event,
-                                DDisplay *ddisp);
-static void scroll_button_release(ScrollTool *tool, GdkEventButton *event,
-                                 DDisplay *ddisp);
-static void scroll_motion(ScrollTool *tool, GdkEventMotion *event,
-                         DDisplay *ddisp);
-static void scroll_double_click(ScrollTool *tool, GdkEventButton *event,
-                               DDisplay *ddisp);
-
-Tool *
-create_scroll_tool(void)
+static void scroll_button_press   (DiaTool        *tool,
+                                   GdkEventButton *event,
+                                   DDisplayBox    *ddisp);
+static void scroll_button_release (DiaTool        *tool,
+                                   GdkEventButton *event,
+                                   DDisplayBox    *ddisp);
+static void scroll_motion         (DiaTool        *tool,
+                                   GdkEventMotion *event,
+                                   DDisplayBox    *ddisp);
+static void scroll_double_click   (DiaTool        *tool,
+                                   GdkEventButton *event,
+                                   DDisplayBox    *ddisp);
+
+G_DEFINE_TYPE (DiaScrollTool, dia_scroll_tool, DIA_TYPE_TOOL)
+
+static void
+activate (DiaTool *tool)
 {
-  ScrollTool *tool;
+  DiaScrollTool *self = DIA_SCROLL_TOOL (tool);
 
-  tool = g_new0(ScrollTool, 1);
-  tool->tool.type = SCROLL_TOOL;
-  tool->tool.button_press_func = (ButtonPressFunc) &scroll_button_press;
-  tool->tool.button_release_func = (ButtonReleaseFunc) &scroll_button_release;
-  tool->tool.motion_func = (MotionFunc) &scroll_motion;
-  tool->tool.double_click_func = (DoubleClickFunc) &scroll_double_click;
+  self->scrolling = FALSE;
+  self->use_hand = TRUE;
 
-  tool->scrolling = FALSE;
-  tool->use_hand = TRUE;
+  ddisplay_set_all_cursor (get_cursor (CURSOR_GRAB));
+}
 
-  ddisplay_set_all_cursor(get_cursor(CURSOR_GRAB));
-  
-  return (Tool *)tool;
+static void
+deactivate (DiaTool *tool)
+{
+  ddisplay_set_all_cursor (default_cursor);
 }
 
-void
-free_scroll_tool(Tool *tool)
+static void
+dia_scroll_tool_class_init (DiaScrollToolClass *klass)
 {
-  g_free(tool);
-  ddisplay_set_all_cursor(default_cursor);
+  DiaToolClass *tool_class = DIA_TOOL_CLASS (klass);
+
+  tool_class->activate = activate;
+  tool_class->deactivate = deactivate;
 
+  tool_class->button_press = scroll_button_press;
+  tool_class->button_release = scroll_button_release;
+  tool_class->motion = scroll_motion;
+  tool_class->double_click = scroll_double_click;
 }
 
 static void
-scroll_double_click(ScrollTool *tool, GdkEventButton *event,
-                   DDisplay *ddisp)
+dia_scroll_tool_init (DiaScrollTool *self)
+{
+}
+
+static void
+scroll_double_click (DiaTool        *tool,
+                     GdkEventButton *event,
+                     DDisplayBox    *ddisp)
 {
   /* Do nothing */
 }
 
 static void
-scroll_button_press(ScrollTool *tool, GdkEventButton *event,
-                    DDisplay *ddisp)
+scroll_button_press (DiaTool        *tool,
+                     GdkEventButton *event,
+                     DDisplayBox    *ddisp)
 {
+  DiaScrollTool *self = DIA_SCROLL_TOOL (tool);
   Point clickedpoint;
 
-  tool->use_hand = (event->state & GDK_SHIFT_MASK) == 0;
-  if (tool->use_hand)
-    ddisplay_set_all_cursor(get_cursor(CURSOR_GRABBING));
+  self->use_hand = (event->state & GDK_SHIFT_MASK) == 0;
+  if (self->use_hand)
+    ddisplay_set_all_cursor (get_cursor(CURSOR_GRABBING));
   else
-    ddisplay_set_all_cursor(get_cursor(CURSOR_SCROLL));
+    ddisplay_set_all_cursor (get_cursor(CURSOR_SCROLL));
 
-  ddisplay_untransform_coords(ddisp,
-                             (int)event->x, (int)event->y,
-                             &clickedpoint.x, &clickedpoint.y);
+  ddisplay_untransform_coords (ddisp->ddisp,
+                               (int)event->x, (int)event->y,
+                               &clickedpoint.x, &clickedpoint.y);
 
-  tool->scrolling = TRUE;
-  tool->last_pos = clickedpoint;
+  self->scrolling = TRUE;
+  self->last_pos = clickedpoint;
 }
 
-
-
-
 static void
-scroll_motion(ScrollTool *tool, GdkEventMotion *event,
-             DDisplay *ddisp)
+scroll_motion (DiaTool        *tool,
+               GdkEventMotion *event,
+               DDisplayBox    *ddisp)
 {
+  DiaScrollTool *self = DIA_SCROLL_TOOL (tool);
   Point to;
   Point delta;
 
   /* set the cursor appropriately, and change use_hand if needed */
-  if (!tool->scrolling) {
+  if (!self->scrolling) {
     /* try to minimise the number of cursor type changes */
     if ((event->state & GDK_SHIFT_MASK) == 0) {
-      if (!tool->use_hand) {
-       tool->use_hand = TRUE;
-       ddisplay_set_all_cursor(get_cursor(CURSOR_GRAB));
+      if (!self->use_hand) {
+        self->use_hand = TRUE;
+        ddisplay_set_all_cursor(get_cursor(CURSOR_GRAB));
       }
     } else
-      if (tool->use_hand) {
-       tool->use_hand = FALSE;
-       ddisplay_set_all_cursor(get_cursor(CURSOR_SCROLL));
+      if (self->use_hand) {
+        self->use_hand = FALSE;
+        ddisplay_set_all_cursor(get_cursor(CURSOR_SCROLL));
       }
     return;
   }
 
-  ddisplay_untransform_coords(ddisp, event->x, event->y, &to.x, &to.y);
+  ddisplay_untransform_coords (ddisp->ddisp, event->x, event->y, &to.x, &to.y);
 
-  if (tool->use_hand) {
-    delta = tool->last_pos;
+  if (self->use_hand) {
+    delta = self->last_pos;
     point_sub(&delta, &to);
 
-    tool->last_pos = to;
-    point_add(&tool->last_pos, &delta);
+    self->last_pos = to;
+    point_add(&self->last_pos, &delta);
 
     /* we use this so you can scroll past the edge of the image */
-    point_add(&delta, &ddisp->origo);
-    ddisplay_set_origo(ddisp, delta.x, delta.y);
-    ddisplay_update_scrollbars(ddisp);
-    ddisplay_add_update_all(ddisp);
+    point_add(&delta, &ddisp->ddisp->origo);
+    ddisplay_set_origo (ddisp->ddisp, delta.x, delta.y);
+    ddisplay_update_scrollbars (ddisp->ddisp);
+    ddisplay_add_update_all(ddisp->ddisp);
   } else {
     delta = to;
-    point_sub(&delta, &tool->last_pos);
+    point_sub(&delta, &self->last_pos);
     point_scale(&delta, 0.5);
 
-    ddisplay_scroll(ddisp, &delta);
-    tool->last_pos = to;
+    ddisplay_scroll (ddisp->ddisp, &delta);
+    self->last_pos = to;
   }
-  ddisplay_flush(ddisp);
+  ddisplay_flush (ddisp->ddisp);
 }
 
-
 static void
-scroll_button_release(ScrollTool *tool, GdkEventButton *event,
-                     DDisplay *ddisp)
+scroll_button_release (DiaTool        *tool,
+                       GdkEventButton *event,
+                       DDisplayBox    *ddisp)
 {
-  tool->use_hand = (event->state & GDK_SHIFT_MASK) == 0;
-  if (tool->use_hand) {
+  DiaScrollTool *self = DIA_SCROLL_TOOL (tool);
+  self->use_hand = (event->state & GDK_SHIFT_MASK) == 0;
+  if (self->use_hand) {
     ddisplay_set_all_cursor(get_cursor(CURSOR_GRAB));
   } else
     ddisplay_set_all_cursor(get_cursor(CURSOR_SCROLL));
 
-  tool->scrolling = FALSE;
+  self->scrolling = FALSE;
 }
-
diff --git a/app/tools/scroll_tool.h b/app/tools/scroll_tool.h
index dae320a5..a58ba0f5 100644
--- a/app/tools/scroll_tool.h
+++ b/app/tools/scroll_tool.h
@@ -21,19 +21,17 @@
 #include "geometry.h"
 #include "tool.h"
 
-typedef struct _ScrollTool ScrollTool;
+#define DIA_TYPE_SCROLL_TOOL (dia_scroll_tool_get_type ())
+G_DECLARE_FINAL_TYPE (DiaScrollTool, dia_scroll_tool, DIA, SCROLL_TOOL, DiaTool)
 
-struct _ScrollTool {
-  Tool tool;
+struct _DiaScrollTool {
+  DiaTool tool;
 
   int scrolling;
   int use_hand;
   Point last_pos;
 };
 
-Tool *create_scroll_tool(void);
-void free_scroll_tool(Tool *tool);
-
 #endif /* SCROLL_TOOL_H */
 
 
diff --git a/app/tools/textedit_tool.c b/app/tools/textedit_tool.c
index 657f382d..c9adabaf 100644
--- a/app/tools/textedit_tool.c
+++ b/app/tools/textedit_tool.c
@@ -24,6 +24,8 @@
 #include "cursor.h"
 #include "object_ops.h"
 
+G_DEFINE_TYPE (DiaTextEditTool, dia_text_edit_tool, DIA_TYPE_TOOL)
+
 /** The text edit tool.  This tool allows the user to switch to a mode where
  * clicking on an editable text will start text edit mode.  Clicking outside
  * of editable text will revert to selection tool.  Note that clicking this
@@ -31,8 +33,9 @@
  * by clicking an object.
  */
 static DiaObject *
-click_select_object(DDisplay *ddisp, Point *clickedpoint,
-                   GdkEventButton *event)
+click_select_object (DDisplay       *ddisp,
+                     Point          *clickedpoint,
+                     GdkEventButton *event)
 {
   real click_distance = ddisplay_untransform_length(ddisp, 3.0);
   Diagram *diagram = ddisp->diagram;
@@ -52,96 +55,93 @@ click_select_object(DDisplay *ddisp, Point *clickedpoint,
     already = g_list_find(diagram->data->selected, obj);
     if (already == NULL) { /* Not already selected */
       if (!(event->state & GDK_SHIFT_MASK)) {
-       /* Not Multi-select => remove current selection */
-       diagram_remove_all_selected(diagram, TRUE);
+        /* Not Multi-select => remove current selection */
+        diagram_remove_all_selected (diagram, TRUE);
       }
-      diagram_select(diagram, obj);
+      diagram_select (diagram, obj);
     }
-    ddisplay_do_update_menu_sensitivity(ddisp);
-    object_add_updates_list(diagram->data->selected, diagram);
-    diagram_flush(diagram);
+    ddisplay_do_update_menu_sensitivity (ddisp);
+    object_add_updates_list (diagram->data->selected, diagram);
+    diagram_flush (diagram);
 
     return obj;
   }
 
-  return obj;  
+  return obj;
 }
 
 static void
-textedit_button_press(TexteditTool *tool, GdkEventButton *event,
-                     DDisplay *ddisp)
+text_edit_button_press (DiaTool        *tool,
+                        GdkEventButton *event,
+                        DDisplayBox    *ddisp)
 {
+  DiaTextEditTool *self = DIA_TEXT_EDIT_TOOL (tool);
   Point clickedpoint;
-  Diagram *diagram = ddisp->diagram;
-  DiaObject *obj = click_select_object (ddisp, &clickedpoint, event);
+  Diagram *diagram = ddisp->ddisp->diagram;
+  DiaObject *obj = click_select_object (ddisp->ddisp, &clickedpoint, event);
 
   if (obj) {
-    if (obj != tool->object)
+    if (obj != self->object)
       textedit_deactivate_focus ();
 
     /*  set cursor position */
-    if (textedit_activate_object(ddisp, obj, &clickedpoint)) {
-      tool->object = obj;
-      tool->start_at = clickedpoint;
-      tool->state = STATE_TEXT_SELECT;
+    if (textedit_activate_object (ddisp->ddisp, obj, &clickedpoint)) {
+      self->object = obj;
+      self->start_at = clickedpoint;
+      self->state = STATE_TEXT_SELECT;
     } else {
       /* Clicked outside of editable object, stop editing */
-      tool_reset();
+      tool_reset ();
     }
   } else {
     textedit_deactivate_focus ();
-    diagram_remove_all_selected(diagram, TRUE);
-    tool_reset();
+    diagram_remove_all_selected (diagram, TRUE);
+    tool_reset ();
   }
 }
 
 static void
-textedit_button_release(TexteditTool *tool, GdkEventButton *event,
-                       DDisplay *ddisp)
+text_edit_button_release (DiaTool        *tool,
+                          GdkEventButton *event,
+                          DDisplayBox    *ddisp)
 {
   Point clickedpoint;
-  DiaObject *obj = click_select_object (ddisp, &clickedpoint, event);
+  DiaObject *obj = click_select_object (ddisp->ddisp, &clickedpoint, event);
   
   if (obj) {
-    ddisplay_do_update_menu_sensitivity(ddisp);
+    ddisplay_do_update_menu_sensitivity (ddisp->ddisp);
 
-    tool->state = STATE_TEXT_EDIT;
+    DIA_TEXT_EDIT_TOOL (tool)->state = STATE_TEXT_EDIT;
     /* no selection in the text editing yes */
   } else {
     /* back to modifying if we dont have an object */
-    textedit_deactivate_focus();
+    textedit_deactivate_focus ();
     tool_reset ();
   }
 }
 
 static void
-textedit_motion(TexteditTool *tool, GdkEventMotion *event,
-               DDisplay *ddisp)
+text_edit_motion (DiaTool        *tool,
+                  GdkEventMotion *event,
+                  DDisplayBox    *ddisp)
 {
   /* if we implement text selection here we could update the visual feedback */
 }
 
 static void
-textedit_double_click(TexteditTool *tool, GdkEventButton *event,
-                     DDisplay *ddisp)
+text_edit_double_click (DiaTool        *tool,
+                        GdkEventButton *event,
+                        DDisplayBox    *ddisp)
 {
   /* if we implment text selection this should select a word */
 }
 
-Tool *
-create_textedit_tool(void)
+static void
+activate (DiaTool *tool)
 {
-  TexteditTool *tool;
   DDisplay *ddisp;
 
-  tool = g_new0(TexteditTool, 1);
-  tool->tool.type = TEXTEDIT_TOOL;
-  tool->tool.button_press_func = (ButtonPressFunc) &textedit_button_press;
-  tool->tool.button_release_func = (ButtonReleaseFunc) &textedit_button_release;
-  tool->tool.motion_func = (MotionFunc) &textedit_motion;
-  tool->tool.double_click_func = (DoubleClickFunc) &textedit_double_click;
-  
-  ddisplay_set_all_cursor(get_cursor(CURSOR_XTERM));
+  ddisplay_set_all_cursor (get_cursor (CURSOR_XTERM));
 
   ddisp = ddisplay_active();
   if (ddisp) {
@@ -149,23 +149,38 @@ create_textedit_tool(void)
       /*  set the focus to the canvas area  */
       gtk_widget_grab_focus (ddisp->canvas);
     }
-    ddisplay_flush(ddisp);
+    ddisplay_flush (ddisp);
     /* the above may have entered the textedit mode, just update in any case */
-    ddisplay_do_update_menu_sensitivity(ddisp);
+    ddisplay_do_update_menu_sensitivity (ddisp);
   }
-
-  return (Tool *)tool;
 }
 
-void
-free_textedit_tool (Tool *tool)
+static void
+deactivate (DiaTool *tool)
 {
-  DDisplay *ddisp = ddisplay_active();
+  DDisplay *ddisp = ddisplay_active ();
   if (ddisp) {
     textedit_deactivate_focus ();
-    ddisplay_flush(ddisp);
+    ddisplay_flush (ddisp);
   }
-  ddisplay_set_all_cursor(default_cursor);
+  ddisplay_set_all_cursor (default_cursor);
+}
 
-  g_free (tool);
+static void
+dia_text_edit_tool_class_init (DiaTextEditToolClass *klass)
+{
+  DiaToolClass *tool_class = DIA_TOOL_CLASS (klass);
+
+  tool_class->activate = activate;
+  tool_class->deactivate = deactivate;
+
+  tool_class->button_press = text_edit_button_press;
+  tool_class->button_release = text_edit_button_release;
+  tool_class->motion = text_edit_motion;
+  tool_class->double_click = text_edit_double_click;
+}
+
+static void
+dia_text_edit_tool_init (DiaTextEditTool *self)
+{
 }
diff --git a/app/tools/textedit_tool.h b/app/tools/textedit_tool.h
index 5ed5807e..4e936b3e 100644
--- a/app/tools/textedit_tool.h
+++ b/app/tools/textedit_tool.h
@@ -26,17 +26,15 @@ enum TexteditToolState {
   STATE_TEXT_EDIT
 };
 
-typedef struct _TexteditTool TexteditTool;
+#define DIA_TYPE_TEXT_EDIT_TOOL (dia_text_edit_tool_get_type ())
+G_DECLARE_FINAL_TYPE (DiaTextEditTool, dia_text_edit_tool, DIA, TEXT_EDIT_TOOL, DiaTool)
 
-struct _TexteditTool {
-  Tool tool;
+struct _DiaTextEditTool {
+  DiaTool tool;
   
   enum TexteditToolState state;
   DiaObject *object;
   Point start_at;
 };
 
-Tool *create_textedit_tool(void);
-void free_textedit_tool(Tool *tool);
-
 #endif /* TEXTEDIT_TOOL_H */
diff --git a/app/tools/tool.c b/app/tools/tool.c
index 492af30c..04647af1 100644
--- a/app/tools/tool.c
+++ b/app/tools/tool.c
@@ -27,11 +27,158 @@
 #include "defaults.h"
 #include "object.h"
 
-Tool *active_tool = NULL;
-Tool *transient_tool = NULL;
+DiaTool *active_tool = NULL;
+DiaTool *transient_tool = NULL;
 static GtkWidget *active_button = NULL;
 static GtkWidget *former_button = NULL;
 
+
+G_DEFINE_TYPE (DiaTool, dia_tool, G_TYPE_OBJECT)
+
+enum {
+  ACTIVATE,
+  DEACTIVATE,
+  BUTTON_PRESS,
+  BUTTON_HOLD,
+  DOUBLE_CLICK,
+  BUTTON_RELEASE,
+  MOTION,
+  LAST_SIGNAL
+};
+static guint signals[LAST_SIGNAL] = { 0 };
+
+static void
+dia_tool_class_init (DiaToolClass *klass)
+{
+  klass->activate = NULL;
+  klass->deactivate = NULL;
+  klass->button_press = NULL;
+  klass->button_hold = NULL;
+  klass->double_click = NULL;
+  klass->button_release = NULL;
+  klass->motion = NULL;
+
+  signals[ACTIVATE] = g_signal_new ("activate",
+                                    G_TYPE_FROM_CLASS (klass),
+                                    G_SIGNAL_RUN_FIRST,
+                                    G_STRUCT_OFFSET (DiaToolClass, activate),
+                                    NULL, NULL, NULL,
+                                    G_TYPE_NONE, 0);
+
+  signals[DEACTIVATE] = g_signal_new ("deactivate",
+                                        G_TYPE_FROM_CLASS (klass),
+                                        G_SIGNAL_RUN_FIRST,
+                                        G_STRUCT_OFFSET (DiaToolClass, activate),
+                                        NULL, NULL, NULL,
+                                        G_TYPE_NONE, 0);
+
+  signals[BUTTON_PRESS] = g_signal_new ("button-press",
+                                        G_TYPE_FROM_CLASS (klass),
+                                        G_SIGNAL_RUN_FIRST,
+                                        G_STRUCT_OFFSET (DiaToolClass, button_press),
+                                        NULL, NULL, NULL,
+                                        G_TYPE_NONE, 2,
+                                        GDK_TYPE_EVENT,
+                                        DIA_TYPE_DISPLAY);
+
+  signals[BUTTON_HOLD] = g_signal_new ("button-hold",
+                                       G_TYPE_FROM_CLASS (klass),
+                                       G_SIGNAL_RUN_FIRST,
+                                       G_STRUCT_OFFSET (DiaToolClass, button_hold),
+                                       NULL, NULL, NULL,
+                                       G_TYPE_NONE, 2,
+                                       GDK_TYPE_EVENT,
+                                       DIA_TYPE_DISPLAY);
+
+  signals[DOUBLE_CLICK] = g_signal_new ("double-click",
+                                        G_TYPE_FROM_CLASS (klass),
+                                        G_SIGNAL_RUN_FIRST,
+                                        G_STRUCT_OFFSET (DiaToolClass, double_click),
+                                        NULL, NULL, NULL,
+                                        G_TYPE_NONE, 2,
+                                        GDK_TYPE_EVENT,
+                                        DIA_TYPE_DISPLAY);
+
+  signals[BUTTON_RELEASE] = g_signal_new ("button-release",
+                                          G_TYPE_FROM_CLASS (klass),
+                                          G_SIGNAL_RUN_FIRST,
+                                          G_STRUCT_OFFSET (DiaToolClass, button_release),
+                                          NULL, NULL, NULL,
+                                          G_TYPE_NONE, 2,
+                                          GDK_TYPE_EVENT,
+                                          DIA_TYPE_DISPLAY);
+
+  signals[MOTION] = g_signal_new ("motion",
+                                  G_TYPE_FROM_CLASS (klass),
+                                  G_SIGNAL_RUN_FIRST,
+                                  G_STRUCT_OFFSET (DiaToolClass, motion),
+                                  NULL, NULL, NULL,
+                                  G_TYPE_NONE, 2,
+                                  GDK_TYPE_EVENT,
+                                  DIA_TYPE_DISPLAY);
+}
+
+static void
+dia_tool_init (DiaTool *self)
+{
+
+}
+
+void
+dia_tool_activate (DiaTool *self)
+{
+  g_signal_emit (self, signals[ACTIVATE], 0);
+}
+
+void
+dia_tool_deactivate (DiaTool *self)
+{
+  g_signal_emit (self, signals[DEACTIVATE], 0);
+}
+
+void
+dia_tool_button_press (DiaTool        *self,
+                       GdkEventButton *event,
+                       DDisplay       *ddisp)
+{
+  g_signal_emit (self, signals[BUTTON_PRESS], 0, event, display_box_new (ddisp));
+}
+
+void
+dia_tool_button_hold (DiaTool        *self,
+                      GdkEventButton *event,
+                      DDisplay       *ddisp)
+{
+  g_signal_emit (self, signals[BUTTON_HOLD], 0, event, display_box_new (ddisp));
+
+}
+
+void
+dia_tool_double_click (DiaTool        *self,
+                       GdkEventButton *event,
+                       DDisplay       *ddisp)
+{
+  g_signal_emit (self, signals[DOUBLE_CLICK], 0, event, display_box_new (ddisp));
+
+}
+
+void
+dia_tool_button_release (DiaTool        *self,
+                         GdkEventButton *event,
+                         DDisplay       *ddisp)
+{
+  g_signal_emit (self, signals[BUTTON_RELEASE], 0, event, display_box_new (ddisp));
+
+}
+
+void
+dia_tool_motion (DiaTool        *self,
+                 GdkEventMotion *event,
+                 DDisplay       *ddisp)
+{
+  g_signal_emit (self, signals[MOTION], 0, event, display_box_new (ddisp));
+}
+
 void 
 tool_select_former(void) 
 {
@@ -51,12 +198,11 @@ tool_reset(void)
 void
 tool_get(ToolState *state)
 {
-  state->type = active_tool->type;
   state->button = active_button;
-  if (state->type == CREATE_OBJECT_TOOL) {
-    state->user_data = ((CreateObjectTool *)active_tool)->user_data;
-    state->extra_data = ((CreateObjectTool *)active_tool)->objtype->name;
-    state->invert_persistence = ((CreateObjectTool *)active_tool)->invert_persistence;
+  if (state->type == DIA_TYPE_CREATE_TOOL) {
+    state->user_data = DIA_CREATE_TOOL (active_tool)->user_data;
+    state->extra_data = DIA_CREATE_TOOL (active_tool)->objtype->name;
+    state->invert_persistence = DIA_CREATE_TOOL (active_tool)->invert_persistence;
   }
   else
   {
@@ -69,90 +215,65 @@ tool_get(ToolState *state)
 void
 tool_restore(const ToolState *state)
 {
-  tool_select(state->type, state->extra_data, state->user_data, state->button,
-              state->invert_persistence);
-}
-
-void
-tool_free(Tool *tool)
-{
-  switch(tool->type) {
-  case MODIFY_TOOL:
-    free_modify_tool(tool);
-    break;
-  case CREATE_OBJECT_TOOL:
-    free_create_object_tool(tool);
-    break;
-  case MAGNIFY_TOOL:
-    free_magnify_tool(tool);
-    break;
-  case SCROLL_TOOL:
-    free_scroll_tool(tool);
-    break;
-  case TEXTEDIT_TOOL :
-    free_textedit_tool(tool);
-    break;
-  default:
-    g_assert(0);    
-  }
+  tool_select (state->type, state->extra_data, state->user_data, state->button,
+               state->invert_persistence);
 }
 
 void 
-tool_select(ToolType type, gpointer extra_data, 
-            gpointer user_data, GtkWidget *button,
-            int invert_persistence)
+tool_select (ToolType   type,
+             gpointer   extra_data, 
+             gpointer   user_data,
+             GtkWidget *button,
+             gboolean   invert_persistence)
 {
   if (button)
     former_button = active_button;
 
-  tool_free(active_tool);
+  dia_tool_deactivate (active_tool);
+  g_object_unref (active_tool);
+  
   switch(type) {
-  case MODIFY_TOOL:
-    active_tool = create_modify_tool();
-    break;
-  case CREATE_OBJECT_TOOL:
-    active_tool =
-      create_create_object_tool(object_get_type((char *)extra_data),
-                               (void *) user_data, invert_persistence);
-    break;
-  case MAGNIFY_TOOL:
-    active_tool = create_magnify_tool();
-    break;
-  case SCROLL_TOOL:
-    active_tool = create_scroll_tool();
-    break;
-  case TEXTEDIT_TOOL :
-    active_tool = create_textedit_tool();
-    break;
-  default:
-    g_assert(0);    
+    case MODIFY_TOOL:
+      active_tool = g_object_new (DIA_TYPE_MODIFY_TOOL, NULL);
+      break;
+    case CREATE_OBJECT_TOOL:
+      active_tool = dia_create_tool_new (object_get_type ((char *) extra_data),
+                                        invert_persistence,
+                                        (void *) user_data);
+      break;
+    case MAGNIFY_TOOL:
+      active_tool = g_object_new (DIA_TYPE_MAGNIFY_TOOL, NULL);
+      break;
+    case SCROLL_TOOL:
+      active_tool = g_object_new (DIA_TYPE_SCROLL_TOOL, NULL);
+      break;
+    case TEXTEDIT_TOOL :
+      active_tool = g_object_new (DIA_TYPE_TEXT_EDIT_TOOL, NULL);
+      break;
+    default:
+      g_assert_not_reached();
   }
+
+  dia_tool_activate (active_tool);
+
   if (button)
     active_button = button;
 }
 
 void
-tool_options_dialog_show(ToolType type, gpointer extra_data, 
-                        gpointer user_data, GtkWidget *button,
-                         int invert_persistence) 
+tool_options_dialog_show (GType      type,
+                          gpointer   extra_data, 
+                          gpointer   user_data,
+                          GtkWidget *button,
+                          gboolean   invert_persistence) 
 {
   DiaObjectType *objtype;
 
-  if (active_tool->type != type) 
-    tool_select(type,extra_data,user_data,button,invert_persistence);
+  if (!G_TYPE_CHECK_INSTANCE_TYPE (active_tool, type)) 
+    tool_select (type, extra_data, user_data, button, invert_persistence);
 
-  switch(type) {
-  case MODIFY_TOOL:
-      break;
-  case CREATE_OBJECT_TOOL:
-    objtype = object_get_type((char *)extra_data);
-    defaults_show(objtype, user_data);
-    break;
-  case MAGNIFY_TOOL:
-    break;
-  case SCROLL_TOOL:
-    break;
-  case TEXTEDIT_TOOL :
-    break;
+  if (DIA_IS_CREATE_TOOL (active_tool)) {
+    objtype = object_get_type ((char *) extra_data);
+    defaults_show (objtype, user_data);
   }
 }
diff --git a/app/tools/tool.h b/app/tools/tool.h
index 174eda1a..2f55a361 100644
--- a/app/tools/tool.h
+++ b/app/tools/tool.h
@@ -20,18 +20,16 @@
 
 #include <gdk/gdk.h>
 
-typedef struct _Tool Tool;
-typedef struct _ToolState ToolState;
+G_BEGIN_DECLS
 
-typedef enum _ToolType ToolType;
+typedef struct _ToolState ToolState;
 
 #include "display.h"
 
-typedef void (* ButtonPressFunc)   (Tool *, GdkEventButton *, DDisplay *ddisp);
-typedef void (* ButtonHoldFunc)    (Tool *, GdkEventButton *, DDisplay *ddisp);
-typedef void (* DoubleClickFunc)   (Tool *, GdkEventButton *, DDisplay *ddisp);
-typedef void (* ButtonReleaseFunc) (Tool *, GdkEventButton *, DDisplay *ddisp);
-typedef void (* MotionFunc)        (Tool *, GdkEventMotion *, DDisplay *ddisp);
+#define DIA_TYPE_TOOL (dia_tool_get_type ())
+G_DECLARE_DERIVABLE_TYPE (DiaTool, dia_tool, DIA, TOOL, GObject)
+
+typedef enum _ToolType ToolType;
 
 enum _ToolType {
   CREATE_OBJECT_TOOL,
@@ -41,36 +39,52 @@ enum _ToolType {
   TEXTEDIT_TOOL
 };
 
-struct _Tool {
-  ToolType type;
-  
-  /*  Action functions  */
-  ButtonPressFunc    button_press_func;
-  ButtonHoldFunc     button_hold_func;
-  ButtonReleaseFunc  button_release_func;
-  MotionFunc         motion_func;
-  DoubleClickFunc    double_click_func;
+struct _DiaToolClass {
+  GObjectClass parent_class;
+
+  void (* activate)       (DiaTool *);
+  void (* deactivate)     (DiaTool *);
+
+  void (* button_press)   (DiaTool *, GdkEventButton *, DDisplayBox *ddisp);
+  void (* button_hold)    (DiaTool *, GdkEventButton *, DDisplayBox *ddisp);
+  void (* double_click)   (DiaTool *, GdkEventButton *, DDisplayBox *ddisp);
+  void (* button_release) (DiaTool *, GdkEventButton *, DDisplayBox *ddisp);
+  void (* motion)         (DiaTool *, GdkEventMotion *, DDisplayBox *ddisp);
 };
 
 struct _ToolState {
-  ToolType type;
+  GType type;
   gpointer extra_data;
   gpointer user_data;
   GtkWidget *button;
   int invert_persistence;
 };
 
-extern Tool *active_tool, *transient_tool;
+extern DiaTool *active_tool, *transient_tool;
 
 void tool_get(ToolState *state);
 void tool_restore(const ToolState *state);
-void tool_free(Tool *tool);
-void tool_select(ToolType type, gpointer extra_data, gpointer user_date,
-                 GtkWidget *button, int invert_persistence);
+void tool_select              (ToolType   type,
+                               gpointer   extra_data,
+                               gpointer   user_date,
+                               GtkWidget *button,
+                               int        invert_persistence);
 void tool_select_former(void);
 void tool_reset(void);
-void tool_options_dialog_show(ToolType type, gpointer extra_data, 
-                             gpointer user_data,GtkWidget *button,
-                              int invert_persistence);
+void tool_options_dialog_show (GType      type,
+                               gpointer   extra_data, 
+                               gpointer   user_data,
+                               GtkWidget *button,
+                               gboolean   invert_persistence);
+
+void dia_tool_activate       (DiaTool *self);
+void dia_tool_deactivate     (DiaTool *self);
+void dia_tool_button_press   (DiaTool *self, GdkEventButton *, DDisplay *ddisp);
+void dia_tool_button_hold    (DiaTool *self, GdkEventButton *, DDisplay *ddisp);
+void dia_tool_double_click   (DiaTool *self, GdkEventButton *, DDisplay *ddisp);
+void dia_tool_button_release (DiaTool *self, GdkEventButton *, DDisplay *ddisp);
+void dia_tool_motion         (DiaTool *self, GdkEventMotion *, DDisplay *ddisp);
+
+G_END_DECLS
 
 #endif /* TOOL_H */
diff --git a/lib/diatypes.h b/lib/diatypes.h
index 4ae01b69..1693aa84 100644
--- a/lib/diatypes.h
+++ b/lib/diatypes.h
@@ -171,12 +171,8 @@ typedef struct _TextAttributes TextAttributes;
 /* In widgets.h: */
 typedef struct _DiaSizeSelector       DiaSizeSelector;
 typedef struct _DiaSizeSelectorClass  DiaSizeSelectorClass;
-typedef struct _DiaLineStyleSelector       DiaLineStyleSelector;
-typedef struct _DiaLineStyleSelectorClass  DiaLineStyleSelectorClass;
 typedef struct _DiaColorSelector       DiaColorSelector;
 typedef struct _DiaColorSelectorClass  DiaColorSelectorClass;
-typedef struct _DiaArrowSelector       DiaArrowSelector;
-typedef struct _DiaArrowSelectorClass  DiaArrowSelectorClass;
 typedef struct _DiaFileSelector       DiaFileSelector;
 typedef struct _DiaFileSelectorClass  DiaFileSelectorClass;
 


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