Commit 52a92a34 authored by Ell's avatar Ell

app: implement GimpToolWidget::hit() in all tool widgets

... and move the common functionality of their hit() and hover()
implementation to a separate function.
parent 385203f4
......@@ -130,6 +130,10 @@ static void gimp_tool_compass_motion (GimpToolWidget *widget
const GimpCoords *coords,
guint32 time,
GdkModifierType state);
static GimpHit gimp_tool_compass_hit (GimpToolWidget *widget,
const GimpCoords *coords,
GdkModifierType state,
gboolean proximity);
static void gimp_tool_compass_hover (GimpToolWidget *widget,
const GimpCoords *coords,
GdkModifierType state,
......@@ -146,6 +150,8 @@ static gboolean gimp_tool_compass_get_cursor (GimpToolWidget *widget
GimpToolCursorType *tool_cursor,
GimpCursorModifier *modifier);
static gint gimp_tool_compass_get_point (GimpToolCompass *compass,
const GimpCoords *coords);
static void gimp_tool_compass_update_hilight (GimpToolCompass *compass);
......@@ -170,6 +176,7 @@ gimp_tool_compass_class_init (GimpToolCompassClass *klass)
widget_class->button_press = gimp_tool_compass_button_press;
widget_class->button_release = gimp_tool_compass_button_release;
widget_class->motion = gimp_tool_compass_motion;
widget_class->hit = gimp_tool_compass_hit;
widget_class->hover = gimp_tool_compass_hover;
widget_class->leave_notify = gimp_tool_compass_leave_notify;
widget_class->motion_modifier = gimp_tool_compass_motion_modifier;
......@@ -781,6 +788,20 @@ gimp_tool_compass_motion (GimpToolWidget *widget,
}
}
GimpHit
gimp_tool_compass_hit (GimpToolWidget *widget,
const GimpCoords *coords,
GdkModifierType state,
gboolean proximity)
{
GimpToolCompass *compass = GIMP_TOOL_COMPASS (widget);
if (gimp_tool_compass_get_point (compass, coords) >= 0)
return GIMP_HIT_DIRECT;
else
return GIMP_HIT_INDIRECT;
}
void
gimp_tool_compass_hover (GimpToolWidget *widget,
const GimpCoords *coords,
......@@ -789,85 +810,71 @@ gimp_tool_compass_hover (GimpToolWidget *widget,
{
GimpToolCompass *compass = GIMP_TOOL_COMPASS (widget);
GimpToolCompassPrivate *private = compass->private;
gint point = -1;
gint i;
gint point;
private->mouse_x = coords->x;
private->mouse_y = coords->y;
for (i = 0; i < private->n_points; i++)
{
if (gimp_canvas_item_hit (private->handles[i],
coords->x, coords->y))
{
GdkModifierType extend_mask = gimp_get_extend_selection_mask ();
GdkModifierType toggle_mask = gimp_get_toggle_behavior_mask ();
gchar *status;
point = i;
point = gimp_tool_compass_get_point (compass, coords);
if (state & toggle_mask)
{
if (state & GDK_MOD1_MASK)
{
status = gimp_suggest_modifiers (_("Click to place "
"vertical and "
"horizontal guides"),
0,
NULL, NULL, NULL);
}
else
{
status = gimp_suggest_modifiers (_("Click to place a "
"horizontal guide"),
GDK_MOD1_MASK & ~state,
NULL, NULL, NULL);
}
gimp_tool_widget_set_status (widget, status);
g_free (status);
break;
}
if (point >= 0)
{
GdkModifierType extend_mask = gimp_get_extend_selection_mask ();
GdkModifierType toggle_mask = gimp_get_toggle_behavior_mask ();
gchar *status;
if (state & toggle_mask)
{
if (state & GDK_MOD1_MASK)
{
status = gimp_suggest_modifiers (_("Click to place a "
"vertical guide"),
toggle_mask & ~state,
NULL, NULL, NULL);
gimp_tool_widget_set_status (widget, status);
g_free (status);
break;
}
if ((state & extend_mask) &&
! ((i == 0) && (private->n_points == 3)))
{
status = gimp_suggest_modifiers (_("Click-Drag to add a "
"new point"),
(toggle_mask |
GDK_MOD1_MASK) & ~state,
status = gimp_suggest_modifiers (_("Click to place "
"vertical and "
"horizontal guides"),
0,
NULL, NULL, NULL);
}
else
{
if ((i == 0) && (private->n_points == 3))
state |= extend_mask;
status = gimp_suggest_modifiers (_("Click-Drag to move this "
"point"),
(extend_mask |
toggle_mask |
GDK_MOD1_MASK) & ~state,
status = gimp_suggest_modifiers (_("Click to place a "
"horizontal guide"),
GDK_MOD1_MASK & ~state,
NULL, NULL, NULL);
}
gimp_tool_widget_set_status (widget, status);
g_free (status);
break;
}
}
else if (state & GDK_MOD1_MASK)
{
status = gimp_suggest_modifiers (_("Click to place a "
"vertical guide"),
toggle_mask & ~state,
NULL, NULL, NULL);
}
else if ((state & extend_mask) &&
! ((point == 0) && (private->n_points == 3)))
{
status = gimp_suggest_modifiers (_("Click-Drag to add a "
"new point"),
(toggle_mask |
GDK_MOD1_MASK) & ~state,
NULL, NULL, NULL);
}
else
{
if ((point == 0) && (private->n_points == 3))
state |= extend_mask;
status = gimp_suggest_modifiers (_("Click-Drag to move this "
"point"),
(extend_mask |
toggle_mask |
GDK_MOD1_MASK) & ~state,
NULL, NULL, NULL);
}
gimp_tool_widget_set_status (widget, status);
if (point == -1)
g_free (status);
}
else
{
if ((private->n_points > 1) && (state & GDK_MOD1_MASK))
{
......@@ -1009,6 +1016,25 @@ gimp_tool_compass_get_cursor (GimpToolWidget *widget,
return FALSE;
}
static gint
gimp_tool_compass_get_point (GimpToolCompass *compass,
const GimpCoords *coords)
{
GimpToolCompassPrivate *private = compass->private;
gint i;
for (i = 0; i < private->n_points; i++)
{
if (gimp_canvas_item_hit (private->handles[i],
coords->x, coords->y))
{
return i;
}
}
return -1;
}
static void
gimp_tool_compass_update_hilight (GimpToolCompass *compass)
{
......
......@@ -127,6 +127,10 @@ static void gimp_tool_gyroscope_motion (GimpToolWidget *wi
const GimpCoords *coords,
guint32 time,
GdkModifierType state);
static GimpHit gimp_tool_gyroscope_hit (GimpToolWidget *widget,
const GimpCoords *coords,
GdkModifierType state,
gboolean proximity);
static void gimp_tool_gyroscope_hover (GimpToolWidget *widget,
const GimpCoords *coords,
GdkModifierType state,
......@@ -173,6 +177,7 @@ gimp_tool_gyroscope_class_init (GimpToolGyroscopeClass *klass)
widget_class->button_press = gimp_tool_gyroscope_button_press;
widget_class->button_release = gimp_tool_gyroscope_button_release;
widget_class->motion = gimp_tool_gyroscope_motion;
widget_class->hit = gimp_tool_gyroscope_hit;
widget_class->hover = gimp_tool_gyroscope_hover;
widget_class->key_press = gimp_tool_gyroscope_key_press;
widget_class->motion_modifier = gimp_tool_gyroscope_motion_modifier;
......@@ -509,6 +514,15 @@ gimp_tool_gyroscope_motion (GimpToolWidget *widget,
gimp_tool_gyroscope_rotate (gyroscope, &axis);
}
static GimpHit
gimp_tool_gyroscope_hit (GimpToolWidget *widget,
const GimpCoords *coords,
GdkModifierType state,
gboolean proximity)
{
return GIMP_HIT_INDIRECT;
}
static void
gimp_tool_gyroscope_hover (GimpToolWidget *widget,
const GimpCoords *coords,
......
......@@ -113,6 +113,10 @@ static void gimp_tool_handle_grid_motion (GimpToolWidget *widge
const GimpCoords *coords,
guint32 time,
GdkModifierType state);
static GimpHit gimp_tool_handle_grid_hit (GimpToolWidget *widget,
const GimpCoords *coords,
GdkModifierType state,
gboolean proximity);
static void gimp_tool_handle_grid_hover (GimpToolWidget *widget,
const GimpCoords *coords,
GdkModifierType state,
......@@ -125,6 +129,8 @@ static gboolean gimp_tool_handle_grid_get_cursor (GimpToolWidget *widge
GimpToolCursorType *tool_cursor,
GimpCursorModifier *modifier);
static gint gimp_tool_handle_grid_get_handle (GimpToolHandleGrid *grid,
const GimpCoords *coords);
static void gimp_tool_handle_grid_update_hilight (GimpToolHandleGrid *grid);
static void gimp_tool_handle_grid_update_matrix (GimpToolHandleGrid *grid);
......@@ -169,6 +175,7 @@ gimp_tool_handle_grid_class_init (GimpToolHandleGridClass *klass)
widget_class->button_press = gimp_tool_handle_grid_button_press;
widget_class->button_release = gimp_tool_handle_grid_button_release;
widget_class->motion = gimp_tool_handle_grid_motion;
widget_class->hit = gimp_tool_handle_grid_hit;
widget_class->hover = gimp_tool_handle_grid_hover;
widget_class->leave_notify = gimp_tool_handle_grid_leave_notify;
widget_class->get_cursor = gimp_tool_handle_grid_get_cursor;
......@@ -795,6 +802,39 @@ gimp_tool_handle_grid_motion (GimpToolWidget *widget,
private->last_y = coords->y;
}
static GimpHit
gimp_tool_handle_grid_hit (GimpToolWidget *widget,
const GimpCoords *coords,
GdkModifierType state,
gboolean proximity)
{
GimpToolHandleGrid *grid = GIMP_TOOL_HANDLE_GRID (widget);
GimpToolHandleGridPrivate *private = grid->private;
if (proximity)
{
gint handle = gimp_tool_handle_grid_get_handle (grid, coords);
switch (private->handle_mode)
{
case GIMP_HANDLE_MODE_ADD_TRANSFORM:
if (handle > 0)
return GIMP_HIT_DIRECT;
else
return GIMP_HIT_INDIRECT;
break;
case GIMP_HANDLE_MODE_MOVE:
case GIMP_HANDLE_MODE_REMOVE:
if (private->handle > 0)
return GIMP_HIT_DIRECT;
break;
}
}
return GIMP_HIT_NONE;
}
static void
gimp_tool_handle_grid_hover (GimpToolWidget *widget,
const GimpCoords *coords,
......@@ -804,24 +844,12 @@ gimp_tool_handle_grid_hover (GimpToolWidget *widget,
GimpToolHandleGrid *grid = GIMP_TOOL_HANDLE_GRID (widget);
GimpToolHandleGridPrivate *private = grid->private;
gchar *status = NULL;
gint i;
private->hover = TRUE;
private->mouse_x = coords->x;
private->mouse_y = coords->y;
private->handle = 0;
for (i = 0; i < 4; i++)
{
if (private->handles[i + 1] &&
gimp_canvas_item_hit (private->handles[i + 1],
coords->x, coords->y))
{
private->handle = i + 1;
break;
}
}
private->handle = gimp_tool_handle_grid_get_handle (grid, coords);
if (proximity)
{
......@@ -957,6 +985,26 @@ gimp_tool_handle_grid_get_cursor (GimpToolWidget *widget,
return TRUE;
}
static gint
gimp_tool_handle_grid_get_handle (GimpToolHandleGrid *grid,
const GimpCoords *coords)
{
GimpToolHandleGridPrivate *private = grid->private;
gint i;
for (i = 0; i < 4; i++)
{
if (private->handles[i + 1] &&
gimp_canvas_item_hit (private->handles[i + 1],
coords->x, coords->y))
{
return i + 1;
}
}
return 0;
}
static void
gimp_tool_handle_grid_update_hilight (GimpToolHandleGrid *grid)
{
......
......@@ -154,6 +154,10 @@ static void gimp_tool_line_motion (GimpToolWidget *widget,
const GimpCoords *coords,
guint32 time,
GdkModifierType state);
static GimpHit gimp_tool_line_hit (GimpToolWidget *widget,
const GimpCoords *coords,
GdkModifierType state,
gboolean proximity);
static void gimp_tool_line_hover (GimpToolWidget *widget,
const GimpCoords *coords,
GdkModifierType state,
......@@ -172,6 +176,9 @@ static gboolean gimp_tool_line_get_cursor (GimpToolWidget *widget,
GimpToolCursorType *tool_cursor,
GimpCursorModifier *modifier);
static gint gimp_tool_line_get_hover (GimpToolLine *line,
const GimpCoords *coords,
GdkModifierType state);
static GimpControllerSlider *
gimp_tool_line_get_slider (GimpToolLine *line,
gint slider);
......@@ -224,6 +231,7 @@ gimp_tool_line_class_init (GimpToolLineClass *klass)
widget_class->button_press = gimp_tool_line_button_press;
widget_class->button_release = gimp_tool_line_button_release;
widget_class->motion = gimp_tool_line_motion;
widget_class->hit = gimp_tool_line_hit;
widget_class->hover = gimp_tool_line_hover;
widget_class->leave_notify = gimp_tool_line_leave_notify;
widget_class->key_press = gimp_tool_line_key_press;
......@@ -810,6 +818,29 @@ gimp_tool_line_motion (GimpToolWidget *widget,
gimp_tool_line_update_status (line, state, TRUE);
}
GimpHit
gimp_tool_line_hit (GimpToolWidget *widget,
const GimpCoords *coords,
GdkModifierType state,
gboolean proximity)
{
GimpToolLine *line = GIMP_TOOL_LINE (widget);
if (! (state & GRAB_LINE_MASK))
{
gint hover = gimp_tool_line_get_hover (line, coords, state);
if (hover != GIMP_TOOL_LINE_HANDLE_NONE)
return GIMP_HIT_DIRECT;
}
else
{
return GIMP_HIT_INDIRECT;
}
return GIMP_HIT_NONE;
}
void
gimp_tool_line_hover (GimpToolWidget *widget,
const GimpCoords *coords,
......@@ -818,80 +849,14 @@ gimp_tool_line_hover (GimpToolWidget *widget,
{
GimpToolLine *line = GIMP_TOOL_LINE (widget);
GimpToolLinePrivate *private = line->private;
gint i;
private->mouse_x = coords->x;
private->mouse_y = coords->y;
private->hover = GIMP_TOOL_LINE_HANDLE_NONE;
if (! (state & GRAB_LINE_MASK))
{
/* find the closest handle to the cursor */
gdouble min_dist = G_MAXDOUBLE;
gint first_handle = private->sliders->len - 1;
/* skip the sliders if the two endpoints are the same, in particular so
* that if the line is created during a button-press event (as in the
* blend tool), the end endpoint is dragged, instead of a slider.
*/
if (private->x1 == private->x2 && private->y1 == private->y2)
first_handle = -1;
for (i = first_handle; i > GIMP_TOOL_LINE_HANDLE_NONE; i--)
{
GimpCanvasItem *handle;
if (GIMP_TOOL_LINE_HANDLE_IS_SLIDER (i))
{
const GimpControllerSlider *slider;
slider = gimp_tool_line_get_slider (line, i);
if (! slider->visible || ! slider->selectable)
continue;
}
handle = gimp_tool_line_get_handle (line, i);
if (gimp_tool_line_handle_hit (handle,
private->mouse_x,
private->mouse_y,
&min_dist))
{
private->hover = i;
}
}
if (private->hover == GIMP_TOOL_LINE_HANDLE_NONE)
{
gboolean constrain;
gdouble value;
gdouble dist;
constrain = (state & gimp_get_constrain_behavior_mask ()) != 0;
value = gimp_tool_line_project_point (line,
private->mouse_x,
private->mouse_y,
constrain,
&dist);
if (value >= 0.0 && value <= 1.0 && dist <= LINE_VICINITY)
{
gboolean can_add;
g_signal_emit (line, line_signals[CAN_ADD_SLIDER], 0,
value, &can_add);
if (can_add)
{
private->hover = HOVER_NEW_SLIDER;
private->new_slider_value = value;
}
}
}
}
private->hover = gimp_tool_line_get_hover (line, coords, state);
else
private->hover = GIMP_TOOL_LINE_HANDLE_NONE;
gimp_tool_line_update_handles (line);
gimp_tool_line_update_circle (line);
......@@ -1121,6 +1086,85 @@ gimp_tool_line_get_cursor (GimpToolWidget *widget,
return FALSE;
}
static gint
gimp_tool_line_get_hover (GimpToolLine *line,
const GimpCoords *coords,
GdkModifierType state)
{
GimpToolLinePrivate *private = line->private;
gint hover = GIMP_TOOL_LINE_HANDLE_NONE;
gdouble min_dist;
gint first_handle;
gint i;
/* find the closest handle to the cursor */
min_dist = G_MAXDOUBLE;
first_handle = private->sliders->len - 1;
/* skip the sliders if the two endpoints are the same, in particular so
* that if the line is created during a button-press event (as in the
* blend tool), the end endpoint is dragged, instead of a slider.
*/
if (private->x1 == private->x2 && private->y1 == private->y2)
first_handle = -1;
for (i = first_handle; i > GIMP_TOOL_LINE_HANDLE_NONE; i--)
{
GimpCanvasItem *handle;
if (GIMP_TOOL_LINE_HANDLE_IS_SLIDER (i))
{
const GimpControllerSlider *slider;
slider = gimp_tool_line_get_slider (line, i);
if (! slider->visible || ! slider->selectable)
continue;
}
handle = gimp_tool_line_get_handle (line, i);
if (gimp_tool_line_handle_hit (handle,
private->mouse_x,
private->mouse_y,
&min_dist))
{
hover = i;
}
}
if (hover == GIMP_TOOL_LINE_HANDLE_NONE)
{
gboolean constrain;
gdouble value;
gdouble dist;
constrain = (state & gimp_get_constrain_behavior_mask ()) != 0;
value = gimp_tool_line_project_point (line,
private->mouse_x,
private->mouse_y,
constrain,
&dist);
if (value >= 0.0 && value <= 1.0 && dist <= LINE_VICINITY)
{
gboolean can_add;
g_signal_emit (line, line_signals[CAN_ADD_SLIDER], 0,
value, &can_add);
if (can_add)
{
hover = HOVER_NEW_SLIDER;
private->new_slider_value = value;
}
}
}
return hover;
}
static GimpControllerSlider *
gimp_tool_line_get_slider (GimpToolLine *line,
gint slider)
......
This diff is collapsed.
......@@ -162,6 +162,10 @@ static void gimp_tool_polygon_motion (GimpToolWidget *widget
const GimpCoords *coords,
guint32 time,
GdkModifierType state);
static GimpHit gimp_tool_polygon_hit (GimpToolWidget *widget,
const GimpCoords *coords,
GdkModifierType state,
gboolean proximity);
static void gimp_tool_polygon_hover (GimpToolWidget *widget,
const GimpCoords *coords,
GdkModifierType state,
......@@ -184,6 +188,9 @@ static gboolean gimp_tool_polygon_get_cursor (GimpToolWidget *widget
GimpToolCursorType *tool_cursor,
GimpCursorModifier *modifier);
static gint gimp_tool_polygon_get_segment_index (GimpToolPolygon *polygon,
const GimpCoords *coords);
G_DEFINE_TYPE (GimpToolPolygon, gimp_tool_polygon, GIMP_TYPE_TOOL_WIDGET)
......@@ -207,6 +214,7 @@ gimp_tool_polygon_class_init (GimpToolPolygonClass *klass)
widget_class->button_press = gimp_tool_polygon_button_press;
widget_class->button_release = gimp_tool_polygon_button_release;
widget_class->motion = gimp_tool_polygon_motion;
widget_class->hit = gimp_tool_polygon_hit;
widget_class->hover = gimp_tool_polygon_hover;
widget_class->leave_notify = gimp_tool_polygon_leave_notify;
widget_class->key_press = gimp_tool_polygon_key_press;
......@@ -1190,6 +1198,29 @@ gimp_tool_polygon_motion (GimpToolWidget *widget,
gimp_tool_polygon_changed (widget);
}
static GimpHit
gimp_tool_polygon_hit (GimpToolWidget *widget,
const GimpCoords *coords,
GdkModifierType state,
gboolean proximity)
{
GimpToolPolygon *polygon = GIMP_TOOL_POLYGON (widget);
GimpToolPolygonPrivate *priv = polygon->private;
if ((priv->n_points > 0 && ! priv->polygon_closed) ||
gimp_tool_polygon_get_segment_index (polygon, coords) != INVALID_INDEX)
{
return GIMP_HIT_DIRECT;
}
else if (priv->polygon_closed &&
gimp_canvas_item_hit (priv->polygon, coords->x, coords->y))
{
return GIMP_HIT_INDIRECT;
}
return GIMP_HIT_NONE;
}
static void
gimp_tool_polygon_hover (GimpToolWidget *widget,
const GimpCoords *coords,
......@@ -1200,36 +1231,10 @@ gimp_tool_polygon_hover (GimpToolWidget *widget,
GimpToolPolygonPrivate *priv = polygon->private;
gboolean hovering_first_point;
priv->grabbed_segment_index = INVALID_INDEX;
priv->grabbed_segment_index = gimp_tool_polygon_get_segment_index (polygon,
coords);
priv->hover = TRUE;
if (! priv->supress_handles)
{
gdouble shortest_dist = POINT_GRAB_THRESHOLD_SQ;
gint i;
for (i = 0; i < priv->n_segment_indices; i++)
{
gdouble dist;
GimpVector2 *point;
point = &priv->points[priv->segment_indices[i]];
dist = gimp_canvas_item_transform_distance_square (priv->polygon,
coords->x,
coords->y,
point->x,
point->y);
if (dist < shortest_dist)
{
shortest_dist = dist;
priv->grabbed_segment_index = i;
}
}
}
hovering_first_point =
gimp_tool_polygon_should_close (polygon,
NO_CLICK_TIME_AVAILABLE,
......@@ -1383,6 +1388,43 @@ gimp_tool_polygon_get_cursor (GimpToolWidget *widget,
return FALSE;
}
static gint
gimp_tool_polygon_get_segment_index (GimpToolPolygon *polygon,
const GimpCoords *coords)
{
GimpToolPolygonPrivate *priv = polygon->private;
gint segment_index = INVALID_INDEX;
if (! priv->supress_handles)
{
gdouble shortest_dist = POINT_GRAB_THRESHOLD_SQ;
gint i;
for (i = 0; i < priv->n_segment_indices; i++)
{
gdouble dist;
GimpVector2 *point;
point = &priv->points[priv->segment_indices[i]];
dist = gimp_canvas_item_transform_distance_square (priv->polygon,
coords->x,
coords->y,
point->x,
point->y);
if (dist < shortest_dist)
{
shortest_dist = dist;
segment_index = i;
}
}
}
return segment_index;
}
/* public functions */
......
......@@ -301,6 +301,10 @@ static void gimp_tool_rectangle_motion (GimpToolWidget *widg
const GimpCoords *coords,
guint32 time,