[glom/glom-1-18] GimpRuler: Use the GTK+-2.0 version of this code.



commit 88e88b78225bf12b745c13441b7ba36b42ad022f
Author: Murray Cumming <murrayc murrayc com>
Date:   Thu Jan 27 16:35:59 2011 +0100

    GimpRuler: Use the GTK+-2.0 version of this code.
    
    * glom/utility_widgets/gimpruler/gimpruler.[h|c]: Use the version of the code
    that builds with GTK+-2.0 rather than GTK+-3.0.

 ChangeLog                                  |    7 +
 glom/utility_widgets/gimpruler/gimpruler.c |  400 ++++++++++++++++++++--------
 glom/utility_widgets/gimpruler/gimpruler.h |   41 ++--
 3 files changed, 316 insertions(+), 132 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 6c9c157..6398acf 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2011-01-27  Murray Cumming  <murrayc murrayc com>
+
+	GimpRuler: Use the GTK+-2.0 version of this code.
+
+	* glom/utility_widgets/gimpruler/gimpruler.[h|c]: Use the version of the code
+	that builds with GTK+-2.0 rather than GTK+-3.0.
+
 2010-09-02  Murray Cumming  <murrayc murrayc com>
 
 	Fix the build with latest gtkmm.
diff --git a/glom/utility_widgets/gimpruler/gimpruler.c b/glom/utility_widgets/gimpruler/gimpruler.c
index d69c465..1ee0cc4 100644
--- a/glom/utility_widgets/gimpruler/gimpruler.c
+++ b/glom/utility_widgets/gimpruler/gimpruler.c
@@ -25,7 +25,7 @@
 #include "libgimpbase/gimpbase.h"
 #include "libgimpmath/gimpmath.h"
 
-/* #include "libgimpwidgets/gimpwidgetstypes.h" */
+/* #include "gimpwidgetstypes.h" */
 
 #include "gimpruler.h"
 
@@ -73,8 +73,13 @@ typedef struct
 
   gint             xsrc;
   gint             ysrc;
+
+  GList           *track_widgets;
 } GimpRulerPrivate;
 
+#define GIMP_RULER_GET_PRIVATE(ruler) \
+  G_TYPE_INSTANCE_GET_PRIVATE (ruler, GIMP_TYPE_RULER, GimpRulerPrivate)
+
 
 static const struct
 {
@@ -87,44 +92,40 @@ static const struct
 };
 
 
-static void          gimp_ruler_set_property         (GObject        *object,
-                                                      guint            prop_id,
-                                                      const GValue   *value,
-                                                      GParamSpec     *pspec);
-static void          gimp_ruler_get_property         (GObject        *object,
-                                                      guint           prop_id,
-                                                      GValue         *value,
-                                                      GParamSpec     *pspec);
-
-static void          gimp_ruler_realize              (GtkWidget      *widget);
-static void          gimp_ruler_unrealize            (GtkWidget      *widget);
-static void          gimp_ruler_size_allocate        (GtkWidget      *widget,
-                                                      GtkAllocation  *allocation);
-static void          gimp_ruler_get_preferred_width  (GtkWidget      *widget,
-                                                      gint           *minimum_width,
-                                                      gint           *natural_width);
-static void          gimp_ruler_get_preferred_height (GtkWidget      *widget,
-                                                      gint           *minimum_height,
-                                                      gint           *natural_height);
-static void          gimp_ruler_style_set            (GtkWidget      *widget,
-                                                      GtkStyle       *prev_style);
-static gboolean      gimp_ruler_motion_notify        (GtkWidget      *widget,
-                                                      GdkEventMotion *event);
-static gboolean      gimp_ruler_draw                 (GtkWidget      *widget,
-                                                      cairo_t        *cr);
-
-static void          gimp_ruler_draw_ticks           (GimpRuler      *ruler);
-static void          gimp_ruler_draw_pos             (GimpRuler      *ruler);
-static void          gimp_ruler_make_pixmap          (GimpRuler      *ruler);
-
-static PangoLayout * gimp_ruler_get_layout           (GtkWidget      *widget,
-                                                      const gchar    *text);
+static void          gimp_ruler_dispose       (GObject        *object);
+static void          gimp_ruler_set_property  (GObject        *object,
+                                               guint            prop_id,
+                                               const GValue   *value,
+                                               GParamSpec     *pspec);
+static void          gimp_ruler_get_property  (GObject        *object,
+                                               guint           prop_id,
+                                               GValue         *value,
+                                               GParamSpec     *pspec);
+
+static void          gimp_ruler_realize       (GtkWidget      *widget);
+static void          gimp_ruler_unrealize     (GtkWidget      *widget);
+static void          gimp_ruler_size_allocate (GtkWidget      *widget,
+                                               GtkAllocation  *allocation);
+static void          gimp_ruler_size_request  (GtkWidget      *widget,
+                                               GtkRequisition *requisition);
+static void          gimp_ruler_style_set     (GtkWidget      *widget,
+                                               GtkStyle       *prev_style);
+static gboolean      gimp_ruler_motion_notify (GtkWidget      *widget,
+                                               GdkEventMotion *event);
+static gboolean      gimp_ruler_expose        (GtkWidget      *widget,
+                                               GdkEventExpose *event);
+
+static void          gimp_ruler_draw_ticks    (GimpRuler      *ruler);
+static void          gimp_ruler_draw_pos      (GimpRuler      *ruler);
+static void          gimp_ruler_make_pixmap   (GimpRuler      *ruler);
+
+static PangoLayout * gimp_ruler_get_layout    (GtkWidget      *widget,
+                                               const gchar    *text);
 
 
 G_DEFINE_TYPE (GimpRuler, gimp_ruler, GTK_TYPE_WIDGET)
 
-#define GIMP_RULER_GET_PRIVATE(ruler) \
-  G_TYPE_INSTANCE_GET_PRIVATE (ruler, GIMP_TYPE_RULER, GimpRulerPrivate)
+#define parent_class gimp_ruler_parent_class
 
 
 static void
@@ -133,17 +134,17 @@ gimp_ruler_class_init (GimpRulerClass *klass)
   GObjectClass   *object_class = G_OBJECT_CLASS (klass);
   GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
 
-  object_class->set_property         = gimp_ruler_set_property;
-  object_class->get_property         = gimp_ruler_get_property;
+  object_class->dispose             = gimp_ruler_dispose;
+  object_class->set_property        = gimp_ruler_set_property;
+  object_class->get_property        = gimp_ruler_get_property;
 
-  widget_class->realize              = gimp_ruler_realize;
-  widget_class->unrealize            = gimp_ruler_unrealize;
-  widget_class->get_preferred_width  = gimp_ruler_get_preferred_width;
-  widget_class->get_preferred_height = gimp_ruler_get_preferred_height;
-  widget_class->size_allocate        = gimp_ruler_size_allocate;
-  widget_class->style_set            = gimp_ruler_style_set;
-  widget_class->motion_notify_event  = gimp_ruler_motion_notify;
-  widget_class->draw                 = gimp_ruler_draw;
+  widget_class->realize             = gimp_ruler_realize;
+  widget_class->unrealize           = gimp_ruler_unrealize;
+  widget_class->size_allocate       = gimp_ruler_size_allocate;
+  widget_class->size_request        = gimp_ruler_size_request;
+  widget_class->style_set           = gimp_ruler_style_set;
+  widget_class->motion_notify_event = gimp_ruler_motion_notify;
+  widget_class->expose_event        = gimp_ruler_expose;
 
   g_type_class_add_private (object_class, sizeof (GimpRulerPrivate));
 
@@ -230,6 +231,18 @@ gimp_ruler_init (GimpRuler *ruler)
 }
 
 static void
+gimp_ruler_dispose (GObject *object)
+{
+  GimpRuler        *ruler = GIMP_RULER (object);
+  GimpRulerPrivate *priv  = GIMP_RULER_GET_PRIVATE (ruler);
+
+  while (priv->track_widgets)
+    gimp_ruler_remove_track_widget (ruler, priv->track_widgets->data);
+
+  G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+static void
 gimp_ruler_set_property (GObject      *object,
                          guint         prop_id,
                          const GValue *value,
@@ -338,8 +351,197 @@ gimp_ruler_new (GtkOrientation orientation)
                        NULL);
 }
 
+static void
+gimp_ruler_update_position (GimpRuler *ruler,
+                            gdouble    x,
+                            gdouble    y)
+{
+  GimpRulerPrivate *priv = GIMP_RULER_GET_PRIVATE (ruler);
+  GtkAllocation     allocation;
+  gdouble           lower;
+  gdouble           upper;
+
+  gtk_widget_get_allocation (GTK_WIDGET (ruler), &allocation);
+  gimp_ruler_get_range (ruler, &lower, &upper, NULL);
+
+  if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
+    {
+      gimp_ruler_set_position (ruler,
+                               lower +
+                               (upper - lower) * x / allocation.width);
+    }
+  else
+    {
+      gimp_ruler_set_position (ruler,
+                               lower +
+                               (upper - lower) * y / allocation.height);
+    }
+}
+
+/* Returns TRUE if a translation should be done */
+static gboolean
+gtk_widget_get_translation_to_window (GtkWidget *widget,
+                                      GdkWindow *window,
+                                      int       *x,
+                                      int       *y)
+{
+  GdkWindow *w, *widget_window;
+
+  if (! gtk_widget_get_has_window (widget))
+    {
+      GtkAllocation allocation;
+
+      gtk_widget_get_allocation (widget, &allocation);
+
+      *x = -allocation.x;
+      *y = -allocation.y;
+    }
+  else
+    {
+      *x = 0;
+      *y = 0;
+    }
+
+  widget_window = gtk_widget_get_window (widget);
+
+  for (w = window;
+       w && w != widget_window;
+       w = gdk_window_get_effective_parent (w))
+    {
+      gdouble px, py;
+
+      gdk_window_coords_to_parent (w, *x, *y, &px, &py);
+
+      *x += px;
+      *y += py;
+    }
+
+  if (w == NULL)
+    {
+      *x = 0;
+      *y = 0;
+      return FALSE;
+    }
+
+  return TRUE;
+}
+
+static void
+gimp_ruler_event_to_widget_coords (GtkWidget *widget,
+                                   GdkWindow *window,
+                                   gdouble    event_x,
+                                   gdouble    event_y,
+                                   gint      *widget_x,
+                                   gint      *widget_y)
+{
+  gint tx, ty;
+
+  if (gtk_widget_get_translation_to_window (widget, window, &tx, &ty))
+    {
+      event_x += tx;
+      event_y += ty;
+    }
+
+  *widget_x = event_x;
+  *widget_y = event_y;
+}
+
+static gboolean
+gimp_ruler_track_widget_motion_notify (GtkWidget      *widget,
+                                       GdkEventMotion *mevent,
+                                       GimpRuler      *ruler)
+{
+  gint widget_x;
+  gint widget_y;
+  gint ruler_x;
+  gint ruler_y;
+
+  widget = gtk_get_event_widget ((GdkEvent *) mevent);
+
+  gimp_ruler_event_to_widget_coords (widget, mevent->window,
+                                     mevent->x, mevent->y,
+                                     &widget_x, &widget_y);
+
+  gtk_widget_translate_coordinates (widget, GTK_WIDGET (ruler),
+                                    widget_x, widget_y,
+                                    &ruler_x, &ruler_y);
+
+  gimp_ruler_update_position (ruler, ruler_x, ruler_y);
+
+  return FALSE;
+}
+
 /**
- * gimp_ruler_set_position:
+ * gimp_ruler_add_track_widget:
+ * @ruler: a #GimpRuler
+ * @widget: the track widget to add
+ *
+ * Adds a "track widget" to the ruler. The ruler will connect to
+ * GtkWidget:motion-notify-event: on the track widget and update its
+ * position marker accordingly. The marker is correctly updated also
+ * for the track widget's children, regardless of whether they are
+ * ordinary children of off-screen children.
+ *
+ * Since: GIMP 2.8
+ */
+void
+gimp_ruler_add_track_widget (GimpRuler *ruler,
+                             GtkWidget *widget)
+{
+  GimpRulerPrivate *priv;
+
+  g_return_if_fail (GIMP_IS_RULER (ruler));
+  g_return_if_fail (GTK_IS_WIDGET (ruler));
+
+  priv = GIMP_RULER_GET_PRIVATE (ruler);
+
+  g_return_if_fail (g_list_find (priv->track_widgets, widget) == NULL);
+
+  priv->track_widgets = g_list_prepend (priv->track_widgets, widget);
+
+  g_signal_connect (widget, "motion-notify-event",
+                    G_CALLBACK (gimp_ruler_track_widget_motion_notify),
+                    ruler);
+  g_signal_connect_swapped (widget, "destroy",
+                            G_CALLBACK (gimp_ruler_remove_track_widget),
+                            ruler);
+}
+
+/**
+ * gimp_ruler_remove_track_widget:
+ * @ruler: a #GimpRuler
+ * @widget: the track widget to remove
+ *
+ * Removes a previously added track widget from the ruler. See
+ * gimp_ruler_add_track_widget().
+ *
+ * Since: GIMP 2.8
+ */
+void
+gimp_ruler_remove_track_widget (GimpRuler *ruler,
+                                GtkWidget *widget)
+{
+  GimpRulerPrivate *priv;
+
+  g_return_if_fail (GIMP_IS_RULER (ruler));
+  g_return_if_fail (GTK_IS_WIDGET (ruler));
+
+  priv = GIMP_RULER_GET_PRIVATE (ruler);
+
+  g_return_if_fail (g_list_find (priv->track_widgets, widget) != NULL);
+
+  priv->track_widgets = g_list_remove (priv->track_widgets, widget);
+
+  g_signal_handlers_disconnect_by_func (widget,
+                                        gimp_ruler_track_widget_motion_notify,
+                                        ruler);
+  g_signal_handlers_disconnect_by_func (widget,
+                                        gimp_ruler_remove_track_widget,
+                                        ruler);
+}
+
+/**
+ * gimp_ruler_set_unit:
  * @ruler: a #GimpRuler
  * @unit:  the #GimpUnit to set the ruler to
  *
@@ -568,14 +770,7 @@ static void
 gimp_ruler_size_allocate (GtkWidget     *widget,
                           GtkAllocation *allocation)
 {
-  GimpRuler     *ruler = GIMP_RULER (widget);
-  GtkAllocation  widget_allocation;
-  gboolean       resized;
-
-  gtk_widget_get_allocation (widget, &widget_allocation);
-
-  resized = (widget_allocation.width  != allocation->width ||
-             widget_allocation.height != allocation->height);
+  GimpRuler *ruler = GIMP_RULER (widget);
 
   gtk_widget_set_allocation (widget, allocation);
 
@@ -585,8 +780,7 @@ gimp_ruler_size_allocate (GtkWidget     *widget,
                               allocation->x, allocation->y,
                               allocation->width, allocation->height);
 
-      if (resized)
-        gimp_ruler_make_pixmap (ruler);
+      gimp_ruler_make_pixmap (ruler);
     }
 }
 
@@ -618,30 +812,6 @@ gimp_ruler_size_request (GtkWidget      *widget,
 }
 
 static void
-gimp_ruler_get_preferred_width (GtkWidget *widget,
-                                gint      *minimum_width,
-                                gint      *natural_width)
-{
-  GtkRequisition requisition;
-
-  gimp_ruler_size_request (widget, &requisition);
-
-  *minimum_width = *natural_width = requisition.width;
-}
-
-static void
-gimp_ruler_get_preferred_height (GtkWidget *widget,
-                                 gint      *minimum_height,
-                                 gint      *natural_height)
-{
-  GtkRequisition requisition;
-
-  gimp_ruler_size_request (widget, &requisition);
-
-  *minimum_height = *natural_height = requisition.height;
-}
-
-static void
 gimp_ruler_style_set (GtkWidget *widget,
                       GtkStyle  *prev_style)
 {
@@ -664,48 +834,38 @@ static gboolean
 gimp_ruler_motion_notify (GtkWidget      *widget,
                           GdkEventMotion *event)
 {
-  GimpRuler        *ruler = GIMP_RULER (widget);
-  GimpRulerPrivate *priv  = GIMP_RULER_GET_PRIVATE (ruler);
-  GtkAllocation     allocation;
-  gdouble           lower;
-  gdouble           upper;
+  GimpRuler *ruler = GIMP_RULER (widget);
 
   gdk_event_request_motions (event);
 
-  gtk_widget_get_allocation (widget, &allocation);
-  gimp_ruler_get_range (ruler, &lower, &upper, NULL);
-
-  if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
-    {
-      gimp_ruler_set_position (ruler,
-                               lower +
-                               (upper - lower) * event->x /
-                               allocation.width);
-    }
-  else
-    {
-      gimp_ruler_set_position (ruler,
-                               lower +
-                               (upper - lower) * event->y /
-                               allocation.height);
-    }
+  gimp_ruler_update_position (ruler, event->x, event->y);
 
   return FALSE;
 }
 
 static gboolean
-gimp_ruler_draw (GtkWidget *widget,
-                 cairo_t   *cr)
+gimp_ruler_expose (GtkWidget      *widget,
+                   GdkEventExpose *event)
 {
-  GimpRuler        *ruler = GIMP_RULER (widget);
-  GimpRulerPrivate *priv  = GIMP_RULER_GET_PRIVATE (ruler);
+  if (gtk_widget_is_drawable (widget))
+    {
+      GimpRuler        *ruler = GIMP_RULER (widget);
+      GimpRulerPrivate *priv  = GIMP_RULER_GET_PRIVATE (ruler);
+      cairo_t          *cr;
 
-  gimp_ruler_draw_ticks (ruler);
+      gimp_ruler_draw_ticks (ruler);
 
-  cairo_set_source_surface (cr, priv->backing_store, 0, 0);
-  cairo_paint (cr);
+      cr = gdk_cairo_create (gtk_widget_get_window (widget));
+      gdk_cairo_region (cr, event->region);
+      cairo_clip (cr);
+
+      cairo_set_source_surface (cr, priv->backing_store, 0, 0);
+      cairo_paint (cr);
+
+      gimp_ruler_draw_pos (ruler);
 
-  gimp_ruler_draw_pos (ruler);
+      cairo_destroy (cr);
+    }
 
   return FALSE;
 }
@@ -822,7 +982,7 @@ gimp_ruler_draw_ticks (GimpRuler *ruler)
     if (ruler_metric.ruler_scale[scale] * fabs (increment) > 2 * text_size)
       break;
 
-  if (scale == (gint)G_N_ELEMENTS (ruler_metric.ruler_scale))
+  if (scale == G_N_ELEMENTS (ruler_metric.ruler_scale))
     scale = G_N_ELEMENTS (ruler_metric.ruler_scale) - 1;
 
   unit = gimp_ruler_get_unit (ruler);
@@ -936,6 +1096,7 @@ gimp_ruler_draw_ticks (GimpRuler *ruler)
                                      pos + digit_height * j + 2 + PANGO_PIXELS (logical_rect.y - digit_offset));
                       pango_cairo_show_layout (cr, layout);
 #endif
+
                     }
                 }
             }
@@ -1004,6 +1165,7 @@ gimp_ruler_draw_pos (GimpRuler *ruler)
           cairo_fill (cr);
         }
 
+
       position = gimp_ruler_get_position (ruler);
 
       gimp_ruler_get_range (ruler, &lower, &upper, NULL);
@@ -1053,17 +1215,24 @@ gimp_ruler_make_pixmap (GimpRuler *ruler)
   GtkWidget        *widget = GTK_WIDGET (ruler);
   GimpRulerPrivate *priv   = GIMP_RULER_GET_PRIVATE (ruler);
   GtkAllocation     allocation;
+  cairo_t          *cr;
+  cairo_surface_t  *surface;
 
   gtk_widget_get_allocation (widget, &allocation);
 
   if (priv->backing_store)
     cairo_surface_destroy (priv->backing_store);
 
+  cr = gdk_cairo_create (gtk_widget_get_window (widget));
+  surface = cairo_get_target (cr);
+
   priv->backing_store =
-    gdk_window_create_similar_surface (gtk_widget_get_window (widget),
-                                       CAIRO_CONTENT_COLOR,
-                                       allocation.width,
-                                       allocation.height);
+    cairo_surface_create_similar (surface,
+                                  CAIRO_CONTENT_COLOR,
+                                  allocation.width,
+                                  allocation.height);
+
+  cairo_destroy (cr);
 }
 
 
@@ -1107,3 +1276,4 @@ gimp_ruler_get_layout (GtkWidget   *widget,
 
   return priv->layout;
 }
+
diff --git a/glom/utility_widgets/gimpruler/gimpruler.h b/glom/utility_widgets/gimpruler/gimpruler.h
index fa288c7..25a3bcd 100644
--- a/glom/utility_widgets/gimpruler/gimpruler.h
+++ b/glom/utility_widgets/gimpruler/gimpruler.h
@@ -53,23 +53,30 @@ struct _GimpRulerClass
 };
 
 
-GType       gimp_ruler_get_type     (void) G_GNUC_CONST;
-
-GtkWidget * gimp_ruler_new          (GtkOrientation  orientation);
-void        gimp_ruler_set_unit     (GimpRuler      *ruler,
-                                     GimpUnit        unit);
-GimpUnit    gimp_ruler_get_unit     (GimpRuler      *ruler);
-void        gimp_ruler_set_position (GimpRuler      *ruler,
-                                     gdouble         position);
-gdouble     gimp_ruler_get_position (GimpRuler      *ruler);
-void        gimp_ruler_set_range    (GimpRuler      *ruler,
-                                     gdouble         lower,
-                                     gdouble         upper,
-                                     gdouble         max_size);
-void        gimp_ruler_get_range    (GimpRuler      *ruler,
-                                     gdouble        *lower,
-                                     gdouble        *upper,
-                                     gdouble        *max_size);
+
+GType       gimp_ruler_get_type            (void) G_GNUC_CONST;
+
+GtkWidget * gimp_ruler_new                 (GtkOrientation  orientation);
+
+void        gimp_ruler_add_track_widget    (GimpRuler      *ruler,
+                                            GtkWidget      *widget);
+void        gimp_ruler_remove_track_widget (GimpRuler      *ruler,
+                                            GtkWidget      *widget);
+
+void        gimp_ruler_set_unit            (GimpRuler      *ruler,
+                                            GimpUnit        unit);
+GimpUnit    gimp_ruler_get_unit            (GimpRuler      *ruler);
+void        gimp_ruler_set_position        (GimpRuler      *ruler,
+                                            gdouble         position);
+gdouble     gimp_ruler_get_position        (GimpRuler      *ruler);
+void        gimp_ruler_set_range           (GimpRuler      *ruler,
+                                            gdouble         lower,
+                                            gdouble         upper,
+                                            gdouble         max_size);
+void        gimp_ruler_get_range           (GimpRuler      *ruler,
+                                            gdouble        *lower,
+                                            gdouble        *upper,
+                                            gdouble        *max_size);
 
 G_END_DECLS
 



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