From 81839e6ebd1007f4674e65e5908ec4fd46fb64a6 Mon Sep 17 00:00:00 2001 From: Alex Valavanis Date: Wed, 26 Dec 2012 12:53:09 +0000 Subject: ruler: (GIMP merge) Add track_widget API and fix GTK+ 3 build failure in color slider (bzr r11988) --- src/widgets/ruler.cpp | 164 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 164 insertions(+) (limited to 'src/widgets/ruler.cpp') diff --git a/src/widgets/ruler.cpp b/src/widgets/ruler.cpp index 851af640a..31ef28c61 100644 --- a/src/widgets/ruler.cpp +++ b/src/widgets/ruler.cpp @@ -78,6 +78,8 @@ typedef struct gint xsrc; gint ysrc; + + GList *track_widgets; } SPRulerPrivate; #define SP_RULER_GET_PRIVATE(ruler) \ @@ -99,6 +101,7 @@ static SPRulerMetric const sp_ruler_metrics[] = { }; +static void sp_ruler_dispose (GObject *object); static void sp_ruler_set_property (GObject *object, guint prop_id, const GValue *value, @@ -158,6 +161,7 @@ sp_ruler_class_init (SPRulerClass *klass) GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); + object_class->dispose = sp_ruler_dispose; object_class->set_property = sp_ruler_set_property; object_class->get_property = sp_ruler_get_property; @@ -273,6 +277,18 @@ sp_ruler_init (SPRuler *ruler) sp_ruler_set_metric(ruler, SP_PX); } +static void +sp_ruler_dispose (GObject *object) +{ + SPRuler *ruler = SP_RULER (object); + SPRulerPrivate *priv = SP_RULER_GET_PRIVATE (ruler); + + while (priv->track_widgets) + sp_ruler_remove_track_widget (ruler, GTK_WIDGET(priv->track_widgets->data)); + + G_OBJECT_CLASS (parent_class)->dispose (object); +} + /** * sp_ruler_set_range: @@ -912,6 +928,154 @@ sp_ruler_update_position (SPRuler *ruler, } } +/* 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 += px; + } + + if (w == NULL) + { + *x = 0; + *y = 0; + return FALSE; + } + + return TRUE; +} + +static void +sp_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 +sp_ruler_track_widget_motion_notify (GtkWidget *widget, + GdkEventMotion *mevent, + SPRuler *ruler) +{ + gint widget_x; + gint widget_y; + gint ruler_x; + gint ruler_y; + + widget = gtk_get_event_widget (reinterpret_cast(mevent)); + + sp_ruler_event_to_widget_coords (widget, mevent->window, + mevent->x, mevent->y, + &widget_x, &widget_y); + + if (gtk_widget_translate_coordinates (widget, GTK_WIDGET (ruler), + widget_x, widget_y, + &ruler_x, &ruler_y)) + { + sp_ruler_update_position (ruler, ruler_x, ruler_y); + } + + return FALSE; +} + +void +sp_ruler_add_track_widget (SPRuler *ruler, + GtkWidget *widget) +{ + SPRulerPrivate *priv; + + g_return_if_fail (SP_IS_RULER (ruler)); + g_return_if_fail (GTK_IS_WIDGET (ruler)); + + priv = SP_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 (sp_ruler_track_widget_motion_notify), + ruler); + g_signal_connect (widget, "destroy", + G_CALLBACK (sp_ruler_remove_track_widget), + ruler); +} + +/** + * sp_ruler_remove_track_widget: + * @ruler: an #SPRuler + * @widget: the track widget to remove + * + * Removes a previously added track widget from the ruler. See + * sp_ruler_add_track_widget(). + */ +void +sp_ruler_remove_track_widget (SPRuler *ruler, + GtkWidget *widget) +{ + SPRulerPrivate *priv; + + g_return_if_fail (SP_IS_RULER (ruler)); + g_return_if_fail (GTK_IS_WIDGET (ruler)); + + priv = SP_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, + (gpointer) G_CALLBACK (sp_ruler_track_widget_motion_notify), + ruler); + g_signal_handlers_disconnect_by_func (widget, + (gpointer) G_CALLBACK (sp_ruler_remove_track_widget), + ruler); +} + /** * sp_ruler_set_position: * @ruler: a #SPRuler -- cgit v1.2.3