[glabels] Refactored Cut/Copy/Paste code



commit 4e81eb872bef66a6b76e9ffd74c09a83323f802e
Author: Jim Evins <evins snaught com>
Date:   Sat Dec 12 01:16:35 2009 -0500

    Refactored Cut/Copy/Paste code
    
    Now offers everything (glabels xml, text, or image) on the standard clipboard.
    Will now paste text or images from other programs as new objects.

 src/label-image.c  |   73 +++++++----
 src/label-image.h  |    3 +
 src/label-object.c |   21 ---
 src/label-object.h |    7 -
 src/label-text.c   |   61 +++++-----
 src/label-text.h   |    5 +
 src/label.c        |  353 +++++++++++++++++++++++++++++++++++++++++++++------
 src/label.h        |   14 +--
 src/ui-commands.c  |   33 +-----
 src/ui.h           |    3 -
 src/window.c       |   26 ++---
 11 files changed, 412 insertions(+), 187 deletions(-)
---
diff --git a/src/label-image.c b/src/label-image.c
index 001ed36..fe463b3 100644
--- a/src/label-image.c
+++ b/src/label-image.c
@@ -59,9 +59,6 @@ static void gl_label_image_finalize      (GObject           *object);
 static void copy                         (glLabelObject     *dst_object,
 					  glLabelObject     *src_object);
 
-static void copy_to_clipboard            (glLabelObject     *object,
-                                          GtkClipboard      *clipboard);
-
 static void set_size                     (glLabelObject     *object,
                                           gdouble            w,
                                           gdouble            h);
@@ -92,7 +89,6 @@ gl_label_image_class_init (glLabelImageClass *class)
 	gl_label_image_parent_class = g_type_class_peek_parent (class);
 
 	label_object_class->copy              = copy;
-	label_object_class->copy_to_clipboard = copy_to_clipboard;
 	label_object_class->set_size          = set_size;
         label_object_class->draw_object       = draw_object;
         label_object_class->draw_shadow       = NULL;
@@ -196,30 +192,6 @@ copy (glLabelObject *dst_object,
 
 
 /*---------------------------------------------------------------------------*/
-/* Private.  Copy pixbuf to clipboard.                                       */
-/*---------------------------------------------------------------------------*/
-static void
-copy_to_clipboard (glLabelObject     *object,
-                   GtkClipboard      *clipboard)
-{
-        glLabelImage *limage;
-
-	gl_debug (DEBUG_LABEL, "START");
-
-	g_return_if_fail (object && GL_IS_LABEL_IMAGE (object));
-
-        limage = GL_LABEL_IMAGE (object);
-
-        if ( limage->priv->pixbuf != NULL )
-        {
-                gtk_clipboard_set_image (clipboard, limage->priv->pixbuf);
-        }
-
-	gl_debug (DEBUG_LABEL, "END");
-}
-
-
-/*---------------------------------------------------------------------------*/
 /* PRIVATE.  Set size method.                                                */
 /*---------------------------------------------------------------------------*/
 static void
@@ -313,6 +285,51 @@ gl_label_image_set_filename (glLabelImage *limage,
 }
 
 
+void
+gl_label_image_set_pixbuf (glLabelImage  *limage,
+                           GdkPixbuf     *pixbuf)
+{
+	glTextNode  *old_filename;
+	GHashTable  *pixbuf_cache;
+        gchar       *name;
+	gdouble      image_w, image_h;
+
+	gl_debug (DEBUG_LABEL, "START");
+
+	g_return_if_fail (limage && GL_IS_LABEL_IMAGE (limage));
+	g_return_if_fail (pixbuf && GDK_IS_PIXBUF (pixbuf));
+
+	old_filename = limage->priv->filename;
+
+	pixbuf_cache = gl_label_get_pixbuf_cache (GL_LABEL_OBJECT(limage)->parent);
+
+	/* Remove reference to previous pixbuf from cache, if needed. */
+	if ( !old_filename->field_flag && (old_filename->data != NULL) ) {
+		gl_pixbuf_cache_remove_pixbuf (pixbuf_cache, old_filename->data);
+	}
+
+	/* Set new filename. */
+        name = g_compute_checksum_for_data (G_CHECKSUM_MD5,
+                                            gdk_pixbuf_get_pixels (pixbuf),
+                                            gdk_pixbuf_get_rowstride (pixbuf)*gdk_pixbuf_get_height (pixbuf));
+	limage->priv->filename = gl_text_node_new_from_text(name);
+	gl_text_node_free (&old_filename);
+
+        limage->priv->pixbuf = g_object_ref (pixbuf);
+        gl_pixbuf_cache_add_pixbuf (pixbuf_cache, name, pixbuf);
+
+        g_free (name);
+
+	image_w = gdk_pixbuf_get_width (limage->priv->pixbuf);
+	image_h = gdk_pixbuf_get_height (limage->priv->pixbuf);
+	gl_label_object_set_size (GL_LABEL_OBJECT(limage), image_w, image_h);
+
+	gl_label_object_emit_changed (GL_LABEL_OBJECT(limage));
+
+	gl_debug (DEBUG_LABEL, "END");
+}
+
+
 /*****************************************************************************/
 /* Get object params.                                                        */
 /*****************************************************************************/
diff --git a/src/label-image.h b/src/label-image.h
index 15216c3..237badd 100644
--- a/src/label-image.h
+++ b/src/label-image.h
@@ -57,6 +57,9 @@ GObject         *gl_label_image_new          (glLabel       *label);
 void             gl_label_image_set_filename (glLabelImage  *limage,
 					      glTextNode    *filename);
 
+void             gl_label_image_set_pixbuf   (glLabelImage  *limage,
+					      GdkPixbuf     *pixbuf);
+
 glTextNode      *gl_label_image_get_filename (glLabelImage  *limage);
 
 const GdkPixbuf *gl_label_image_get_pixbuf   (glLabelImage  *limage,
diff --git a/src/label-object.c b/src/label-object.c
index 55540bf..da63b28 100644
--- a/src/label-object.c
+++ b/src/label-object.c
@@ -242,27 +242,6 @@ gl_label_object_dup (glLabelObject *src_object,
 
 
 /*****************************************************************************/
-/* Copy object interesting object data to clipboard.                         */
-/*****************************************************************************/
-void
-gl_label_object_copy_to_clipboard (glLabelObject     *object,
-                                   GtkClipboard      *clipboard)
-{
-        gl_debug (DEBUG_LABEL, "START");
-
-        g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
-
-	if ( GL_LABEL_OBJECT_GET_CLASS(object)->copy_to_clipboard != NULL )
-        {
-		/* We have an object specific method, use it */
-		GL_LABEL_OBJECT_GET_CLASS(object)->copy_to_clipboard (object, clipboard);
-	}
-
-        gl_debug (DEBUG_LABEL, "END");
-}
-
-
-/*****************************************************************************/
 /* Emit "changed" signal (for derived objects).                              */
 /*****************************************************************************/
 void
diff --git a/src/label-object.h b/src/label-object.h
index eeb586d..3be4462 100644
--- a/src/label-object.h
+++ b/src/label-object.h
@@ -148,9 +148,6 @@ struct _glLabelObjectClass {
 ,
                                                    glLabelObject     *src_object);
 
-        void              (*copy_to_clipboard)    (glLabelObject     *object,
-                                                   GtkClipboard      *clipboard);
-
         /*
          * Draw methods
          */
@@ -201,10 +198,6 @@ glLabelObject *gl_label_object_dup                   (glLabelObject     *src_obj
                                                       glLabel           *label);
 
 
-void           gl_label_object_copy_to_clipboard     (glLabelObject     *object,
-                                                      GtkClipboard      *clipboard);
-
-
 void           gl_label_object_emit_changed          (glLabelObject     *object);
 
 void           gl_label_object_set_parent            (glLabelObject     *object,
diff --git a/src/label-text.c b/src/label-text.c
index dd9f565..aef20b8 100644
--- a/src/label-text.c
+++ b/src/label-text.c
@@ -77,9 +77,6 @@ static void gl_label_text_finalize      (GObject          *object);
 static void copy                        (glLabelObject    *dst_object,
 					 glLabelObject    *src_object);
 
-static void copy_to_clipboard           (glLabelObject    *object,
-                                         GtkClipboard     *clipboard);
-
 static void buffer_changed_cb           (GtkTextBuffer    *textbuffer,
 					 glLabelText      *ltext);
 
@@ -171,8 +168,6 @@ gl_label_text_class_init (glLabelTextClass *class)
 
 	label_object_class->copy                  = copy;
 
-	label_object_class->copy_to_clipboard     = copy_to_clipboard;
-
 	label_object_class->get_size              = get_size;
 
 	label_object_class->set_font_family       = set_font_family;
@@ -308,55 +303,45 @@ copy (glLabelObject *dst_object,
 }
 
 
-/*---------------------------------------------------------------------------*/
-/* Private.  Copy text to clipboard.                                         */
-/*---------------------------------------------------------------------------*/
-static void
-copy_to_clipboard (glLabelObject     *object,
-                   GtkClipboard      *clipboard)
+/*****************************************************************************/
+/* Set object params.                                                        */
+/*****************************************************************************/
+void
+gl_label_text_set_lines (glLabelText *ltext,
+			 GList       *lines)
 {
-        glLabelText *ltext;
-	GtkTextIter  start, end;
-	gchar       *text;
+	gchar *text;
 
 	gl_debug (DEBUG_LABEL, "START");
 
-	g_return_if_fail (object && GL_IS_LABEL_TEXT (object));
-
-        ltext = GL_LABEL_TEXT (object);
+	g_return_if_fail (ltext && GL_IS_LABEL_TEXT (ltext));
 
-	gtk_text_buffer_get_bounds (ltext->priv->buffer, &start, &end);
-	text = gtk_text_buffer_get_text (ltext->priv->buffer,
-					 &start, &end, FALSE);
+	text = gl_text_node_lines_expand (lines, NULL);
+	gtk_text_buffer_set_text (ltext->priv->buffer, text, -1);
+	g_free (text);
 
-        gtk_clipboard_set_text (clipboard, text, -1);
+        ltext->priv->size_changed = TRUE;
 
 	gl_debug (DEBUG_LABEL, "END");
 }
 
 
-/*****************************************************************************/
-/* Set object params.                                                        */
-/*****************************************************************************/
 void
-gl_label_text_set_lines (glLabelText *ltext,
-			 GList       *lines)
+gl_label_text_set_text (glLabelText *ltext,
+                        const gchar *text)
 {
-	gchar *text;
-
 	gl_debug (DEBUG_LABEL, "START");
 
 	g_return_if_fail (ltext && GL_IS_LABEL_TEXT (ltext));
 
-	text = gl_text_node_lines_expand (lines, NULL);
 	gtk_text_buffer_set_text (ltext->priv->buffer, text, -1);
-	g_free (text);
 
         ltext->priv->size_changed = TRUE;
 
 	gl_debug (DEBUG_LABEL, "END");
 }
 
+
 /*****************************************************************************/
 /* Get object params.                                                        */
 /*****************************************************************************/
@@ -388,6 +373,22 @@ gl_label_text_get_lines (glLabelText *ltext)
 }
 
 
+gchar *
+gl_label_text_get_text (glLabelText      *ltext)
+{
+	GtkTextIter  start, end;
+	gchar       *text;
+
+	g_return_val_if_fail (ltext && GL_IS_LABEL_TEXT (ltext), NULL);
+
+	gtk_text_buffer_get_bounds (ltext->priv->buffer, &start, &end);
+	text = gtk_text_buffer_get_text (ltext->priv->buffer,
+					 &start, &end, FALSE);
+
+	return text;
+}
+
+
 /*****************************************************************************/
 /* Text buffer "changed" callback.                                           */
 /*****************************************************************************/
diff --git a/src/label-text.h b/src/label-text.h
index 07086e1..a7eb845 100644
--- a/src/label-text.h
+++ b/src/label-text.h
@@ -61,8 +61,13 @@ GObject       *gl_label_text_new             (glLabel          *label);
 void           gl_label_text_set_lines       (glLabelText      *ltext,
                                               GList            *lines);
 
+void           gl_label_text_set_text        (glLabelText      *ltext,
+                                              const gchar      *text);
+
 GtkTextBuffer *gl_label_text_get_buffer      (glLabelText      *ltext);
 
+gchar         *gl_label_text_get_text        (glLabelText      *ltext);
+
 GList         *gl_label_text_get_lines       (glLabelText      *ltext);
 
 void           gl_label_text_set_auto_shrink (glLabelText      *ltext,
diff --git a/src/label.c b/src/label.c
index 770ecbc..7c82881 100644
--- a/src/label.c
+++ b/src/label.c
@@ -29,6 +29,8 @@
 #include "file-util.h"
 #include "xml-label.h"
 #include "prefs.h"
+#include "label-text.h"
+#include "label-image.h"
 #include "marshal.h"
 
 #include "debug.h"
@@ -78,9 +80,14 @@ struct _glLabelPrivate {
 	
 	/* Default object fill properties */
 	guint              default_fill_color;
-
 };
 
+typedef struct {
+        gchar             *xml_buffer;
+        gchar             *text;
+        GdkPixbuf         *pixbuf;
+} ClipboardData;
+
 enum {
 	SELECTION_CHANGED,
 	CHANGED,
@@ -115,9 +122,30 @@ static void do_modify              (glLabel       *label);
 static void begin_selection_op     (glLabel       *label);
 static void end_selection_op       (glLabel       *label);
 
-static void paste_received_cb      (GtkClipboard  *clipboard,
-                                    const gchar   *buffer,
-                                    glLabel       *label);
+static void clipboard_get_cb       (GtkClipboard     *clipboard,
+                                    GtkSelectionData *selection_data,
+                                    guint             info,
+                                    ClipboardData    *data);
+
+static void clipboard_clear_cb     (GtkClipboard     *clipboard,
+                                    ClipboardData    *data);
+
+static void receive_targets_cb     (GtkClipboard     *clipboard,
+                                    GdkAtom          *targets,
+                                    gint              n_targets,
+                                    glLabel          *label);
+
+static void paste_xml_received_cb  (GtkClipboard     *clipboard,
+                                    GtkSelectionData *selection_data,
+                                    glLabel          *label);
+
+static void paste_text_received_cb (GtkClipboard     *clipboard,
+                                    const gchar      *text,
+                                    glLabel          *label);
+
+static void paste_image_received_cb(GtkClipboard     *clipboard,
+                                    GdkPixbuf        *pixbuf,
+                                    glLabel          *label);
 
 
 /*****************************************************************************/
@@ -1868,7 +1896,7 @@ gl_label_set_selection_font_family (glLabel      *label,
 /*****************************************************************************/
 void
 gl_label_set_selection_font_size (glLabel  *label,
-				 gdouble  font_size)
+                                  gdouble   font_size)
 {
         GList         *selection_list;
 	GList         *p;
@@ -1997,7 +2025,7 @@ gl_label_set_selection_text_alignment (glLabel        *label,
 /*****************************************************************************/
 void
 gl_label_set_selection_text_line_spacing (glLabel  *label,
-				         gdouble  text_line_spacing)
+                                          gdouble   text_line_spacing)
 {
         GList         *selection_list;
 	GList         *p;
@@ -2030,7 +2058,7 @@ gl_label_set_selection_text_line_spacing (glLabel  *label,
 /*****************************************************************************/
 void
 gl_label_set_selection_text_color (glLabel      *label,
-				  glColorNode *text_color_node)
+                                   glColorNode  *text_color_node)
 {
         GList         *selection_list;
 	GList         *p;
@@ -2063,7 +2091,7 @@ gl_label_set_selection_text_color (glLabel      *label,
 /*****************************************************************************/
 void
 gl_label_set_selection_fill_color (glLabel      *label,
-				  glColorNode *fill_color_node)
+                                   glColorNode  *fill_color_node)
 {
         GList         *selection_list;
 	GList         *p;
@@ -2096,7 +2124,7 @@ gl_label_set_selection_fill_color (glLabel      *label,
 /*****************************************************************************/
 void
 gl_label_set_selection_line_color (glLabel      *label,
-				  glColorNode *line_color_node)
+                                   glColorNode  *line_color_node)
 {
         GList         *selection_list;
 	GList         *p;
@@ -2161,15 +2189,13 @@ gl_label_set_selection_line_width (glLabel  *label,
 /* "Cut" selected items and place on clipboard.                              */
 /*****************************************************************************/
 void
-gl_label_cut_selection (glLabel       *label,
-                        GtkClipboard  *glabels_clipboard,
-                        GtkClipboard  *std_clipboard)
+gl_label_cut_selection (glLabel       *label)
 {
 	gl_debug (DEBUG_LABEL, "START");
 
 	g_return_if_fail (label && GL_IS_LABEL (label));
 
-	gl_label_copy_selection (label, glabels_clipboard, std_clipboard);
+	gl_label_copy_selection (label);
 	gl_label_delete_selection (label);
 
 	gl_debug (DEBUG_LABEL, "END");
@@ -2180,10 +2206,9 @@ gl_label_cut_selection (glLabel       *label,
 /* "Copy" selected items to clipboard.                                       */
 /*****************************************************************************/
 void
-gl_label_copy_selection (glLabel       *label,
-                         GtkClipboard  *glabels_clipboard,
-                         GtkClipboard  *std_clipboard)
+gl_label_copy_selection (glLabel       *label)
 {
+        GtkClipboard      *clipboard;
 	GList             *selection_list;
         glLabel           *label_copy;
 	GList             *p;
@@ -2192,14 +2217,34 @@ gl_label_copy_selection (glLabel       *label,
         glXMLLabelStatus   status;
         const GdkPixbuf   *pixbuf;
 
+        ClipboardData     *data;
+
+        static GtkTargetEntry glabels_targets[] = { { "application/glabels", 0, 0 },
+                                                    { "text/xml",            0, 0 },
+        };
+
+        GtkTargetList  *target_list;
+        GtkTargetEntry *target_table;
+        guint           n_targets;
+
 	gl_debug (DEBUG_LABEL, "START");
 
 	g_return_if_fail (label && GL_IS_LABEL (label));
 
+        clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
+
         selection_list = gl_label_get_selection_list (label);
 
 	if (selection_list)
         {
+
+                data = g_new0 (ClipboardData, 1);
+
+                target_list = gtk_target_list_new (glabels_targets, G_N_ELEMENTS(glabels_targets));
+
+                /*
+                 * Serialize selection by encoding as an XML label document.
+                 */
 		label_copy = GL_LABEL(gl_label_new ());
 
 		gl_label_set_template (label_copy, label->priv->template);
@@ -2212,25 +2257,52 @@ gl_label_copy_selection (glLabel       *label,
 			gl_label_object_dup (object, label_copy);
 		}
 
-                buffer = gl_xml_label_save_buffer (label_copy, &status);
-                
-                gtk_clipboard_set_text (glabels_clipboard, buffer, -1);
+                data->xml_buffer = gl_xml_label_save_buffer (label_copy, &status);
 
-                g_free (buffer);
                 g_object_unref (G_OBJECT (label_copy));
 
-	}
 
-        /*
-         * We may also want to make text and images available on standard
-         * clipboard.
-         */
-        if ( gl_label_is_selection_atomic (label) )
-        {
-                object = GL_LABEL_OBJECT (selection_list->data);
+                /*
+                 * Is it an atomic text selection?  If so, also make available as text.
+                 */
+                if ( gl_label_is_selection_atomic (label) &&
+                     GL_IS_LABEL_TEXT (selection_list->data) )
+                {
+                        glLabelText *text_object = GL_LABEL_TEXT (selection_list->data);
+
+                        gtk_target_list_add_text_targets (target_list, 1);
+
+                        data->text = gl_label_text_get_text (text_object);
+                }
+
+
+                /*
+                 * Is it an atomic image selection?  If so, also make available as pixbuf.
+                 */
+                if ( gl_label_is_selection_atomic (label) &&
+                     GL_IS_LABEL_IMAGE (selection_list->data) )
+                {
+                        glLabelImage       *image_object = GL_LABEL_IMAGE (selection_list->data);
+                        const GdkPixbuf    *pixbuf = gl_label_image_get_pixbuf (image_object, NULL);
+
+                        gtk_target_list_add_image_targets (target_list, 2, TRUE);
+
+                        data->pixbuf = g_object_ref (G_OBJECT (pixbuf));
+                }
+
+
+                target_table = gtk_target_table_new_from_list (target_list, &n_targets);
+
+                gtk_clipboard_set_with_data (clipboard,
+                                             target_table, n_targets,
+                                             (GtkClipboardGetFunc)clipboard_get_cb,
+                                             (GtkClipboardClearFunc)clipboard_clear_cb,
+                                             data);
+
+                gtk_target_table_free (target_table, n_targets);
+                gtk_target_list_unref (target_list);
+	}
 
-                gl_label_object_copy_to_clipboard (object, std_clipboard);
-        }
 
         g_list_free (selection_list);
 
@@ -2239,52 +2311,249 @@ gl_label_copy_selection (glLabel       *label,
 
 
 /*****************************************************************************/
-/* "Paste" from private clipboard selection.                                 */
+/* "Paste" from clipboard.                                                   */
 /*****************************************************************************/
 void
-gl_label_paste (glLabel       *label,
-                GtkClipboard  *glabels_clipboard,
-                GtkClipboard  *std_clipboard)
+gl_label_paste (glLabel       *label)
 {
+        GtkClipboard  *clipboard;
+
 	gl_debug (DEBUG_LABEL, "START");
 
 	g_return_if_fail (label && GL_IS_LABEL (label));
 
-        gtk_clipboard_request_text (glabels_clipboard,
-                                    (GtkClipboardTextReceivedFunc)paste_received_cb,
-                                    label);
+        clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
+
+        gtk_clipboard_request_targets (clipboard,
+                                       (GtkClipboardTargetsReceivedFunc)receive_targets_cb,
+                                       label);
+
+	gl_debug (DEBUG_LABEL, "END");
+}
+
+
+/*****************************************************************************/
+/* Is there anything that can be pasted?                                     */
+/*****************************************************************************/
+gboolean
+gl_label_can_paste (glLabel       *label)
+{
+        GtkClipboard *clipboard;
+        gboolean      can_flag;
+
+	gl_debug (DEBUG_LABEL, "START");
+
+        clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
+
+        can_flag = gtk_clipboard_wait_is_target_available (clipboard,
+                                                           gdk_atom_intern("application/glabels", TRUE))
+                || gtk_clipboard_wait_is_text_available (clipboard)
+                || gtk_clipboard_wait_is_image_available (clipboard);
+
+	gl_debug (DEBUG_LABEL, "END");
+        return can_flag;
+}
+
+
+/****************************************************************************/
+/* Clipboard "Get" function.                                                */
+/****************************************************************************/
+static void
+clipboard_get_cb (GtkClipboard     *clipboard,
+                  GtkSelectionData *selection_data,
+                  guint             info,
+                  ClipboardData    *data)
+{
+	gl_debug (DEBUG_LABEL, "START");
+
+        switch (info)
+        {
+
+        case 0:
+                gtk_selection_data_set (selection_data,
+                                        gtk_selection_data_get_target (selection_data),
+                                        8,
+                                        data->xml_buffer, strlen (data->xml_buffer));
+                break;
+
+        case 1:
+                gtk_selection_data_set_text (selection_data, data->text, -1);
+                break;
+
+        case 2:
+                gtk_selection_data_set_pixbuf (selection_data, data->pixbuf);
+                break;
+
+        default:
+                g_assert_not_reached ();
+                break;
+
+        }
+
+	gl_debug (DEBUG_LABEL, "END");
+}
+
+
+/****************************************************************************/
+/* Clipboard "Clear" function.                                              */
+/****************************************************************************/
+static void
+clipboard_clear_cb (GtkClipboard     *clipboard,
+                    ClipboardData    *data)
+{
+	gl_debug (DEBUG_LABEL, "START");
+
+        g_free (data->xml_buffer);
+        g_free (data->text);
+        if (data->pixbuf)
+        {
+                g_object_unref (data->pixbuf);
+        }
+
+        g_free (data);
 
 	gl_debug (DEBUG_LABEL, "END");
 }
 
 
 /****************************************************************************/
-/* Paste received callback.                                                 */
+/* Deal with clipboard data.                                                */
+/****************************************************************************/
+static void
+receive_targets_cb (GtkClipboard *clipboard,
+                    GdkAtom      *targets,
+                    gint          n_targets,
+                    glLabel      *label)
+{
+        gint i;
+
+        /*
+         * Application/glabels
+         */
+        for ( i = 0; i < n_targets; i++ )
+        {
+                if ( strcmp(gdk_atom_name(targets[i]), "application/glabels") == 0 )
+                {
+                        gtk_clipboard_request_contents (clipboard,
+                                                        gdk_atom_intern("application/glabels", TRUE),
+                                                        (GtkClipboardReceivedFunc)paste_xml_received_cb,
+                                                        label);
+                        return;
+                }
+        }
+
+        /*
+         * Text
+         */
+        if ( gtk_targets_include_text (targets, n_targets) )
+        {
+                gtk_clipboard_request_text (clipboard,
+                                            (GtkClipboardTextReceivedFunc)paste_text_received_cb,
+                                            label);
+                return;
+        }
+
+        /*
+         * Image
+         */
+        if ( gtk_targets_include_image (targets, n_targets, TRUE) )
+        {
+                gtk_clipboard_request_image (clipboard,
+                                             (GtkClipboardImageReceivedFunc)paste_image_received_cb,
+                                             label);
+                return;
+        }
+}
+
+
+/****************************************************************************/
+/* Paste received glabels XML callback.                                     */
 /****************************************************************************/
 static void
-paste_received_cb (GtkClipboard *clipboard,
-                   const gchar  *buffer,
-                   glLabel      *label)
+paste_xml_received_cb (GtkClipboard     *clipboard,
+                       GtkSelectionData *selection_data,
+                       glLabel          *label)
 {
+        const gchar      *xml_buffer;
         glLabel          *label_copy;
         glXMLLabelStatus  status;
         GList            *p;
         glLabelObject    *object, *newobject;
 
-        label_copy = gl_xml_label_open_buffer (buffer, &status);
+	gl_debug (DEBUG_LABEL, "START");
 
+        xml_buffer = gtk_selection_data_get_data (selection_data);
+
+        /*
+         * Deserialize XML label document and extract objects.
+         */
+        label_copy = gl_xml_label_open_buffer (xml_buffer, &status);
         if ( label_copy )
         {
+                gl_label_unselect_all (label);
+
                 for (p = label_copy->priv->object_list; p != NULL; p = p->next)
                 {
                         object = (glLabelObject *) p->data;
                         newobject = gl_label_object_dup (object, label);
 
+                        gl_label_select_object (label, newobject);
+
                         gl_debug (DEBUG_LABEL, "object pasted");
                 }
 
                 g_object_unref (G_OBJECT (label_copy));
         }
+
+	gl_debug (DEBUG_LABEL, "END");
+}
+
+
+/****************************************************************************/
+/* Paste received text callback.                                            */
+/****************************************************************************/
+static void
+paste_text_received_cb (GtkClipboard     *clipboard,
+                        const gchar      *text,
+                        glLabel          *label)
+{
+        glLabelObject    *object;
+
+	gl_debug (DEBUG_LABEL, "START");
+
+        gl_label_unselect_all (label);
+
+        object = GL_LABEL_OBJECT (gl_label_text_new (label));
+        gl_label_text_set_text (GL_LABEL_TEXT (object), text);
+        gl_label_object_set_position (object, 18, 18);
+
+        gl_label_select_object (label, object);
+
+	gl_debug (DEBUG_LABEL, "END");
+}
+
+
+/****************************************************************************/
+/* Paste received image callback.                                           */
+/****************************************************************************/
+static void
+paste_image_received_cb (GtkClipboard     *clipboard,
+                         GdkPixbuf        *pixbuf,
+                         glLabel          *label)
+{
+        glLabelObject    *object;
+
+	gl_debug (DEBUG_LABEL, "START");
+
+        gl_label_unselect_all (label);
+
+        object = GL_LABEL_OBJECT (gl_label_image_new (label));
+        gl_label_image_set_pixbuf (GL_LABEL_IMAGE (object), pixbuf);
+        gl_label_object_set_position (object, 18, 18);
+
+        gl_label_select_object (label, object);
+
+	gl_debug (DEBUG_LABEL, "END");
 }
 
 
diff --git a/src/label.h b/src/label.h
index 35b86c4..5ff735b 100644
--- a/src/label.h
+++ b/src/label.h
@@ -252,17 +252,13 @@ void          gl_label_set_selection_line_width (glLabel        *label,
 /*
  * Clipboard operations
  */
-void          gl_label_cut_selection             (glLabel       *label,
-                                                  GtkClipboard  *glabels_clipboard,
-                                                  GtkClipboard  *std_clipboard);
+void          gl_label_cut_selection             (glLabel       *label);
 
-void          gl_label_copy_selection            (glLabel       *label,
-                                                  GtkClipboard  *glabels_clipboard,
-                                                  GtkClipboard  *std_clipboard);
+void          gl_label_copy_selection            (glLabel       *label);
 
-void          gl_label_paste                     (glLabel       *label,
-                                                  GtkClipboard  *glabels_clipboard,
-                                                  GtkClipboard  *std_clipboard);
+void          gl_label_paste                     (glLabel       *label);
+
+gboolean      gl_label_can_paste                 (glLabel       *label);
 
 
 /*
diff --git a/src/ui-commands.c b/src/ui-commands.c
index 28db965..e69679a 100644
--- a/src/ui-commands.c
+++ b/src/ui-commands.c
@@ -258,21 +258,12 @@ void
 gl_ui_cmd_edit_cut (GtkAction *action,
                     glWindow  *window)
 {
-        GtkClipboard  *glabels_clipboard;
-        GtkClipboard  *std_clipboard;
-
         gl_debug (DEBUG_COMMANDS, "START");
 
         g_return_if_fail (action && GTK_IS_ACTION(action));
         g_return_if_fail (window && GL_IS_WINDOW(window));
 
-        glabels_clipboard = gtk_widget_get_clipboard (GTK_WIDGET (window),
-                                                      GL_UI_GLABELS_CLIPBOARD);
-
-        std_clipboard     = gtk_widget_get_clipboard (GTK_WIDGET (window),
-                                                      GDK_SELECTION_CLIPBOARD);
-
-        gl_label_cut_selection (window->label, glabels_clipboard, std_clipboard);
+        gl_label_cut_selection (window->label);
 
         gl_debug (DEBUG_COMMANDS, "END");
 }
@@ -285,21 +276,12 @@ void
 gl_ui_cmd_edit_copy (GtkAction *action,
                      glWindow  *window)
 {
-        GtkClipboard  *glabels_clipboard;
-        GtkClipboard  *std_clipboard;
-
         gl_debug (DEBUG_COMMANDS, "START");
 
         g_return_if_fail (action && GTK_IS_ACTION(action));
         g_return_if_fail (window && GL_IS_WINDOW(window));
 
-        glabels_clipboard = gtk_widget_get_clipboard (GTK_WIDGET (window),
-                                                      GL_UI_GLABELS_CLIPBOARD);
-
-        std_clipboard     = gtk_widget_get_clipboard (GTK_WIDGET (window),
-                                                      GDK_SELECTION_CLIPBOARD);
-
-        gl_label_copy_selection (window->label, glabels_clipboard, std_clipboard);
+        gl_label_copy_selection (window->label);
 
         gl_debug (DEBUG_COMMANDS, "END");
 }
@@ -312,21 +294,12 @@ void
 gl_ui_cmd_edit_paste (GtkAction *action,
                       glWindow  *window)
 {
-        GtkClipboard  *glabels_clipboard;
-        GtkClipboard  *std_clipboard;
-
         gl_debug (DEBUG_COMMANDS, "START");
 
         g_return_if_fail (action && GTK_IS_ACTION(action));
         g_return_if_fail (window && GL_IS_WINDOW(window));
 
-        glabels_clipboard = gtk_widget_get_clipboard (GTK_WIDGET (window),
-                                                      GL_UI_GLABELS_CLIPBOARD);
-
-        std_clipboard     = gtk_widget_get_clipboard (GTK_WIDGET (window),
-                                                      GDK_SELECTION_CLIPBOARD);
-
-        gl_label_paste (window->label, glabels_clipboard, std_clipboard);
+        gl_label_paste (window->label);
 
         gl_debug (DEBUG_COMMANDS, "END");
 }
diff --git a/src/ui.h b/src/ui.h
index f6db062..57428ef 100644
--- a/src/ui.h
+++ b/src/ui.h
@@ -29,9 +29,6 @@
 G_BEGIN_DECLS
 
 
-#define GL_UI_GLABELS_CLIPBOARD gdk_atom_intern ("GLABELS", FALSE)
-
-
 GtkUIManager *gl_ui_new                    (glWindow          *window);
 
 void          gl_ui_unref                  (GtkUIManager      *ui);
diff --git a/src/window.c b/src/window.c
index c989660..0d96806 100644
--- a/src/window.c
+++ b/src/window.c
@@ -232,8 +232,7 @@ static void
 gl_window_destroy (GtkObject *gtk_object)
 {
 	glWindow          *window;
-        GtkClipboard      *glabels_clipboard;
-        GtkClipboard      *std_clipboard;
+        GtkClipboard      *clipboard;
 
 	gl_debug (DEBUG_WINDOW, "START");
 
@@ -250,10 +249,10 @@ gl_window_destroy (GtkObject *gtk_object)
 
         if (window->label)
         {
-                glabels_clipboard = gtk_widget_get_clipboard (GTK_WIDGET (window),
-                                                              GL_UI_GLABELS_CLIPBOARD);
+                clipboard = gtk_widget_get_clipboard (GTK_WIDGET (window),
+                                                      GDK_SELECTION_CLIPBOARD);
 
-                g_signal_handlers_disconnect_by_func (G_OBJECT (glabels_clipboard),
+                g_signal_handlers_disconnect_by_func (G_OBJECT (clipboard),
                                                       G_CALLBACK (clipboard_changed_cb),
                                                       window);
 
@@ -359,7 +358,7 @@ gl_window_set_label (glWindow    *window,
 		     glLabel     *label)
 {
 	gchar             *string;
-        GtkClipboard      *glabels_clipboard;
+        GtkClipboard      *clipboard;
         GtkWidget         *focus_widget;
 
 	gl_debug (DEBUG_WINDOW, "START");
@@ -408,8 +407,8 @@ gl_window_set_label (glWindow    *window,
 	g_free (string);
 
 
-        glabels_clipboard = gtk_widget_get_clipboard (GTK_WIDGET (window),
-                                                      GL_UI_GLABELS_CLIPBOARD);
+        clipboard = gtk_widget_get_clipboard (GTK_WIDGET (window),
+                                              GDK_SELECTION_CLIPBOARD);
 
 
 	g_signal_connect (G_OBJECT(window->label), "selection_changed",
@@ -433,7 +432,7 @@ gl_window_set_label (glWindow    *window,
 	g_signal_connect (G_OBJECT(label), "modified_changed",
 			  G_CALLBACK(modified_changed_cb), window);
 
-	g_signal_connect (G_OBJECT(glabels_clipboard), "owner_change",
+	g_signal_connect (G_OBJECT(clipboard), "owner_change",
 			  G_CALLBACK(clipboard_changed_cb), window);
 
 	g_signal_connect (G_OBJECT(window), "set_focus",
@@ -726,22 +725,15 @@ static void
 set_copy_paste_sensitivity (glWindow  *window,
                             GtkWidget *focus_widget)
 {
-        GtkClipboard *glabels_clipboard;
-
 	gl_debug (DEBUG_WINDOW, "START");
 
 	g_return_if_fail (window && GL_IS_WINDOW (window));
 
-        glabels_clipboard = gtk_widget_get_clipboard (GTK_WIDGET (window),
-                                                      GL_UI_GLABELS_CLIPBOARD);
-
         if ( focus_widget == GL_VIEW(window->view)->canvas )
         {
                 gl_ui_update_selection_verbs (window->ui, GL_VIEW (window->view), TRUE);
 
-                gl_ui_update_paste_verbs (window->ui,
-                                          gtk_clipboard_wait_is_text_available (glabels_clipboard));
-
+                gl_ui_update_paste_verbs (window->ui, gl_label_can_paste (window->label));
         }
         else
         {



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