1
1
mirror of https://gitlab.gnome.org/GNOME/gimp.git synced 2025-10-06 01:12:40 +02:00
Files
gimp/app/actions/context-commands.c
Jacob Boerema 5273f26ef0 app, pdb: fix #13480 inconsistent use of maximum radius...
for generated brushes.
The maximum radius we allowed for generated brushes was not used
consistently everywhere.
In the API call we clamped it to 0.0-32767.0, while the param_spec
set min and max to 0.1 and 4000.0, and the brush editor used a
maximum of 1000.0.
Using a large value (probably anything larger than 4000) would
sooner or later lead to a crash.

Instead of manual changes everywhere, let's define a maximum and
minimum in one place and use that wherever we need the min/max values.
Use the values as set in the param_spec for the defines.
The only place we can't easily do that is in brush.pdb, so we add
a comment above our defines that the values need updating there too.

Actually we should probably use more defines for other values too,
that way there is less chance of min/max values getting out of synch
throughout our code.
2025-04-11 02:02:40 +00:00

1065 lines
34 KiB
C

/* GIMP - The GNU Image Manipulation Program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* 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 <string.h>
#include <gegl.h>
#include <gtk/gtk.h>
#include "libgimpbase/gimpbase.h"
#include "libgimpcolor/gimpcolor.h"
#include "libgimpwidgets/gimpwidgets.h"
#include "actions-types.h"
#include "operations/layer-modes/gimp-layer-modes.h"
#include "core/gimp.h"
#include "core/gimpbrushgenerated.h"
#include "core/gimpcontext.h"
#include "core/gimpdatafactory.h"
#include "core/gimpimage.h"
#include "core/gimplist.h"
#include "core/gimppaintinfo.h"
#include "core/gimptoolinfo.h"
#include "paint/gimppaintoptions.h"
#include "widgets/gimpdialogfactory.h"
#include "widgets/gimpsessioninfo.h"
#include "widgets/gimppaletteeditor.h"
#include "widgets/gimpcolormapeditor.h"
#include "actions.h"
#include "context-commands.h"
#include "gimp-intl.h"
/* local function prototypes */
static void context_select_object (GimpActionSelectType select_type,
GimpContext *context,
GimpContainer *container);
static gint context_paint_mode_index (GimpLayerMode paint_mode,
const GimpLayerMode *modes,
gint n_modes);
static void context_select_color (GimpActionSelectType select_type,
GeglColor *color,
gboolean use_colormap,
gboolean use_palette);
static gint context_get_color_index (gboolean use_colormap,
gboolean use_palette,
GeglColor *color);
static gint context_max_color_index (gboolean use_colormap,
gboolean use_palette);
static gboolean context_set_color_index (gint index,
gboolean use_colormap,
gboolean use_palette,
GeglColor *color);
static GimpPaletteEditor * context_get_palette_editor (void);
static GimpColormapEditor * context_get_colormap_editor (void);
/* public functions */
void
context_colors_default_cmd_callback (GimpAction *action,
GVariant *value,
gpointer data)
{
GimpContext *context;
return_if_no_context (context, data);
gimp_context_set_default_colors (context);
}
void
context_colors_swap_cmd_callback (GimpAction *action,
GVariant *value,
gpointer data)
{
GimpContext *context;
return_if_no_context (context, data);
gimp_context_swap_colors (context);
}
#define SELECT_COLOR_CMD_CALLBACK(name, fgbg, use_colormap, use_palette) \
void \
context_##name##_##fgbg##ground_cmd_callback (GimpAction *action, \
GVariant *value, \
gpointer data) \
{ \
GimpContext *context; \
GeglColor *color; \
GimpActionSelectType select_type; \
return_if_no_context (context, data); \
\
select_type = (GimpActionSelectType) g_variant_get_int32 (value); \
\
color = gegl_color_duplicate (gimp_context_get_##fgbg##ground (context)); \
context_select_color (select_type, color, \
use_colormap, use_palette); \
gimp_context_set_##fgbg##ground (context, color); \
g_object_unref (color); \
}
SELECT_COLOR_CMD_CALLBACK (palette, fore, FALSE, TRUE)
SELECT_COLOR_CMD_CALLBACK (palette, back, FALSE, TRUE)
SELECT_COLOR_CMD_CALLBACK (colormap, fore, TRUE, FALSE)
SELECT_COLOR_CMD_CALLBACK (colormap, back, TRUE, FALSE)
SELECT_COLOR_CMD_CALLBACK (swatch, fore, TRUE, TRUE)
SELECT_COLOR_CMD_CALLBACK (swatch, back, TRUE, TRUE)
void
context_foreground_red_cmd_callback (GimpAction *action,
GVariant *value,
gpointer data)
{
GimpContext *context;
GeglColor *color;
const Babl *format;
gdouble pixel[4];
GimpActionSelectType select_type;
return_if_no_context (context, data);
select_type = (GimpActionSelectType) g_variant_get_int32 (value);
color = gegl_color_duplicate (gimp_context_get_foreground (context));
format = gimp_context_get_rgba_format (context, color, "double", NULL);
gegl_color_get_pixel (color, format, pixel);
/* TODO: if value was already out-of-gamut, say we want to decrease it
* progressively. Should the algorithm allow it to be decreased while still
* staying out-of-gamut? Currently the function always clamps the result to
* min/max.
*/
pixel[0] = action_select_value (select_type,
pixel[0],
0.0, 1.0, 1.0,
1.0 / 255.0, 0.01, 0.1, 0.0, FALSE);
gegl_color_set_pixel (color, format, pixel);
gimp_context_set_foreground (context, color);
g_object_unref (color);
}
void
context_foreground_green_cmd_callback (GimpAction *action,
GVariant *value,
gpointer data)
{
GimpContext *context;
GeglColor *color;
const Babl *format;
gdouble pixel[4];
GimpActionSelectType select_type;
return_if_no_context (context, data);
select_type = (GimpActionSelectType) g_variant_get_int32 (value);
color = gegl_color_duplicate (gimp_context_get_foreground (context));
format = gimp_context_get_rgba_format (context, color, "double", NULL);
gegl_color_get_pixel (color, format, pixel);
pixel[1] = action_select_value (select_type,
pixel[1],
0.0, 1.0, 1.0,
1.0 / 255.0, 0.01, 0.1, 0.0, FALSE);
gegl_color_set_pixel (color, format, pixel);
gimp_context_set_foreground (context, color);
g_object_unref (color);
}
void
context_foreground_blue_cmd_callback (GimpAction *action,
GVariant *value,
gpointer data)
{
GimpContext *context;
GeglColor *color;
const Babl *format;
gdouble pixel[4];
GimpActionSelectType select_type;
return_if_no_context (context, data);
select_type = (GimpActionSelectType) g_variant_get_int32 (value);
color = gegl_color_duplicate (gimp_context_get_foreground (context));
format = gimp_context_get_rgba_format (context, color, "double", NULL);
gegl_color_get_pixel (color, format, pixel);
pixel[2] = action_select_value (select_type,
pixel[2],
0.0, 1.0, 1.0,
1.0 / 255.0, 0.01, 0.1, 0.0, FALSE);
gegl_color_set_pixel (color, format, pixel);
gimp_context_set_foreground (context, color);
g_object_unref (color);
}
void
context_background_red_cmd_callback (GimpAction *action,
GVariant *value,
gpointer data)
{
GimpContext *context;
GeglColor *color;
const Babl *format;
gdouble pixel[4];
GimpActionSelectType select_type;
return_if_no_context (context, data);
select_type = (GimpActionSelectType) g_variant_get_int32 (value);
color = gegl_color_duplicate (gimp_context_get_background (context));
format = gimp_context_get_rgba_format (context, color, "double", NULL);
gegl_color_get_pixel (color, format, pixel);
pixel[0] = action_select_value (select_type,
pixel[0],
0.0, 1.0, 1.0,
1.0 / 255.0, 0.01, 0.1, 0.0, FALSE);
gegl_color_set_pixel (color, format, pixel);
gimp_context_set_background (context, color);
g_object_unref (color);
}
void
context_background_green_cmd_callback (GimpAction *action,
GVariant *value,
gpointer data)
{
GimpContext *context;
GeglColor *color;
const Babl *format;
gdouble pixel[4];
GimpActionSelectType select_type;
return_if_no_context (context, data);
select_type = (GimpActionSelectType) g_variant_get_int32 (value);
color = gegl_color_duplicate (gimp_context_get_background (context));
format = gimp_context_get_rgba_format (context, color, "double", NULL);
gegl_color_get_pixel (color, format, pixel);
pixel[1] = action_select_value (select_type,
pixel[1],
0.0, 1.0, 1.0,
1.0 / 255.0, 0.01, 0.1, 0.0, FALSE);
gegl_color_set_pixel (color, format, pixel);
gimp_context_set_background (context, color);
g_object_unref (color);
}
void
context_background_blue_cmd_callback (GimpAction *action,
GVariant *value,
gpointer data)
{
GimpContext *context;
GeglColor *color;
const Babl *format;
gdouble pixel[4];
GimpActionSelectType select_type;
return_if_no_context (context, data);
select_type = (GimpActionSelectType) g_variant_get_int32 (value);
color = gegl_color_duplicate (gimp_context_get_background (context));
format = gimp_context_get_rgba_format (context, color, "double", NULL);
gegl_color_get_pixel (color, format, pixel);
pixel[2] = action_select_value (select_type,
pixel[2],
0.0, 1.0, 1.0,
1.0 / 255.0, 0.01, 0.1, 0.0, FALSE);
gegl_color_set_pixel (color, format, pixel);
gimp_context_set_background (context, color);
g_object_unref (color);
}
void
context_foreground_hue_cmd_callback (GimpAction *action,
GVariant *value,
gpointer data)
{
GimpContext *context;
GeglColor *color;
gfloat pixel[3];
GimpActionSelectType select_type;
return_if_no_context (context, data);
select_type = (GimpActionSelectType) g_variant_get_int32 (value);
color = gegl_color_duplicate (gimp_context_get_foreground (context));
gegl_color_get_pixel (color, babl_format_with_space ("HSV float", NULL), pixel);
pixel[0] = (gfloat) action_select_value (select_type,
pixel[0],
0.0, 1.0, 1.0,
1.0 / 360.0, 0.01, 0.1, 0.0, FALSE);
gegl_color_set_pixel (color, babl_format_with_space ("HSV float", NULL), pixel);
gimp_context_set_foreground (context, color);
g_object_unref (color);
}
void
context_foreground_saturation_cmd_callback (GimpAction *action,
GVariant *value,
gpointer data)
{
GimpContext *context;
GeglColor *color;
gfloat pixel[3];
GimpActionSelectType select_type;
return_if_no_context (context, data);
select_type = (GimpActionSelectType) g_variant_get_int32 (value);
color = gegl_color_duplicate (gimp_context_get_foreground (context));
gegl_color_get_pixel (color, babl_format_with_space ("HSV float", NULL), pixel);
pixel[1] = (gfloat) action_select_value (select_type,
pixel[1],
0.0, 1.0, 1.0,
0.01, 0.01, 0.1, 0.0, FALSE);
gegl_color_set_pixel (color, babl_format_with_space ("HSV float", NULL), pixel);
gimp_context_set_foreground (context, color);
g_object_unref (color);
}
void
context_foreground_value_cmd_callback (GimpAction *action,
GVariant *value,
gpointer data)
{
GimpContext *context;
GeglColor *color;
gfloat pixel[3];
GimpActionSelectType select_type;
return_if_no_context (context, data);
select_type = (GimpActionSelectType) g_variant_get_int32 (value);
color = gegl_color_duplicate (gimp_context_get_foreground (context));
gegl_color_get_pixel (color, babl_format_with_space ("HSV float", NULL), pixel);
pixel[2] = (gfloat) action_select_value (select_type,
pixel[2],
0.0, 1.0, 1.0,
0.01, 0.01, 0.1, 0.0, FALSE);
gegl_color_set_pixel (color, babl_format_with_space ("HSV float", NULL), pixel);
gimp_context_set_foreground (context, color);
g_object_unref (color);
}
void
context_background_hue_cmd_callback (GimpAction *action,
GVariant *value,
gpointer data)
{
GimpContext *context;
GeglColor *color;
gfloat pixel[3];
GimpActionSelectType select_type;
return_if_no_context (context, data);
select_type = (GimpActionSelectType) g_variant_get_int32 (value);
color = gegl_color_duplicate (gimp_context_get_background (context));
gegl_color_get_pixel (color, babl_format_with_space ("HSV float", NULL), pixel);
pixel[0] = (gfloat) action_select_value (select_type,
pixel[0],
0.0, 1.0, 1.0,
1.0 / 360.0, 0.01, 0.1, 0.0, FALSE);
gegl_color_set_pixel (color, babl_format_with_space ("HSV float", NULL), pixel);
gimp_context_set_background (context, color);
g_object_unref (color);
}
void
context_background_saturation_cmd_callback (GimpAction *action,
GVariant *value,
gpointer data)
{
GimpContext *context;
GeglColor *color;
gfloat pixel[3];
GimpActionSelectType select_type;
return_if_no_context (context, data);
select_type = (GimpActionSelectType) g_variant_get_int32 (value);
color = gegl_color_duplicate (gimp_context_get_background (context));
gegl_color_get_pixel (color, babl_format_with_space ("HSV float", NULL), pixel);
pixel[1] = (gfloat) action_select_value (select_type,
pixel[1],
0.0, 1.0, 1.0,
0.01, 0.01, 0.1, 0.0, FALSE);
gegl_color_set_pixel (color, babl_format_with_space ("HSV float", NULL), pixel);
gimp_context_set_background (context, color);
g_object_unref (color);
}
void
context_background_value_cmd_callback (GimpAction *action,
GVariant *value,
gpointer data)
{
GimpContext *context;
GeglColor *color;
gfloat pixel[3];
GimpActionSelectType select_type;
return_if_no_context (context, data);
select_type = (GimpActionSelectType) g_variant_get_int32 (value);
color = gegl_color_duplicate (gimp_context_get_background (context));
gegl_color_get_pixel (color, babl_format_with_space ("HSV float", NULL), pixel);
pixel[2] = (gfloat) action_select_value (select_type,
pixel[2],
0.0, 1.0, 1.0,
0.01, 0.01, 0.1, 0.0, FALSE);
gegl_color_set_pixel (color, babl_format_with_space ("HSV float", NULL), pixel);
gimp_context_set_background (context, color);
g_object_unref (color);
}
void
context_opacity_cmd_callback (GimpAction *action,
GVariant *value,
gpointer data)
{
GimpContext *context;
GimpToolInfo *tool_info;
GimpActionSelectType select_type;
return_if_no_context (context, data);
select_type = (GimpActionSelectType) g_variant_get_int32 (value);
tool_info = gimp_context_get_tool (context);
if (tool_info && GIMP_IS_TOOL_OPTIONS (tool_info->tool_options))
{
action_select_property (select_type,
action_data_get_display (data),
G_OBJECT (tool_info->tool_options),
"opacity",
1.0 / 255.0, 0.01, 0.1, 0.1, FALSE);
}
}
void
context_paint_mode_cmd_callback (GimpAction *action,
GVariant *value,
gpointer data)
{
GimpContext *context;
GimpToolInfo *tool_info;
GimpLayerMode *modes;
gint n_modes;
GimpLayerMode paint_mode;
gint index;
GimpActionSelectType select_type;
return_if_no_context (context, data);
select_type = (GimpActionSelectType) g_variant_get_int32 (value);
paint_mode = gimp_context_get_paint_mode (context);
modes = gimp_layer_mode_get_context_array (paint_mode,
GIMP_LAYER_MODE_CONTEXT_PAINT,
&n_modes);
index = context_paint_mode_index (paint_mode, modes, n_modes);
index = action_select_value (select_type,
index, 0, n_modes - 1, 0,
0.0, 1.0, 1.0, 0.0, FALSE);
paint_mode = modes[index];
g_free (modes);
gimp_context_set_paint_mode (context, paint_mode);
tool_info = gimp_context_get_tool (context);
if (tool_info && GIMP_IS_TOOL_OPTIONS (tool_info->tool_options))
{
GimpDisplay *display;
const char *value_desc;
gimp_enum_get_value (GIMP_TYPE_LAYER_MODE, paint_mode,
NULL, NULL, &value_desc, NULL);
display = action_data_get_display (data);
if (value_desc && display)
{
action_message (display, G_OBJECT (tool_info->tool_options),
_("Paint Mode: %s"), value_desc);
}
}
}
void
context_tool_select_cmd_callback (GimpAction *action,
GVariant *value,
gpointer data)
{
GimpContext *context;
GimpActionSelectType select_type;
return_if_no_context (context, data);
select_type = (GimpActionSelectType) g_variant_get_int32 (value);
context_select_object (select_type,
context, context->gimp->tool_info_list);
}
void
context_brush_select_cmd_callback (GimpAction *action,
GVariant *value,
gpointer data)
{
GimpContext *context;
GimpActionSelectType select_type;
return_if_no_context (context, data);
select_type = (GimpActionSelectType) g_variant_get_int32 (value);
context_select_object (select_type,
context,
gimp_data_factory_get_container (context->gimp->brush_factory));
}
void
context_pattern_select_cmd_callback (GimpAction *action,
GVariant *value,
gpointer data)
{
GimpContext *context;
GimpActionSelectType select_type;
return_if_no_context (context, data);
select_type = (GimpActionSelectType) g_variant_get_int32 (value);
context_select_object (select_type,
context,
gimp_data_factory_get_container (context->gimp->pattern_factory));
}
void
context_palette_select_cmd_callback (GimpAction *action,
GVariant *value,
gpointer data)
{
GimpContext *context;
GimpActionSelectType select_type;
return_if_no_context (context, data);
select_type = (GimpActionSelectType) g_variant_get_int32 (value);
context_select_object (select_type,
context,
gimp_data_factory_get_container (context->gimp->palette_factory));
}
void
context_gradient_select_cmd_callback (GimpAction *action,
GVariant *value,
gpointer data)
{
GimpContext *context;
GimpActionSelectType select_type;
return_if_no_context (context, data);
select_type = (GimpActionSelectType) g_variant_get_int32 (value);
context_select_object (select_type,
context,
gimp_data_factory_get_container (context->gimp->gradient_factory));
}
void
context_font_select_cmd_callback (GimpAction *action,
GVariant *value,
gpointer data)
{
GimpContext *context;
GimpActionSelectType select_type;
return_if_no_context (context, data);
select_type = (GimpActionSelectType) g_variant_get_int32 (value);
context_select_object (select_type,
context,
gimp_data_factory_get_container (context->gimp->font_factory));
}
void
context_brush_spacing_cmd_callback (GimpAction *action,
GVariant *value,
gpointer data)
{
GimpContext *context;
GimpBrush *brush;
GimpActionSelectType select_type;
return_if_no_context (context, data);
select_type = (GimpActionSelectType) g_variant_get_int32 (value);
brush = gimp_context_get_brush (context);
if (GIMP_IS_BRUSH (brush) && gimp_data_is_writable (GIMP_DATA (brush)))
{
action_select_property (select_type,
action_data_get_display (data),
G_OBJECT (brush),
"spacing",
1.0, 5.0, 20.0, 0.1, FALSE);
}
}
void
context_brush_shape_cmd_callback (GimpAction *action,
GVariant *value,
gpointer data)
{
GimpContext *context;
GimpBrush *brush;
GimpBrushGeneratedShape shape;
return_if_no_context (context, data);
shape = (GimpBrushGeneratedShape) g_variant_get_int32 (value);
brush = gimp_context_get_brush (context);
if (GIMP_IS_BRUSH_GENERATED (brush) &&
gimp_data_is_writable (GIMP_DATA (brush)))
{
GimpBrushGenerated *generated = GIMP_BRUSH_GENERATED (brush);
GimpDisplay *display;
const char *value_desc;
gimp_brush_generated_set_shape (generated, shape);
gimp_enum_get_value (GIMP_TYPE_BRUSH_GENERATED_SHAPE, shape,
NULL, NULL, &value_desc, NULL);
display = action_data_get_display (data);
if (value_desc && display)
{
action_message (display, G_OBJECT (brush),
_("Brush Shape: %s"), value_desc);
}
}
}
void
context_brush_radius_cmd_callback (GimpAction *action,
GVariant *value,
gpointer data)
{
GimpContext *context;
GimpBrush *brush;
GimpActionSelectType select_type;
return_if_no_context (context, data);
select_type = (GimpActionSelectType) g_variant_get_int32 (value);
brush = gimp_context_get_brush (context);
if (GIMP_IS_BRUSH_GENERATED (brush) &&
gimp_data_is_writable (GIMP_DATA (brush)))
{
GimpBrushGenerated *generated = GIMP_BRUSH_GENERATED (brush);
GimpDisplay *display;
gdouble radius;
gdouble min_radius;
radius = gimp_brush_generated_get_radius (generated);
/* If the user uses a high precision radius adjustment command
* then we allow a minimum radius of 0.1 px, otherwise we set the
* minimum radius to 1.0 px and adjust the radius to 1.0 px if it
* is less than 1.0 px. This prevents irritating 0.1, 1.1, 2.1 etc
* radius sequences when 1.0 px steps are used.
*/
switch (select_type)
{
case GIMP_ACTION_SELECT_SMALL_PREVIOUS:
case GIMP_ACTION_SELECT_SMALL_NEXT:
case GIMP_ACTION_SELECT_PERCENT_PREVIOUS:
case GIMP_ACTION_SELECT_PERCENT_NEXT:
min_radius = 0.1;
break;
default:
min_radius = 1.0;
if (radius < 1.0)
radius = 1.0;
break;
}
radius = action_select_value (select_type,
radius,
min_radius, GIMP_BRUSH_GENERATED_MAX_RADIUS, min_radius,
0.1, 1.0, 10.0, 0.05, FALSE);
gimp_brush_generated_set_radius (generated, radius);
display = action_data_get_display (data);
if (display)
{
action_message (action_data_get_display (data), G_OBJECT (brush),
_("Brush Radius: %2.2f"), radius);
}
}
}
void
context_brush_spikes_cmd_callback (GimpAction *action,
GVariant *value,
gpointer data)
{
GimpContext *context;
GimpBrush *brush;
GimpActionSelectType select_type;
return_if_no_context (context, data);
select_type = (GimpActionSelectType) g_variant_get_int32 (value);
brush = gimp_context_get_brush (context);
if (GIMP_IS_BRUSH_GENERATED (brush) &&
gimp_data_is_writable (GIMP_DATA (brush)))
{
action_select_property (select_type,
action_data_get_display (data),
G_OBJECT (brush),
"spikes",
0.0, 1.0, 4.0, 0.1, FALSE);
}
}
void
context_brush_hardness_cmd_callback (GimpAction *action,
GVariant *value,
gpointer data)
{
GimpContext *context;
GimpBrush *brush;
GimpActionSelectType select_type;
return_if_no_context (context, data);
select_type = (GimpActionSelectType) g_variant_get_int32 (value);
brush = gimp_context_get_brush (context);
if (GIMP_IS_BRUSH_GENERATED (brush) &&
gimp_data_is_writable (GIMP_DATA (brush)))
{
action_select_property (select_type,
action_data_get_display (data),
G_OBJECT (brush),
"hardness",
0.001, 0.01, 0.1, 0.1, FALSE);
}
}
void
context_brush_aspect_cmd_callback (GimpAction *action,
GVariant *value,
gpointer data)
{
GimpContext *context;
GimpBrush *brush;
GimpActionSelectType select_type;
return_if_no_context (context, data);
select_type = (GimpActionSelectType) g_variant_get_int32 (value);
brush = gimp_context_get_brush (context);
if (GIMP_IS_BRUSH_GENERATED (brush) &&
gimp_data_is_writable (GIMP_DATA (brush)))
{
action_select_property (select_type,
action_data_get_display (data),
G_OBJECT (brush),
"aspect-ratio",
0.1, 1.0, 4.0, 0.1, FALSE);
}
}
void
context_brush_angle_cmd_callback (GimpAction *action,
GVariant *value,
gpointer data)
{
GimpContext *context;
GimpBrush *brush;
GimpActionSelectType select_type;
return_if_no_context (context, data);
select_type = (GimpActionSelectType) g_variant_get_int32 (value);
brush = gimp_context_get_brush (context);
if (GIMP_IS_BRUSH_GENERATED (brush) &&
gimp_data_is_writable (GIMP_DATA (brush)))
{
GimpBrushGenerated *generated = GIMP_BRUSH_GENERATED (brush);
GimpDisplay *display;
gdouble angle;
angle = gimp_brush_generated_get_angle (generated);
if (select_type == GIMP_ACTION_SELECT_FIRST)
angle = 0.0;
else if (select_type == GIMP_ACTION_SELECT_LAST)
angle = 90.0;
else
angle = action_select_value (select_type,
angle,
0.0, 180.0, 0.0,
0.1, 1.0, 15.0, 0.1, TRUE);
gimp_brush_generated_set_angle (generated, angle);
display = action_data_get_display (data);
if (display)
{
action_message (action_data_get_display (data), G_OBJECT (brush),
_("Brush Angle: %2.2f"), angle);
}
}
}
void
context_toggle_dynamics_cmd_callback (GimpAction *action,
GVariant *value,
gpointer data)
{
GimpContext *context;
GimpPaintInfo *paint_info;
gboolean enabled;
return_if_no_context (context, data);
paint_info = gimp_context_get_paint_info (context);
if (paint_info)
{
GimpPaintOptions *paint_options;
GimpDisplay *display;
paint_options = paint_info->paint_options;
enabled = gimp_paint_options_are_dynamics_enabled (paint_options);
gimp_paint_options_enable_dynamics (paint_options, ! enabled);
display = action_data_get_display (data);
if (enabled)
action_message (display, G_OBJECT (paint_options),
_("Dynamics disabled"));
else
action_message (display, G_OBJECT (paint_options),
_("Dynamics enabled"));
}
}
/* private functions */
static void
context_select_object (GimpActionSelectType select_type,
GimpContext *context,
GimpContainer *container)
{
GimpObject *current;
current =
gimp_context_get_by_type (context,
gimp_container_get_children_type (container));
current = action_select_object (select_type, container, current);
if (current)
gimp_context_set_by_type (context,
gimp_container_get_children_type (container),
current);
}
static gint
context_paint_mode_index (GimpLayerMode paint_mode,
const GimpLayerMode *modes,
gint n_modes)
{
gint i = 0;
while (i < (n_modes - 1) && modes[i] != paint_mode)
i++;
return i;
}
static void
context_select_color (GimpActionSelectType select_type,
GeglColor *color,
gboolean use_colormap,
gboolean use_palette)
{
gint index;
gint max;
index = context_get_color_index (use_colormap, use_palette, color);
max = context_max_color_index (use_colormap, use_palette);
index = action_select_value (select_type,
index,
0, max, 0,
0, 1, 4, 0, FALSE);
context_set_color_index (index, use_colormap, use_palette, color);
}
static gint
context_get_color_index (gboolean use_colormap,
gboolean use_palette,
GeglColor *color)
{
if (use_colormap)
{
GimpColormapEditor *editor = context_get_colormap_editor ();
if (editor)
{
gint index = gimp_colormap_editor_get_index (editor, color);
if (index != -1)
return index;
}
}
if (use_palette)
{
GimpPaletteEditor *editor = context_get_palette_editor ();
if (editor)
{
gint index = gimp_palette_editor_get_index (editor, color);
if (index != -1)
return index;
}
}
return 0;
}
static gint
context_max_color_index (gboolean use_colormap,
gboolean use_palette)
{
if (use_colormap)
{
GimpColormapEditor *editor = context_get_colormap_editor ();
if (editor)
{
gint index = gimp_colormap_editor_max_index (editor);
if (index != -1)
return index;
}
}
if (use_palette)
{
GimpPaletteEditor *editor = context_get_palette_editor ();
if (editor)
{
gint index = gimp_palette_editor_max_index (editor);
if (index != -1)
return index;
}
}
return 0;
}
static gboolean
context_set_color_index (gint index,
gboolean use_colormap,
gboolean use_palette,
GeglColor *color)
{
if (use_colormap)
{
GimpColormapEditor *editor = context_get_colormap_editor ();
if (editor && gimp_colormap_editor_set_index (editor, index, color))
return TRUE;
}
if (use_palette)
{
GimpPaletteEditor *editor = context_get_palette_editor ();
if (editor && gimp_palette_editor_set_index (editor, index, color))
return TRUE;
}
return FALSE;
}
static GimpPaletteEditor *
context_get_palette_editor (void)
{
GtkWidget *widget;
g_return_val_if_fail (GIMP_IS_DIALOG_FACTORY (gimp_dialog_factory_get_singleton ()), NULL);
widget = gimp_dialog_factory_find_widget (gimp_dialog_factory_get_singleton (),
"gimp-palette-editor");
if (widget)
return GIMP_PALETTE_EDITOR (gtk_bin_get_child (GTK_BIN (widget)));
return NULL;
}
static GimpColormapEditor *
context_get_colormap_editor (void)
{
GtkWidget *widget;
g_return_val_if_fail (GIMP_IS_DIALOG_FACTORY (gimp_dialog_factory_get_singleton ()), NULL);
widget = gimp_dialog_factory_find_widget (gimp_dialog_factory_get_singleton (),
"gimp-indexed-palette");
if (widget)
return GIMP_COLORMAP_EDITOR (gtk_bin_get_child (GTK_BIN (widget)));
return NULL;
}