[gimp/blend-tool-fun: 1/6] app: Add UI for adjusting the gradient points in GimpBlendTool
- From: Michael Henning <mhenning src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp/blend-tool-fun: 1/6] app: Add UI for adjusting the gradient points in GimpBlendTool
- Date: Fri, 20 Jun 2014 15:32:12 +0000 (UTC)
commit 38c3fd49679cfca3e5c7eae4a0b29d5ad36d1e8e
Author: Michael Henning <drawoc darkrefraction com>
Date: Sat Jun 7 23:18:29 2014 -0400
app: Add UI for adjusting the gradient points in GimpBlendTool
app/tools/gimpblendtool.c | 419 +++++++++++++++++++++++++++++++++++----------
app/tools/gimpblendtool.h | 9 +
2 files changed, 338 insertions(+), 90 deletions(-)
---
diff --git a/app/tools/gimpblendtool.c b/app/tools/gimpblendtool.c
index 9d86671..5ed1e39 100644
--- a/app/tools/gimpblendtool.c
+++ b/app/tools/gimpblendtool.c
@@ -1,6 +1,9 @@
/* GIMP - The GNU Image Manipulation Program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
+ * Major improvements for interactivity
+ * Copyright (C) 2014 Michael Henning <drawoc darkrefraction com>
+ *
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
@@ -21,7 +24,9 @@
#include <gegl.h>
#include <gtk/gtk.h>
+#include <gdk/gdkkeysyms.h>
+#include "libgimpmath/gimpmath.h"
#include "libgimpwidgets/gimpwidgets.h"
#include "tools-types.h"
@@ -48,11 +53,21 @@
#include "gimp-intl.h"
+#define POINT_GRAB_THRESHOLD_SQ (SQR (GIMP_TOOL_HANDLE_SIZE_CIRCLE / 2))
+
/* local function prototypes */
static gboolean gimp_blend_tool_initialize (GimpTool *tool,
GimpDisplay *display,
GError **error);
+static void gimp_blend_tool_control (GimpTool *tool,
+ GimpToolAction action,
+ GimpDisplay *display);
+static void gimp_blend_tool_oper_update (GimpTool *tool,
+ const GimpCoords *coords,
+ GdkModifierType state,
+ gboolean proximity,
+ GimpDisplay *display);
static void gimp_blend_tool_button_press (GimpTool *tool,
const GimpCoords *coords,
guint32 time,
@@ -70,6 +85,11 @@ static void gimp_blend_tool_motion (GimpTool *tool,
guint32 time,
GdkModifierType state,
GimpDisplay *display);
+static void gimp_blend_tool_point_motion (GimpBlendTool *blend_tool,
+ gboolean constrain_angle);
+static gboolean gimp_blend_tool_key_press (GimpTool *tool,
+ GdkEventKey *kevent,
+ GimpDisplay *display);
static void gimp_blend_tool_active_modifier_key (GimpTool *tool,
GdkModifierType key,
gboolean press,
@@ -82,6 +102,14 @@ static void gimp_blend_tool_cursor_update (GimpTool *tool,
static void gimp_blend_tool_draw (GimpDrawTool *draw_tool);
static void gimp_blend_tool_update_items (GimpBlendTool *blend_tool);
+static void gimp_blend_tool_update_item_hilight (GimpBlendTool *blend_tool);
+
+static GimpBlendToolPoint gimp_blend_tool_get_point_under_cursor (GimpBlendTool *blend_tool);
+
+static void gimp_blend_tool_start (GimpBlendTool *bt,
+ GimpDisplay *display);
+static void gimp_blend_tool_halt (GimpBlendTool *bt);
+static void gimp_blend_tool_commit (GimpBlendTool *bt);
static void gimp_blend_tool_push_status (GimpBlendTool *blend_tool,
GdkModifierType state,
@@ -121,9 +149,12 @@ gimp_blend_tool_class_init (GimpBlendToolClass *klass)
GimpDrawToolClass *draw_tool_class = GIMP_DRAW_TOOL_CLASS (klass);
tool_class->initialize = gimp_blend_tool_initialize;
+ tool_class->control = gimp_blend_tool_control;
+ tool_class->oper_update = gimp_blend_tool_oper_update;
tool_class->button_press = gimp_blend_tool_button_press;
tool_class->button_release = gimp_blend_tool_button_release;
tool_class->motion = gimp_blend_tool_motion;
+ tool_class->key_press = gimp_blend_tool_key_press;
tool_class->active_modifier_key = gimp_blend_tool_active_modifier_key;
tool_class->cursor_update = gimp_blend_tool_cursor_update;
@@ -192,6 +223,46 @@ gimp_blend_tool_initialize (GimpTool *tool,
}
static void
+gimp_blend_tool_control (GimpTool *tool,
+ GimpToolAction action,
+ GimpDisplay *display)
+{
+ GimpBlendTool *blend_tool = GIMP_BLEND_TOOL (tool);
+
+ switch (action)
+ {
+ case GIMP_TOOL_ACTION_PAUSE:
+ case GIMP_TOOL_ACTION_RESUME:
+ break;
+
+ case GIMP_TOOL_ACTION_HALT:
+ gimp_blend_tool_halt (blend_tool);
+ break;
+
+ case GIMP_TOOL_ACTION_COMMIT:
+ gimp_blend_tool_commit (blend_tool);
+ break;
+ }
+
+ GIMP_TOOL_CLASS (parent_class)->control (tool, action, display);
+}
+
+static void
+gimp_blend_tool_oper_update (GimpTool *tool,
+ const GimpCoords *coords,
+ GdkModifierType state,
+ gboolean proximity,
+ GimpDisplay *display)
+{
+ GimpBlendTool *blend_tool = GIMP_BLEND_TOOL (tool);
+
+ blend_tool->mouse_x = coords->x;
+ blend_tool->mouse_y = coords->y;
+
+ gimp_blend_tool_update_item_hilight (blend_tool);
+}
+
+static void
gimp_blend_tool_button_press (GimpTool *tool,
const GimpCoords *coords,
guint32 time,
@@ -201,19 +272,46 @@ gimp_blend_tool_button_press (GimpTool *tool,
{
GimpBlendTool *blend_tool = GIMP_BLEND_TOOL (tool);
- blend_tool->start_x = blend_tool->end_x = coords->x;
- blend_tool->start_y = blend_tool->end_y = coords->y;
-
blend_tool->last_x = blend_tool->mouse_x = coords->x;
blend_tool->last_y = blend_tool->mouse_y = coords->y;
+ if (tool->display && display != tool->display)
+ {
+ gimp_tool_pop_status (tool, tool->display);
+ gimp_blend_tool_halt (blend_tool);
+ }
+
+ if (! tool->display)
+ gimp_blend_tool_start (blend_tool, display);
+
+ switch (gimp_blend_tool_get_point_under_cursor (blend_tool))
+ {
+ case POINT_NONE:
+ blend_tool->start_x = coords->x;
+ blend_tool->start_y = coords->y;
+ /* fall thru */
+
+ case POINT_END:
+ blend_tool->end_x = coords->x;
+ blend_tool->end_y = coords->y;
+
+ blend_tool->grabbed_point = POINT_END;
+ break;
+
+ case POINT_START:
+ blend_tool->start_x = coords->x;
+ blend_tool->start_y = coords->y;
+
+ blend_tool->grabbed_point = POINT_START;
+ break;
+ }
+
tool->display = display;
+ gimp_blend_tool_update_items (blend_tool);
gimp_tool_control_activate (tool->control);
gimp_blend_tool_push_status (blend_tool, state, display);
-
- gimp_draw_tool_start (GIMP_DRAW_TOOL (tool), display);
}
static void
@@ -225,58 +323,16 @@ gimp_blend_tool_button_release (GimpTool *tool,
GimpDisplay *display)
{
GimpBlendTool *blend_tool = GIMP_BLEND_TOOL (tool);
- GimpBlendOptions *options = GIMP_BLEND_TOOL_GET_OPTIONS (tool);
- GimpPaintOptions *paint_options = GIMP_PAINT_OPTIONS (options);
- GimpContext *context = GIMP_CONTEXT (options);
- GimpImage *image = gimp_display_get_image (display);
gimp_tool_pop_status (tool, display);
+ /* XXX: Push a useful status message */
- gimp_draw_tool_stop (GIMP_DRAW_TOOL (tool));
+ blend_tool->grabbed_point = POINT_NONE;
gimp_tool_control_halt (tool->control);
- if ((release_type != GIMP_BUTTON_RELEASE_CANCEL) &&
- ((blend_tool->start_x != blend_tool->end_x) ||
- (blend_tool->start_y != blend_tool->end_y)))
- {
- GimpDrawable *drawable = gimp_image_get_active_drawable (image);
- GimpProgress *progress;
- gint off_x;
- gint off_y;
-
- progress = gimp_progress_start (GIMP_PROGRESS (tool),
- _("Blending"), FALSE);
-
- gimp_item_get_offset (GIMP_ITEM (drawable), &off_x, &off_y);
-
- gimp_drawable_blend (drawable,
- context,
- gimp_context_get_gradient (context),
- gimp_context_get_paint_mode (context),
- options->gradient_type,
- gimp_context_get_opacity (context),
- options->offset,
- paint_options->gradient_options->gradient_repeat,
- paint_options->gradient_options->gradient_reverse,
- options->supersample,
- options->supersample_depth,
- options->supersample_threshold,
- options->dither,
- blend_tool->start_x - off_x,
- blend_tool->start_y - off_y,
- blend_tool->end_x - off_x,
- blend_tool->end_y - off_y,
- progress);
-
- if (progress)
- gimp_progress_end (progress);
-
- gimp_image_flush (image);
- }
-
- tool->display = NULL;
- tool->drawable = NULL;
+ /* XXX: handle cancel properly */
+ /* if (release_type == GIMP_BUTTON_RELEASE_CANCEL) */
}
static void
@@ -305,15 +361,8 @@ gimp_blend_tool_motion (GimpTool *tool,
}
else
{
- blend_tool->end_x = coords->x;
- blend_tool->end_y = coords->y;
- }
-
- if (state & gimp_get_constrain_behavior_mask ())
- {
- gimp_constrain_line (blend_tool->start_x, blend_tool->start_y,
- &blend_tool->end_x, &blend_tool->end_y,
- GIMP_CONSTRAIN_LINE_15_DEGREES);
+ gimp_blend_tool_point_motion (blend_tool,
+ state & gimp_get_constrain_behavior_mask ());
}
gimp_tool_pop_status (tool, display);
@@ -326,26 +375,80 @@ gimp_blend_tool_motion (GimpTool *tool,
}
static void
-gimp_blend_tool_active_modifier_key (GimpTool *tool,
- GdkModifierType key,
- gboolean press,
- GdkModifierType state,
- GimpDisplay *display)
+gimp_blend_tool_point_motion (GimpBlendTool *blend_tool,
+ gboolean constrain_angle)
{
- GimpBlendTool *blend_tool = GIMP_BLEND_TOOL (tool);
-
- if (key == gimp_get_constrain_behavior_mask ())
+ switch (blend_tool->grabbed_point)
{
+ case POINT_START:
+ blend_tool->start_x = blend_tool->mouse_x;
+ blend_tool->start_y = blend_tool->mouse_y;
+
+ /* Restrict to multiples of 15 degrees if ctrl is pressed */
+ if (constrain_angle)
+ {
+ gimp_constrain_line (blend_tool->end_x, blend_tool->end_y,
+ &blend_tool->start_x, &blend_tool->start_y,
+ GIMP_CONSTRAIN_LINE_15_DEGREES);
+ }
+ break;
+
+ case POINT_END:
blend_tool->end_x = blend_tool->mouse_x;
blend_tool->end_y = blend_tool->mouse_y;
- /* Restrict to multiples of 15 degrees if ctrl is pressed */
- if (press)
+ if (constrain_angle)
{
gimp_constrain_line (blend_tool->start_x, blend_tool->start_y,
&blend_tool->end_x, &blend_tool->end_y,
GIMP_CONSTRAIN_LINE_15_DEGREES);
}
+ break;
+
+ default:
+ break;
+ }
+}
+
+static gboolean
+gimp_blend_tool_key_press (GimpTool *tool,
+ GdkEventKey *kevent,
+ GimpDisplay *display)
+{
+ switch (kevent->keyval)
+ {
+ case GDK_KEY_BackSpace:
+ return TRUE;
+
+ case GDK_KEY_Return:
+ case GDK_KEY_KP_Enter:
+ case GDK_KEY_ISO_Enter:
+ gimp_tool_control (tool, GIMP_TOOL_ACTION_COMMIT, display);
+ /* fall thru */
+
+ case GDK_KEY_Escape:
+ gimp_tool_control (tool, GIMP_TOOL_ACTION_HALT, display);
+ return TRUE;
+
+ default:
+ break;
+ }
+
+ return FALSE;
+}
+
+static void
+gimp_blend_tool_active_modifier_key (GimpTool *tool,
+ GdkModifierType key,
+ gboolean press,
+ GdkModifierType state,
+ GimpDisplay *display)
+{
+ GimpBlendTool *blend_tool = GIMP_BLEND_TOOL (tool);
+
+ if (key == gimp_get_constrain_behavior_mask ())
+ {
+ gimp_blend_tool_point_motion (blend_tool, press);
gimp_tool_pop_status (tool, display);
gimp_blend_tool_push_status (blend_tool, state, display);
@@ -365,9 +468,13 @@ gimp_blend_tool_cursor_update (GimpTool *tool,
GdkModifierType state,
GimpDisplay *display)
{
- GimpImage *image = gimp_display_get_image (display);
- GimpDrawable *drawable = gimp_image_get_active_drawable (image);
- GimpCursorModifier modifier = GIMP_CURSOR_MODIFIER_NONE;
+ GimpBlendTool *blend_tool = GIMP_BLEND_TOOL (tool);
+ GimpImage *image = gimp_display_get_image (display);
+ GimpDrawable *drawable = gimp_image_get_active_drawable (image);
+ GimpCursorModifier modifier = GIMP_CURSOR_MODIFIER_NONE;
+
+ blend_tool->mouse_x = coords->x;
+ blend_tool->mouse_y = coords->y;
if (gimp_viewable_get_children (GIMP_VIEWABLE (drawable)) ||
gimp_item_is_content_locked (GIMP_ITEM (drawable)) ||
@@ -375,6 +482,10 @@ gimp_blend_tool_cursor_update (GimpTool *tool,
{
modifier = GIMP_CURSOR_MODIFIER_BAD;
}
+ else if (gimp_blend_tool_get_point_under_cursor (blend_tool))
+ {
+ modifier = GIMP_CURSOR_MODIFIER_MOVE;
+ }
gimp_tool_control_set_cursor_modifier (tool->control, modifier);
@@ -385,37 +496,33 @@ static void
gimp_blend_tool_draw (GimpDrawTool *draw_tool)
{
GimpBlendTool *blend_tool = GIMP_BLEND_TOOL (draw_tool);
- GimpCanvasGroup *group;
- group = gimp_draw_tool_add_stroke_group (draw_tool);
- gimp_draw_tool_push_group (draw_tool, group);
+ blend_tool->line =
+ gimp_draw_tool_add_line (draw_tool,
+ blend_tool->start_x,
+ blend_tool->start_y,
+ blend_tool->end_x,
+ blend_tool->end_y);
blend_tool->start_handle =
gimp_draw_tool_add_handle (draw_tool,
- GIMP_HANDLE_CIRCLE,
+ GIMP_HANDLE_FILLED_CIRCLE,
blend_tool->start_x,
blend_tool->start_y,
GIMP_TOOL_HANDLE_SIZE_CIRCLE,
GIMP_TOOL_HANDLE_SIZE_CIRCLE,
GIMP_HANDLE_ANCHOR_CENTER);
- blend_tool->line =
- gimp_draw_tool_add_line (draw_tool,
- blend_tool->start_x,
- blend_tool->start_y,
- blend_tool->end_x,
- blend_tool->end_y);
-
blend_tool->end_handle =
gimp_draw_tool_add_handle (draw_tool,
- GIMP_HANDLE_CIRCLE,
+ GIMP_HANDLE_FILLED_CIRCLE,
blend_tool->end_x,
blend_tool->end_y,
GIMP_TOOL_HANDLE_SIZE_CIRCLE,
GIMP_TOOL_HANDLE_SIZE_CIRCLE,
GIMP_HANDLE_ANCHOR_CENTER);
- gimp_draw_tool_pop_group (draw_tool);
+ gimp_blend_tool_update_item_hilight (blend_tool);
}
static void
@@ -423,19 +530,151 @@ gimp_blend_tool_update_items (GimpBlendTool *blend_tool)
{
if (gimp_draw_tool_is_active (GIMP_DRAW_TOOL (blend_tool)))
{
- gimp_canvas_handle_set_position (blend_tool->start_handle,
- blend_tool->start_x,
- blend_tool->start_y);
-
gimp_canvas_line_set (blend_tool->line,
blend_tool->start_x,
blend_tool->start_y,
blend_tool->end_x,
blend_tool->end_y);
+ gimp_canvas_handle_set_position (blend_tool->start_handle,
+ blend_tool->start_x,
+ blend_tool->start_y);
+
gimp_canvas_handle_set_position (blend_tool->end_handle,
blend_tool->end_x,
blend_tool->end_y);
+
+ gimp_blend_tool_update_item_hilight (blend_tool);
+ }
+}
+
+static void
+gimp_blend_tool_update_item_hilight (GimpBlendTool *blend_tool)
+{
+ if (gimp_draw_tool_is_active (GIMP_DRAW_TOOL (blend_tool)))
+ {
+ GimpBlendToolPoint hilight_point;
+
+ if (blend_tool->grabbed_point)
+ hilight_point = blend_tool->grabbed_point;
+ else
+ hilight_point = gimp_blend_tool_get_point_under_cursor (blend_tool);
+
+ gimp_canvas_item_set_highlight (blend_tool->start_handle,
+ hilight_point == POINT_START);
+ gimp_canvas_item_set_highlight (blend_tool->end_handle,
+ hilight_point == POINT_END);
+ }
+}
+
+static GimpBlendToolPoint
+gimp_blend_tool_get_point_under_cursor (GimpBlendTool *blend_tool)
+{
+ GimpDrawTool *draw_tool = GIMP_DRAW_TOOL (blend_tool);
+ gdouble dist;
+
+ if (!draw_tool->display)
+ return POINT_NONE;
+
+ /* Check the points in the reverse order of drawing */
+
+ /* Check end point */
+ dist = gimp_draw_tool_calc_distance_square (draw_tool,
+ draw_tool->display,
+ blend_tool->mouse_x,
+ blend_tool->mouse_y,
+ blend_tool->end_x,
+ blend_tool->end_y);
+ if (dist < POINT_GRAB_THRESHOLD_SQ)
+ return POINT_END;
+
+ /* Check start point */
+ dist = gimp_draw_tool_calc_distance_square (draw_tool,
+ draw_tool->display,
+ blend_tool->mouse_x,
+ blend_tool->mouse_y,
+ blend_tool->start_x,
+ blend_tool->start_y);
+ if (dist < POINT_GRAB_THRESHOLD_SQ)
+ return POINT_START;
+
+ /* No point found */
+ return POINT_NONE;
+}
+
+static void
+gimp_blend_tool_start (GimpBlendTool *blend_tool,
+ GimpDisplay *display)
+{
+ GimpTool *tool = GIMP_TOOL (blend_tool);
+ GimpImage *image = gimp_display_get_image (display);
+ GimpDrawable *drawable = gimp_image_get_active_drawable (image);
+
+ tool->display = display;
+ tool->drawable = drawable;
+
+ if (! gimp_draw_tool_is_active (GIMP_DRAW_TOOL (blend_tool)))
+ gimp_draw_tool_start (GIMP_DRAW_TOOL (blend_tool), display);
+}
+
+static void
+gimp_blend_tool_halt (GimpBlendTool *blend_tool)
+{
+ GimpTool *tool = GIMP_TOOL (blend_tool);
+
+ tool->display = NULL;
+ tool->drawable = NULL;
+
+ if (gimp_draw_tool_is_active (GIMP_DRAW_TOOL (blend_tool)))
+ gimp_draw_tool_stop (GIMP_DRAW_TOOL (blend_tool));
+}
+
+static void
+gimp_blend_tool_commit (GimpBlendTool *blend_tool)
+{
+ GimpTool *tool = GIMP_TOOL (blend_tool);
+
+ GimpBlendOptions *options = GIMP_BLEND_TOOL_GET_OPTIONS (tool);
+ GimpPaintOptions *paint_options = GIMP_PAINT_OPTIONS (options);
+ GimpContext *context = GIMP_CONTEXT (options);
+ GimpImage *image = gimp_display_get_image (tool->display);
+
+ if ((blend_tool->start_x != blend_tool->end_x) ||
+ (blend_tool->start_y != blend_tool->end_y))
+ {
+ GimpDrawable *drawable = gimp_image_get_active_drawable (image);
+ GimpProgress *progress;
+ gint off_x;
+ gint off_y;
+
+ progress = gimp_progress_start (GIMP_PROGRESS (tool),
+ _("Blending"), FALSE);
+
+ gimp_item_get_offset (GIMP_ITEM (drawable), &off_x, &off_y);
+
+ gimp_drawable_blend (drawable,
+ context,
+ gimp_context_get_gradient (context),
+ gimp_context_get_paint_mode (context),
+ options->gradient_type,
+ gimp_context_get_opacity (context),
+ options->offset,
+ paint_options->gradient_options->gradient_repeat,
+ paint_options->gradient_options->gradient_reverse,
+ options->supersample,
+ options->supersample_depth,
+ options->supersample_threshold,
+ options->dither,
+ blend_tool->start_x - off_x,
+ blend_tool->start_y - off_y,
+ blend_tool->end_x - off_x,
+ blend_tool->end_y - off_y,
+ progress);
+
+ if (progress)
+ gimp_progress_end (progress);
+
+ gimp_image_flush (image);
}
}
diff --git a/app/tools/gimpblendtool.h b/app/tools/gimpblendtool.h
index 1e1ea6c..59b5253 100644
--- a/app/tools/gimpblendtool.h
+++ b/app/tools/gimpblendtool.h
@@ -21,6 +21,13 @@
#include "gimpdrawtool.h"
+typedef enum
+{
+ /* POINT_NONE evaluates to FALSE */
+ POINT_NONE = 0,
+ POINT_START,
+ POINT_END
+} GimpBlendToolPoint;
#define GIMP_TYPE_BLEND_TOOL (gimp_blend_tool_get_type ())
#define GIMP_BLEND_TOOL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_BLEND_TOOL,
GimpBlendTool))
@@ -39,6 +46,8 @@ struct _GimpBlendTool
{
GimpDrawTool parent_instance;
+ GimpBlendToolPoint grabbed_point;
+
gdouble start_x; /* starting x coord */
gdouble start_y; /* starting y coord */
gdouble end_x; /* ending x coord */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]