app: convert midpoints to stops via double-click in the blend tool

When a midpoint is double-clicked, convert it into a gradient stop
(i.e., split the corresponding segment at the midpoint,) by
responding to the line's handle-clicked signal.
This commit is contained in:
Ell 2017-08-01 18:45:13 -04:00
parent 63c8fc73dd
commit 420ea8037a
2 changed files with 149 additions and 57 deletions

View File

@ -49,33 +49,47 @@
/* local function prototypes */
static gboolean gimp_blend_tool_editor_line_can_add_slider (GimpToolLine *line,
gdouble value,
GimpBlendTool *blend_tool);
static gint gimp_blend_tool_editor_line_add_slider (GimpToolLine *line,
gdouble value,
GimpBlendTool *blend_tool);
static void gimp_blend_tool_editor_line_prepare_to_remove_slider (GimpToolLine *line,
gint slider,
gboolean remove,
GimpBlendTool *blend_tool);
static void gimp_blend_tool_editor_line_remove_slider (GimpToolLine *line,
gint slider,
GimpBlendTool *blend_tool);
static gboolean gimp_blend_tool_editor_line_can_add_slider (GimpToolLine *line,
gdouble value,
GimpBlendTool *blend_tool);
static gint gimp_blend_tool_editor_line_add_slider (GimpToolLine *line,
gdouble value,
GimpBlendTool *blend_tool);
static void gimp_blend_tool_editor_line_prepare_to_remove_slider (GimpToolLine *line,
gint slider,
gboolean remove,
GimpBlendTool *blend_tool);
static void gimp_blend_tool_editor_line_remove_slider (GimpToolLine *line,
gint slider,
GimpBlendTool *blend_tool);
static gboolean gimp_blend_tool_editor_line_handle_clicked (GimpToolLine *line,
gint handle,
GdkModifierType state,
GimpButtonPressType press_type,
GimpBlendTool *blend_tool);
static gboolean gimp_blend_tool_editor_is_gradient_editable (GimpBlendTool *blend_tool);
static gboolean gimp_blend_tool_editor_is_gradient_editable (GimpBlendTool *blend_tool);
static GimpGradientSegment * gimp_blend_tool_editor_handle_get_segment (GimpBlendTool *blend_tool,
gint handle);
static gboolean gimp_blend_tool_editor_handle_is_endpoint (GimpBlendTool *blend_tool,
gint handle);
static gboolean gimp_blend_tool_editor_handle_is_stop (GimpBlendTool *blend_tool,
gint handle);
static gboolean gimp_blend_tool_editor_handle_is_midpoint (GimpBlendTool *blend_tool,
gint handle);
static GimpGradientSegment * gimp_blend_tool_editor_handle_get_segment (GimpBlendTool *blend_tool,
gint handle);
static void gimp_blend_tool_editor_block_handlers (GimpBlendTool *blend_tool);
static void gimp_blend_tool_editor_unblock_handlers (GimpBlendTool *blend_tool);
static gboolean gimp_blend_tool_editor_are_handlers_blocked (GimpBlendTool *blend_tool);
static void gimp_blend_tool_editor_block_handlers (GimpBlendTool *blend_tool);
static void gimp_blend_tool_editor_unblock_handlers (GimpBlendTool *blend_tool);
static gboolean gimp_blend_tool_editor_are_handlers_blocked (GimpBlendTool *blend_tool);
static void gimp_blend_tool_editor_freeze_gradient (GimpBlendTool *blend_tool);
static void gimp_blend_tool_editor_thaw_gradient (GimpBlendTool *blend_tool);
static void gimp_blend_tool_editor_freeze_gradient (GimpBlendTool *blend_tool);
static void gimp_blend_tool_editor_thaw_gradient (GimpBlendTool *blend_tool);
static void gimp_blend_tool_editor_update_sliders (GimpBlendTool *blend_tool);
static gint gimp_blend_tool_editor_add_stop (GimpBlendTool *blend_tool,
gdouble value);
static void gimp_blend_tool_editor_update_sliders (GimpBlendTool *blend_tool);
/* private functions */
@ -98,13 +112,9 @@ gimp_blend_tool_editor_line_add_slider (GimpToolLine *line,
gdouble value,
GimpBlendTool *blend_tool)
{
GimpBlendOptions *options = GIMP_BLEND_TOOL_GET_OPTIONS (blend_tool);
GimpPaintOptions *paint_options = GIMP_PAINT_OPTIONS (options);
gdouble offset = options->offset / 100.0;
GimpGradientSegment *seg;
gint slider;
gimp_blend_tool_editor_freeze_gradient (blend_tool);
GimpBlendOptions *options = GIMP_BLEND_TOOL_GET_OPTIONS (blend_tool);
GimpPaintOptions *paint_options = GIMP_PAINT_OPTIONS (options);
gdouble offset = options->offset / 100.0;
/* adjust slider value according to the offset */
value = (value - offset) / (1.0 - offset);
@ -113,17 +123,7 @@ gimp_blend_tool_editor_line_add_slider (GimpToolLine *line,
if (paint_options->gradient_options->gradient_reverse)
value = 1.0 - value;
gimp_gradient_split_at (blend_tool->gradient,
GIMP_CONTEXT (options), NULL, value, &seg, NULL);
slider =
gimp_gradient_segment_range_get_n_segments (blend_tool->gradient,
blend_tool->gradient->segments,
seg) - 1;
gimp_blend_tool_editor_thaw_gradient (blend_tool);
return slider;
return gimp_blend_tool_editor_add_stop (blend_tool, value);
}
static void
@ -179,6 +179,40 @@ gimp_blend_tool_editor_line_remove_slider (GimpToolLine *line,
gimp_blend_tool_set_tentative_gradient (blend_tool, NULL);
}
static gboolean
gimp_blend_tool_editor_line_handle_clicked (GimpToolLine *line,
gint handle,
GdkModifierType state,
GimpButtonPressType press_type,
GimpBlendTool *blend_tool)
{
if (gimp_blend_tool_editor_handle_is_midpoint (blend_tool, handle))
{
if (press_type == GIMP_BUTTON_PRESS_DOUBLE &&
gimp_blend_tool_editor_is_gradient_editable (blend_tool))
{
const GimpControllerSlider *sliders;
gint stop;
sliders = gimp_tool_line_get_sliders (line, NULL);
if (sliders[handle].value > sliders[handle].min + EPSILON &&
sliders[handle].value < sliders[handle].max - EPSILON)
{
stop = gimp_blend_tool_editor_add_stop (blend_tool,
sliders[handle].value);
gimp_tool_line_set_selection (line, stop);
}
/* return FALSE, so that the new slider can be dragged immediately */
return FALSE;
}
}
return FALSE;
}
static gboolean
gimp_blend_tool_editor_is_gradient_editable (GimpBlendTool *blend_tool)
{
@ -188,6 +222,36 @@ gimp_blend_tool_editor_is_gradient_editable (GimpBlendTool *blend_tool)
gimp_data_is_writable (GIMP_DATA (blend_tool->gradient));
}
static gboolean
gimp_blend_tool_editor_handle_is_endpoint (GimpBlendTool *blend_tool,
gint handle)
{
return handle == GIMP_TOOL_LINE_HANDLE_START ||
handle == GIMP_TOOL_LINE_HANDLE_END;
}
static gboolean
gimp_blend_tool_editor_handle_is_stop (GimpBlendTool *blend_tool,
gint handle)
{
gint n_sliders;
gimp_tool_line_get_sliders (GIMP_TOOL_LINE (blend_tool->widget), &n_sliders);
return handle >= 0 && handle < n_sliders / 2;
}
static gboolean
gimp_blend_tool_editor_handle_is_midpoint (GimpBlendTool *blend_tool,
gint handle)
{
gint n_sliders;
gimp_tool_line_get_sliders (GIMP_TOOL_LINE (blend_tool->widget), &n_sliders);
return handle >= n_sliders / 2;
}
static GimpGradientSegment *
gimp_blend_tool_editor_handle_get_segment (GimpBlendTool *blend_tool,
gint handle)
@ -281,6 +345,29 @@ gimp_blend_tool_editor_thaw_gradient(GimpBlendTool *blend_tool)
gimp_blend_tool_editor_unblock_handlers (blend_tool);
}
static gint
gimp_blend_tool_editor_add_stop (GimpBlendTool *blend_tool,
gdouble value)
{
GimpBlendOptions *options = GIMP_BLEND_TOOL_GET_OPTIONS (blend_tool);
GimpGradientSegment *seg;
gint stop;
gimp_blend_tool_editor_freeze_gradient (blend_tool);
gimp_gradient_split_at (blend_tool->gradient,
GIMP_CONTEXT (options), NULL, value, &seg, NULL);
stop =
gimp_gradient_segment_range_get_n_segments (blend_tool->gradient,
blend_tool->gradient->segments,
seg) - 1;
gimp_blend_tool_editor_thaw_gradient (blend_tool);
return stop;
}
static void
gimp_blend_tool_editor_update_sliders (GimpBlendTool *blend_tool)
{
@ -450,6 +537,9 @@ gimp_blend_tool_editor_start (GimpBlendTool *blend_tool)
g_signal_connect (blend_tool->widget, "remove-slider",
G_CALLBACK (gimp_blend_tool_editor_line_remove_slider),
blend_tool);
g_signal_connect (blend_tool->widget, "handle-clicked",
G_CALLBACK (gimp_blend_tool_editor_line_handle_clicked),
blend_tool);
}
void

View File

@ -200,22 +200,23 @@ gimp_blend_tool_init (GimpBlendTool *blend_tool)
{
GimpTool *tool = GIMP_TOOL (blend_tool);
gimp_tool_control_set_scroll_lock (tool->control, TRUE);
gimp_tool_control_set_preserve (tool->control, FALSE);
gimp_tool_control_set_dirty_mask (tool->control,
GIMP_DIRTY_IMAGE |
GIMP_DIRTY_IMAGE_STRUCTURE |
GIMP_DIRTY_DRAWABLE |
GIMP_DIRTY_ACTIVE_DRAWABLE);
gimp_tool_control_set_wants_click (tool->control, TRUE);
gimp_tool_control_set_precision (tool->control,
GIMP_CURSOR_PRECISION_SUBPIXEL);
gimp_tool_control_set_tool_cursor (tool->control,
GIMP_TOOL_CURSOR_BLEND);
gimp_tool_control_set_action_opacity (tool->control,
"context/context-opacity-set");
gimp_tool_control_set_action_object_1 (tool->control,
"context/context-gradient-select-set");
gimp_tool_control_set_scroll_lock (tool->control, TRUE);
gimp_tool_control_set_preserve (tool->control, FALSE);
gimp_tool_control_set_dirty_mask (tool->control,
GIMP_DIRTY_IMAGE |
GIMP_DIRTY_IMAGE_STRUCTURE |
GIMP_DIRTY_DRAWABLE |
GIMP_DIRTY_ACTIVE_DRAWABLE);
gimp_tool_control_set_wants_click (tool->control, TRUE);
gimp_tool_control_set_wants_double_click (tool->control, TRUE);
gimp_tool_control_set_precision (tool->control,
GIMP_CURSOR_PRECISION_SUBPIXEL);
gimp_tool_control_set_tool_cursor (tool->control,
GIMP_TOOL_CURSOR_BLEND);
gimp_tool_control_set_action_opacity (tool->control,
"context/context-opacity-set");
gimp_tool_control_set_action_object_1 (tool->control,
"context/context-gradient-select-set");
gimp_draw_tool_set_default_status (GIMP_DRAW_TOOL (tool),
_("Click-Drag to draw a gradient"));
@ -342,7 +343,8 @@ gimp_blend_tool_button_press (GimpTool *tool,
blend_info_new (start_x, start_y, end_x, end_y));
}
gimp_tool_control_activate (tool->control);
if (press_type == GIMP_BUTTON_PRESS_NORMAL)
gimp_tool_control_activate (tool->control);
}
static void