Files
gimp/app/tools/gimpvectortool.c
Jehan 71605b092c app: remove definitions of gimp_image_[gs]et_active_(layer|channel|vectors).
These are not used anymore anywhere in our codebase! I'm sure some issues still
exist in various places, yet we can now consider that the multi-item awareness
project is finally over! Wouhou! 🥳

One big question which remains is whether I want to get back to the old naming
of "active" items, rather than "selected" items. The main reason to change the
wording globally was to be able to easily find remnants of non-multi-item aware
code. Now that it's all gone, I could very simply revert to the old naming.

This is in particular a big question for the public API for plug-ins, as the
"active" wording has been used for decades litterally. The only difference now
with how it used to be is that we could have several active items at once.
2023-01-11 02:18:32 +01:00

883 lines
31 KiB
C

/* GIMP - The GNU Image Manipulation Program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* Vector tool
* Copyright (C) 2003 Simon Budig <simon@gimp.org>
*
* 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
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "config.h"
#include <gegl.h>
#include <gtk/gtk.h>
#include "libgimpconfig/gimpconfig.h"
#include "libgimpwidgets/gimpwidgets.h"
#include "tools-types.h"
#include "config/gimpdialogconfig.h"
#include "core/gimp.h"
#include "core/gimpimage.h"
#include "core/gimpimage-pick-item.h"
#include "core/gimpimage-undo.h"
#include "core/gimpimage-undo-push.h"
#include "core/gimptoolinfo.h"
#include "core/gimpundostack.h"
#include "paint/gimppaintoptions.h" /* GIMP_PAINT_OPTIONS_CONTEXT_MASK */
#include "vectors/gimpvectors.h"
#include "widgets/gimpdialogfactory.h"
#include "widgets/gimpdockcontainer.h"
#include "widgets/gimphelp-ids.h"
#include "widgets/gimpmenufactory.h"
#include "widgets/gimpuimanager.h"
#include "widgets/gimpwidgets-utils.h"
#include "display/gimpdisplay.h"
#include "display/gimpdisplayshell.h"
#include "display/gimptoolpath.h"
#include "gimptoolcontrol.h"
#include "gimpvectoroptions.h"
#include "gimpvectortool.h"
#include "dialogs/fill-dialog.h"
#include "dialogs/stroke-dialog.h"
#include "gimp-intl.h"
#define TOGGLE_MASK gimp_get_extend_selection_mask ()
#define MOVE_MASK GDK_MOD1_MASK
#define INSDEL_MASK gimp_get_toggle_behavior_mask ()
/* local function prototypes */
static void gimp_vector_tool_dispose (GObject *object);
static void gimp_vector_tool_control (GimpTool *tool,
GimpToolAction action,
GimpDisplay *display);
static void gimp_vector_tool_button_press (GimpTool *tool,
const GimpCoords *coords,
guint32 time,
GdkModifierType state,
GimpButtonPressType press_type,
GimpDisplay *display);
static void gimp_vector_tool_button_release (GimpTool *tool,
const GimpCoords *coords,
guint32 time,
GdkModifierType state,
GimpButtonReleaseType release_type,
GimpDisplay *display);
static void gimp_vector_tool_motion (GimpTool *tool,
const GimpCoords *coords,
guint32 time,
GdkModifierType state,
GimpDisplay *display);
static void gimp_vector_tool_modifier_key (GimpTool *tool,
GdkModifierType key,
gboolean press,
GdkModifierType state,
GimpDisplay *display);
static void gimp_vector_tool_cursor_update (GimpTool *tool,
const GimpCoords *coords,
GdkModifierType state,
GimpDisplay *display);
static void gimp_vector_tool_start (GimpVectorTool *vector_tool,
GimpDisplay *display);
static void gimp_vector_tool_halt (GimpVectorTool *vector_tool);
static void gimp_vector_tool_path_changed (GimpToolWidget *path,
GimpVectorTool *vector_tool);
static void gimp_vector_tool_path_begin_change
(GimpToolWidget *path,
const gchar *desc,
GimpVectorTool *vector_tool);
static void gimp_vector_tool_path_end_change (GimpToolWidget *path,
gboolean success,
GimpVectorTool *vector_tool);
static void gimp_vector_tool_path_activate (GimpToolWidget *path,
GdkModifierType state,
GimpVectorTool *vector_tool);
static void gimp_vector_tool_vectors_changed (GimpImage *image,
GimpVectorTool *vector_tool);
static void gimp_vector_tool_vectors_removed (GimpVectors *vectors,
GimpVectorTool *vector_tool);
static void gimp_vector_tool_to_selection (GimpVectorTool *vector_tool);
static void gimp_vector_tool_to_selection_extended
(GimpVectorTool *vector_tool,
GdkModifierType state);
static void gimp_vector_tool_fill_vectors (GimpVectorTool *vector_tool,
GtkWidget *button);
static void gimp_vector_tool_fill_callback (GtkWidget *dialog,
GList *items,
GList *drawables,
GimpContext *context,
GimpFillOptions *options,
gpointer data);
static void gimp_vector_tool_stroke_vectors (GimpVectorTool *vector_tool,
GtkWidget *button);
static void gimp_vector_tool_stroke_callback (GtkWidget *dialog,
GList *items,
GList *drawables,
GimpContext *context,
GimpStrokeOptions *options,
gpointer data);
G_DEFINE_TYPE (GimpVectorTool, gimp_vector_tool, GIMP_TYPE_DRAW_TOOL)
#define parent_class gimp_vector_tool_parent_class
void
gimp_vector_tool_register (GimpToolRegisterCallback callback,
gpointer data)
{
(* callback) (GIMP_TYPE_VECTOR_TOOL,
GIMP_TYPE_VECTOR_OPTIONS,
gimp_vector_options_gui,
GIMP_PAINT_OPTIONS_CONTEXT_MASK |
GIMP_CONTEXT_PROP_MASK_PATTERN |
GIMP_CONTEXT_PROP_MASK_GRADIENT, /* for stroking */
"gimp-vector-tool",
_("Paths"),
_("Paths Tool: Create and edit paths"),
N_("Pat_hs"), "b",
NULL, GIMP_HELP_TOOL_PATH,
GIMP_ICON_TOOL_PATH,
data);
}
static void
gimp_vector_tool_class_init (GimpVectorToolClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GimpToolClass *tool_class = GIMP_TOOL_CLASS (klass);
object_class->dispose = gimp_vector_tool_dispose;
tool_class->control = gimp_vector_tool_control;
tool_class->button_press = gimp_vector_tool_button_press;
tool_class->button_release = gimp_vector_tool_button_release;
tool_class->motion = gimp_vector_tool_motion;
tool_class->modifier_key = gimp_vector_tool_modifier_key;
tool_class->cursor_update = gimp_vector_tool_cursor_update;
}
static void
gimp_vector_tool_init (GimpVectorTool *vector_tool)
{
GimpTool *tool = GIMP_TOOL (vector_tool);
gimp_tool_control_set_handle_empty_image (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_PATHS);
vector_tool->saved_mode = GIMP_VECTOR_MODE_DESIGN;
}
static void
gimp_vector_tool_dispose (GObject *object)
{
GimpVectorTool *vector_tool = GIMP_VECTOR_TOOL (object);
gimp_vector_tool_set_vectors (vector_tool, NULL);
g_clear_object (&vector_tool->widget);
G_OBJECT_CLASS (parent_class)->dispose (object);
}
static void
gimp_vector_tool_control (GimpTool *tool,
GimpToolAction action,
GimpDisplay *display)
{
GimpVectorTool *vector_tool = GIMP_VECTOR_TOOL (tool);
switch (action)
{
case GIMP_TOOL_ACTION_PAUSE:
case GIMP_TOOL_ACTION_RESUME:
break;
case GIMP_TOOL_ACTION_HALT:
gimp_vector_tool_halt (vector_tool);
break;
case GIMP_TOOL_ACTION_COMMIT:
break;
}
GIMP_TOOL_CLASS (parent_class)->control (tool, action, display);
}
static void
gimp_vector_tool_button_press (GimpTool *tool,
const GimpCoords *coords,
guint32 time,
GdkModifierType state,
GimpButtonPressType press_type,
GimpDisplay *display)
{
GimpVectorTool *vector_tool = GIMP_VECTOR_TOOL (tool);
if (tool->display && display != tool->display)
gimp_tool_control (tool, GIMP_TOOL_ACTION_HALT, tool->display);
if (! tool->display)
{
gimp_vector_tool_start (vector_tool, display);
gimp_tool_widget_hover (vector_tool->widget, coords, state, TRUE);
}
if (gimp_tool_widget_button_press (vector_tool->widget, coords, time, state,
press_type))
{
vector_tool->grab_widget = vector_tool->widget;
}
gimp_tool_control_activate (tool->control);
}
static void
gimp_vector_tool_button_release (GimpTool *tool,
const GimpCoords *coords,
guint32 time,
GdkModifierType state,
GimpButtonReleaseType release_type,
GimpDisplay *display)
{
GimpVectorTool *vector_tool = GIMP_VECTOR_TOOL (tool);
gimp_tool_control_halt (tool->control);
if (vector_tool->grab_widget)
{
gimp_tool_widget_button_release (vector_tool->grab_widget,
coords, time, state, release_type);
vector_tool->grab_widget = NULL;
}
}
static void
gimp_vector_tool_motion (GimpTool *tool,
const GimpCoords *coords,
guint32 time,
GdkModifierType state,
GimpDisplay *display)
{
GimpVectorTool *vector_tool = GIMP_VECTOR_TOOL (tool);
if (vector_tool->grab_widget)
{
gimp_tool_widget_motion (vector_tool->grab_widget, coords, time, state);
}
}
static void
gimp_vector_tool_modifier_key (GimpTool *tool,
GdkModifierType key,
gboolean press,
GdkModifierType state,
GimpDisplay *display)
{
GimpVectorTool *vector_tool = GIMP_VECTOR_TOOL (tool);
GimpVectorOptions *options = GIMP_VECTOR_TOOL_GET_OPTIONS (tool);
if (key == TOGGLE_MASK)
return;
if (key == INSDEL_MASK || key == MOVE_MASK)
{
GimpVectorMode button_mode = options->edit_mode;
if (press)
{
if (key == (state & (INSDEL_MASK | MOVE_MASK)))
{
/* first modifier pressed */
vector_tool->saved_mode = options->edit_mode;
}
}
else
{
if (! (state & (INSDEL_MASK | MOVE_MASK)))
{
/* last modifier released */
button_mode = vector_tool->saved_mode;
}
}
if (state & MOVE_MASK)
{
button_mode = GIMP_VECTOR_MODE_MOVE;
}
else if (state & INSDEL_MASK)
{
button_mode = GIMP_VECTOR_MODE_EDIT;
}
if (button_mode != options->edit_mode)
{
g_object_set (options, "vectors-edit-mode", button_mode, NULL);
}
}
}
static void
gimp_vector_tool_cursor_update (GimpTool *tool,
const GimpCoords *coords,
GdkModifierType state,
GimpDisplay *display)
{
GimpVectorTool *vector_tool = GIMP_VECTOR_TOOL (tool);
GimpDisplayShell *shell = gimp_display_get_shell (display);
if (display != tool->display || ! vector_tool->widget)
{
GimpToolCursorType tool_cursor = GIMP_TOOL_CURSOR_PATHS;
if (gimp_image_pick_vectors (gimp_display_get_image (display),
coords->x, coords->y,
FUNSCALEX (shell,
GIMP_TOOL_HANDLE_SIZE_CIRCLE / 2),
FUNSCALEY (shell,
GIMP_TOOL_HANDLE_SIZE_CIRCLE / 2)))
{
tool_cursor = GIMP_TOOL_CURSOR_HAND;
}
gimp_tool_control_set_tool_cursor (tool->control, tool_cursor);
}
GIMP_TOOL_CLASS (parent_class)->cursor_update (tool, coords, state, display);
}
static void
gimp_vector_tool_start (GimpVectorTool *vector_tool,
GimpDisplay *display)
{
GimpTool *tool = GIMP_TOOL (vector_tool);
GimpVectorOptions *options = GIMP_VECTOR_TOOL_GET_OPTIONS (tool);
GimpDisplayShell *shell = gimp_display_get_shell (display);
GimpToolWidget *widget;
tool->display = display;
vector_tool->widget = widget = gimp_tool_path_new (shell);
gimp_draw_tool_set_widget (GIMP_DRAW_TOOL (tool), widget);
g_object_bind_property (G_OBJECT (options), "vectors-edit-mode",
G_OBJECT (widget), "edit-mode",
G_BINDING_SYNC_CREATE |
G_BINDING_BIDIRECTIONAL);
g_object_bind_property (G_OBJECT (options), "vectors-polygonal",
G_OBJECT (widget), "polygonal",
G_BINDING_SYNC_CREATE |
G_BINDING_BIDIRECTIONAL);
gimp_tool_path_set_vectors (GIMP_TOOL_PATH (widget),
vector_tool->vectors);
g_signal_connect (widget, "changed",
G_CALLBACK (gimp_vector_tool_path_changed),
vector_tool);
g_signal_connect (widget, "begin-change",
G_CALLBACK (gimp_vector_tool_path_begin_change),
vector_tool);
g_signal_connect (widget, "end-change",
G_CALLBACK (gimp_vector_tool_path_end_change),
vector_tool);
g_signal_connect (widget, "activate",
G_CALLBACK (gimp_vector_tool_path_activate),
vector_tool);
gimp_draw_tool_start (GIMP_DRAW_TOOL (tool), display);
}
static void
gimp_vector_tool_halt (GimpVectorTool *vector_tool)
{
GimpTool *tool = GIMP_TOOL (vector_tool);
if (tool->display)
gimp_tool_pop_status (tool, tool->display);
gimp_vector_tool_set_vectors (vector_tool, NULL);
if (gimp_draw_tool_is_active (GIMP_DRAW_TOOL (tool)))
gimp_draw_tool_stop (GIMP_DRAW_TOOL (tool));
gimp_draw_tool_set_widget (GIMP_DRAW_TOOL (tool), NULL);
g_clear_object (&vector_tool->widget);
tool->display = NULL;
}
static void
gimp_vector_tool_path_changed (GimpToolWidget *path,
GimpVectorTool *vector_tool)
{
GimpDisplayShell *shell = gimp_tool_widget_get_shell (path);
GimpImage *image = gimp_display_get_image (shell->display);
GimpVectors *vectors;
g_object_get (path,
"vectors", &vectors,
NULL);
if (vectors != vector_tool->vectors)
{
if (vectors && ! gimp_item_is_attached (GIMP_ITEM (vectors)))
{
gimp_image_add_vectors (image, vectors,
GIMP_IMAGE_ACTIVE_PARENT, -1, TRUE);
gimp_image_flush (image);
gimp_vector_tool_set_vectors (vector_tool, vectors);
}
else
{
gimp_vector_tool_set_vectors (vector_tool, vectors);
if (vectors)
{
GList *list = g_list_prepend (NULL, vectors);
gimp_image_set_selected_vectors (image, list);
g_list_free (list);
}
}
}
if (vectors)
g_object_unref (vectors);
}
static void
gimp_vector_tool_path_begin_change (GimpToolWidget *path,
const gchar *desc,
GimpVectorTool *vector_tool)
{
GimpDisplayShell *shell = gimp_tool_widget_get_shell (path);
GimpImage *image = gimp_display_get_image (shell->display);
gimp_image_undo_push_vectors_mod (image, desc, vector_tool->vectors);
}
static void
gimp_vector_tool_path_end_change (GimpToolWidget *path,
gboolean success,
GimpVectorTool *vector_tool)
{
GimpDisplayShell *shell = gimp_tool_widget_get_shell (path);
GimpImage *image = gimp_display_get_image (shell->display);
if (! success)
{
GimpUndo *undo;
GimpUndoAccumulator accum = { 0, };
undo = gimp_undo_stack_pop_undo (gimp_image_get_undo_stack (image),
GIMP_UNDO_MODE_UNDO, &accum);
gimp_image_undo_event (image, GIMP_UNDO_EVENT_UNDO_EXPIRED, undo);
gimp_undo_free (undo, GIMP_UNDO_MODE_UNDO);
g_object_unref (undo);
}
gimp_image_flush (image);
}
static void
gimp_vector_tool_path_activate (GimpToolWidget *path,
GdkModifierType state,
GimpVectorTool *vector_tool)
{
gimp_vector_tool_to_selection_extended (vector_tool, state);
}
static void
gimp_vector_tool_vectors_changed (GimpImage *image,
GimpVectorTool *vector_tool)
{
GimpVectors *vectors = NULL;
/* The vectors tool can only work on one path at a time. */
if (g_list_length (gimp_image_get_selected_vectors (image)) == 1)
vectors = gimp_image_get_selected_vectors (image)->data;
gimp_vector_tool_set_vectors (vector_tool, vectors);
}
static void
gimp_vector_tool_vectors_removed (GimpVectors *vectors,
GimpVectorTool *vector_tool)
{
gimp_vector_tool_set_vectors (vector_tool, NULL);
}
void
gimp_vector_tool_set_vectors (GimpVectorTool *vector_tool,
GimpVectors *vectors)
{
GimpTool *tool;
GimpItem *item = NULL;
GimpVectorOptions *options;
g_return_if_fail (GIMP_IS_VECTOR_TOOL (vector_tool));
g_return_if_fail (vectors == NULL || GIMP_IS_VECTORS (vectors));
tool = GIMP_TOOL (vector_tool);
options = GIMP_VECTOR_TOOL_GET_OPTIONS (vector_tool);
if (vectors)
item = GIMP_ITEM (vectors);
if (vectors == vector_tool->vectors)
return;
if (vector_tool->vectors)
{
GimpImage *old_image;
old_image = gimp_item_get_image (GIMP_ITEM (vector_tool->vectors));
g_signal_handlers_disconnect_by_func (old_image,
gimp_vector_tool_vectors_changed,
vector_tool);
g_signal_handlers_disconnect_by_func (vector_tool->vectors,
gimp_vector_tool_vectors_removed,
vector_tool);
g_clear_object (&vector_tool->vectors);
if (options->to_selection_button)
{
gtk_widget_set_sensitive (options->to_selection_button, FALSE);
g_signal_handlers_disconnect_by_func (options->to_selection_button,
gimp_vector_tool_to_selection,
tool);
g_signal_handlers_disconnect_by_func (options->to_selection_button,
gimp_vector_tool_to_selection_extended,
tool);
}
if (options->fill_button)
{
gtk_widget_set_sensitive (options->fill_button, FALSE);
g_signal_handlers_disconnect_by_func (options->fill_button,
gimp_vector_tool_fill_vectors,
tool);
}
if (options->stroke_button)
{
gtk_widget_set_sensitive (options->stroke_button, FALSE);
g_signal_handlers_disconnect_by_func (options->stroke_button,
gimp_vector_tool_stroke_vectors,
tool);
}
}
if (! vectors ||
(tool->display &&
gimp_display_get_image (tool->display) != gimp_item_get_image (item)))
{
gimp_vector_tool_halt (vector_tool);
}
if (! vectors)
return;
vector_tool->vectors = g_object_ref (vectors);
g_signal_connect_object (gimp_item_get_image (item), "selected-vectors-changed",
G_CALLBACK (gimp_vector_tool_vectors_changed),
vector_tool, 0);
g_signal_connect_object (vectors, "removed",
G_CALLBACK (gimp_vector_tool_vectors_removed),
vector_tool, 0);
if (options->to_selection_button)
{
g_signal_connect_swapped (options->to_selection_button, "clicked",
G_CALLBACK (gimp_vector_tool_to_selection),
tool);
g_signal_connect_swapped (options->to_selection_button, "extended-clicked",
G_CALLBACK (gimp_vector_tool_to_selection_extended),
tool);
gtk_widget_set_sensitive (options->to_selection_button, TRUE);
}
if (options->fill_button)
{
g_signal_connect_swapped (options->fill_button, "clicked",
G_CALLBACK (gimp_vector_tool_fill_vectors),
tool);
gtk_widget_set_sensitive (options->fill_button, TRUE);
}
if (options->stroke_button)
{
g_signal_connect_swapped (options->stroke_button, "clicked",
G_CALLBACK (gimp_vector_tool_stroke_vectors),
tool);
gtk_widget_set_sensitive (options->stroke_button, TRUE);
}
if (tool->display)
{
gimp_tool_path_set_vectors (GIMP_TOOL_PATH (vector_tool->widget), vectors);
}
else
{
GimpContext *context = gimp_get_user_context (tool->tool_info->gimp);
GimpDisplay *display = gimp_context_get_display (context);
if (! display ||
gimp_display_get_image (display) != gimp_item_get_image (item))
{
GList *list;
display = NULL;
for (list = gimp_get_display_iter (gimp_item_get_image (item)->gimp);
list;
list = g_list_next (list))
{
display = list->data;
if (gimp_display_get_image (display) == gimp_item_get_image (item))
{
gimp_context_set_display (context, display);
break;
}
display = NULL;
}
}
if (display)
gimp_vector_tool_start (vector_tool, display);
}
if (options->edit_mode != GIMP_VECTOR_MODE_DESIGN)
g_object_set (options, "vectors-edit-mode",
GIMP_VECTOR_MODE_DESIGN, NULL);
}
static void
gimp_vector_tool_to_selection (GimpVectorTool *vector_tool)
{
gimp_vector_tool_to_selection_extended (vector_tool, 0);
}
static void
gimp_vector_tool_to_selection_extended (GimpVectorTool *vector_tool,
GdkModifierType state)
{
GimpImage *image;
if (! vector_tool->vectors)
return;
image = gimp_item_get_image (GIMP_ITEM (vector_tool->vectors));
gimp_item_to_selection (GIMP_ITEM (vector_tool->vectors),
gimp_modifiers_to_channel_op (state),
TRUE, FALSE, 0, 0);
gimp_image_flush (image);
}
static void
gimp_vector_tool_fill_vectors (GimpVectorTool *vector_tool,
GtkWidget *button)
{
GimpDialogConfig *config;
GimpImage *image;
GList *drawables;
GList *vectors_list = NULL;
GtkWidget *dialog;
if (! vector_tool->vectors)
return;
image = gimp_item_get_image (GIMP_ITEM (vector_tool->vectors));
config = GIMP_DIALOG_CONFIG (image->gimp->config);
drawables = gimp_image_get_selected_drawables (image);
if (! drawables)
{
gimp_tool_message (GIMP_TOOL (vector_tool),
GIMP_TOOL (vector_tool)->display,
_("There are no selected layers or channels to fill."));
return;
}
vectors_list = g_list_prepend (NULL, vector_tool->vectors);
dialog = fill_dialog_new (vectors_list, drawables,
GIMP_CONTEXT (GIMP_TOOL_GET_OPTIONS (vector_tool)),
_("Fill Path"),
GIMP_ICON_TOOL_BUCKET_FILL,
GIMP_HELP_PATH_FILL,
button,
config->fill_options,
gimp_vector_tool_fill_callback,
vector_tool);
gtk_widget_show (dialog);
g_list_free (vectors_list);
g_list_free (drawables);
}
static void
gimp_vector_tool_fill_callback (GtkWidget *dialog,
GList *items,
GList *drawables,
GimpContext *context,
GimpFillOptions *options,
gpointer data)
{
GimpDialogConfig *config = GIMP_DIALOG_CONFIG (context->gimp->config);
GimpImage *image = gimp_item_get_image (items->data);
GError *error = NULL;
gimp_config_sync (G_OBJECT (options),
G_OBJECT (config->fill_options), 0);
gimp_image_undo_group_start (image,
GIMP_UNDO_GROUP_DRAWABLE_MOD,
"Fill");
for (GList *iter = items; iter; iter = iter->next)
if (! gimp_item_fill (iter->data, drawables, options,
TRUE, NULL, &error))
{
gimp_message_literal (context->gimp,
G_OBJECT (dialog),
GIMP_MESSAGE_WARNING,
error ? error->message : "NULL");
g_clear_error (&error);
break;
}
gimp_image_undo_group_end (image);
gimp_image_flush (image);
gtk_widget_destroy (dialog);
}
static void
gimp_vector_tool_stroke_vectors (GimpVectorTool *vector_tool,
GtkWidget *button)
{
GimpDialogConfig *config;
GimpImage *image;
GList *drawables;
GList *vectors_list = NULL;
GtkWidget *dialog;
if (! vector_tool->vectors)
return;
image = gimp_item_get_image (GIMP_ITEM (vector_tool->vectors));
config = GIMP_DIALOG_CONFIG (image->gimp->config);
drawables = gimp_image_get_selected_drawables (image);
if (! drawables)
{
gimp_tool_message (GIMP_TOOL (vector_tool),
GIMP_TOOL (vector_tool)->display,
_("There are no selected layers or channels to stroke to."));
return;
}
vectors_list = g_list_prepend (NULL, vector_tool->vectors);
dialog = stroke_dialog_new (vectors_list, drawables,
GIMP_CONTEXT (GIMP_TOOL_GET_OPTIONS (vector_tool)),
_("Stroke Path"),
GIMP_ICON_PATH_STROKE,
GIMP_HELP_PATH_STROKE,
button,
config->stroke_options,
gimp_vector_tool_stroke_callback,
vector_tool);
gtk_widget_show (dialog);
g_list_free (vectors_list);
g_list_free (drawables);
}
static void
gimp_vector_tool_stroke_callback (GtkWidget *dialog,
GList *items,
GList *drawables,
GimpContext *context,
GimpStrokeOptions *options,
gpointer data)
{
GimpDialogConfig *config = GIMP_DIALOG_CONFIG (context->gimp->config);
GimpImage *image = gimp_item_get_image (items->data);
GError *error = NULL;
gimp_config_sync (G_OBJECT (options),
G_OBJECT (config->stroke_options), 0);
gimp_image_undo_group_start (image,
GIMP_UNDO_GROUP_DRAWABLE_MOD,
"Stroke");
for (GList *iter = items; iter; iter = iter->next)
if (! gimp_item_stroke (iter->data, drawables, context, options, NULL,
TRUE, NULL, &error))
{
gimp_message_literal (context->gimp,
G_OBJECT (dialog),
GIMP_MESSAGE_WARNING,
error ? error->message : "NULL");
g_clear_error (&error);
break;
}
gimp_image_undo_group_end (image);
gimp_image_flush (image);
gtk_widget_destroy (dialog);
}