]> git.sur5r.net Git - glabels/blobdiff - src/label-object.c
Imported Upstream version 3.0.0
[glabels] / src / label-object.c
index fd79e28a67d92f6f5719311467eec02ae4126633..92a8ec20862771f6fbc530086f0a93c40fecffcb 100644 (file)
@@ -1,33 +1,29 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
-
 /*
- *  (GLABELS) Label and Business Card Creation program for GNOME
- *
- *  label_object.c:  GLabels label object base class
+ *  label-object.c
+ *  Copyright (C) 2001-2009  Jim Evins <evins@snaught.com>.
  *
- *  Copyright (C) 2001-2007  Jim Evins <evins@snaught.com>.
+ *  This file is part of gLabels.
  *
- *  This program is free software; you can redistribute it and/or modify
+ *  gLabels is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
+ *  the Free Software Foundation, either version 3 of the License, or
  *  (at your option) any later version.
  *
- *  This program is distributed in the hope that it will be useful,
+ *  gLabels is distributed in the hope that it will be useful,
  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  *  GNU General Public License for more details.
  *
  *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *  along with gLabels.  If not, see <http://www.gnu.org/licenses/>.
  */
+
 #include <config.h>
 
 #include "label-object.h"
 
-#include <glib/gmem.h>
-#include <glib/gstrfuncs.h>
-#include <glib/gmessages.h>
+#include <glib/gi18n.h>
+#include <glib.h>
 #include <math.h>
 
 #include "marshal.h"
 
 #define DEFAULT_SHADOW_X_OFFSET (3.6)
 #define DEFAULT_SHADOW_Y_OFFSET (3.6)
+#define DEFAULT_SHADOW_COLOR    GL_COLOR_BLACK
 #define DEFAULT_SHADOW_OPACITY  (0.5)
 
+#define HANDLE_FILL_RGBA_ARGS      0.0,   0.75,  0.0,   0.4
+#define HANDLE_OUTLINE_RGBA_ARGS   0.0,   0.0,   0.0,   0.8
+
+#define HANDLE_OUTLINE_WIDTH_PIXELS   1.0
+#define HANDLE_PIXELS 7
+
+
 /*========================================================*/
 /* Private types.                                         */
 /*========================================================*/
 
 struct _glLabelObjectPrivate {
+
        gchar             *name;
+
+        gboolean           selected_flag;
+        glLabel           *parent;
+
        gdouble            x, y;
        gdouble            w, h;
         cairo_matrix_t     matrix;
@@ -63,42 +72,38 @@ struct _glLabelObjectPrivate {
 };
 
 enum {
-       CHANGED,
-       MOVED,
-       FLIP_ROTATE,
-       TOP,
-       BOTTOM,
-        REMOVED,
-       LAST_SIGNAL
+        CHANGED,
+        MOVED,
+        LAST_SIGNAL
 };
 
+
 /*========================================================*/
 /* Private globals.                                       */
 /*========================================================*/
 
+static guint instance = 0;
+
 static guint signals[LAST_SIGNAL] = {0};
 
-static guint instance = 0;
 
 /*========================================================*/
 /* Private function prototypes.                           */
 /*========================================================*/
 
-static void gl_label_object_finalize      (GObject            *object);
-
-static void merge_changed_cb              (glLabel            *label,
-                                          glLabelObject      *object);
+static void     gl_label_object_finalize  (GObject            *object);
 
-static void set_size                      (glLabelObject      *object,
+static void     set_size                  (glLabelObject      *object,
                                           gdouble             w,
-                                          gdouble             h);
+                                          gdouble             h,
+                                           gboolean            checkpoint);
 
 
-\f
 /*****************************************************************************/
 /* Boilerplate object stuff.                                                 */
 /*****************************************************************************/
-G_DEFINE_TYPE (glLabelObject, gl_label_object, G_TYPE_OBJECT);
+G_DEFINE_TYPE (glLabelObject, gl_label_object, G_TYPE_OBJECT)
+
 
 static void
 gl_label_object_class_init (glLabelObjectClass *class)
@@ -111,7 +116,9 @@ gl_label_object_class_init (glLabelObjectClass *class)
 
        object_class->finalize = gl_label_object_finalize;
 
-       class->set_size = set_size;
+       class->set_size     = set_size;
+       class->draw_handles = gl_label_object_draw_handles_box; /* Default style */
+       class->handle_at    = gl_label_object_box_handle_at;    /* Default style */
 
        signals[CHANGED] =
                g_signal_new ("changed",
@@ -129,43 +136,6 @@ gl_label_object_class_init (glLabelObjectClass *class)
                              G_SIGNAL_RUN_LAST,
                              G_STRUCT_OFFSET (glLabelObjectClass, moved),
                              NULL, NULL,
-                             gl_marshal_VOID__DOUBLE_DOUBLE,
-                             G_TYPE_NONE,
-                             2, G_TYPE_DOUBLE, G_TYPE_DOUBLE);
-       signals[FLIP_ROTATE] =
-               g_signal_new ("flip_rotate",
-                             G_OBJECT_CLASS_TYPE (object_class),
-                             G_SIGNAL_RUN_LAST,
-                             G_STRUCT_OFFSET (glLabelObjectClass, flip_rotate),
-                             NULL, NULL,
-                             gl_marshal_VOID__VOID,
-                             G_TYPE_NONE,
-                             0);
-       signals[TOP] =
-               g_signal_new ("top",
-                             G_OBJECT_CLASS_TYPE (object_class),
-                             G_SIGNAL_RUN_LAST,
-                             G_STRUCT_OFFSET (glLabelObjectClass, top),
-                             NULL, NULL,
-                             gl_marshal_VOID__VOID,
-                             G_TYPE_NONE,
-                             0);
-
-       signals[BOTTOM] =
-               g_signal_new ("bottom",
-                             G_OBJECT_CLASS_TYPE (object_class),
-                             G_SIGNAL_RUN_LAST,
-                             G_STRUCT_OFFSET (glLabelObjectClass, bottom),
-                             NULL, NULL,
-                             gl_marshal_VOID__VOID,
-                             G_TYPE_NONE,
-                             0);
-       signals[REMOVED] =
-               g_signal_new ("removed",
-                             G_OBJECT_CLASS_TYPE (object_class),
-                             G_SIGNAL_RUN_LAST,
-                             G_STRUCT_OFFSET (glLabelObjectClass, removed),
-                             NULL, NULL,
                              gl_marshal_VOID__VOID,
                              G_TYPE_NONE,
                              0);
@@ -173,6 +143,7 @@ gl_label_object_class_init (glLabelObjectClass *class)
        gl_debug (DEBUG_LABEL, "END");
 }
 
+
 static void
 gl_label_object_init (glLabelObject *object)
 {
@@ -188,11 +159,13 @@ gl_label_object_init (glLabelObject *object)
        object->priv->shadow_x = DEFAULT_SHADOW_X_OFFSET;
        object->priv->shadow_y = DEFAULT_SHADOW_Y_OFFSET;
        object->priv->shadow_color_node = gl_color_node_new_default ();
+        object->priv->shadow_color_node->color = DEFAULT_SHADOW_COLOR;
        object->priv->shadow_opacity = DEFAULT_SHADOW_OPACITY;
 
        gl_debug (DEBUG_LABEL, "END");
 }
 
+
 static void
 gl_label_object_finalize (GObject *object)
 {
@@ -210,6 +183,7 @@ gl_label_object_finalize (GObject *object)
        gl_debug (DEBUG_LABEL, "END");
 }
 
+
 /*****************************************************************************/
 /* New label object.                                                         */
 /*****************************************************************************/
@@ -222,13 +196,14 @@ gl_label_object_new (glLabel *label)
 
        object = g_object_new (gl_label_object_get_type(), NULL);
 
-       gl_label_object_set_parent (object, label);
+        gl_label_object_set_parent (object, label);
 
        gl_debug (DEBUG_LABEL, "END");
 
        return G_OBJECT (object);
 }
 
+
 /*****************************************************************************/
 /* Duplicate object.                                                         */
 /*****************************************************************************/
@@ -250,31 +225,31 @@ gl_label_object_dup (glLabelObject *src_object,
 
        dst_object = g_object_new (G_OBJECT_TYPE(src_object), NULL);
 
-       gl_label_object_set_parent (dst_object, label);
+        gl_label_object_set_parent (dst_object, label);
+        dst_object->priv->selected_flag = src_object->priv->selected_flag;
 
        gl_label_object_get_position      (src_object, &x, &y);
-       gl_label_object_get_size          (src_object, &w, &h);
+       gl_label_object_get_raw_size      (src_object, &w, &h);
        gl_label_object_get_matrix        (src_object, &matrix);
        gl_label_object_get_shadow_offset (src_object, &shadow_x, &shadow_y);
        shadow_color_node = gl_label_object_get_shadow_color   (src_object);
        shadow_opacity    = gl_label_object_get_shadow_opacity (src_object);
        shadow_state      = gl_label_object_get_shadow_state   (src_object);
 
-       gl_label_object_set_position (dst_object, x, y);
-       gl_label_object_set_size     (dst_object, w, h);
+       gl_label_object_set_position (dst_object, x, y, FALSE);
+       gl_label_object_set_raw_size (dst_object, w, h, FALSE);
        gl_label_object_set_matrix   (dst_object, &matrix);
-       gl_label_object_set_shadow_offset  (dst_object, shadow_x, shadow_y);
-       gl_label_object_set_shadow_color   (dst_object, shadow_color_node);
-       gl_label_object_set_shadow_opacity (dst_object, shadow_opacity);
-       gl_label_object_set_shadow_state   (dst_object, shadow_state);
+       gl_label_object_set_shadow_offset  (dst_object, shadow_x, shadow_y, FALSE);
+       gl_label_object_set_shadow_color   (dst_object, shadow_color_node, FALSE);
+       gl_label_object_set_shadow_opacity (dst_object, shadow_opacity, FALSE);
+       gl_label_object_set_shadow_state   (dst_object, shadow_state, FALSE);
 
        gl_color_node_free (&shadow_color_node);
 
-       if ( GL_LABEL_OBJECT_GET_CLASS(src_object)->copy != NULL ) {
-
+       if ( GL_LABEL_OBJECT_GET_CLASS(src_object)->copy != NULL )
+        {
                /* We have an object specific method, use it */
                GL_LABEL_OBJECT_GET_CLASS(src_object)->copy (dst_object, src_object);
-
        }
 
        gl_debug (DEBUG_LABEL, "END");
@@ -282,99 +257,89 @@ gl_label_object_dup (glLabelObject *src_object,
        return dst_object;
 }
 
+
 /*****************************************************************************/
 /* Emit "changed" signal (for derived objects).                              */
 /*****************************************************************************/
 void
 gl_label_object_emit_changed (glLabelObject *object)
 {
-       gl_debug (DEBUG_LABEL, "START");
+        gl_debug (DEBUG_LABEL, "START");
 
-       g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
+        g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
 
-       g_signal_emit (G_OBJECT(object), signals[CHANGED], 0);
+        g_signal_emit (G_OBJECT(object), signals[CHANGED], 0);
 
-       gl_debug (DEBUG_LABEL, "END");
+        gl_debug (DEBUG_LABEL, "END");
 }
 
+
 /*****************************************************************************/
 /* Set parent label of object.                                               */
 /*****************************************************************************/
 void
 gl_label_object_set_parent (glLabelObject *object,
-                           glLabel       *label)
+                            glLabel       *label)
 {
-       glLabel *old_parent;
-
-       gl_debug (DEBUG_LABEL, "START");
+        gl_debug (DEBUG_LABEL, "START");
 
-       g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
-       g_return_if_fail (label && GL_IS_LABEL (label));
-
-       old_parent = object->parent;
-       if ( old_parent != NULL ) {
-               g_signal_handlers_disconnect_by_func (old_parent,
-                                                     G_CALLBACK(merge_changed_cb),
-                                                     object);
-               gl_label_remove_object( old_parent, object );
-       }
-       gl_label_add_object( label, object );
-
-       g_signal_connect (G_OBJECT(label), "merge_changed",
-                         G_CALLBACK(merge_changed_cb), object);
-
-       g_signal_emit (G_OBJECT(object), signals[CHANGED], 0);
+        g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
+        g_return_if_fail (label && GL_IS_LABEL (label));
 
-       gl_debug (DEBUG_LABEL, "END");
+        object->priv->parent = label;
 }
 
+
 /*****************************************************************************/
 /* Get parent label of object.                                               */
 /*****************************************************************************/
 glLabel *
 gl_label_object_get_parent (glLabelObject *object)
 {
-       gl_debug (DEBUG_LABEL, "START");
+        gl_debug (DEBUG_LABEL, "START");
 
-       g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), NULL);
+        g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), NULL);
 
-       gl_debug (DEBUG_LABEL, "END");
+        gl_debug (DEBUG_LABEL, "END");
 
-       return object->parent;
+        return object->priv->parent;
 }
 
+
 /*****************************************************************************/
-/* Set remove object from parent.                                            */
+/* Select object.                                                            */
 /*****************************************************************************/
 void
-gl_label_object_remove (glLabelObject *object)
+gl_label_object_select (glLabelObject     *object)
 {
-       glLabel *parent;
-
-       gl_debug (DEBUG_LABEL, "START");
-
-       g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
-
-       parent = object->parent;
-       if ( parent != NULL ) {
-               g_signal_handlers_disconnect_by_func (parent,
-                                                     G_CALLBACK(merge_changed_cb),
-                                                     object);
-               gl_label_remove_object (parent, object);
+        object->priv->selected_flag = TRUE;
+}
 
-                g_signal_emit (G_OBJECT(object), signals[REMOVED], 0);
 
-                g_object_unref (G_OBJECT(object));
-       }
+/*****************************************************************************/
+/* Unselect object.                                                          */
+/*****************************************************************************/
+void
+gl_label_object_unselect (glLabelObject     *object)
+{
+        object->priv->selected_flag = FALSE;
+}
 
 
-       gl_debug (DEBUG_LABEL, "END");
+/*****************************************************************************/
+/* Is object selected?                                                       */
+/*****************************************************************************/
+gboolean
+gl_label_object_is_selected (glLabelObject     *object)
+{
+        return object->priv->selected_flag;
 }
 
+
 /*****************************************************************************/
 /* Set name of object.                                                       */
 /*****************************************************************************/
-void
+void    
 gl_label_object_set_name (glLabelObject *object,
                          gchar         *name)
 {
@@ -385,11 +350,12 @@ gl_label_object_set_name (glLabelObject *object,
        g_free(object->priv->name);
        object->priv->name = name;
 
-       g_signal_emit (G_OBJECT(object), signals[CHANGED], 0);
+        gl_label_object_emit_changed (object);
 
        gl_debug (DEBUG_LABEL, "END");
 }
 
+
 /*****************************************************************************/
 /* Get name of object.                                                       */
 /*****************************************************************************/
@@ -405,21 +371,28 @@ gl_label_object_get_name (glLabelObject *object)
        return g_strdup(object->priv->name);
 }
 
+
 /*****************************************************************************/
 /* Set position of object.                                                   */
 /*****************************************************************************/
-void
+void    
 gl_label_object_set_position (glLabelObject *object,
                              gdouble        x,
-                             gdouble        y)
+                             gdouble        y,
+                              gboolean       checkpoint)
 {
-       gdouble dx, dy;
+       gdouble  dx, dy;
 
        gl_debug (DEBUG_LABEL, "START");
 
        g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
 
-       if ( (x != object->priv->x) || (y != object->priv->y) ) {
+       if ( (x != object->priv->x) || (y != object->priv->y) )
+        {
+                if ( checkpoint )
+                {
+                        gl_label_checkpoint (object->priv->parent, _("Move"));
+                }
 
                dx = x - object->priv->x;
                dy = y - object->priv->y;
@@ -427,26 +400,33 @@ gl_label_object_set_position (glLabelObject *object,
                object->priv->x = x;
                object->priv->y = y;
 
-               g_signal_emit (G_OBJECT(object), signals[MOVED], 0, dx, dy);
+                g_signal_emit (G_OBJECT(object), signals[MOVED], 0);
 
        }
 
        gl_debug (DEBUG_LABEL, "END");
 }
 
+
 /*****************************************************************************/
 /* Set position of object relative to old position.                          */
 /*****************************************************************************/
-void
+void    
 gl_label_object_set_position_relative (glLabelObject *object,
                                       gdouble        dx,
-                                      gdouble        dy)
+                                      gdouble        dy,
+                                       gboolean       checkpoint)
 {
        gl_debug (DEBUG_LABEL, "START");
 
        g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
 
-       if ( (dx != 0.0) || (dy != 0.0) ) {
+       if ( (dx != 0.0) || (dy != 0.0) )
+        {
+                if ( checkpoint )
+                {
+                        gl_label_checkpoint (object->priv->parent, _("Move"));
+                }
 
                object->priv->x += dx;
                object->priv->y += dy;
@@ -455,13 +435,13 @@ gl_label_object_set_position_relative (glLabelObject *object,
                          object->priv->x,
                          object->priv->y);
 
-               g_signal_emit (G_OBJECT(object), signals[MOVED], 0, dx, dy);
-
+                g_signal_emit (G_OBJECT(object), signals[MOVED], 0);
        }
 
        gl_debug (DEBUG_LABEL, "END");
 }
 
+
 /*****************************************************************************/
 /* Get position of object.                                                   */
 /*****************************************************************************/
@@ -480,82 +460,110 @@ gl_label_object_get_position (glLabelObject *object,
        gl_debug (DEBUG_LABEL, "END");
 }
 
+
 /*---------------------------------------------------------------------------*/
 /* PRIVATE.  Default set size method.                                        */
 /*---------------------------------------------------------------------------*/
 static void
 set_size (glLabelObject *object,
          gdouble        w,
-         gdouble        h)
+         gdouble        h,
+          gboolean       checkpoint)
 {
        g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
 
-       if ( (object->priv->w != w) || (object->priv->h != h) ) {
+       if ( (object->priv->w != w) || (object->priv->h != h) )
+        {
+                if ( checkpoint )
+                {
+                        gl_label_checkpoint (object->priv->parent, _("Resize"));
+                }
 
                object->priv->w = w;
                object->priv->h = h;
 
-               g_signal_emit (G_OBJECT(object), signals[CHANGED], 0);
+                gl_label_object_emit_changed (object);
        }
 }
 
+
 /*****************************************************************************/
 /* Set size of object.                                                       */
 /*****************************************************************************/
-void
+void    
 gl_label_object_set_size (glLabelObject *object,
                          gdouble        w,
-                         gdouble        h)
+                         gdouble        h,
+                          gboolean       checkpoint)
 {
        gl_debug (DEBUG_LABEL, "START");
 
        g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
 
-       if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_size != NULL ) {
-
+       if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_size != NULL )
+        {
                /* We have an object specific method, use it */
-               GL_LABEL_OBJECT_GET_CLASS(object)->set_size (object, w, h);
+               GL_LABEL_OBJECT_GET_CLASS(object)->set_size (object, w, h, checkpoint);
 
                object->priv->aspect_ratio = h / w;
-
        }
 
+       gl_debug (DEBUG_LABEL, "END");
+}
+
+
+/*****************************************************************************/
+/* Set raw size of object.                                                   */
+/*****************************************************************************/
+void
+gl_label_object_set_raw_size (glLabelObject *object,
+                              gdouble        w,
+                              gdouble        h,
+                              gboolean       checkpoint)
+{
+       gl_debug (DEBUG_LABEL, "START");
+
+       g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
+
+        set_size (object, w, h, checkpoint);
+        object->priv->aspect_ratio = h / w;
 
        gl_debug (DEBUG_LABEL, "END");
 }
 
+
 /*****************************************************************************/
 /* Set size of object honoring current aspect ratio.                         */
 /*****************************************************************************/
-void
+void    
 gl_label_object_set_size_honor_aspect (glLabelObject *object,
                                       gdouble        w,
-                                      gdouble        h)
+                                      gdouble        h,
+                                       gboolean       checkpoint)
 {
        gl_debug (DEBUG_LABEL, "START");
 
        g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
 
-       if ( h > w*object->priv->aspect_ratio ) {
-
+       if ( h > w*object->priv->aspect_ratio )
+        {
                h = w * object->priv->aspect_ratio;
-
-       } else {
-
+       }
+        else
+        {
                w = h / object->priv->aspect_ratio;
-
        }
 
-       if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_size != NULL ) {
-
+       if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_size != NULL )
+        {
                /* We have an object specific method, use it */
-               GL_LABEL_OBJECT_GET_CLASS(object)->set_size (object, w, h);
-
+               GL_LABEL_OBJECT_GET_CLASS(object)->set_size (object, w, h, checkpoint);
        }
 
        gl_debug (DEBUG_LABEL, "END");
 }
 
+
 /*****************************************************************************/
 /* Get raw size method (don't let object content adjust size).               */
 /*****************************************************************************/
@@ -570,6 +578,7 @@ gl_label_object_get_raw_size (glLabelObject *object,
        *h = object->priv->h;
 }
 
+
 /*****************************************************************************/
 /* Get size of object.                                                       */
 /*****************************************************************************/
@@ -582,20 +591,20 @@ gl_label_object_get_size (glLabelObject *object,
 
        g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
 
-       if ( GL_LABEL_OBJECT_GET_CLASS(object)->get_size != NULL ) {
-
+       if ( GL_LABEL_OBJECT_GET_CLASS(object)->get_size != NULL )
+        {
                /* We have an object specific method, use it */
                GL_LABEL_OBJECT_GET_CLASS(object)->get_size (object, w, h);
-
-       } else {
-
+       }
+        else
+        {
                gl_label_object_get_raw_size (object, w, h);
-
        }
 
        gl_debug (DEBUG_LABEL, "END");
 }
 
+
 /*****************************************************************************/
 /* Get extent of object.                                                     */
 /*****************************************************************************/
@@ -641,6 +650,7 @@ gl_label_object_get_extent (glLabelObject *object,
        gl_debug (DEBUG_LABEL, "END");
 }
 
+
 /*****************************************************************************/
 /* Can text properties be set for this object?                               */
 /*****************************************************************************/
@@ -651,167 +661,171 @@ gl_label_object_can_text (glLabelObject     *object)
 
        g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), FALSE);
 
-       if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_font_family != NULL ) {
-
+       if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_font_family != NULL )
+        {
                return TRUE;
-
-       } else {
-
+       }
+        else
+        {
                return FALSE;
-
        }
-
 }
 
+
 /*****************************************************************************/
 /* Set font family for all text contained in object.                         */
 /*****************************************************************************/
-void
+void    
 gl_label_object_set_font_family (glLabelObject     *object,
-                                const gchar       *font_family)
+                                const gchar       *font_family,
+                                 gboolean           checkpoint)
 {
        gl_debug (DEBUG_LABEL, "START");
 
        g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
 
-       if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_font_family != NULL ) {
-
+       if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_font_family != NULL )
+        {
                /* We have an object specific method, use it */
-               GL_LABEL_OBJECT_GET_CLASS(object)->set_font_family (object, font_family);
-
+               GL_LABEL_OBJECT_GET_CLASS(object)->set_font_family (object, font_family, checkpoint);
        }
 
        gl_debug (DEBUG_LABEL, "END");
 }
 
+
 /****************************************************************************/
 /* Set font size for all text contained in object.                          */
 /****************************************************************************/
-void
+void    
 gl_label_object_set_font_size (glLabelObject     *object,
-                              gdouble            font_size)
+                              gdouble            font_size,
+                               gboolean           checkpoint)
 {
        gl_debug (DEBUG_LABEL, "START");
 
        g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
 
-       if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_font_size != NULL ) {
-
+       if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_font_size != NULL )
+        {
                /* We have an object specific method, use it */
-               GL_LABEL_OBJECT_GET_CLASS(object)->set_font_size (object, font_size);
-
+               GL_LABEL_OBJECT_GET_CLASS(object)->set_font_size (object, font_size, checkpoint);
        }
 
        gl_debug (DEBUG_LABEL, "END");
 }
 
+
 /****************************************************************************/
 /* Set font weight for all text contained in object.                        */
 /****************************************************************************/
-void
+void    
 gl_label_object_set_font_weight (glLabelObject     *object,
-                                PangoWeight        font_weight)
+                                PangoWeight        font_weight,
+                                 gboolean           checkpoint)
 {
        gl_debug (DEBUG_LABEL, "START");
 
        g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
 
-       if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_font_weight != NULL ) {
-
+       if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_font_weight != NULL )
+        {
                /* We have an object specific method, use it */
-               GL_LABEL_OBJECT_GET_CLASS(object)->set_font_weight (object, font_weight);
-
+               GL_LABEL_OBJECT_GET_CLASS(object)->set_font_weight (object, font_weight, checkpoint);
        }
 
        gl_debug (DEBUG_LABEL, "END");
 }
 
+
 /****************************************************************************/
 /* Set font italic flag for all text contained in object.                   */
 /****************************************************************************/
-void
+void    
 gl_label_object_set_font_italic_flag (glLabelObject     *object,
-                                     gboolean           font_italic_flag)
+                                     gboolean           font_italic_flag,
+                                      gboolean           checkpoint)
 {
        gl_debug (DEBUG_LABEL, "START");
 
        g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
 
-       if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_font_italic_flag != NULL ) {
-
+       if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_font_italic_flag != NULL )
+        {
                /* We have an object specific method, use it */
-               GL_LABEL_OBJECT_GET_CLASS(object)->set_font_italic_flag (object,
-                                                                        font_italic_flag);
-
+               GL_LABEL_OBJECT_GET_CLASS(object)->set_font_italic_flag (object, font_italic_flag, checkpoint);
        }
 
        gl_debug (DEBUG_LABEL, "END");
 }
 
+
 /****************************************************************************/
 /* Set text alignment for all text contained in object.                     */
 /****************************************************************************/
-void
+void    
 gl_label_object_set_text_alignment (glLabelObject     *object,
-                                   PangoAlignment     text_alignment)
+                                   PangoAlignment     text_alignment,
+                                    gboolean           checkpoint)
 {
        gl_debug (DEBUG_LABEL, "START");
 
        g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
 
-       if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_text_alignment != NULL ) {
-
+       if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_text_alignment != NULL )
+        {
                /* We have an object specific method, use it */
-               GL_LABEL_OBJECT_GET_CLASS(object)->set_text_alignment (object,
-                                                                      text_alignment);
-
+               GL_LABEL_OBJECT_GET_CLASS(object)->set_text_alignment (object, text_alignment, checkpoint);
        }
 
        gl_debug (DEBUG_LABEL, "END");
 }
 
+
 /****************************************************************************/
 /* Set text line spacing for all text contained in object.                  */
 /****************************************************************************/
-void
+void    
 gl_label_object_set_text_line_spacing (glLabelObject     *object,
-                                      gdouble            text_line_spacing)
+                                      gdouble            text_line_spacing,
+                                       gboolean           checkpoint)
 {
        gl_debug (DEBUG_LABEL, "START");
 
        g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
 
-       if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_text_line_spacing != NULL ) {
-
+       if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_text_line_spacing != NULL )
+        {
                /* We have an object specific method, use it */
-               GL_LABEL_OBJECT_GET_CLASS(object)->set_text_line_spacing (object, text_line_spacing);
-
+               GL_LABEL_OBJECT_GET_CLASS(object)->set_text_line_spacing (object, text_line_spacing, checkpoint);
        }
 
        gl_debug (DEBUG_LABEL, "END");
 }
 
+
 /****************************************************************************/
 /* Set text color for all text contained in object.                         */
 /****************************************************************************/
-void
+void    
 gl_label_object_set_text_color (glLabelObject     *object,
-                               glColorNode       *text_color_node)
+                               glColorNode       *text_color_node,
+                                gboolean           checkpoint)
 {
        gl_debug (DEBUG_LABEL, "START");
 
        g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
 
-       if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_text_color != NULL ) {
-
+       if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_text_color != NULL )
+        {
                /* We have an object specific method, use it */
-               GL_LABEL_OBJECT_GET_CLASS(object)->set_text_color (object, text_color_node);
-
+               GL_LABEL_OBJECT_GET_CLASS(object)->set_text_color (object, text_color_node, checkpoint);
        }
 
        gl_debug (DEBUG_LABEL, "END");
 }
 
+
 /*****************************************************************************/
 /* Get font family for all text contained in object.                         */
 /*****************************************************************************/
@@ -824,11 +838,10 @@ gl_label_object_get_font_family (glLabelObject     *object)
 
        g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), NULL);
 
-       if ( GL_LABEL_OBJECT_GET_CLASS(object)->get_font_family != NULL ) {
-
+       if ( GL_LABEL_OBJECT_GET_CLASS(object)->get_font_family != NULL )
+        {
                /* We have an object specific method, use it */
                ret = GL_LABEL_OBJECT_GET_CLASS(object)->get_font_family (object);
-
        }
 
        gl_debug (DEBUG_LABEL, "END");
@@ -836,6 +849,7 @@ gl_label_object_get_font_family (glLabelObject     *object)
        return ret;
 }
 
+
 /****************************************************************************/
 /* Get font size for all text contained in object.                          */
 /****************************************************************************/
@@ -848,11 +862,10 @@ gl_label_object_get_font_size (glLabelObject     *object)
 
        g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), 0.0);
 
-       if ( GL_LABEL_OBJECT_GET_CLASS(object)->get_font_size != NULL ) {
-
+       if ( GL_LABEL_OBJECT_GET_CLASS(object)->get_font_size != NULL )
+        {
                /* We have an object specific method, use it */
                ret = GL_LABEL_OBJECT_GET_CLASS(object)->get_font_size (object);
-
        }
 
        gl_debug (DEBUG_LABEL, "END");
@@ -860,6 +873,7 @@ gl_label_object_get_font_size (glLabelObject     *object)
        return ret;
 }
 
+
 /****************************************************************************/
 /* Get font weight for all text contained in object.                        */
 /****************************************************************************/
@@ -872,11 +886,10 @@ gl_label_object_get_font_weight (glLabelObject     *object)
 
        g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), PANGO_WEIGHT_NORMAL);
 
-       if ( GL_LABEL_OBJECT_GET_CLASS(object)->get_font_weight != NULL ) {
-
+       if ( GL_LABEL_OBJECT_GET_CLASS(object)->get_font_weight != NULL )
+        {
                /* We have an object specific method, use it */
                ret = GL_LABEL_OBJECT_GET_CLASS(object)->get_font_weight (object);
-
        }
 
        gl_debug (DEBUG_LABEL, "END");
@@ -884,6 +897,7 @@ gl_label_object_get_font_weight (glLabelObject     *object)
        return ret;
 }
 
+
 /****************************************************************************/
 /* Get font italic flag for all text contained in object.                   */
 /****************************************************************************/
@@ -896,11 +910,10 @@ gl_label_object_get_font_italic_flag (glLabelObject     *object)
 
        g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), FALSE);
 
-       if ( GL_LABEL_OBJECT_GET_CLASS(object)->get_font_italic_flag != NULL ) {
-
+       if ( GL_LABEL_OBJECT_GET_CLASS(object)->get_font_italic_flag != NULL )
+        {
                /* We have an object specific method, use it */
                ret = GL_LABEL_OBJECT_GET_CLASS(object)->get_font_italic_flag (object);
-
        }
 
        gl_debug (DEBUG_LABEL, "END");
@@ -908,6 +921,7 @@ gl_label_object_get_font_italic_flag (glLabelObject     *object)
        return ret;
 }
 
+
 /****************************************************************************/
 /* Get text alignment for all text contained in object.                     */
 /****************************************************************************/
@@ -920,11 +934,10 @@ gl_label_object_get_text_alignment (glLabelObject     *object)
 
        g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), PANGO_ALIGN_LEFT);
 
-       if ( GL_LABEL_OBJECT_GET_CLASS(object)->get_text_alignment != NULL ) {
-
+       if ( GL_LABEL_OBJECT_GET_CLASS(object)->get_text_alignment != NULL )
+        {
                /* We have an object specific method, use it */
                ret = GL_LABEL_OBJECT_GET_CLASS(object)->get_text_alignment (object);
-
        }
 
        gl_debug (DEBUG_LABEL, "END");
@@ -932,6 +945,7 @@ gl_label_object_get_text_alignment (glLabelObject     *object)
        return ret;
 }
 
+
 /****************************************************************************/
 /* Get text line spacing for all text contained in object.                  */
 /****************************************************************************/
@@ -944,11 +958,10 @@ gl_label_object_get_text_line_spacing (glLabelObject     *object)
 
        g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), 0.0);
 
-       if ( GL_LABEL_OBJECT_GET_CLASS(object)->get_text_line_spacing != NULL ) {
-
+       if ( GL_LABEL_OBJECT_GET_CLASS(object)->get_text_line_spacing != NULL )
+        {
                /* We have an object specific method, use it */
                ret = GL_LABEL_OBJECT_GET_CLASS(object)->get_text_line_spacing (object);
-
        }
 
        gl_debug (DEBUG_LABEL, "END");
@@ -956,6 +969,7 @@ gl_label_object_get_text_line_spacing (glLabelObject     *object)
        return ret;
 }
 
+
 /****************************************************************************/
 /* Get text color for all text contained in object.                         */
 /****************************************************************************/
@@ -968,11 +982,10 @@ gl_label_object_get_text_color (glLabelObject     *object)
 
        g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), 0);
 
-       if ( GL_LABEL_OBJECT_GET_CLASS(object)->get_text_color != NULL ) {
-
+       if ( GL_LABEL_OBJECT_GET_CLASS(object)->get_text_color != NULL )
+        {
                /* We have an object specific method, use it */
                ret = GL_LABEL_OBJECT_GET_CLASS(object)->get_text_color (object);
-
        }
 
        gl_debug (DEBUG_LABEL, "END");
@@ -980,6 +993,7 @@ gl_label_object_get_text_color (glLabelObject     *object)
        return ret;
 }
 
+
 /*****************************************************************************/
 /* Can fill properties be set for this object?                               */
 /*****************************************************************************/
@@ -990,39 +1004,40 @@ gl_label_object_can_fill (glLabelObject     *object)
 
        g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), FALSE);
 
-       if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_fill_color != NULL ) {
-
+       if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_fill_color != NULL )
+        {
                return TRUE;
-
-       } else {
-
+       }
+        else
+        {
                return FALSE;
-
        }
 
 }
 
+
 /****************************************************************************/
 /* Set fill color for object.                                               */
 /****************************************************************************/
-void
+void    
 gl_label_object_set_fill_color (glLabelObject     *object,
-                               glColorNode       *fill_color_node)
+                               glColorNode       *fill_color_node,
+                                gboolean           checkpoint)
 {
        gl_debug (DEBUG_LABEL, "START");
 
        g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
 
-       if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_fill_color != NULL ) {
-
+       if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_fill_color != NULL )
+        {
                /* We have an object specific method, use it */
-               GL_LABEL_OBJECT_GET_CLASS(object)->set_fill_color (object, fill_color_node);
-
+               GL_LABEL_OBJECT_GET_CLASS(object)->set_fill_color (object, fill_color_node, checkpoint);
        }
 
        gl_debug (DEBUG_LABEL, "END");
 }
 
+
 /****************************************************************************/
 /* Get fill color for object.                                               */
 /****************************************************************************/
@@ -1035,11 +1050,10 @@ gl_label_object_get_fill_color (glLabelObject     *object)
 
        g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), 0);
 
-       if ( GL_LABEL_OBJECT_GET_CLASS(object)->get_fill_color != NULL ) {
-
+       if ( GL_LABEL_OBJECT_GET_CLASS(object)->get_fill_color != NULL )
+        {
                /* We have an object specific method, use it */
                ret = GL_LABEL_OBJECT_GET_CLASS(object)->get_fill_color (object);
-
        }
 
        gl_debug (DEBUG_LABEL, "END");
@@ -1047,6 +1061,7 @@ gl_label_object_get_fill_color (glLabelObject     *object)
        return ret;
 }
 
+
 /*****************************************************************************/
 /* Can line color property be set for this object?                           */
 /*****************************************************************************/
@@ -1057,39 +1072,40 @@ gl_label_object_can_line_color (glLabelObject     *object)
 
        g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), FALSE);
 
-       if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_line_color != NULL ) {
-
+       if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_line_color != NULL )
+        {
                return TRUE;
-
-       } else {
-
+       }
+        else
+        {
                return FALSE;
-
        }
 
 }
 
+
 /****************************************************************************/
 /* Set line color for object.                                               */
 /****************************************************************************/
-void
+void    
 gl_label_object_set_line_color (glLabelObject     *object,
-                               glColorNode       *line_color_node)
+                               glColorNode       *line_color_node,
+                                gboolean           checkpoint)
 {
        gl_debug (DEBUG_LABEL, "START");
 
        g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
 
-       if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_line_color != NULL ) {
-
+       if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_line_color != NULL )
+        {
                /* We have an object specific method, use it */
-               GL_LABEL_OBJECT_GET_CLASS(object)->set_line_color (object, line_color_node);
-
+               GL_LABEL_OBJECT_GET_CLASS(object)->set_line_color (object, line_color_node, checkpoint);
        }
 
        gl_debug (DEBUG_LABEL, "END");
 }
 
+
 /****************************************************************************/
 /* Get line color for object.                                               */
 /****************************************************************************/
@@ -1102,11 +1118,10 @@ gl_label_object_get_line_color (glLabelObject     *object)
 
        g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), 0);
 
-       if ( GL_LABEL_OBJECT_GET_CLASS(object)->get_line_color != NULL ) {
-
+       if ( GL_LABEL_OBJECT_GET_CLASS(object)->get_line_color != NULL )
+        {
                /* We have an object specific method, use it */
                ret = GL_LABEL_OBJECT_GET_CLASS(object)->get_line_color (object);
-
        }
 
        gl_debug (DEBUG_LABEL, "END");
@@ -1114,6 +1129,7 @@ gl_label_object_get_line_color (glLabelObject     *object)
        return ret;
 }
 
+
 /*****************************************************************************/
 /* Can line width property be set for this object?                           */
 /*****************************************************************************/
@@ -1124,39 +1140,40 @@ gl_label_object_can_line_width (glLabelObject     *object)
 
        g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), FALSE);
 
-       if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_line_width != NULL ) {
-
+       if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_line_width != NULL )
+        {
                return TRUE;
-
-       } else {
-
+       }
+        else
+        {
                return FALSE;
-
        }
 
 }
 
+
 /****************************************************************************/
 /* Set line width for object.                                               */
 /****************************************************************************/
-void
+void    
 gl_label_object_set_line_width (glLabelObject     *object,
-                               gdouble            line_width)
+                               gdouble            line_width,
+                                gboolean           checkpoint)
 {
        gl_debug (DEBUG_LABEL, "START");
 
        g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
 
-       if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_line_width != NULL ) {
-
+       if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_line_width != NULL )
+        {
                /* We have an object specific method, use it */
-               GL_LABEL_OBJECT_GET_CLASS(object)->set_line_width (object, line_width);
-
+               GL_LABEL_OBJECT_GET_CLASS(object)->set_line_width (object, line_width, checkpoint);
        }
 
        gl_debug (DEBUG_LABEL, "END");
 }
 
+
 /****************************************************************************/
 /* Get line width for object.                                               */
 /****************************************************************************/
@@ -1169,11 +1186,10 @@ gl_label_object_get_line_width (glLabelObject     *object)
 
        g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), 0.0);
 
-       if ( GL_LABEL_OBJECT_GET_CLASS(object)->get_line_width != NULL ) {
-
+       if ( GL_LABEL_OBJECT_GET_CLASS(object)->get_line_width != NULL )
+        {
                /* We have an object specific method, use it */
                ret = GL_LABEL_OBJECT_GET_CLASS(object)->get_line_width (object);
-
        }
 
        gl_debug (DEBUG_LABEL, "END");
@@ -1181,12 +1197,14 @@ gl_label_object_get_line_width (glLabelObject     *object)
        return ret;
 }
 
+
 /****************************************************************************/
 /* Set shadow state of object.                                              */
 /****************************************************************************/
-void
+void    
 gl_label_object_set_shadow_state (glLabelObject     *object,
-                                 gboolean           state)
+                                 gboolean           state,
+                                  gboolean           checkpoint)
 {
        gl_debug (DEBUG_LABEL, "START");
 
@@ -1194,13 +1212,20 @@ gl_label_object_set_shadow_state (glLabelObject     *object,
 
        if (object->priv->shadow_state != state)
        {
+                if ( checkpoint )
+                {
+                        gl_label_checkpoint (object->priv->parent, _("Shadow state"));
+                }
+
                object->priv->shadow_state = state;
+
                gl_label_object_emit_changed (object);
        }
 
        gl_debug (DEBUG_LABEL, "END");
 }
 
+
 /****************************************************************************/
 /* Get shadow state of object.                                              */
 /****************************************************************************/
@@ -1214,13 +1239,15 @@ gl_label_object_get_shadow_state (glLabelObject     *object)
        return object->priv->shadow_state;
 }
 
+
 /****************************************************************************/
 /* Set offset of object's shadow.                                           */
 /****************************************************************************/
-void
+void    
 gl_label_object_set_shadow_offset (glLabelObject     *object,
                                   gdouble            x,
-                                  gdouble            y)
+                                  gdouble            y,
+                                   gboolean           checkpoint)
 {
        gl_debug (DEBUG_LABEL, "START");
 
@@ -1228,6 +1255,11 @@ gl_label_object_set_shadow_offset (glLabelObject     *object,
 
        if ( (x != object->priv->shadow_x) || (y != object->priv->shadow_y) )
        {
+                if ( checkpoint )
+                {
+                        gl_label_checkpoint (object->priv->parent, _("Shadow offset"));
+                }
+
                object->priv->shadow_x = x;
                object->priv->shadow_y = y;
 
@@ -1237,6 +1269,7 @@ gl_label_object_set_shadow_offset (glLabelObject     *object,
        gl_debug (DEBUG_LABEL, "END");
 }
 
+
 /****************************************************************************/
 /* Get offset of object's shadow.                                           */
 /****************************************************************************/
@@ -1255,12 +1288,14 @@ gl_label_object_get_shadow_offset (glLabelObject     *object,
        gl_debug (DEBUG_LABEL, "END");
 }
 
+
 /****************************************************************************/
 /* Set color of object's shadow.                                            */
 /****************************************************************************/
-void
+void    
 gl_label_object_set_shadow_color (glLabelObject     *object,
-                                 glColorNode       *color_node)
+                                 glColorNode       *color_node,
+                                  gboolean           checkpoint)
 {
        gl_debug (DEBUG_LABEL, "START");
 
@@ -1268,14 +1303,21 @@ gl_label_object_set_shadow_color (glLabelObject     *object,
 
        if ( !gl_color_node_equal (object->priv->shadow_color_node, color_node ))
        {
+                if ( checkpoint )
+                {
+                        gl_label_checkpoint (object->priv->parent, _("Shadow color"));
+                }
+
                gl_color_node_free (&(object->priv->shadow_color_node));
                object->priv->shadow_color_node = gl_color_node_dup (color_node);
-               gl_label_object_emit_changed (GL_LABEL_OBJECT(object));
+
+               gl_label_object_emit_changed (object);
        }
 
        gl_debug (DEBUG_LABEL, "END");
 }
 
+
 /****************************************************************************/
 /* Get color of object's shadow.                                            */
 /****************************************************************************/
@@ -1289,12 +1331,14 @@ gl_label_object_get_shadow_color (glLabelObject     *object)
        return gl_color_node_dup (object->priv->shadow_color_node);
 }
 
+
 /****************************************************************************/
 /* Set opacity of object's shadow.                                          */
 /****************************************************************************/
-void
+void    
 gl_label_object_set_shadow_opacity (glLabelObject     *object,
-                                   gdouble            alpha)
+                                   gdouble            alpha,
+                                    gboolean           checkpoint)
 {
        gl_debug (DEBUG_LABEL, "START");
 
@@ -1302,13 +1346,20 @@ gl_label_object_set_shadow_opacity (glLabelObject     *object,
 
        if (object->priv->shadow_opacity != alpha)
        {
-               object->priv->shadow_opacity = alpha;
+                if ( checkpoint )
+                {
+                        gl_label_checkpoint (object->priv->parent, _("Shadow opacity"));
+                }
+
+                object->priv->shadow_opacity = alpha;
+
                gl_label_object_emit_changed (object);
        }
 
        gl_debug (DEBUG_LABEL, "END");
 }
 
+
 /****************************************************************************/
 /* Get opacity of object's shadow.                                          */
 /****************************************************************************/
@@ -1322,6 +1373,7 @@ gl_label_object_get_shadow_opacity (glLabelObject     *object)
        return object->priv->shadow_opacity;
 }
 
+
 /****************************************************************************/
 /* Flip object horizontally.                                                */
 /****************************************************************************/
@@ -1337,11 +1389,10 @@ gl_label_object_flip_horiz (glLabelObject *object)
         cairo_matrix_init_scale (&flip_matrix, -1.0, 1.0);
         cairo_matrix_multiply (&object->priv->matrix, &object->priv->matrix, &flip_matrix);
 
-       g_signal_emit (G_OBJECT(object), signals[FLIP_ROTATE], 0);
-
        gl_debug (DEBUG_LABEL, "END");
 }
 
+
 /****************************************************************************/
 /* Flip object vertically.                                                  */
 /****************************************************************************/
@@ -1357,11 +1408,10 @@ gl_label_object_flip_vert (glLabelObject *object)
         cairo_matrix_init_scale (&flip_matrix, 1.0, -1.0);
         cairo_matrix_multiply (&object->priv->matrix, &object->priv->matrix, &flip_matrix);
 
-       g_signal_emit (G_OBJECT(object), signals[FLIP_ROTATE], 0);
-
        gl_debug (DEBUG_LABEL, "END");
 }
 
+
 /****************************************************************************/
 /* Rotate object.                                                           */
 /****************************************************************************/
@@ -1378,11 +1428,10 @@ gl_label_object_rotate (glLabelObject *object,
         cairo_matrix_init_rotate (&rotate_matrix, theta_degs*(G_PI/180.));
         cairo_matrix_multiply (&object->priv->matrix, &object->priv->matrix, &rotate_matrix);
 
-       g_signal_emit (G_OBJECT(object), signals[FLIP_ROTATE], 0);
-
        gl_debug (DEBUG_LABEL, "END");
 }
 
+
 /****************************************************************************/
 /* Set raw affine                                                           */
 /****************************************************************************/
@@ -1397,6 +1446,7 @@ gl_label_object_set_matrix (glLabelObject  *object,
         object->priv->matrix = *matrix;
 }
 
+
 /****************************************************************************/
 /* Get raw affine                                                           */
 /****************************************************************************/
@@ -1411,53 +1461,6 @@ gl_label_object_get_matrix (glLabelObject  *object,
         *matrix = object->priv->matrix;
 }
 
-/****************************************************************************/
-/* Bring label object to front/top.                                         */
-/****************************************************************************/
-void
-gl_label_object_raise_to_top (glLabelObject *object)
-{
-       glLabel *label;
-
-       gl_debug (DEBUG_LABEL, "START");
-
-       label = object->parent;
-
-       gl_label_raise_object_to_top (label, object);
-
-       g_signal_emit (G_OBJECT(object), signals[TOP], 0);
-
-       gl_debug (DEBUG_LABEL, "END");
-}
-
-/****************************************************************************/
-/* Send label object to rear/bottom.                                        */
-/****************************************************************************/
-void
-gl_label_object_lower_to_bottom (glLabelObject *object)
-{
-       glLabel *label;
-
-       gl_debug (DEBUG_LABEL, "START");
-
-       label = object->parent;
-
-       gl_label_lower_object_to_bottom (label, object);
-
-       g_signal_emit (G_OBJECT(object), signals[BOTTOM], 0);
-
-       gl_debug (DEBUG_LABEL, "END");
-}
-
-/*--------------------------------------------------------------------------*/
-/* PRIVATE.  Label's merge data changed callback.                           */
-/*--------------------------------------------------------------------------*/
-static void
-merge_changed_cb (glLabel       *label,
-                 glLabelObject *object)
-{
-       gl_label_object_emit_changed (object);
-}
 
 /*****************************************************************************/
 /* Draw object                                                               */
@@ -1484,8 +1487,8 @@ gl_label_object_draw (glLabelObject *object,
         cairo_save (cr);
         cairo_translate (cr, x0, y0);
 
-        if ( GL_LABEL_OBJECT_GET_CLASS(object)->draw_shadow != NULL ) {
-
+        if ( GL_LABEL_OBJECT_GET_CLASS(object)->draw_shadow != NULL )
+        {
                 shadow_state = gl_label_object_get_shadow_state (object);
 
                 if ( shadow_state )
@@ -1505,8 +1508,8 @@ gl_label_object_draw (glLabelObject *object,
                 }
         }
 
-        if ( GL_LABEL_OBJECT_GET_CLASS(object)->draw_object != NULL ) {
-
+        if ( GL_LABEL_OBJECT_GET_CLASS(object)->draw_object != NULL )
+        {
                 cairo_save (cr);
                 cairo_transform (cr, &matrix);
 
@@ -1523,3 +1526,369 @@ gl_label_object_draw (glLabelObject *object,
        gl_debug (DEBUG_LABEL, "END");
 }
 
+
+/*****************************************************************************/
+/* Is object located at coordinates.                                         */
+/*****************************************************************************/
+gboolean
+gl_label_object_is_located_at (glLabelObject     *object,
+                               cairo_t           *cr,
+                               gdouble            x_pixels,
+                               gdouble            y_pixels)
+{
+        gboolean            ret_val = FALSE;
+        gdouble             x0, y0;
+        cairo_matrix_t      matrix;
+        gdouble             x, y;
+
+       gl_debug (DEBUG_LABEL, "START");
+
+       g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), FALSE);
+
+        if ( GL_LABEL_OBJECT_GET_CLASS(object)->draw_object != NULL )
+        {
+
+                gl_label_object_get_position (object, &x0, &y0);
+                gl_label_object_get_matrix (object, &matrix);
+
+                cairo_save (cr);
+
+                cairo_translate (cr, x0, y0);
+                cairo_transform (cr, &matrix);
+
+                x = x_pixels;
+                y = y_pixels;
+                cairo_device_to_user (cr, &x, &y);
+
+                ret_val = GL_LABEL_OBJECT_GET_CLASS(object)->object_at (object, cr, x, y);
+
+                cairo_restore (cr);
+        }
+
+       gl_debug (DEBUG_LABEL, "END");
+
+        return ret_val;
+}
+
+
+/*****************************************************************************/
+/* Draw object handles                                                       */
+/*****************************************************************************/
+void
+gl_label_object_draw_handles (glLabelObject     *object,
+                              cairo_t           *cr)
+{
+        gdouble        x0, y0;
+        cairo_matrix_t matrix;
+
+       gl_debug (DEBUG_LABEL, "START");
+
+       g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
+
+        if ( GL_LABEL_OBJECT_GET_CLASS(object)->draw_object != NULL )
+        {
+
+                gl_label_object_get_position (object, &x0, &y0);
+                gl_label_object_get_matrix (object, &matrix);
+
+                cairo_save (cr);
+
+                cairo_translate (cr, x0, y0);
+                cairo_transform (cr, &matrix);
+
+                GL_LABEL_OBJECT_GET_CLASS(object)->draw_handles (object, cr);
+
+                cairo_restore (cr);
+        }
+
+       gl_debug (DEBUG_LABEL, "END");
+}
+
+
+/*--------------------------------------------------------------------------*/
+/* Draw individual handle                                                   */
+/*--------------------------------------------------------------------------*/
+static void
+draw_handle (cairo_t                *cr,
+             glLabelObject          *object,
+             gdouble                 x_handle,
+             gdouble                 y_handle)
+{
+        gdouble scale_x, scale_y;
+
+
+        gl_debug (DEBUG_VIEW, "START");
+
+        cairo_save (cr);
+
+        cairo_translate (cr, x_handle, y_handle);
+
+        scale_x = 1.0;
+        scale_y = 1.0;
+        cairo_device_to_user_distance (cr, &scale_x, &scale_y);
+        cairo_scale (cr, scale_x, scale_y);
+
+        cairo_rectangle (cr,
+                         -HANDLE_PIXELS/2.0, -HANDLE_PIXELS/2.0,
+                         HANDLE_PIXELS, HANDLE_PIXELS);
+
+        cairo_set_source_rgba (cr, HANDLE_FILL_RGBA_ARGS);
+        cairo_fill_preserve (cr);
+                               
+        cairo_set_line_width (cr, HANDLE_OUTLINE_WIDTH_PIXELS);
+        cairo_set_source_rgba (cr, HANDLE_OUTLINE_RGBA_ARGS);
+        cairo_stroke (cr);
+
+        cairo_restore (cr);
+
+        gl_debug (DEBUG_VIEW, "END");
+}
+
+
+/*--------------------------------------------------------------------------*/
+/* Create handle path                                                       */
+/*--------------------------------------------------------------------------*/
+static void
+create_handle_path (cairo_t                *cr,
+                    glLabelObject          *object,
+                    gdouble                 x_handle,
+                    gdouble                 y_handle)
+{
+        gdouble scale_x, scale_y;
+
+
+        gl_debug (DEBUG_VIEW, "START");
+
+        cairo_save (cr);
+
+        cairo_translate (cr, x_handle, y_handle);
+
+        scale_x = 1.0;
+        scale_y = 1.0;
+        cairo_device_to_user_distance (cr, &scale_x, &scale_y);
+        cairo_scale (cr, scale_x, scale_y);
+
+        cairo_rectangle (cr,
+                         -HANDLE_PIXELS/2.0, -HANDLE_PIXELS/2.0,
+                         HANDLE_PIXELS, HANDLE_PIXELS);
+
+        cairo_restore (cr);
+
+        gl_debug (DEBUG_VIEW, "END");
+}
+
+
+/*****************************************************************************/
+/* Draw box style handles.                                                   */
+/*****************************************************************************/
+void
+gl_label_object_draw_handles_box (glLabelObject     *object,
+                                  cairo_t           *cr)
+{
+        gdouble w, h;
+
+        gl_label_object_get_size (GL_LABEL_OBJECT(object), &w, &h);
+
+        /* North */
+        draw_handle (cr, object, w/2, 0);
+
+        /* North East */
+        draw_handle (cr, object, w, 0);
+
+        /* East */
+        draw_handle (cr, object, w, h/2);
+
+        /* South East */
+        draw_handle (cr, object, w, h);
+
+        /* South */
+        draw_handle (cr, object, w/2, h);
+
+        /* South West */
+        draw_handle (cr, object, 0, h);
+
+        /* West */
+        draw_handle (cr, object, 0, h/2);
+
+        /* North West */
+        draw_handle (cr, object, 0, 0);
+}
+
+
+/*****************************************************************************/
+/* Draw line style handles.                                                  */
+/*****************************************************************************/
+void
+gl_label_object_draw_handles_line (glLabelObject     *object,
+                                   cairo_t           *cr)
+{
+        gdouble w, h;
+
+        gl_label_object_get_size (GL_LABEL_OBJECT(object), &w, &h);
+
+        /* P2 */
+        draw_handle (cr, object, w, h);
+
+        /* P1 */
+        draw_handle (cr, object, 0, 0);
+}
+
+
+/*****************************************************************************/
+/* Get handle at given coordinates, if any.                                  */
+/*****************************************************************************/
+glLabelObjectHandle
+gl_label_object_handle_at (glLabelObject     *object,
+                           cairo_t           *cr,
+                           gdouble            x_pixels,
+                           gdouble            y_pixels)
+{
+        glLabelObjectHandle handle = GL_LABEL_OBJECT_HANDLE_NONE;
+        gdouble             x0, y0;
+        cairo_matrix_t      matrix;
+        gdouble             x, y;
+
+       gl_debug (DEBUG_LABEL, "START");
+
+       g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), handle);
+
+        if ( GL_LABEL_OBJECT_GET_CLASS(object)->draw_object != NULL )
+        {
+
+                gl_label_object_get_position (object, &x0, &y0);
+                gl_label_object_get_matrix (object, &matrix);
+
+                cairo_save (cr);
+
+                cairo_translate (cr, x0, y0);
+                cairo_transform (cr, &matrix);
+
+                x = x_pixels;
+                y = y_pixels;
+                cairo_device_to_user (cr, &x, &y);
+
+                handle = GL_LABEL_OBJECT_GET_CLASS(object)->handle_at (object, cr, x, y);
+
+                cairo_restore (cr);
+        }
+
+       gl_debug (DEBUG_LABEL, "END");
+
+        return handle;
+}
+
+
+/*****************************************************************************/
+/* Get handle at given coordinates for box style handles, if any.            */
+/*****************************************************************************/
+glLabelObjectHandle
+gl_label_object_box_handle_at (glLabelObject     *object,
+                               cairo_t           *cr,
+                               gdouble            x,
+                               gdouble            y)
+{
+        gdouble w, h;
+
+        gl_label_object_get_size (GL_LABEL_OBJECT(object), &w, &h);
+
+        /* South East */
+        create_handle_path (cr, object, w, h);
+        if (cairo_in_fill (cr, x, y))
+        {
+                return GL_LABEL_OBJECT_HANDLE_SE;
+        }
+        
+        /* South West */
+        create_handle_path (cr, object, 0, h);
+        if (cairo_in_fill (cr, x, y))
+        {
+                return GL_LABEL_OBJECT_HANDLE_SW;
+        }
+
+        /* North East */
+        create_handle_path (cr, object, w, 0);
+        if (cairo_in_fill (cr, x, y))
+        {
+                return GL_LABEL_OBJECT_HANDLE_NE;
+        }
+
+        /* North West */
+        create_handle_path (cr, object, 0, 0);
+        if (cairo_in_fill (cr, x, y))
+        {
+                return GL_LABEL_OBJECT_HANDLE_NW;
+        }
+
+        /* East */
+        create_handle_path (cr, object, w, h/2);
+        if (cairo_in_fill (cr, x, y))
+        {
+                return GL_LABEL_OBJECT_HANDLE_E;
+        }
+
+        /* South */
+        create_handle_path (cr, object, w/2, h);
+        if (cairo_in_fill (cr, x, y))
+        {
+                return GL_LABEL_OBJECT_HANDLE_S;
+        }
+
+        /* West */
+        create_handle_path (cr, object, 0, h/2);
+        if (cairo_in_fill (cr, x, y))
+        {
+                return GL_LABEL_OBJECT_HANDLE_W;
+        }
+
+        /* North */
+        create_handle_path (cr, object, w/2, 0);
+        if (cairo_in_fill (cr, x, y))
+        {
+                return GL_LABEL_OBJECT_HANDLE_N;
+        }
+
+        return GL_LABEL_OBJECT_HANDLE_NONE;
+}
+
+
+/*****************************************************************************/
+/* Get handle at given coordinates for line style handles, if any.           */
+/*****************************************************************************/
+glLabelObjectHandle
+gl_label_object_line_handle_at (glLabelObject     *object,
+                                cairo_t           *cr,
+                                gdouble            x,
+                                gdouble            y)
+{
+        gdouble w, h;
+
+        gl_label_object_get_size (GL_LABEL_OBJECT(object), &w, &h);
+
+        /* P2 */
+        create_handle_path (cr, object, w, h);
+        if (cairo_in_fill (cr, x, y))
+        {
+                return GL_LABEL_OBJECT_HANDLE_P2;
+        }
+        
+        /* P1 */
+        create_handle_path (cr, object, 0, h);
+        if (cairo_in_fill (cr, x, y))
+        {
+                return GL_LABEL_OBJECT_HANDLE_P1;
+        }
+
+        return GL_LABEL_OBJECT_HANDLE_NONE;
+}
+
+
+
+
+/*
+ * Local Variables:       -- emacs
+ * mode: C                -- emacs
+ * c-basic-offset: 8      -- emacs
+ * tab-width: 8           -- emacs
+ * indent-tabs-mode: nil  -- emacs
+ * End:                   -- emacs
+ */