[gimp] app: enable copy and paste for curves



commit fdde593fc51121e18a12ee65c703b90ca2b12f7e
Author: Michael Natterer <mitch gimp org>
Date:   Tue Feb 16 19:58:51 2010 +0100

    app: enable copy and paste for curves
    
    Add GimpCurve support to the clipboard and handle ctrl-x, ctrl-c and
    ctrl-v in GimpCurveView.

 app/widgets/gimpclipboard.c        |  210 +++++++++++++++++++++++++
 app/widgets/gimpclipboard.h        |    4 +
 app/widgets/gimpcurveview.c        |  298 ++++++++++++++++++++++++++----------
 app/widgets/gimpcurveview.h        |    6 +
 app/widgets/gimpdeviceinfoeditor.c |    1 +
 app/widgets/gimpselectiondata.c    |   55 +++++++
 app/widgets/gimpselectiondata.h    |    7 +
 7 files changed, 501 insertions(+), 80 deletions(-)
---
diff --git a/app/widgets/gimpclipboard.c b/app/widgets/gimpclipboard.c
index cd0653e..5da1959 100644
--- a/app/widgets/gimpclipboard.c
+++ b/app/widgets/gimpclipboard.c
@@ -25,6 +25,7 @@
 
 #include "core/gimp.h"
 #include "core/gimpbuffer.h"
+#include "core/gimpcurve.h"
 
 #include "gimpclipboard.h"
 #include "gimppixbuf.h"
@@ -48,8 +49,12 @@ struct _GimpClipboard
   GtkTargetEntry *svg_target_entries;
   gint            n_svg_target_entries;
 
+  GtkTargetEntry *curve_target_entries;
+  gint            n_curve_target_entries;
+
   GimpBuffer     *buffer;
   gchar          *svg;
+  GimpCurve      *curve;
 };
 
 
@@ -61,6 +66,7 @@ static GdkAtom * gimp_clipboard_wait_for_targets (Gimp             *gimp,
                                                   gint             *n_targets);
 static GdkAtom   gimp_clipboard_wait_for_buffer  (Gimp             *gimp);
 static GdkAtom   gimp_clipboard_wait_for_svg     (Gimp             *gimp);
+static GdkAtom   gimp_clipboard_wait_for_curve   (Gimp             *gimp);
 
 static void      gimp_clipboard_send_buffer      (GtkClipboard     *clipboard,
                                                   GtkSelectionData *selection_data,
@@ -70,6 +76,10 @@ static void      gimp_clipboard_send_svg         (GtkClipboard     *clipboard,
                                                   GtkSelectionData *selection_data,
                                                   guint             info,
                                                   Gimp             *gimp);
+static void      gimp_clipboard_send_curve       (GtkClipboard     *clipboard,
+                                                  GtkSelectionData *selection_data,
+                                                  guint             info,
+                                                  Gimp             *gimp);
 
 
 /*  public functions  */
@@ -162,6 +172,13 @@ gimp_clipboard_init (Gimp *gimp)
   gimp_clip->svg_target_entries[1].target = g_strdup ("image/svg+xml");
   gimp_clip->svg_target_entries[1].flags  = 0;
   gimp_clip->svg_target_entries[1].info   = 1;
+
+  gimp_clip->n_curve_target_entries = 1;
+  gimp_clip->curve_target_entries   = g_new0 (GtkTargetEntry, 1);
+
+  gimp_clip->curve_target_entries[0].target = g_strdup ("application/x-gimp-curve");
+  gimp_clip->curve_target_entries[0].flags  = 0;
+  gimp_clip->curve_target_entries[0].info   = 0;
 }
 
 void
@@ -249,6 +266,39 @@ gimp_clipboard_has_svg (Gimp *gimp)
 }
 
 /**
+ * gimp_clipboard_has_curve:
+ * @gimp: pointer to #Gimp
+ *
+ * Tests if there's curve data in %GDK_SELECTION_CLIPBOARD.
+ * This is done in a main-loop similar to
+ * gtk_clipboard_wait_is_text_available(). The same caveats apply here.
+ *
+ * Return value: %TRUE if there's curve data in the clipboard, %FALSE otherwise
+ **/
+gboolean
+gimp_clipboard_has_curve (Gimp *gimp)
+{
+  GimpClipboard *gimp_clip;
+  GtkClipboard  *clipboard;
+
+  g_return_val_if_fail (GIMP_IS_GIMP (gimp), FALSE);
+
+  clipboard = gtk_clipboard_get_for_display (gdk_display_get_default (),
+                                             GDK_SELECTION_CLIPBOARD);
+
+  if (clipboard                                              &&
+      gtk_clipboard_get_owner (clipboard) != G_OBJECT (gimp) &&
+      gimp_clipboard_wait_for_curve (gimp)  != GDK_NONE)
+    {
+      return TRUE;
+    }
+
+  gimp_clip = gimp_clipboard_get (gimp);
+
+  return (gimp_clip->curve != NULL);
+}
+
+/**
  * gimp_clipboard_get_buffer:
  * @gimp: pointer to #Gimp
  *
@@ -373,6 +423,59 @@ gimp_clipboard_get_svg (Gimp  *gimp,
 }
 
 /**
+ * gimp_clipboard_get_curve:
+ * @gimp: pointer to #Gimp
+ *
+ * Retrieves curve data from %GDK_SELECTION_CLIPBOARD or from the global
+ * curve buffer of @gimp.
+ *
+ * The returned curve needs to be unref'ed when it's no longer needed.
+ *
+ * Return value: a reference to a #GimpCurve or %NULL if there's no
+ *               curve data
+ **/
+GimpCurve *
+gimp_clipboard_get_curve (Gimp *gimp)
+{
+  GimpClipboard *gimp_clip;
+  GtkClipboard  *clipboard;
+  GdkAtom        atom;
+  GimpCurve     *curve = NULL;
+
+  g_return_val_if_fail (GIMP_IS_GIMP (gimp), NULL);
+
+  clipboard = gtk_clipboard_get_for_display (gdk_display_get_default (),
+                                             GDK_SELECTION_CLIPBOARD);
+
+  if (clipboard                                                        &&
+      gtk_clipboard_get_owner (clipboard)           != G_OBJECT (gimp) &&
+      (atom = gimp_clipboard_wait_for_curve (gimp)) != GDK_NONE)
+    {
+      GtkSelectionData *data;
+
+      gimp_set_busy (gimp);
+
+      data = gtk_clipboard_wait_for_contents (clipboard, atom);
+
+      if (data)
+        {
+          curve = gimp_selection_data_get_curve (data);
+
+          gtk_selection_data_free (data);
+        }
+
+      gimp_unset_busy (gimp);
+    }
+
+  gimp_clip = gimp_clipboard_get (gimp);
+
+  if (! curve && gimp_clip->curve)
+    curve = g_object_ref (gimp_clip->curve);
+
+  return curve;
+}
+
+/**
  * gimp_clipboard_set_buffer:
  * @gimp:   pointer to #Gimp
  * @buffer: a #GimpBuffer, or %NULL.
@@ -492,6 +595,51 @@ gimp_clipboard_set_text (Gimp        *gimp,
     gtk_clipboard_set_text (clipboard, text, -1);
 }
 
+/**
+ * gimp_clipboard_set_curve:
+ * @gimp: pointer to #Gimp
+ * @curve: a #GimpCurve, or %NULL
+ *
+ * Offers curve data in %GDK_SELECTION_CLIPBOARD.
+ **/
+void
+gimp_clipboard_set_curve (Gimp      *gimp,
+                          GimpCurve *curve)
+{
+  GimpClipboard *gimp_clip;
+  GtkClipboard  *clipboard;
+
+  g_return_if_fail (GIMP_IS_GIMP (gimp));
+  g_return_if_fail (curve == NULL || GIMP_IS_CURVE (curve));
+
+  clipboard = gtk_clipboard_get_for_display (gdk_display_get_default (),
+                                             GDK_SELECTION_CLIPBOARD);
+  if (! clipboard)
+    return;
+
+  gimp_clip = gimp_clipboard_get (gimp);
+
+  gimp_clipboard_clear (gimp_clip);
+
+  if (curve)
+    {
+      gimp_clip->curve = g_object_ref (curve);
+
+      gtk_clipboard_set_with_owner (clipboard,
+                                    gimp_clip->curve_target_entries,
+                                    gimp_clip->n_curve_target_entries,
+                                    (GtkClipboardGetFunc) gimp_clipboard_send_curve,
+                                    (GtkClipboardClearFunc) NULL,
+                                    G_OBJECT (gimp));
+
+      gtk_clipboard_set_can_store (clipboard, gimp_clip->curve_target_entries, 1);
+    }
+  else if (gtk_clipboard_get_owner (clipboard) == G_OBJECT (gimp))
+    {
+      gtk_clipboard_clear (clipboard);
+    }
+}
+
 
 /*  private functions  */
 
@@ -515,6 +663,12 @@ gimp_clipboard_clear (GimpClipboard *gimp_clip)
       g_free (gimp_clip->svg);
       gimp_clip->svg = NULL;
     }
+
+  if (gimp_clip->curve)
+    {
+      g_object_unref (gimp_clip->curve);
+      gimp_clip->curve = NULL;
+    }
 }
 
 static void
@@ -536,6 +690,11 @@ gimp_clipboard_free (GimpClipboard *gimp_clip)
 
   g_free (gimp_clip->svg_target_entries);
 
+  for (i = 0; i < gimp_clip->n_curve_target_entries; i++)
+    g_free (gimp_clip->curve_target_entries[i].target);
+
+  g_free (gimp_clip->curve_target_entries);
+
   g_slice_free (GimpClipboard, gimp_clip);
 }
 
@@ -680,6 +839,35 @@ gimp_clipboard_wait_for_svg (Gimp *gimp)
   return result;
 }
 
+static GdkAtom
+gimp_clipboard_wait_for_curve (Gimp *gimp)
+{
+  GdkAtom *targets;
+  gint     n_targets;
+  GdkAtom  result = GDK_NONE;
+
+  targets = gimp_clipboard_wait_for_targets (gimp, &n_targets);
+
+  if (targets)
+    {
+      GdkAtom curve_atom = gdk_atom_intern_static_string ("application/x-gimp-curve");
+      gint    i;
+
+      for (i = 0; i < n_targets; i++)
+        {
+          if (targets[i] == curve_atom)
+            {
+              result = curve_atom;
+              break;
+            }
+        }
+
+      g_free (targets);
+    }
+
+  return result;
+}
+
 static void
 gimp_clipboard_send_buffer (GtkClipboard     *clipboard,
                             GtkSelectionData *selection_data,
@@ -735,3 +923,25 @@ gimp_clipboard_send_svg (GtkClipboard     *clipboard,
 
   gimp_unset_busy (gimp);
 }
+
+static void
+gimp_clipboard_send_curve (GtkClipboard     *clipboard,
+                           GtkSelectionData *selection_data,
+                           guint             info,
+                           Gimp             *gimp)
+{
+  GimpClipboard *gimp_clip = gimp_clipboard_get (gimp);
+
+  gimp_set_busy (gimp);
+
+  if (gimp_clip->curve)
+    {
+      if (gimp->be_verbose)
+        g_printerr ("clipboard: sending curve data as '%s'\n",
+                    gimp_clip->curve_target_entries[info].target);
+
+      gimp_selection_data_set_curve (selection_data, gimp_clip->curve);
+    }
+
+  gimp_unset_busy (gimp);
+}
diff --git a/app/widgets/gimpclipboard.h b/app/widgets/gimpclipboard.h
index 74674c4..eddd15e 100644
--- a/app/widgets/gimpclipboard.h
+++ b/app/widgets/gimpclipboard.h
@@ -24,10 +24,12 @@ void         gimp_clipboard_exit       (Gimp        *gimp);
 
 gboolean     gimp_clipboard_has_buffer (Gimp        *gimp);
 gboolean     gimp_clipboard_has_svg    (Gimp        *gimp);
+gboolean     gimp_clipboard_has_curve  (Gimp        *gimp);
 
 GimpBuffer * gimp_clipboard_get_buffer (Gimp        *gimp);
 gchar      * gimp_clipboard_get_svg    (Gimp        *gimp,
                                         gsize       *svg_length);
+GimpCurve  * gimp_clipboard_get_curve  (Gimp        *gimp);
 
 void         gimp_clipboard_set_buffer (Gimp        *gimp,
                                         GimpBuffer  *buffer);
@@ -35,6 +37,8 @@ void         gimp_clipboard_set_svg    (Gimp        *gimp,
                                         const gchar *svg);
 void         gimp_clipboard_set_text   (Gimp        *gimp,
                                         const gchar *text);
+void         gimp_clipboard_set_curve  (Gimp        *gimp,
+                                        GimpCurve   *curve);
 
 
 #endif /* __GIMP_CLIPBOARD_H__ */
diff --git a/app/widgets/gimpcurveview.c b/app/widgets/gimpcurveview.c
index b794b85..c8511a9 100644
--- a/app/widgets/gimpcurveview.c
+++ b/app/widgets/gimpcurveview.c
@@ -22,56 +22,72 @@
 #include <gtk/gtk.h>
 #include <gdk/gdkkeysyms.h>
 
+#include "libgimpconfig/gimpconfig.h"
 #include "libgimpmath/gimpmath.h"
 
 #include "widgets-types.h"
 
+#include "core/gimp.h"
 #include "core/gimpcurve.h"
 #include "core/gimpcurve-map.h"
 #include "core/gimpmarshal.h"
 
+#include "gimpclipboard.h"
 #include "gimpcurveview.h"
 
 
 enum
 {
   PROP_0,
+  PROP_GIMP,
   PROP_BASE_LINE,
   PROP_GRID_ROWS,
   PROP_GRID_COLUMNS
 };
 
+enum
+{
+  CUT_CLIPBOARD,
+  COPY_CLIPBOARD,
+  PASTE_CLIPBOARD,
+  LAST_SIGNAL
+};
 
-static void       gimp_curve_view_finalize       (GObject          *object);
-static void       gimp_curve_view_dispose        (GObject          *object);
-static void       gimp_curve_view_set_property   (GObject          *object,
-                                                  guint             property_id,
-                                                  const GValue     *value,
-                                                  GParamSpec       *pspec);
-static void       gimp_curve_view_get_property   (GObject          *object,
-                                                  guint             property_id,
-                                                  GValue           *value,
-                                                  GParamSpec       *pspec);
-
-static void       gimp_curve_view_style_set      (GtkWidget        *widget,
-                                                  GtkStyle         *prev_style);
-static gboolean   gimp_curve_view_expose         (GtkWidget        *widget,
-                                                  GdkEventExpose   *event);
-static gboolean   gimp_curve_view_button_press   (GtkWidget        *widget,
-                                                  GdkEventButton   *bevent);
-static gboolean   gimp_curve_view_button_release (GtkWidget        *widget,
-                                                  GdkEventButton   *bevent);
-static gboolean   gimp_curve_view_motion_notify  (GtkWidget        *widget,
-                                                  GdkEventMotion   *bevent);
-static gboolean   gimp_curve_view_leave_notify   (GtkWidget        *widget,
-                                                  GdkEventCrossing *cevent);
-static gboolean   gimp_curve_view_key_press      (GtkWidget        *widget,
-                                                  GdkEventKey      *kevent);
-
-static void       gimp_curve_view_set_cursor     (GimpCurveView    *view,
-                                                  gdouble           x,
-                                                  gdouble           y);
-static void       gimp_curve_view_unset_cursor   (GimpCurveView *view);
+
+static void       gimp_curve_view_finalize        (GObject          *object);
+static void       gimp_curve_view_dispose         (GObject          *object);
+static void       gimp_curve_view_set_property    (GObject          *object,
+                                                   guint             property_id,
+                                                   const GValue     *value,
+                                                   GParamSpec       *pspec);
+static void       gimp_curve_view_get_property    (GObject          *object,
+                                                   guint             property_id,
+                                                   GValue           *value,
+                                                   GParamSpec       *pspec);
+
+static void       gimp_curve_view_style_set       (GtkWidget        *widget,
+                                                   GtkStyle         *prev_style);
+static gboolean   gimp_curve_view_expose          (GtkWidget        *widget,
+                                                   GdkEventExpose   *event);
+static gboolean   gimp_curve_view_button_press    (GtkWidget        *widget,
+                                                   GdkEventButton   *bevent);
+static gboolean   gimp_curve_view_button_release  (GtkWidget        *widget,
+                                                   GdkEventButton   *bevent);
+static gboolean   gimp_curve_view_motion_notify   (GtkWidget        *widget,
+                                                   GdkEventMotion   *bevent);
+static gboolean   gimp_curve_view_leave_notify    (GtkWidget        *widget,
+                                                   GdkEventCrossing *cevent);
+static gboolean   gimp_curve_view_key_press       (GtkWidget        *widget,
+                                                   GdkEventKey      *kevent);
+
+static void       gimp_curve_view_cut_clipboard   (GimpCurveView    *view);
+static void       gimp_curve_view_copy_clipboard  (GimpCurveView    *view);
+static void       gimp_curve_view_paste_clipboard (GimpCurveView    *view);
+
+static void       gimp_curve_view_set_cursor      (GimpCurveView    *view,
+                                                   gdouble           x,
+                                                   gdouble           y);
+static void       gimp_curve_view_unset_cursor    (GimpCurveView *view);
 
 
 G_DEFINE_TYPE (GimpCurveView, gimp_curve_view,
@@ -79,12 +95,15 @@ G_DEFINE_TYPE (GimpCurveView, gimp_curve_view,
 
 #define parent_class gimp_curve_view_parent_class
 
+static guint curve_view_signals[LAST_SIGNAL] = { 0 };
+
 
 static void
 gimp_curve_view_class_init (GimpCurveViewClass *klass)
 {
   GObjectClass   *object_class = G_OBJECT_CLASS (klass);
   GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+  GtkBindingSet  *binding_set;
 
   object_class->finalize             = gimp_curve_view_finalize;
   object_class->dispose              = gimp_curve_view_dispose;
@@ -99,22 +118,70 @@ gimp_curve_view_class_init (GimpCurveViewClass *klass)
   widget_class->leave_notify_event   = gimp_curve_view_leave_notify;
   widget_class->key_press_event      = gimp_curve_view_key_press;
 
+  klass->cut_clipboard               = gimp_curve_view_cut_clipboard;
+  klass->copy_clipboard              = gimp_curve_view_copy_clipboard;
+  klass->paste_clipboard             = gimp_curve_view_paste_clipboard;
+
+  g_object_class_install_property (object_class, PROP_GIMP,
+                                   g_param_spec_object ("gimp",
+                                                        NULL, NULL,
+                                                        GIMP_TYPE_GIMP,
+                                                        GIMP_PARAM_READWRITE));
+
   g_object_class_install_property (object_class, PROP_BASE_LINE,
                                    g_param_spec_boolean ("base-line",
                                                          NULL, NULL,
                                                          TRUE,
                                                          GIMP_PARAM_READWRITE |
                                                          G_PARAM_CONSTRUCT_ONLY));
+
   g_object_class_install_property (object_class, PROP_GRID_ROWS,
                                    g_param_spec_int ("grid-rows", NULL, NULL,
                                                      0, 100, 8,
                                                      GIMP_PARAM_READWRITE |
                                                      G_PARAM_CONSTRUCT_ONLY));
+
   g_object_class_install_property (object_class, PROP_GRID_COLUMNS,
                                    g_param_spec_int ("grid-columns", NULL, NULL,
                                                      0, 100, 8,
                                                      GIMP_PARAM_READWRITE |
                                                      G_PARAM_CONSTRUCT_ONLY));
+
+  curve_view_signals[CUT_CLIPBOARD] =
+    g_signal_new ("cut-clipboard",
+                  G_TYPE_FROM_CLASS (klass),
+                  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+                  G_STRUCT_OFFSET (GimpCurveViewClass, cut_clipboard),
+                  NULL, NULL,
+                  gimp_marshal_VOID__VOID,
+                  G_TYPE_NONE, 0);
+
+  curve_view_signals[COPY_CLIPBOARD] =
+    g_signal_new ("copy-clipboard",
+                  G_TYPE_FROM_CLASS (klass),
+                  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+                  G_STRUCT_OFFSET (GimpCurveViewClass, copy_clipboard),
+                  NULL, NULL,
+                  gimp_marshal_VOID__VOID,
+                  G_TYPE_NONE, 0);
+
+  curve_view_signals[PASTE_CLIPBOARD] =
+    g_signal_new ("paste-clipboard",
+                  G_TYPE_FROM_CLASS (klass),
+                  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+                  G_STRUCT_OFFSET (GimpCurveViewClass, paste_clipboard),
+                  NULL, NULL,
+                  gimp_marshal_VOID__VOID,
+                  G_TYPE_NONE, 0);
+
+  binding_set = gtk_binding_set_by_class (klass);
+
+  gtk_binding_entry_add_signal (binding_set, GDK_x, GDK_CONTROL_MASK,
+                                "cut-clipboard", 0);
+  gtk_binding_entry_add_signal (binding_set, GDK_c, GDK_CONTROL_MASK,
+                                "copy-clipboard", 0);
+  gtk_binding_entry_add_signal (binding_set, GDK_v, GDK_CONTROL_MASK,
+                                "paste-clipboard", 0);
 }
 
 static void
@@ -179,6 +246,9 @@ gimp_curve_view_set_property (GObject      *object,
 
   switch (property_id)
     {
+    case PROP_GIMP:
+      view->gimp = g_value_get_object (value); /* don't ref */
+      break;
     case PROP_GRID_ROWS:
       view->grid_rows = g_value_get_int (value);
       break;
@@ -204,6 +274,9 @@ gimp_curve_view_get_property (GObject    *object,
 
   switch (property_id)
     {
+    case PROP_GIMP:
+      g_value_set_object (value, view->gimp);
+      break;
     case PROP_GRID_ROWS:
       g_value_set_int (value, view->grid_rows);
       break;
@@ -785,82 +858,147 @@ static gboolean
 gimp_curve_view_key_press (GtkWidget   *widget,
                            GdkEventKey *kevent)
 {
-  GimpCurveView *view   = GIMP_CURVE_VIEW (widget);
-  GimpCurve     *curve  = view->curve;
-  gint           i      = view->selected;
-  gdouble        x, y;
-  gboolean       retval = FALSE;
+  GimpCurveView *view    = GIMP_CURVE_VIEW (widget);
+  GimpCurve     *curve   = view->curve;
+  gboolean       handled = FALSE;
 
-  if (view->grabbed || ! curve ||
-      gimp_curve_get_curve_type (curve) == GIMP_CURVE_FREE)
-    return FALSE;
+  if (! view->grabbed && curve &&
+      gimp_curve_get_curve_type (curve) == GIMP_CURVE_SMOOTH)
+    {
+      gint    i = view->selected;
+      gdouble x, y;
 
-  gimp_curve_get_point (curve, i, NULL, &y);
+      gimp_curve_get_point (curve, i, NULL, &y);
 
-  switch (kevent->keyval)
-    {
-    case GDK_Left:
-      for (i = i - 1; i >= 0 && ! retval; i--)
+      switch (kevent->keyval)
         {
-          gimp_curve_get_point (curve, i, &x, NULL);
+        case GDK_Left:
+          for (i = i - 1; i >= 0 && ! handled; i--)
+            {
+              gimp_curve_get_point (curve, i, &x, NULL);
+
+              if (x >= 0.0)
+                {
+                  gimp_curve_view_set_selected (view, i);
 
-          if (x >= 0.0)
+                  handled = TRUE;
+                }
+            }
+          break;
+
+        case GDK_Right:
+          for (i = i + 1; i < curve->n_points && ! handled; i++)
             {
-              gimp_curve_view_set_selected (view, i);
+              gimp_curve_get_point (curve, i, &x, NULL);
 
-              retval = TRUE;
+              if (x >= 0.0)
+                {
+                  gimp_curve_view_set_selected (view, i);
+
+                  handled = TRUE;
+                }
             }
-        }
-      break;
+          break;
 
-    case GDK_Right:
-      for (i = i + 1; i < curve->n_points && ! retval; i++)
-        {
-          gimp_curve_get_point (curve, i, &x, NULL);
+        case GDK_Up:
+          if (y < 1.0)
+            {
+              y = y + (kevent->state & GDK_SHIFT_MASK ?
+                       (16.0 / 255.0) : (1.0 / 255.0));
+
+              gimp_curve_move_point (curve, i, CLAMP (y, 0.0, 1.0));
+
+              handled = TRUE;
+            }
+          break;
 
-          if (x >= 0.0)
+        case GDK_Down:
+          if (y > 0)
             {
-              gimp_curve_view_set_selected (view, i);
+              y = y - (kevent->state & GDK_SHIFT_MASK ?
+                       (16.0 / 255.0) : (1.0 / 255.0));
 
-              retval = TRUE;
+              gimp_curve_move_point (curve, i, CLAMP (y, 0.0, 1.0));
+
+              handled = TRUE;
             }
+          break;
+
+        default:
+          break;
         }
-      break;
+    }
 
-    case GDK_Up:
-      if (y < 1.0)
-        {
-          y = y + (kevent->state & GDK_SHIFT_MASK ?
-                   (16.0 / 255.0) : (1.0 / 255.0));
+  if (handled)
+    {
+      set_cursor (view, GDK_TCROSS);
 
-          gimp_curve_move_point (curve, i, CLAMP (y, 0.0, 1.0));
+      return TRUE;
+    }
 
-          retval = TRUE;
-        }
-      break;
+  return GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, kevent);
+}
 
-    case GDK_Down:
-      if (y > 0)
-        {
-          y = y - (kevent->state & GDK_SHIFT_MASK ?
-                   (16.0 / 255.0) : (1.0 / 255.0));
+static void
+gimp_curve_view_cut_clipboard (GimpCurveView *view)
+{
+  g_printerr ("%s\n", G_STRFUNC);
 
-          gimp_curve_move_point (curve, i, CLAMP (y, 0.0, 1.0));
+  if (! view->curve || ! view->gimp)
+    {
+      gtk_widget_error_bell (GTK_WIDGET (view));
+      return;
+    }
 
-          retval = TRUE;
-        }
-      break;
+  gimp_curve_view_copy_clipboard (view);
 
-    default:
-      break;
+  gimp_curve_reset (view->curve, FALSE);
+}
+
+static void
+gimp_curve_view_copy_clipboard (GimpCurveView *view)
+{
+  GimpCurve *copy;
+
+  g_printerr ("%s\n", G_STRFUNC);
+
+  if (! view->curve || ! view->gimp)
+    {
+      gtk_widget_error_bell (GTK_WIDGET (view));
+      return;
     }
 
-  if (retval)
-    set_cursor (view, GDK_TCROSS);
+  copy = GIMP_CURVE (gimp_data_duplicate (GIMP_DATA (view->curve)));
+  gimp_clipboard_set_curve (view->gimp, copy);
+  g_object_unref (copy);
+}
+
+static void
+gimp_curve_view_paste_clipboard (GimpCurveView *view)
+{
+  GimpCurve *copy;
+
+  g_printerr ("%s\n", G_STRFUNC);
 
-  return retval;
+  if (! view->curve || ! view->gimp)
+    {
+      gtk_widget_error_bell (GTK_WIDGET (view));
+      return;
+    }
+
+  copy = gimp_clipboard_get_curve (view->gimp);
+
+  if (copy)
+    {
+      gimp_config_copy (GIMP_CONFIG (copy),
+                        GIMP_CONFIG (view->curve), 0);
+      g_object_unref (copy);
+    }
 }
 
+
+/*  public functions  */
+
 GtkWidget *
 gimp_curve_view_new (void)
 {
diff --git a/app/widgets/gimpcurveview.h b/app/widgets/gimpcurveview.h
index b3ad32b..98df87c 100644
--- a/app/widgets/gimpcurveview.h
+++ b/app/widgets/gimpcurveview.h
@@ -36,6 +36,8 @@ struct _GimpCurveView
 {
   GimpHistogramView  parent_instance;
 
+  Gimp              *gimp; /* only needed for copy & paste */
+
   GimpCurve         *curve;
 
   gboolean           draw_base_line;
@@ -63,6 +65,10 @@ struct _GimpCurveView
 struct _GimpCurveViewClass
 {
   GimpHistogramViewClass  parent_class;
+
+  void (* cut_clipboard)   (GimpCurveView *view);
+  void (* copy_clipboard)  (GimpCurveView *view);
+  void (* paste_clipboard) (GimpCurveView *view);
 };
 
 
diff --git a/app/widgets/gimpdeviceinfoeditor.c b/app/widgets/gimpdeviceinfoeditor.c
index f1bd06a..89929bc 100644
--- a/app/widgets/gimpdeviceinfoeditor.c
+++ b/app/widgets/gimpdeviceinfoeditor.c
@@ -441,6 +441,7 @@ gimp_device_info_editor_constructor (GType                   type,
 
           view = gimp_curve_view_new ();
           g_object_set (view,
+                        "gimp",         GIMP_CONTEXT (private->info)->gimp,
                         "border-width", CURVE_BORDER,
                         NULL);
           gtk_widget_set_size_request (view,
diff --git a/app/widgets/gimpselectiondata.c b/app/widgets/gimpselectiondata.c
index 69705c5..567d8cf 100644
--- a/app/widgets/gimpselectiondata.c
+++ b/app/widgets/gimpselectiondata.c
@@ -23,6 +23,7 @@
 #include <gtk/gtk.h>
 
 #include "libgimpcolor/gimpcolor.h"
+#include "libgimpconfig/gimpconfig.h"
 
 #include "widgets-types.h"
 
@@ -31,6 +32,7 @@
 #include "core/gimp.h"
 #include "core/gimpbrush.h"
 #include "core/gimpcontainer.h"
+#include "core/gimpcurve.h"
 #include "core/gimpdatafactory.h"
 #include "core/gimpgradient.h"
 #include "core/gimpimage.h"
@@ -362,6 +364,59 @@ gimp_selection_data_get_stream (GtkSelectionData *selection,
 }
 
 void
+gimp_selection_data_set_curve (GtkSelectionData *selection,
+                               GimpCurve        *curve)
+{
+  gchar *str;
+
+  g_return_if_fail (selection != NULL);
+  g_return_if_fail (GIMP_IS_CURVE (curve));
+
+  str = gimp_config_serialize_to_string (GIMP_CONFIG (curve), NULL);
+
+  gtk_selection_data_set (selection,
+                          gtk_selection_data_get_target (selection),
+                          8, (guchar *) str, strlen (str));
+
+  g_free (str);
+}
+
+GimpCurve *
+gimp_selection_data_get_curve (GtkSelectionData *selection)
+{
+  GimpCurve *curve;
+  gint       length;
+  GError    *error = NULL;
+
+  g_return_val_if_fail (selection != NULL, NULL);
+
+  length = gtk_selection_data_get_length (selection);
+
+  if (gtk_selection_data_get_format (selection) != 8 || length < 1)
+    {
+      g_warning ("Received invalid curve data!");
+      return NULL;
+    }
+
+  curve = GIMP_CURVE (gimp_curve_new ("pasted curve"));
+
+  if (! gimp_config_deserialize_string (GIMP_CONFIG (curve),
+                                        (const gchar *)
+                                        gtk_selection_data_get_data (selection),
+                                        length,
+                                        NULL,
+                                        &error))
+    {
+      g_warning ("Received invalid curve data: %s", error->message);
+      g_clear_error (&error);
+      g_object_unref (curve);
+      return NULL;
+    }
+
+  return curve;
+}
+
+void
 gimp_selection_data_set_image (GtkSelectionData *selection,
                                GimpImage        *image)
 {
diff --git a/app/widgets/gimpselectiondata.h b/app/widgets/gimpselectiondata.h
index 7cff6ea..bf52b97 100644
--- a/app/widgets/gimpselectiondata.h
+++ b/app/widgets/gimpselectiondata.h
@@ -43,6 +43,13 @@ const guchar  * gimp_selection_data_get_stream    (GtkSelectionData *selection,
                                                    gsize            *stream_length);
 
 
+/*  curve  */
+
+void            gimp_selection_data_set_curve     (GtkSelectionData *selection,
+                                                   GimpCurve        *curve);
+GimpCurve     * gimp_selection_data_get_curve     (GtkSelectionData *selection);
+
+
 /*  image  */
 
 void            gimp_selection_data_set_image     (GtkSelectionData *selection,



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