diff --git a/app/display/gimpcanvasgroup.c b/app/display/gimpcanvasgroup.c index ab31d61c4f..efbfd44b80 100644 --- a/app/display/gimpcanvasgroup.c +++ b/app/display/gimpcanvasgroup.c @@ -72,6 +72,11 @@ static void gimp_canvas_group_draw (GimpCanvasItem *item, cairo_t *cr); static cairo_region_t * gimp_canvas_group_get_extents (GimpCanvasItem *item, GimpDisplayShell *shell); +static gboolean gimp_canvas_group_hit (GimpCanvasItem *item, + GimpDisplayShell *shell, + gdouble x, + gdouble y); + static void gimp_canvas_group_child_update (GimpCanvasItem *item, cairo_region_t *region, GimpCanvasGroup *group); @@ -94,6 +99,7 @@ gimp_canvas_group_class_init (GimpCanvasGroupClass *klass) item_class->draw = gimp_canvas_group_draw; item_class->get_extents = gimp_canvas_group_get_extents; + item_class->hit = gimp_canvas_group_hit; g_object_class_install_property (object_class, PROP_GROUP_STROKING, g_param_spec_boolean ("group-stroking", @@ -224,6 +230,24 @@ gimp_canvas_group_get_extents (GimpCanvasItem *item, return region; } +static gboolean +gimp_canvas_group_hit (GimpCanvasItem *item, + GimpDisplayShell *shell, + gdouble x, + gdouble y) +{ + GimpCanvasGroupPrivate *private = GET_PRIVATE (item); + GList *list; + + for (list = private->items; list; list = g_list_next (list)) + { + if (gimp_canvas_item_hit (list->data, x, y)) + return TRUE; + } + + return FALSE; +} + static void gimp_canvas_group_child_update (GimpCanvasItem *item, cairo_region_t *region, diff --git a/app/display/gimpcanvashandle.c b/app/display/gimpcanvashandle.c index 350b301ce7..4f510169cd 100644 --- a/app/display/gimpcanvashandle.c +++ b/app/display/gimpcanvashandle.c @@ -85,6 +85,10 @@ static void gimp_canvas_handle_draw (GimpCanvasItem *item, cairo_t *cr); static cairo_region_t * gimp_canvas_handle_get_extents (GimpCanvasItem *item, GimpDisplayShell *shell); +static gboolean gimp_canvas_handle_hit (GimpCanvasItem *item, + GimpDisplayShell *shell, + gdouble x, + gdouble y); G_DEFINE_TYPE (GimpCanvasHandle, gimp_canvas_handle, @@ -104,6 +108,7 @@ gimp_canvas_handle_class_init (GimpCanvasHandleClass *klass) item_class->draw = gimp_canvas_handle_draw; item_class->get_extents = gimp_canvas_handle_get_extents; + item_class->hit = gimp_canvas_handle_hit; g_object_class_install_property (object_class, PROP_TYPE, g_param_spec_enum ("type", NULL, NULL, @@ -380,6 +385,50 @@ gimp_canvas_handle_get_extents (GimpCanvasItem *item, return cairo_region_create_rectangle ((cairo_rectangle_int_t *) &rectangle); } +static gboolean +gimp_canvas_handle_hit (GimpCanvasItem *item, + GimpDisplayShell *shell, + gdouble x, + gdouble y) +{ + GimpCanvasHandlePrivate *private = GET_PRIVATE (item); + gdouble handle_tx, handle_ty; + gdouble tx, ty; + + gimp_canvas_handle_transform (item, shell, &handle_tx, &handle_ty); + + gimp_display_shell_transform_xy_f (shell, + x, y, + &tx, &ty); + + switch (private->type) + { + case GIMP_HANDLE_SQUARE: + case GIMP_HANDLE_FILLED_SQUARE: + return (tx == CLAMP (tx, handle_tx, handle_tx + private->width) && + ty == CLAMP (ty, handle_ty, handle_ty + private->height)); + + case GIMP_HANDLE_CIRCLE: + case GIMP_HANDLE_FILLED_CIRCLE: + case GIMP_HANDLE_CROSS: + { + gint width = private->width; + + if (width != private->height) + width = (width + private->height) / 2; + + width /= 2; + + return ((SQR (handle_tx - tx) + SQR (handle_ty - ty)) < SQR (width)); + } + + default: + break; + } + + return FALSE; +} + GimpCanvasItem * gimp_canvas_handle_new (GimpDisplayShell *shell, GimpHandleType type, diff --git a/app/display/gimpcanvasitem.c b/app/display/gimpcanvasitem.c index 3ec86520e9..5dc8b38838 100644 --- a/app/display/gimpcanvasitem.c +++ b/app/display/gimpcanvasitem.c @@ -96,6 +96,10 @@ static void gimp_canvas_item_real_stroke (GimpCanvasItem *ite static void gimp_canvas_item_real_fill (GimpCanvasItem *item, GimpDisplayShell *shell, cairo_t *cr); +static gboolean gimp_canvas_item_real_hit (GimpCanvasItem *item, + GimpDisplayShell *shell, + gdouble x, + gdouble y); G_DEFINE_TYPE (GimpCanvasItem, gimp_canvas_item, @@ -121,6 +125,7 @@ gimp_canvas_item_class_init (GimpCanvasItemClass *klass) klass->get_extents = gimp_canvas_item_real_get_extents; klass->stroke = gimp_canvas_item_real_stroke; klass->fill = gimp_canvas_item_real_fill; + klass->hit = gimp_canvas_item_real_hit; item_signals[UPDATE] = g_signal_new ("update", @@ -318,6 +323,15 @@ gimp_canvas_item_real_fill (GimpCanvasItem *item, cairo_fill (cr); } +static gboolean +gimp_canvas_item_real_hit (GimpCanvasItem *item, + GimpDisplayShell *shell, + gdouble x, + gdouble y) +{ + return FALSE; +} + /* public functions */ @@ -355,6 +369,20 @@ gimp_canvas_item_get_extents (GimpCanvasItem *item) return NULL; } +gboolean +gimp_canvas_item_hit (GimpCanvasItem *item, + gdouble x, + gdouble y) +{ + GimpCanvasItemPrivate *private; + + g_return_val_if_fail (GIMP_IS_CANVAS_ITEM (item), NULL); + + private = GET_PRIVATE (item); + + return GIMP_CANVAS_ITEM_GET_CLASS (item)->hit (item, private->shell, x, y); +} + void gimp_canvas_item_set_visible (GimpCanvasItem *item, gboolean visible) diff --git a/app/display/gimpcanvasitem.h b/app/display/gimpcanvasitem.h index a72342efa2..492df6c9b1 100644 --- a/app/display/gimpcanvasitem.h +++ b/app/display/gimpcanvasitem.h @@ -61,6 +61,11 @@ struct _GimpCanvasItemClass void (* fill) (GimpCanvasItem *item, GimpDisplayShell *shell, cairo_t *cr); + + gboolean (* hit) (GimpCanvasItem *item, + GimpDisplayShell *shell, + gdouble x, + gdouble y); }; @@ -70,6 +75,10 @@ void gimp_canvas_item_draw (GimpCanvasItem *item, cairo_t *cr); cairo_region_t * gimp_canvas_item_get_extents (GimpCanvasItem *item); +gboolean gimp_canvas_item_hit (GimpCanvasItem *item, + gdouble x, + gdouble y); + void gimp_canvas_item_set_visible (GimpCanvasItem *item, gboolean visible); gboolean gimp_canvas_item_get_visible (GimpCanvasItem *item);