X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=gtk%2Fgtkcolorplane.c;h=33dc0260c4129dc215526ad131c79c08a2ba66e3;hb=1708ae3f1a962d3bbfcc0e673c5fa9f629d16eae;hp=644203484401ce05a7af41318dcc884d2c4c934f;hpb=e06ccb0fbb151411ee312fcd02ade9752729c54a;p=~andy%2Fgtk diff --git a/gtk/gtkcolorplane.c b/gtk/gtkcolorplane.c index 644203484..33dc0260c 100644 --- a/gtk/gtkcolorplane.c +++ b/gtk/gtkcolorplane.c @@ -12,37 +12,54 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * License along with this library. If not, see . */ #include "config.h" -#include "gtkhsv.h" -#include "gtkcolorplane.h" +#include "gtkcolorplaneprivate.h" + +#include "gtkaccessible.h" +#include "gtkadjustment.h" +#include "gtkcolorutils.h" +#include "gtkpressandholdprivate.h" +#include "gtkintl.h" struct _GtkColorPlanePrivate { + GtkAdjustment *h_adj; + GtkAdjustment *s_adj; + GtkAdjustment *v_adj; + cairo_surface_t *surface; - gdouble h, s, v; - gint x, y; gboolean in_drag; + + GtkPressAndHold *press_and_hold; }; -enum +G_DEFINE_TYPE (GtkColorPlane, gtk_color_plane, GTK_TYPE_DRAWING_AREA) + +static void +sv_to_xy (GtkColorPlane *plane, + gint *x, + gint *y) { - CHANGED, - LAST_SIGNAL -}; + gdouble s, v; + gint width, height; -guint signals[LAST_SIGNAL]; + width = gtk_widget_get_allocated_width (GTK_WIDGET (plane)); + height = gtk_widget_get_allocated_height (GTK_WIDGET (plane)); -G_DEFINE_TYPE (GtkColorPlane, gtk_color_plane, GTK_TYPE_DRAWING_AREA) + s = gtk_adjustment_get_value (plane->priv->s_adj); + v = gtk_adjustment_get_value (plane->priv->v_adj); + + *x = CLAMP (width * v, 0, width - 1); + *y = CLAMP (height * (1 - s), 0, height - 1); +} static gboolean -sv_draw (GtkWidget *widget, - cairo_t *cr) +plane_draw (GtkWidget *widget, + cairo_t *cr) { GtkColorPlane *plane = GTK_COLOR_PLANE (widget); gint x, y; @@ -51,8 +68,7 @@ sv_draw (GtkWidget *widget, cairo_set_source_surface (cr, plane->priv->surface, 0, 0); cairo_paint (cr); - x = plane->priv->x; - y = plane->priv->y; + sv_to_xy (plane, &x, &y); width = gtk_widget_get_allocated_width (widget); height = gtk_widget_get_allocated_height (widget); @@ -83,7 +99,7 @@ sv_draw (GtkWidget *widget, } static void -create_sv_surface (GtkColorPlane *plane) +create_surface (GtkColorPlane *plane) { GtkWidget *widget = GTK_WIDGET (plane); cairo_t *cr; @@ -116,9 +132,9 @@ create_sv_surface (GtkColorPlane *plane) stride = cairo_format_stride_for_width (CAIRO_FORMAT_RGB24, width); - data = g_malloc (4 * height * stride); + data = g_malloc (height * stride); - h = plane->priv->h; + h = gtk_adjustment_get_value (plane->priv->h_adj); sf = 1.0 / (height - 1); vf = 1.0 / (width - 1); for (y = 0; y < height; y++) @@ -148,26 +164,11 @@ create_sv_surface (GtkColorPlane *plane) g_free (data); } -static void -hsv_to_xy (GtkColorPlane *plane) -{ - gint width, height; - - width = gtk_widget_get_allocated_width (GTK_WIDGET (plane)); - height = gtk_widget_get_allocated_height (GTK_WIDGET (plane)); - - plane->priv->x = CLAMP (width * plane->priv->v, 0, width - 1); - plane->priv->y = CLAMP (height * (1 - plane->priv->s), 0, height - 1); -} - static gboolean -sv_configure (GtkWidget *widget, - GdkEventConfigure *event) +plane_configure (GtkWidget *widget, + GdkEventConfigure *event) { - GtkColorPlane *plane = GTK_COLOR_PLANE (widget); - - create_sv_surface (plane); - hsv_to_xy (plane); + create_surface (GTK_COLOR_PLANE (widget)); return TRUE; } @@ -193,52 +194,71 @@ set_cross_grab (GtkWidget *widget, } static gboolean -sv_grab_broken (GtkWidget *widget, - GdkEventGrabBroken *event) +plane_grab_broken (GtkWidget *widget, + GdkEventGrabBroken *event) { - GtkColorPlane *plane = GTK_COLOR_PLANE (widget); + GTK_COLOR_PLANE (widget)->priv->in_drag = FALSE; + return TRUE; +} - plane->priv->in_drag = FALSE; +static void +h_changed (GtkColorPlane *plane) +{ + create_surface (plane); + gtk_widget_queue_draw (GTK_WIDGET (plane)); +} - return TRUE; +static void +sv_changed (GtkColorPlane *plane) +{ + gtk_widget_queue_draw (GTK_WIDGET (plane)); } static void -sv_update_color (GtkColorPlane *plane, - gint x, - gint y) +update_color (GtkColorPlane *plane, + gint x, + gint y) { GtkWidget *widget = GTK_WIDGET (plane); + gdouble s, v; - plane->priv->x = x; - plane->priv->y = y; + s = CLAMP (1 - y * (1.0 / gtk_widget_get_allocated_height (widget)), 0, 1); + v = CLAMP (x * (1.0 / gtk_widget_get_allocated_width (widget)), 0, 1); + gtk_adjustment_set_value (plane->priv->s_adj, s); + gtk_adjustment_set_value (plane->priv->v_adj, v); - plane->priv->s = CLAMP (1 - y * (1.0 / gtk_widget_get_allocated_height (widget)), 0, 1); - plane->priv->v = CLAMP (x * (1.0 / gtk_widget_get_allocated_width (widget)), 0, 1); - g_signal_emit (plane, signals[CHANGED], 0); gtk_widget_queue_draw (widget); } static gboolean -sv_button_press (GtkWidget *widget, - GdkEventButton *event) +plane_button_press (GtkWidget *widget, + GdkEventButton *event) { GtkColorPlane *plane = GTK_COLOR_PLANE (widget); + if (event->button == GDK_BUTTON_SECONDARY) + { + gboolean handled; + + g_signal_emit_by_name (widget, "popup-menu", &handled); + + return TRUE; + } + if (plane->priv->in_drag || event->button != GDK_BUTTON_PRIMARY) return FALSE; plane->priv->in_drag = TRUE; set_cross_grab (widget, gdk_event_get_device ((GdkEvent*)event), event->time); - sv_update_color (plane, event->x, event->y); + update_color (plane, event->x, event->y); gtk_widget_grab_focus (widget); return TRUE; } static gboolean -sv_button_release (GtkWidget *widget, - GdkEventButton *event) +plane_button_release (GtkWidget *widget, + GdkEventButton *event) { GtkColorPlane *plane = GTK_COLOR_PLANE (widget); @@ -247,15 +267,15 @@ sv_button_release (GtkWidget *widget, plane->priv->in_drag = FALSE; - sv_update_color (plane, event->x, event->y); + update_color (plane, event->x, event->y); gdk_device_ungrab (gdk_event_get_device ((GdkEvent *) event), event->time); return TRUE; } static gboolean -sv_motion (GtkWidget *widget, - GdkEventMotion *event) +plane_motion_notify (GtkWidget *widget, + GdkEventMotion *event) { GtkColorPlane *plane = GTK_COLOR_PLANE (widget); @@ -263,7 +283,49 @@ sv_motion (GtkWidget *widget, return FALSE; gdk_event_request_motions (event); - sv_update_color (plane, event->x, event->y); + update_color (plane, event->x, event->y); + + return TRUE; +} + +static void +hold_action (GtkPressAndHold *pah, + gint x, + gint y, + GtkColorPlane *plane) +{ + gboolean handled; + + g_signal_emit_by_name (plane, "popup-menu", &handled); +} + +static gboolean +plane_touch (GtkWidget *widget, + GdkEventTouch *event) +{ + GtkColorPlane *plane = GTK_COLOR_PLANE (widget); + + if (!plane->priv->press_and_hold) + { + gint drag_threshold; + + g_object_get (gtk_widget_get_settings (widget), + "gtk-dnd-drag-threshold", &drag_threshold, + NULL); + + plane->priv->press_and_hold = gtk_press_and_hold_new (); + + g_object_set (plane->priv->press_and_hold, + "drag-threshold", drag_threshold, + "hold-time", 1000, + NULL); + + g_signal_connect (plane->priv->press_and_hold, "hold", + G_CALLBACK (hold_action), plane); + } + + gtk_press_and_hold_process_event (plane->priv->press_and_hold, (GdkEvent *)event); + update_color (plane, event->x, event->y); return TRUE; } @@ -273,48 +335,51 @@ sv_move (GtkColorPlane *plane, gdouble ds, gdouble dv) { - if (plane->priv->s + ds > 1) + gdouble s, v; + + s = gtk_adjustment_get_value (plane->priv->s_adj); + v = gtk_adjustment_get_value (plane->priv->v_adj); + + if (s + ds > 1) { - if (plane->priv->s < 1) - plane->priv->s = 1; + if (s < 1) + s = 1; else goto error; } - else if (plane->priv->s + ds < 0) + else if (s + ds < 0) { - if (plane->priv->s > 0) - plane->priv->s = 0; + if (s > 0) + s = 0; else goto error; } else { - plane->priv->s += ds; + s += ds; } - if (plane->priv->v + dv > 1) + if (v + dv > 1) { - if (plane->priv->v < 1) - plane->priv->v = 1; + if (v < 1) + v = 1; else goto error; } - else if (plane->priv->v + dv < 0) + else if (v + dv < 0) { - if (plane->priv->v > 0) - plane->priv->v = 0; + if (v > 0) + v = 0; else goto error; } else { - plane->priv->v += dv; + v += dv; } - hsv_to_xy (plane); - g_signal_emit (plane, signals[CHANGED], 0); - - gtk_widget_queue_draw (GTK_WIDGET (plane)); + gtk_adjustment_set_value (plane->priv->s_adj, s); + gtk_adjustment_set_value (plane->priv->v_adj, v); return; error: @@ -322,13 +387,12 @@ error: } static gboolean -sv_key_press (GtkWidget *widget, - GdkEventKey *event) +plane_key_press (GtkWidget *widget, + GdkEventKey *event) { GtkColorPlane *plane = GTK_COLOR_PLANE (widget); gdouble step; - /* FIXME: turn into bindings */ if ((event->state & GDK_MOD1_MASK) != 0) step = 0.1; else @@ -347,7 +411,7 @@ sv_key_press (GtkWidget *widget, event->keyval == GDK_KEY_KP_Right) sv_move (plane, 0, step); else - return FALSE; + return GTK_WIDGET_CLASS (gtk_color_plane_parent_class)->key_press_event (widget, event); return TRUE; } @@ -355,22 +419,40 @@ sv_key_press (GtkWidget *widget, static void gtk_color_plane_init (GtkColorPlane *plane) { + AtkObject *atk_obj; + plane->priv = G_TYPE_INSTANCE_GET_PRIVATE (plane, GTK_TYPE_COLOR_PLANE, GtkColorPlanePrivate); + gtk_widget_set_can_focus (GTK_WIDGET (plane), TRUE); gtk_widget_set_events (GTK_WIDGET (plane), GDK_KEY_PRESS_MASK + | GDK_TOUCH_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK); + + atk_obj = gtk_widget_get_accessible (GTK_WIDGET (plane)); + if (GTK_IS_ACCESSIBLE (atk_obj)) + { + atk_object_set_name (atk_obj, _("Color Plane")); + atk_object_set_role (atk_obj, ATK_ROLE_COLOR_CHOOSER); + } } static void -sv_finalize (GObject *object) +plane_finalize (GObject *object) { GtkColorPlane *plane = GTK_COLOR_PLANE (object); - cairo_surface_destroy (plane->priv->surface); + if (plane->priv->surface) + cairo_surface_destroy (plane->priv->surface); + + g_clear_object (&plane->priv->h_adj); + g_clear_object (&plane->priv->s_adj); + g_clear_object (&plane->priv->v_adj); + + g_clear_object (&plane->priv->press_and_hold); G_OBJECT_CLASS (gtk_color_plane_parent_class)->finalize (object); } @@ -381,75 +463,35 @@ gtk_color_plane_class_init (GtkColorPlaneClass *class) GObjectClass *object_class = G_OBJECT_CLASS (class); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class); - object_class->finalize = sv_finalize; - - widget_class->draw = sv_draw; - widget_class->configure_event = sv_configure; - widget_class->button_press_event = sv_button_press; - widget_class->button_release_event = sv_button_release; - widget_class->motion_notify_event = sv_motion; - widget_class->grab_broken_event = sv_grab_broken; - widget_class->key_press_event = sv_key_press; - - signals[CHANGED] = - g_signal_new ("changed", - GTK_TYPE_COLOR_PLANE, - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (GtkColorPlaneClass, changed), - NULL, NULL, - NULL, - G_TYPE_NONE, 0); - - g_type_class_add_private (class, sizeof (GtkColorPlanePrivate)); -} - -gdouble -gtk_color_plane_get_h (GtkColorPlane *plane) -{ - return plane->priv->h; -} + object_class->finalize = plane_finalize; -gdouble -gtk_color_plane_get_s (GtkColorPlane *plane) -{ - return plane->priv->s; -} + widget_class->draw = plane_draw; + widget_class->configure_event = plane_configure; + widget_class->button_press_event = plane_button_press; + widget_class->button_release_event = plane_button_release; + widget_class->motion_notify_event = plane_motion_notify; + widget_class->grab_broken_event = plane_grab_broken; + widget_class->key_press_event = plane_key_press; + widget_class->touch_event = plane_touch; -gdouble -gtk_color_plane_get_v (GtkColorPlane *plane) -{ - return plane->priv->v; + g_type_class_add_private (class, sizeof (GtkColorPlanePrivate)); } -void -gtk_color_plane_set_h (GtkColorPlane *plane, - gdouble h) +GtkWidget * +gtk_color_plane_new (GtkAdjustment *h_adj, + GtkAdjustment *s_adj, + GtkAdjustment *v_adj) { - plane->priv->h = h; - create_sv_surface (plane); - gtk_widget_queue_draw (GTK_WIDGET (plane)); -} + GtkColorPlane *plane; -void -gtk_color_plane_set_s (GtkColorPlane *plane, - gdouble s) -{ - plane->priv->s = s; - hsv_to_xy (plane); - gtk_widget_queue_draw (GTK_WIDGET (plane)); -} + plane = (GtkColorPlane *) g_object_new (GTK_TYPE_COLOR_PLANE, NULL); -void -gtk_color_plane_set_v (GtkColorPlane *plane, - gdouble v) -{ - plane->priv->v = v; - hsv_to_xy (plane); - gtk_widget_queue_draw (GTK_WIDGET (plane)); -} + plane->priv->h_adj = g_object_ref_sink (h_adj); + plane->priv->s_adj = g_object_ref_sink (s_adj); + plane->priv->v_adj = g_object_ref_sink (v_adj); + g_signal_connect_swapped (h_adj, "value-changed", G_CALLBACK (h_changed), plane); + g_signal_connect_swapped (s_adj, "value-changed", G_CALLBACK (sv_changed), plane); + g_signal_connect_swapped (v_adj, "value-changed", G_CALLBACK (sv_changed), plane); -GtkWidget * -gtk_color_plane_new (void) -{ - return (GtkWidget *) g_object_new (GTK_TYPE_COLOR_PLANE, NULL); + return (GtkWidget *)plane; }