1
1
mirror of https://gitlab.gnome.org/GNOME/gimp.git synced 2025-10-06 01:12:40 +02:00

libgimp: API refactor GUI for GimpResource

Simplifies chooser widgets (e.g. GimpBrushSelect) by eliminating attributes (e.g. opacity) of chosen resource.
See #8745, but this commit fixes that by first refactoring the code.

Refactors GUI widgets (e.g. GimpBrushSelectButton and GimpBrushSelect etc.)

Refactor by "Extract class" GimpResourceSelectButton from GimpBrushSelectButton etc.
This moves common code into an inherited class (formerly called GimpSelectButton)
but the subclasses still exist.
The subclasses mainly just do drawing now.

Refactor by "Extract module" GimpResourceSelect from GimpBrushSelect etc.
Moves common code into one file, generic at runtime on type of GimpResource,
that is, the new code dispatches on type i.e. switch statements.
In the future, when core is changed some of that can be deleted.
The files gimpbrushselect.[c,h] etc. are deleted.
The module adapts the API from core to the API of callbacks to libgimp.

Note that core is running the resource chooser (select) widgets remotely.
Core is still calling back over the wire via PDB with more attributes
than necessary.
The new design gets the attributes from the resource themselves,
instead of receiving them from core callback.
The libgimp side adapts by discarding unneeded attributes.
In the future, core (running choosers for plugins) can be simplified also.

Fix gimp_prop_chooser_brush_new same as other resources.

Finish changes, and clean style.

Annotations
This commit is contained in:
lloyd konneker
2022-10-15 15:11:05 -04:00
committed by Jehan
parent 8d5f470507
commit d59a7af38c
78 changed files with 4053 additions and 4741 deletions

View File

@@ -433,6 +433,8 @@ libappcore_a_sources = \
gimpprojectable.h \
gimpprojection.c \
gimpprojection.h \
gimpresource.c \
gimpresource.h \
gimpsamplepoint.c \
gimpsamplepoint.h \
gimpsamplepointundo.c \

View File

@@ -37,6 +37,7 @@
#include "vectors/gimpvectors.h"
/* resource types */
#include "gimpresource.h"
#include "gimpbrush.h"
#include "gimpgradient.h"
#include "gimppalette.h"

53
app/core/gimpresource.c Normal file
View File

@@ -0,0 +1,53 @@
/* LIBGIMP - The GIMP Library
* Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
*
* This library is free software: you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see
* <https://www.gnu.org/licenses/>.
*/
#include "config.h"
#include <cairo.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
#include <gegl.h>
#include "gimpresource.h"
/* This class exists to support gimp_param_spec_resource,
* which is needed to communicate with libgimp.
* So that gimp_param_spec_resource has a GIMP_TYPE_RESOURCE on the app side.
*
* This class on libgimp side is a superclass.
* On app side of wire, it is not a superclass (e.g. GimpBrush does not inherit.)
* On app side, the class is never inherited and never instantiated.
*
* The code is derived from libgimp/gimpresource.c
*/
G_DEFINE_TYPE (GimpResource, gimp_resource, G_TYPE_OBJECT)
/* Class construction */
static void
gimp_resource_class_init (GimpResourceClass *klass)
{
g_debug("gimp_resource_class_init");
}
/* Instance construction. */
static void
gimp_resource_init (GimpResource *self)
{
g_debug("gimp_resource_init");
}

32
app/core/gimpresource.h Normal file
View File

@@ -0,0 +1,32 @@
/* 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/>.
*/
#ifndef __GIMP_RESOURCE_H__
#define __GIMP_RESOURCE_H__
#define GIMP_TYPE_RESOURCE (gimp_resource_get_type ())
G_DECLARE_DERIVABLE_TYPE (GimpResource, gimp_resource, GIMP, RESOURCE, GObject)
struct _GimpResourceClass
{
GObjectClass parent_class;
/* Padding for future expansion */
gpointer padding[8];
};
#endif /* __GIMP_RESOURCE_H__ */

View File

@@ -217,6 +217,7 @@ libappcore_sources = [
'gimpprogress.c',
'gimpprojectable.c',
'gimpprojection.c',
'gimpresource.c',
'gimpsamplepoint.c',
'gimpsamplepointundo.c',
'gimpscanconvert.c',

View File

@@ -49,31 +49,19 @@ brushes_popup_invoker (GimpProcedure *procedure,
gboolean success = TRUE;
const gchar *brush_callback;
const gchar *popup_title;
const gchar *initial_brush;
gdouble opacity;
gint spacing;
gint paint_mode;
const gchar *initial_brush_name;
brush_callback = g_value_get_string (gimp_value_array_index (args, 0));
popup_title = g_value_get_string (gimp_value_array_index (args, 1));
initial_brush = g_value_get_string (gimp_value_array_index (args, 2));
opacity = g_value_get_double (gimp_value_array_index (args, 3));
spacing = g_value_get_int (gimp_value_array_index (args, 4));
paint_mode = g_value_get_enum (gimp_value_array_index (args, 5));
initial_brush_name = g_value_get_string (gimp_value_array_index (args, 2));
if (success)
{
if (paint_mode == GIMP_LAYER_MODE_OVERLAY_LEGACY)
paint_mode = GIMP_LAYER_MODE_SOFTLIGHT_LEGACY;
if (gimp->no_interface ||
if (gimp->no_interface ||
! gimp_pdb_lookup_procedure (gimp->pdb, brush_callback) ||
! gimp_pdb_dialog_new (gimp, context, progress,
gimp_data_factory_get_container (gimp->brush_factory),
popup_title, brush_callback, initial_brush,
"opacity", opacity / 100.0,
"paint-mode", paint_mode,
"spacing", spacing,
popup_title, brush_callback, initial_brush_name,
NULL))
success = FALSE;
}
@@ -119,28 +107,16 @@ brushes_set_popup_invoker (GimpProcedure *procedure,
gboolean success = TRUE;
const gchar *brush_callback;
const gchar *brush_name;
gdouble opacity;
gint spacing;
gint paint_mode;
brush_callback = g_value_get_string (gimp_value_array_index (args, 0));
brush_name = g_value_get_string (gimp_value_array_index (args, 1));
opacity = g_value_get_double (gimp_value_array_index (args, 2));
spacing = g_value_get_int (gimp_value_array_index (args, 3));
paint_mode = g_value_get_enum (gimp_value_array_index (args, 4));
if (success)
{
if (paint_mode == GIMP_LAYER_MODE_OVERLAY_LEGACY)
paint_mode = GIMP_LAYER_MODE_SOFTLIGHT_LEGACY;
if (gimp->no_interface ||
! gimp_pdb_lookup_procedure (gimp->pdb, brush_callback) ||
! gimp_pdb_dialog_set (gimp, gimp_data_factory_get_container (gimp->brush_factory),
brush_callback, brush_name,
"opacity", opacity / 100.0,
"paint-mode", paint_mode,
"spacing", spacing,
NULL))
success = FALSE;
}
@@ -161,8 +137,8 @@ register_brush_select_procs (GimpPDB *pdb)
gimp_object_set_static_name (GIMP_OBJECT (procedure),
"gimp-brushes-popup");
gimp_procedure_set_static_help (procedure,
"Invokes the Gimp brush selection.",
"This procedure opens the brush selection dialog.",
"Invokes the GIMP brush selection dialog.",
"Opens a dialog letting a user choose a brush.",
NULL);
gimp_procedure_set_static_attribution (procedure,
"Andy Thomas",
@@ -171,7 +147,7 @@ register_brush_select_procs (GimpPDB *pdb)
gimp_procedure_add_argument (procedure,
gimp_param_spec_string ("brush-callback",
"brush callback",
"The callback PDB proc to call when brush selection is made",
"The callback PDB proc to call when user chooses a brush",
FALSE, FALSE, TRUE,
NULL,
GIMP_PARAM_READWRITE));
@@ -183,31 +159,12 @@ register_brush_select_procs (GimpPDB *pdb)
NULL,
GIMP_PARAM_READWRITE));
gimp_procedure_add_argument (procedure,
gimp_param_spec_string ("initial-brush",
"initial brush",
"The name of the brush to set as the first selected",
gimp_param_spec_string ("initial-brush-name",
"initial brush name",
"The name of the brush to set as the initial choice",
FALSE, TRUE, FALSE,
NULL,
GIMP_PARAM_READWRITE));
gimp_procedure_add_argument (procedure,
g_param_spec_double ("opacity",
"opacity",
"The initial opacity of the brush",
0, 100, 0,
GIMP_PARAM_READWRITE));
gimp_procedure_add_argument (procedure,
g_param_spec_int ("spacing",
"spacing",
"The initial spacing of the brush (if < 0 then use brush default spacing)",
G_MININT32, 1000, 0,
GIMP_PARAM_READWRITE));
gimp_procedure_add_argument (procedure,
g_param_spec_enum ("paint-mode",
"paint mode",
"The initial paint mode",
GIMP_TYPE_LAYER_MODE,
GIMP_LAYER_MODE_NORMAL,
GIMP_PARAM_READWRITE));
gimp_pdb_register_procedure (pdb, procedure);
g_object_unref (procedure);
@@ -219,7 +176,7 @@ register_brush_select_procs (GimpPDB *pdb)
"gimp-brushes-close-popup");
gimp_procedure_set_static_help (procedure,
"Close the brush selection dialog.",
"This procedure closes an opened brush selection dialog.",
"Closes an open brush selection dialog.",
NULL);
gimp_procedure_set_static_attribution (procedure,
"Andy Thomas",
@@ -242,8 +199,8 @@ register_brush_select_procs (GimpPDB *pdb)
gimp_object_set_static_name (GIMP_OBJECT (procedure),
"gimp-brushes-set-popup");
gimp_procedure_set_static_help (procedure,
"Sets the current brush in a brush selection dialog.",
"Sets the current brush in a brush selection dialog.",
"Sets the selected brush in a brush selection dialog.",
"Sets the selected brush in a brush selection dialog.",
NULL);
gimp_procedure_set_static_attribution (procedure,
"Andy Thomas",
@@ -263,25 +220,6 @@ register_brush_select_procs (GimpPDB *pdb)
FALSE, FALSE, FALSE,
NULL,
GIMP_PARAM_READWRITE));
gimp_procedure_add_argument (procedure,
g_param_spec_double ("opacity",
"opacity",
"The initial opacity of the brush",
0, 100, 0,
GIMP_PARAM_READWRITE));
gimp_procedure_add_argument (procedure,
g_param_spec_int ("spacing",
"spacing",
"The initial spacing of the brush (if < 0 then use brush default spacing)",
G_MININT32, 1000, 0,
GIMP_PARAM_READWRITE));
gimp_procedure_add_argument (procedure,
g_param_spec_enum ("paint-mode",
"paint mode",
"The initial paint mode",
GIMP_TYPE_LAYER_MODE,
GIMP_LAYER_MODE_NORMAL,
GIMP_PARAM_READWRITE));
gimp_pdb_register_procedure (pdb, procedure);
g_object_unref (procedure);
}

View File

@@ -49,11 +49,11 @@ fonts_popup_invoker (GimpProcedure *procedure,
gboolean success = TRUE;
const gchar *font_callback;
const gchar *popup_title;
const gchar *initial_font;
const gchar *initial_font_name;
font_callback = g_value_get_string (gimp_value_array_index (args, 0));
popup_title = g_value_get_string (gimp_value_array_index (args, 1));
initial_font = g_value_get_string (gimp_value_array_index (args, 2));
initial_font_name = g_value_get_string (gimp_value_array_index (args, 2));
if (success)
{
@@ -62,7 +62,7 @@ fonts_popup_invoker (GimpProcedure *procedure,
! gimp_data_factory_data_wait (gimp->font_factory) ||
! gimp_pdb_dialog_new (gimp, context, progress,
gimp_data_factory_get_container (gimp->font_factory),
popup_title, font_callback, initial_font,
popup_title, font_callback, initial_font_name,
NULL))
success = FALSE;
}
@@ -141,8 +141,8 @@ register_font_select_procs (GimpPDB *pdb)
gimp_object_set_static_name (GIMP_OBJECT (procedure),
"gimp-fonts-popup");
gimp_procedure_set_static_help (procedure,
"Invokes the Gimp font selection.",
"This procedure opens the font selection dialog.",
"Invokes the Gimp font selection dialog.",
"Opens a dialog letting a user choose a font.",
NULL);
gimp_procedure_set_static_attribution (procedure,
"Sven Neumann <sven@gimp.org>",
@@ -151,7 +151,7 @@ register_font_select_procs (GimpPDB *pdb)
gimp_procedure_add_argument (procedure,
gimp_param_spec_string ("font-callback",
"font callback",
"The callback PDB proc to call when font selection is made",
"The callback PDB proc to call when user chooses a font",
FALSE, FALSE, TRUE,
NULL,
GIMP_PARAM_READWRITE));
@@ -163,9 +163,9 @@ register_font_select_procs (GimpPDB *pdb)
NULL,
GIMP_PARAM_READWRITE));
gimp_procedure_add_argument (procedure,
gimp_param_spec_string ("initial-font",
"initial font",
"The name of the font to set as the first selected",
gimp_param_spec_string ("initial-font-name",
"initial font name",
"The name of the initial font choice.",
FALSE, TRUE, FALSE,
NULL,
GIMP_PARAM_READWRITE));
@@ -180,7 +180,7 @@ register_font_select_procs (GimpPDB *pdb)
"gimp-fonts-close-popup");
gimp_procedure_set_static_help (procedure,
"Close the font selection dialog.",
"This procedure closes an opened font selection dialog.",
"Closes an open font selection dialog.",
NULL);
gimp_procedure_set_static_attribution (procedure,
"Sven Neumann <sven@gimp.org>",
@@ -189,7 +189,7 @@ register_font_select_procs (GimpPDB *pdb)
gimp_procedure_add_argument (procedure,
gimp_param_spec_string ("font-callback",
"font callback",
"The name of the callback registered for this pop-up",
"The name of the callback registered in the PDB for this dialog",
FALSE, FALSE, TRUE,
NULL,
GIMP_PARAM_READWRITE));
@@ -213,7 +213,7 @@ register_font_select_procs (GimpPDB *pdb)
gimp_procedure_add_argument (procedure,
gimp_param_spec_string ("font-callback",
"font callback",
"The name of the callback registered for this pop-up",
"The name of the callback registered in the PDB for the dialog.",
FALSE, FALSE, TRUE,
NULL,
GIMP_PARAM_READWRITE));

View File

@@ -50,25 +50,25 @@ gradients_popup_invoker (GimpProcedure *procedure,
gboolean success = TRUE;
const gchar *gradient_callback;
const gchar *popup_title;
const gchar *initial_gradient;
gint sample_size;
const gchar *initial_gradient_name;
gradient_callback = g_value_get_string (gimp_value_array_index (args, 0));
popup_title = g_value_get_string (gimp_value_array_index (args, 1));
initial_gradient = g_value_get_string (gimp_value_array_index (args, 2));
sample_size = g_value_get_int (gimp_value_array_index (args, 3));
initial_gradient_name = g_value_get_string (gimp_value_array_index (args, 2));
if (success)
{
if (sample_size < 1 || sample_size > 10000)
sample_size = GIMP_GRADIENT_DEFAULT_SAMPLE_SIZE;
/* Formerly, this procedure had another parameter:
* the sample size of the gradient's data passed in the changed callback.
* Now the sample size is determined by core, and in the future,
* the callback won't return a sample of the data at all.
*/
if (gimp->no_interface ||
! gimp_pdb_lookup_procedure (gimp->pdb, gradient_callback) ||
! gimp_pdb_dialog_new (gimp, context, progress,
gimp_data_factory_get_container (gimp->gradient_factory),
popup_title, gradient_callback, initial_gradient,
"sample-size", sample_size,
popup_title, gradient_callback, initial_gradient_name,
NULL))
success = FALSE;
}
@@ -144,8 +144,8 @@ register_gradient_select_procs (GimpPDB *pdb)
gimp_object_set_static_name (GIMP_OBJECT (procedure),
"gimp-gradients-popup");
gimp_procedure_set_static_help (procedure,
"Invokes the Gimp gradients selection.",
"This procedure opens the gradient selection dialog.",
"Invokes the Gimp gradients selection dialog.",
"Opens a dialog letting a user choose a gradient.",
NULL);
gimp_procedure_set_static_attribution (procedure,
"Andy Thomas",
@@ -154,7 +154,7 @@ register_gradient_select_procs (GimpPDB *pdb)
gimp_procedure_add_argument (procedure,
gimp_param_spec_string ("gradient-callback",
"gradient callback",
"The callback PDB proc to call when gradient selection is made",
"The callback PDB proc to call when user chooses a gradient",
FALSE, FALSE, TRUE,
NULL,
GIMP_PARAM_READWRITE));
@@ -166,18 +166,12 @@ register_gradient_select_procs (GimpPDB *pdb)
NULL,
GIMP_PARAM_READWRITE));
gimp_procedure_add_argument (procedure,
gimp_param_spec_string ("initial-gradient",
"initial gradient",
"The name of the gradient to set as the first selected",
gimp_param_spec_string ("initial-gradient-name",
"initial gradient name",
"The name of the initial gradient choice",
FALSE, TRUE, FALSE,
NULL,
GIMP_PARAM_READWRITE));
gimp_procedure_add_argument (procedure,
g_param_spec_int ("sample-size",
"sample size",
"Size of the sample to return when the gradient is changed",
1, 10000, 1,
GIMP_PARAM_READWRITE | GIMP_PARAM_NO_VALIDATE));
gimp_pdb_register_procedure (pdb, procedure);
g_object_unref (procedure);
@@ -189,7 +183,7 @@ register_gradient_select_procs (GimpPDB *pdb)
"gimp-gradients-close-popup");
gimp_procedure_set_static_help (procedure,
"Close the gradient selection dialog.",
"This procedure closes an opened gradient selection dialog.",
"Closes an open gradient selection dialog.",
NULL);
gimp_procedure_set_static_attribution (procedure,
"Andy Thomas",

View File

@@ -49,11 +49,11 @@ palettes_popup_invoker (GimpProcedure *procedure,
gboolean success = TRUE;
const gchar *palette_callback;
const gchar *popup_title;
const gchar *initial_palette;
const gchar *initial_palette_name;
palette_callback = g_value_get_string (gimp_value_array_index (args, 0));
popup_title = g_value_get_string (gimp_value_array_index (args, 1));
initial_palette = g_value_get_string (gimp_value_array_index (args, 2));
initial_palette_name = g_value_get_string (gimp_value_array_index (args, 2));
if (success)
{
@@ -61,7 +61,7 @@ palettes_popup_invoker (GimpProcedure *procedure,
! gimp_pdb_lookup_procedure (gimp->pdb, palette_callback) ||
! gimp_pdb_dialog_new (gimp, context, progress,
gimp_data_factory_get_container (gimp->palette_factory),
popup_title, palette_callback, initial_palette,
popup_title, palette_callback, initial_palette_name,
NULL))
success = FALSE;
}
@@ -137,8 +137,8 @@ register_palette_select_procs (GimpPDB *pdb)
gimp_object_set_static_name (GIMP_OBJECT (procedure),
"gimp-palettes-popup");
gimp_procedure_set_static_help (procedure,
"Invokes the Gimp palette selection.",
"This procedure opens the palette selection dialog.",
"Invokes the Gimp palette selection dialog.",
"Opens a dialog letting a user choose a palette.",
NULL);
gimp_procedure_set_static_attribution (procedure,
"Michael Natterer <mitch@gimp.org>",
@@ -147,7 +147,7 @@ register_palette_select_procs (GimpPDB *pdb)
gimp_procedure_add_argument (procedure,
gimp_param_spec_string ("palette-callback",
"palette callback",
"The callback PDB proc to call when palette selection is made",
"The callback PDB proc to call when user chooses a palette",
FALSE, FALSE, TRUE,
NULL,
GIMP_PARAM_READWRITE));
@@ -159,9 +159,9 @@ register_palette_select_procs (GimpPDB *pdb)
NULL,
GIMP_PARAM_READWRITE));
gimp_procedure_add_argument (procedure,
gimp_param_spec_string ("initial-palette",
"initial palette",
"The name of the palette to set as the first selected",
gimp_param_spec_string ("initial-palette-name",
"initial palette name",
"The palette to set as the initial choice.",
FALSE, TRUE, FALSE,
NULL,
GIMP_PARAM_READWRITE));
@@ -176,7 +176,7 @@ register_palette_select_procs (GimpPDB *pdb)
"gimp-palettes-close-popup");
gimp_procedure_set_static_help (procedure,
"Close the palette selection dialog.",
"This procedure closes an opened palette selection dialog.",
"Closes an open palette selection dialog.",
NULL);
gimp_procedure_set_static_attribution (procedure,
"Michael Natterer <mitch@gimp.org>",

View File

@@ -49,11 +49,11 @@ patterns_popup_invoker (GimpProcedure *procedure,
gboolean success = TRUE;
const gchar *pattern_callback;
const gchar *popup_title;
const gchar *initial_pattern;
const gchar *initial_pattern_name;
pattern_callback = g_value_get_string (gimp_value_array_index (args, 0));
popup_title = g_value_get_string (gimp_value_array_index (args, 1));
initial_pattern = g_value_get_string (gimp_value_array_index (args, 2));
initial_pattern_name = g_value_get_string (gimp_value_array_index (args, 2));
if (success)
{
@@ -61,7 +61,7 @@ patterns_popup_invoker (GimpProcedure *procedure,
! gimp_pdb_lookup_procedure (gimp->pdb, pattern_callback) ||
! gimp_pdb_dialog_new (gimp, context, progress,
gimp_data_factory_get_container (gimp->pattern_factory),
popup_title, pattern_callback, initial_pattern,
popup_title, pattern_callback, initial_pattern_name,
NULL))
success = FALSE;
}
@@ -138,7 +138,7 @@ register_pattern_select_procs (GimpPDB *pdb)
"gimp-patterns-popup");
gimp_procedure_set_static_help (procedure,
"Invokes the Gimp pattern selection.",
"This procedure opens the pattern selection dialog.",
"Opens the pattern selection dialog.",
NULL);
gimp_procedure_set_static_attribution (procedure,
"Andy Thomas",
@@ -147,7 +147,7 @@ register_pattern_select_procs (GimpPDB *pdb)
gimp_procedure_add_argument (procedure,
gimp_param_spec_string ("pattern-callback",
"pattern callback",
"The callback PDB proc to call when pattern selection is made",
"The callback PDB proc to call when the user chooses a pattern",
FALSE, FALSE, TRUE,
NULL,
GIMP_PARAM_READWRITE));
@@ -159,9 +159,9 @@ register_pattern_select_procs (GimpPDB *pdb)
NULL,
GIMP_PARAM_READWRITE));
gimp_procedure_add_argument (procedure,
gimp_param_spec_string ("initial-pattern",
"initial pattern",
"The name of the pattern to set as the first selected",
gimp_param_spec_string ("initial-pattern-name",
"initial pattern name",
"The name of the pattern to set as the initial choice",
FALSE, TRUE, FALSE,
NULL,
GIMP_PARAM_READWRITE));
@@ -176,7 +176,7 @@ register_pattern_select_procs (GimpPDB *pdb)
"gimp-patterns-close-popup");
gimp_procedure_set_static_help (procedure,
"Close the pattern selection dialog.",
"This procedure closes an opened pattern selection dialog.",
"Closes an open pattern selection dialog.",
NULL);
gimp_procedure_set_static_attribution (procedure,
"Andy Thomas",

View File

@@ -112,14 +112,11 @@ libgimp_introspectable_headers = \
../libgimp/gimpenums.h \
${PDB_WRAPPERS_H} \
../libgimp/gimpbatchprocedure.h \
../libgimp/gimpbrushselect.h \
../libgimp/gimpchannel.h \
../libgimp/gimpdisplay.h \
../libgimp/gimpdrawable.h \
../libgimp/gimpfileprocedure.h \
../libgimp/gimpfontselect.h \
../libgimp/gimpgimprc.h \
../libgimp/gimpgradientselect.h \
../libgimp/gimpimage.h \
../libgimp/gimpimagecolorprofile.h \
../libgimp/gimpimagemetadata.h \
@@ -128,16 +125,15 @@ libgimp_introspectable_headers = \
../libgimp/gimplayer.h \
../libgimp/gimplayermask.h \
../libgimp/gimploadprocedure.h \
../libgimp/gimppaletteselect.h \
../libgimp/gimpparamspecs.h \
../libgimp/gimpparamspecs-resource.h \
../libgimp/gimppatternselect.h \
../libgimp/gimppdb.h \
../libgimp/gimpplugin.h \
../libgimp/gimpprocedure.h \
../libgimp/gimpprocedureconfig.h \
../libgimp/gimpprogress.h \
../libgimp/gimpresource.h \
../libgimp/gimpresourceselect.h \
../libgimp/gimpresource-subclass.h \
../libgimp/gimpsaveprocedure.h \
../libgimp/gimpselection.h \
@@ -151,14 +147,11 @@ libgimp_introspectable = \
../libgimp/gimp.c \
${PDB_WRAPPERS_C} \
../libgimp/gimpbatchprocedure.c \
../libgimp/gimpbrushselect.c \
../libgimp/gimpchannel.c \
../libgimp/gimpdisplay.c \
../libgimp/gimpdrawable.c \
../libgimp/gimpfileprocedure.c \
../libgimp/gimpfontselect.c \
../libgimp/gimpgimprc.c \
../libgimp/gimpgradientselect.c \
../libgimp/gimpimage.c \
../libgimp/gimpimagecolorprofile.c \
../libgimp/gimpimagemetadata.c \
@@ -168,15 +161,14 @@ libgimp_introspectable = \
../libgimp/gimplayer.c \
../libgimp/gimplayermask.c \
../libgimp/gimploadprocedure.c \
../libgimp/gimppaletteselect.c \
../libgimp/gimpparamspecs.c \
../libgimp/gimppatternselect.c \
../libgimp/gimppdb.c \
../libgimp/gimpplugin.c \
../libgimp/gimpprocedure.c \
../libgimp/gimpprocedureconfig.c \
../libgimp/gimpprogress.c \
../libgimp/gimpresource.c \
../libgimp/gimpresourceselect.c \
../libgimp/gimpresource-subclass.c \
../libgimp/gimpsaveprocedure.c \
../libgimp/gimpselection.c \
@@ -201,9 +193,10 @@ libgimpui_introspectable_headers = \
../libgimp/gimpproceduredialog.h \
../libgimp/gimpprocview.h \
../libgimp/gimpprogressbar.h \
../libgimp/gimppropbrushchooser.h \
../libgimp/gimppropchooser.h \
../libgimp/gimppropchooserfactory.h \
../libgimp/gimpresourceselectbutton.h \
../libgimp/gimpsaveproceduredialog.h \
../libgimp/gimpselectbutton.h \
../libgimp/gimpzoompreview.h
libgimpui_introspectable = \
@@ -222,8 +215,9 @@ libgimpui_introspectable = \
../libgimp/gimpprocbrowserdialog.c \
../libgimp/gimpproceduredialog.c \
../libgimp/gimpprocview.c \
../libgimp/gimppropbrushchooser.c \
../libgimp/gimppropchooser.c \
../libgimp/gimppropchooserfactory.c \
../libgimp/gimpsaveproceduredialog.c \
../libgimp/gimpprogressbar.c \
../libgimp/gimpselectbutton.c \
../libgimp/gimpresourceselectbutton.c \
../libgimp/gimpzoompreview.c

View File

@@ -25,8 +25,6 @@ EXPORTS
gimp_brush_is_valid
gimp_brush_new
gimp_brush_rename
gimp_brush_select_destroy
gimp_brush_select_new
gimp_brush_set_angle
gimp_brush_set_aspect_ratio
gimp_brush_set_hardness
@@ -299,8 +297,6 @@ EXPORTS
gimp_font_get_type
gimp_font_id_is_valid
gimp_font_is_valid
gimp_font_select_destroy
gimp_font_select_new
gimp_fonts_close_popup
gimp_fonts_get_list
gimp_fonts_popup
@@ -355,8 +351,6 @@ EXPORTS
gimp_gradient_segment_set_middle_pos
gimp_gradient_segment_set_right_color
gimp_gradient_segment_set_right_pos
gimp_gradient_select_destroy
gimp_gradient_select_new
gimp_gradients_close_popup
gimp_gradients_get_list
gimp_gradients_popup
@@ -661,8 +655,6 @@ EXPORTS
gimp_palette_is_valid
gimp_palette_new
gimp_palette_rename
gimp_palette_select_destroy
gimp_palette_select_new
gimp_palette_set_columns
gimp_palettes_close_popup
gimp_palettes_get_list
@@ -681,6 +673,7 @@ EXPORTS
gimp_param_layer_mask_get_type
gimp_param_palette_get_type
gimp_param_pattern_get_type
gimp_param_resource_get_type
gimp_param_selection_get_type
gimp_param_spec_brush
gimp_param_spec_channel
@@ -695,6 +688,7 @@ EXPORTS
gimp_param_spec_layer_mask
gimp_param_spec_palette
gimp_param_spec_pattern
gimp_param_spec_resource
gimp_param_spec_selection
gimp_param_spec_text_layer
gimp_param_spec_vectors
@@ -705,8 +699,6 @@ EXPORTS
gimp_pattern_get_type
gimp_pattern_id_is_valid
gimp_pattern_is_valid
gimp_pattern_select_destroy
gimp_pattern_select_new
gimp_patterns_close_popup
gimp_patterns_get_list
gimp_patterns_popup
@@ -818,6 +810,9 @@ EXPORTS
gimp_quit
gimp_resource_get_id
gimp_resource_get_type
gimp_resource_select_destroy
gimp_resource_select_new
gimp_resource_select_set
gimp_save_procedure_get_support_comment
gimp_save_procedure_get_support_exif
gimp_save_procedure_get_support_iptc

View File

@@ -37,13 +37,10 @@
#include <libgimp/gimptypes.h>
#include <libgimp/gimpbatchprocedure.h>
#include <libgimp/gimpbrushselect.h>
#include <libgimp/gimpchannel.h>
#include <libgimp/gimpdisplay.h>
#include <libgimp/gimpdrawable.h>
#include <libgimp/gimpfontselect.h>
#include <libgimp/gimpgimprc.h>
#include <libgimp/gimpgradientselect.h>
#include <libgimp/gimpimage.h>
#include <libgimp/gimpimagecolorprofile.h>
#include <libgimp/gimpimagemetadata.h>
@@ -52,10 +49,8 @@
#include <libgimp/gimplayer.h>
#include <libgimp/gimplayermask.h>
#include <libgimp/gimploadprocedure.h>
#include <libgimp/gimppaletteselect.h>
#include <libgimp/gimpparamspecs.h>
#include <libgimp/gimpparamspecs-resource.h>
#include <libgimp/gimppatternselect.h>
#include <libgimp/gimppdb.h>
#include <libgimp/gimpplugin.h>
#include <libgimp/gimpprocedureconfig.h>
@@ -69,6 +64,11 @@
#include <libgimp/gimpthumbnailprocedure.h>
#include <libgimp/gimpvectors.h>
/* Resources and their widgets. Order important. */
#include <libgimp/gimpresource.h>
#include <libgimp/gimpresourceselect.h>
#include <libgimp/gimpresource-subclass.h>
#include <libgimp/gimp_pdb_headers.h>
#undef __GIMP_H_INSIDE__

View File

@@ -1,265 +0,0 @@
/* LIBGIMP - The GIMP Library
* Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
*
* gimpbrushselect.c
*
* This library is free software: you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see
* <https://www.gnu.org/licenses/>.
*/
#include "config.h"
#include "gimp.h"
typedef struct
{
gchar *brush_callback;
guint idle_id;
gchar *brush_name;
gdouble opacity;
gint spacing;
gint paint_mode;
gint width;
gint height;
gint brush_mask_size;
guchar *brush_mask_data;
GimpRunBrushCallback callback;
gboolean closing;
gpointer data;
GDestroyNotify data_destroy;
} GimpBrushData;
/* local function prototypes */
static void gimp_brush_data_free (GimpBrushData *data);
static GimpValueArray * gimp_temp_brush_run (GimpProcedure *procedure,
const GimpValueArray *args,
gpointer run_data);
static gboolean gimp_temp_brush_idle (GimpBrushData *data);
/* public functions */
/**
* gimp_brush_select_new:
* @title: Title of the brush selection dialog.
* @brush_name: The name of the brush to set as the first selected.
* @opacity: The initial opacity of the brush.
* @spacing: The initial spacing of the brush (if < 0 then use brush default spacing).
* @paint_mode: The initial paint mode.
* @callback: (scope notified): The callback function to call each time a settings change.
* @data: (closure callback): the run_data given to @callback.
* @data_destroy: (destroy data): the destroy function for @data.
*
* Invokes a brush selection dialog then run @callback with the selected
* brush, various settings and user's @data.
*
* Returns: (transfer none): the name of a temporary PDB procedure. The
* string belongs to the brush selection dialog and will be
* freed automatically when the dialog is closed.
**/
const gchar *
gimp_brush_select_new (const gchar *title,
const gchar *brush_name,
gdouble opacity,
gint spacing,
GimpLayerMode paint_mode,
GimpRunBrushCallback callback,
gpointer data,
GDestroyNotify data_destroy)
{
GimpPlugIn *plug_in = gimp_get_plug_in ();
GimpProcedure *procedure;
gchar *brush_callback;
GimpBrushData *brush_data;
brush_callback = gimp_pdb_temp_procedure_name (gimp_get_pdb ());
brush_data = g_slice_new0 (GimpBrushData);
brush_data->brush_callback = brush_callback;
brush_data->callback = callback;
brush_data->data = data;
brush_data->data_destroy = data_destroy;
procedure = gimp_procedure_new (plug_in,
brush_callback,
GIMP_PDB_PROC_TYPE_TEMPORARY,
gimp_temp_brush_run,
brush_data,
(GDestroyNotify)
gimp_brush_data_free);
GIMP_PROC_ARG_STRING (procedure, "brush-name",
"Brush name",
"The brush name",
NULL,
G_PARAM_READWRITE);
GIMP_PROC_ARG_DOUBLE (procedure, "opacity",
"Opacity",
NULL,
0.0, 100.0, 100.0,
G_PARAM_READWRITE);
GIMP_PROC_ARG_INT (procedure, "spacing",
"Spacing",
NULL,
-1, 1000, 20,
G_PARAM_READWRITE);
GIMP_PROC_ARG_ENUM (procedure, "paint-mode",
"Paint mode",
NULL,
GIMP_TYPE_LAYER_MODE,
GIMP_LAYER_MODE_NORMAL,
G_PARAM_READWRITE);
GIMP_PROC_ARG_INT (procedure, "mask-width",
"Brush width",
NULL,
0, 10000, 0,
G_PARAM_READWRITE);
GIMP_PROC_ARG_INT (procedure, "mask-height",
"Brush height",
NULL,
0, 10000, 0,
G_PARAM_READWRITE);
GIMP_PROC_ARG_INT (procedure, "mask-len",
"Mask length",
"Length of brush mask data",
0, G_MAXINT, 0,
G_PARAM_READWRITE);
GIMP_PROC_ARG_UINT8_ARRAY (procedure, "mask-data",
"Mask data",
"The brush mask data",
G_PARAM_READWRITE);
GIMP_PROC_ARG_BOOLEAN (procedure, "closing",
"Closing",
"If the dialog was closing",
FALSE,
G_PARAM_READWRITE);
gimp_plug_in_add_temp_procedure (plug_in, procedure);
g_object_unref (procedure);
if (gimp_brushes_popup (brush_callback, title, brush_name,
opacity, spacing, paint_mode))
{
/* Allow callbacks to be watched */
gimp_plug_in_extension_enable (plug_in);
return brush_callback;
}
gimp_plug_in_remove_temp_procedure (plug_in, brush_callback);
return NULL;
}
void
gimp_brush_select_destroy (const gchar *brush_callback)
{
GimpPlugIn *plug_in = gimp_get_plug_in ();
g_return_if_fail (brush_callback != NULL);
gimp_plug_in_remove_temp_procedure (plug_in, brush_callback);
}
/* private functions */
static void
gimp_brush_data_free (GimpBrushData *data)
{
if (data->idle_id)
g_source_remove (data->idle_id);
if (data->brush_callback)
{
gimp_brushes_close_popup (data->brush_callback);
g_free (data->brush_callback);
}
g_free (data->brush_name);
g_free (data->brush_mask_data);
if (data->data_destroy)
data->data_destroy (data->data);
g_slice_free (GimpBrushData, data);
}
static GimpValueArray *
gimp_temp_brush_run (GimpProcedure *procedure,
const GimpValueArray *args,
gpointer run_data)
{
GimpBrushData *data = run_data;
g_free (data->brush_name);
g_free (data->brush_mask_data);
data->brush_name = GIMP_VALUES_DUP_STRING (args, 0);
data->opacity = GIMP_VALUES_GET_DOUBLE (args, 1);
data->spacing = GIMP_VALUES_GET_INT (args, 2);
data->paint_mode = GIMP_VALUES_GET_ENUM (args, 3);
data->width = GIMP_VALUES_GET_INT (args, 4);
data->height = GIMP_VALUES_GET_INT (args, 5);
data->brush_mask_size = GIMP_VALUES_GET_INT (args, 6);
data->brush_mask_data = GIMP_VALUES_DUP_UINT8_ARRAY (args, 7);
data->closing = GIMP_VALUES_GET_BOOLEAN (args, 8);
if (! data->idle_id)
data->idle_id = g_idle_add ((GSourceFunc) gimp_temp_brush_idle, data);
return gimp_procedure_new_return_values (procedure, GIMP_PDB_SUCCESS, NULL);
}
static gboolean
gimp_temp_brush_idle (GimpBrushData *data)
{
data->idle_id = 0;
if (data->callback)
data->callback (data->brush_name,
data->opacity,
data->spacing,
data->paint_mode,
data->width,
data->height,
data->brush_mask_size,
data->brush_mask_data,
data->closing,
data->data);
if (data->closing)
{
gchar *brush_callback = data->brush_callback;
data->brush_callback = NULL;
gimp_brush_select_destroy (brush_callback);
g_free (brush_callback);
}
return G_SOURCE_REMOVE;
}

View File

@@ -1,68 +0,0 @@
/* LIBGIMP - The GIMP Library
* Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
*
* gimpbrushselect.h
*
* This library is free software: you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see
* <https://www.gnu.org/licenses/>.
*/
#if !defined (__GIMP_H_INSIDE__) && !defined (GIMP_COMPILATION)
#error "Only <libgimp/gimp.h> can be included directly."
#endif
#ifndef __GIMP_BRUSH_SELECT_H__
#define __GIMP_BRUSH_SELECT_H__
G_BEGIN_DECLS
/**
* GimpRunBrushCallback:
* @brush_name: Name of the brush
* @opacity: Opacity
* @spacing: Spacing
* @paint_mode: Paint mode
* @width: width
* @height: height
* @mask_size: Mask size.
* @mask_data: (array length=mask_size): Mask data
* @dialog_closing: Dialog closing?
* @user_data: (closure): user data
*/
typedef void (* GimpRunBrushCallback) (const gchar *brush_name,
gdouble opacity,
gint spacing,
GimpLayerMode paint_mode,
gint width,
gint height,
gint mask_size,
const guchar *mask_data,
gboolean dialog_closing,
gpointer user_data);
const gchar * gimp_brush_select_new (const gchar *title,
const gchar *brush_name,
gdouble opacity,
gint spacing,
GimpLayerMode paint_mode,
GimpRunBrushCallback callback,
gpointer data,
GDestroyNotify data_destroy);
void gimp_brush_select_destroy (const gchar *brush_callback);
G_END_DECLS
#endif /* __GIMP_BRUSH_SELECT_H__ */

View File

@@ -30,34 +30,29 @@
/**
* SECTION: gimpbrushselect
* @title: gimpbrushselect
* @short_description: Functions providing a brush selection dialog.
* @short_description: Methods of a font chooser dialog
*
* Functions providing a brush selection dialog.
* A dialog letting a user choose a brush. Read more at
* gimpfontselect.
**/
/**
* gimp_brushes_popup:
* @brush_callback: The callback PDB proc to call when brush selection is made.
* @brush_callback: The callback PDB proc to call when user chooses a brush.
* @popup_title: Title of the brush selection dialog.
* @initial_brush: The name of the brush to set as the first selected.
* @opacity: The initial opacity of the brush.
* @spacing: The initial spacing of the brush (if < 0 then use brush default spacing).
* @paint_mode: The initial paint mode.
* @initial_brush_name: The name of the brush to set as the initial choice.
*
* Invokes the Gimp brush selection.
* Invokes the GIMP brush selection dialog.
*
* This procedure opens the brush selection dialog.
* Opens a dialog letting a user choose a brush.
*
* Returns: TRUE on success.
**/
gboolean
gimp_brushes_popup (const gchar *brush_callback,
const gchar *popup_title,
const gchar *initial_brush,
gdouble opacity,
gint spacing,
GimpLayerMode paint_mode)
gimp_brushes_popup (const gchar *brush_callback,
const gchar *popup_title,
const gchar *initial_brush_name)
{
GimpValueArray *args;
GimpValueArray *return_vals;
@@ -66,10 +61,7 @@ gimp_brushes_popup (const gchar *brush_callback,
args = gimp_value_array_new_from_types (NULL,
G_TYPE_STRING, brush_callback,
G_TYPE_STRING, popup_title,
G_TYPE_STRING, initial_brush,
G_TYPE_DOUBLE, opacity,
G_TYPE_INT, spacing,
GIMP_TYPE_LAYER_MODE, paint_mode,
G_TYPE_STRING, initial_brush_name,
G_TYPE_NONE);
return_vals = gimp_pdb_run_procedure_array (gimp_get_pdb (),
@@ -90,7 +82,7 @@ gimp_brushes_popup (const gchar *brush_callback,
*
* Close the brush selection dialog.
*
* This procedure closes an opened brush selection dialog.
* Closes an open brush selection dialog.
*
* Returns: TRUE on success.
**/
@@ -121,22 +113,16 @@ gimp_brushes_close_popup (const gchar *brush_callback)
* gimp_brushes_set_popup:
* @brush_callback: The name of the callback registered for this pop-up.
* @brush_name: The name of the brush to set as selected.
* @opacity: The initial opacity of the brush.
* @spacing: The initial spacing of the brush (if < 0 then use brush default spacing).
* @paint_mode: The initial paint mode.
*
* Sets the current brush in a brush selection dialog.
* Sets the selected brush in a brush selection dialog.
*
* Sets the current brush in a brush selection dialog.
* Sets the selected brush in a brush selection dialog.
*
* Returns: TRUE on success.
**/
gboolean
gimp_brushes_set_popup (const gchar *brush_callback,
const gchar *brush_name,
gdouble opacity,
gint spacing,
GimpLayerMode paint_mode)
gimp_brushes_set_popup (const gchar *brush_callback,
const gchar *brush_name)
{
GimpValueArray *args;
GimpValueArray *return_vals;
@@ -145,9 +131,6 @@ gimp_brushes_set_popup (const gchar *brush_callback,
args = gimp_value_array_new_from_types (NULL,
G_TYPE_STRING, brush_callback,
G_TYPE_STRING, brush_name,
G_TYPE_DOUBLE, opacity,
G_TYPE_INT, spacing,
GIMP_TYPE_LAYER_MODE, paint_mode,
G_TYPE_NONE);
return_vals = gimp_pdb_run_procedure_array (gimp_get_pdb (),

View File

@@ -32,18 +32,12 @@ G_BEGIN_DECLS
/* For information look into the C source or the html documentation */
gboolean gimp_brushes_popup (const gchar *brush_callback,
const gchar *popup_title,
const gchar *initial_brush,
gdouble opacity,
gint spacing,
GimpLayerMode paint_mode);
gboolean gimp_brushes_close_popup (const gchar *brush_callback);
gboolean gimp_brushes_set_popup (const gchar *brush_callback,
const gchar *brush_name,
gdouble opacity,
gint spacing,
GimpLayerMode paint_mode);
gboolean gimp_brushes_popup (const gchar *brush_callback,
const gchar *popup_title,
const gchar *initial_brush_name);
gboolean gimp_brushes_close_popup (const gchar *brush_callback);
gboolean gimp_brushes_set_popup (const gchar *brush_callback,
const gchar *brush_name);
G_END_DECLS

File diff suppressed because it is too large Load Diff

View File

@@ -25,76 +25,35 @@
#ifndef __GIMP_BRUSH_SELECT_BUTTON_H__
#define __GIMP_BRUSH_SELECT_BUTTON_H__
#include <libgimp/gimpselectbutton.h>
#include <libgimp/gimpresourceselectbutton.h>
G_BEGIN_DECLS
/* For information look into the C source or the html documentation */
/* This defines certain structs and the usual macros.
* A final type has no private.
*/
#define GIMP_TYPE_BRUSH_SELECT_BUTTON (gimp_brush_select_button_get_type ())
G_DECLARE_FINAL_TYPE (GimpBrushSelectButton,
gimp_brush_select_button,
GIMP, BRUSH_SELECT_BUTTON,
GimpResourceSelectButton)
#define GIMP_TYPE_BRUSH_SELECT_BUTTON (gimp_brush_select_button_get_type ())
#define GIMP_BRUSH_SELECT_BUTTON(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_BRUSH_SELECT_BUTTON, GimpBrushSelectButton))
#define GIMP_BRUSH_SELECT_BUTTON_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_BRUSH_SELECT_BUTTON, GimpBrushSelectButtonClass))
#define GIMP_IS_BRUSH_SELECT_BUTTON(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_BRUSH_SELECT_BUTTON))
#define GIMP_IS_BRUSH_SELECT_BUTTON_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_BRUSH_SELECT_BUTTON))
#define GIMP_BRUSH_SELECT_BUTTON_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_BRUSH_SELECT_BUTTON, GimpBrushSelectButtonClass))
typedef struct _GimpBrushSelectButtonPrivate GimpBrushSelectButtonPrivate;
typedef struct _GimpBrushSelectButtonClass GimpBrushSelectButtonClass;
struct _GimpBrushSelectButton
{
GimpSelectButton parent_instance;
GimpBrushSelectButtonPrivate *priv;
};
struct _GimpBrushSelectButtonClass
{
GimpSelectButtonClass parent_class;
GimpResourceSelectButtonClass parent_class;
/* brush_set signal is emitted when brush is chosen */
void (* brush_set) (GimpBrushSelectButton *button,
const gchar *brush_name,
gdouble opacity,
gint spacing,
GimpLayerMode paint_mode,
gint width,
gint height,
const guchar *mask_data,
gboolean dialog_closing);
/* Padding for future expansion */
void (*_gimp_reserved1) (void);
void (*_gimp_reserved2) (void);
void (*_gimp_reserved3) (void);
void (*_gimp_reserved4) (void);
void (*_gimp_reserved5) (void);
void (*_gimp_reserved6) (void);
void (*_gimp_reserved7) (void);
void (*_gimp_reserved8) (void);
/* _set signal is not defined. Use resource_set signal from superclass */
};
GType gimp_brush_select_button_get_type (void) G_GNUC_CONST;
GtkWidget * gimp_brush_select_button_new (const gchar *title,
const gchar *brush_name,
gdouble opacity,
gint spacing,
GimpLayerMode paint_mode);
const gchar * gimp_brush_select_button_get_brush (GimpBrushSelectButton *button,
gdouble *opacity,
gint *spacing,
GimpLayerMode *paint_mode);
void gimp_brush_select_button_set_brush (GimpBrushSelectButton *button,
const gchar *brush_name,
gdouble opacity,
gint spacing,
GimpLayerMode paint_mode);
GtkWidget * gimp_brush_select_button_new (const gchar *title,
GimpResource *resource);
/* FUTURE eliminate. Use superclass method get_resource */
GimpBrush * gimp_brush_select_button_get_brush (GimpBrushSelectButton *self);
void gimp_brush_select_button_set_brush (GimpBrushSelectButton *self,
GimpBrush *brush);
G_END_DECLS

View File

@@ -1,179 +0,0 @@
/* LIBGIMP - The GIMP Library
* Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
*
* gimpfontselect.c
*
* This library is free software: you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see
* <https://www.gnu.org/licenses/>.
*/
#include "config.h"
#include "gimp.h"
typedef struct
{
gchar *font_callback;
guint idle_id;
gchar *font_name;
GimpRunFontCallback callback;
gboolean closing;
gpointer data;
GDestroyNotify data_destroy;
} GimpFontData;
/* local function prototypes */
static void gimp_font_data_free (GimpFontData *data);
static GimpValueArray * gimp_temp_font_run (GimpProcedure *procedure,
const GimpValueArray *args,
gpointer run_data);
static gboolean gimp_temp_font_idle (GimpFontData *data);
/* public functions */
const gchar *
gimp_font_select_new (const gchar *title,
const gchar *font_name,
GimpRunFontCallback callback,
gpointer data,
GDestroyNotify data_destroy)
{
GimpPlugIn *plug_in = gimp_get_plug_in ();
GimpProcedure *procedure;
gchar *font_callback;
GimpFontData *font_data;
font_callback = gimp_pdb_temp_procedure_name (gimp_get_pdb ());
font_data = g_slice_new0 (GimpFontData);
font_data->font_callback = font_callback;
font_data->callback = callback;
font_data->data = data;
font_data->data_destroy = data_destroy;
procedure = gimp_procedure_new (plug_in,
font_callback,
GIMP_PDB_PROC_TYPE_TEMPORARY,
gimp_temp_font_run,
font_data,
(GDestroyNotify)
gimp_font_data_free);
GIMP_PROC_ARG_STRING (procedure, "font-name",
"Font name",
"The font name",
NULL,
G_PARAM_READWRITE);
GIMP_PROC_ARG_BOOLEAN (procedure, "closing",
"Closing",
"If the dialog was closing",
FALSE,
G_PARAM_READWRITE);
gimp_plug_in_add_temp_procedure (plug_in, procedure);
g_object_unref (procedure);
if (gimp_fonts_popup (font_callback, title, font_name))
{
/* Allow callbacks to be watched */
gimp_plug_in_extension_enable (plug_in);
return font_callback;
}
gimp_plug_in_remove_temp_procedure (plug_in, font_callback);
return NULL;
}
void
gimp_font_select_destroy (const gchar *font_callback)
{
GimpPlugIn *plug_in = gimp_get_plug_in ();
g_return_if_fail (font_callback != NULL);
gimp_plug_in_remove_temp_procedure (plug_in, font_callback);
}
/* private functions */
static void
gimp_font_data_free (GimpFontData *data)
{
if (data->idle_id)
g_source_remove (data->idle_id);
g_free (data->font_name);
if (data->font_callback)
{
gimp_fonts_close_popup (data->font_callback);
g_free (data->font_callback);
}
if (data->data_destroy)
data->data_destroy (data->data);
g_slice_free (GimpFontData, data);
}
static GimpValueArray *
gimp_temp_font_run (GimpProcedure *procedure,
const GimpValueArray *args,
gpointer run_data)
{
GimpFontData *data = run_data;
g_free (data->font_name);
data->font_name = GIMP_VALUES_DUP_STRING (args, 0);
data->closing = GIMP_VALUES_GET_BOOLEAN (args, 1);
if (! data->idle_id)
data->idle_id = g_idle_add ((GSourceFunc) gimp_temp_font_idle,
data);
return gimp_procedure_new_return_values (procedure, GIMP_PDB_SUCCESS, NULL);
}
static gboolean
gimp_temp_font_idle (GimpFontData *data)
{
data->idle_id = 0;
if (data->callback)
data->callback (data->font_name,
data->closing,
data->data);
if (data->closing)
{
gchar *font_callback = data->font_callback;
data->font_callback = NULL;
gimp_font_select_destroy (font_callback);
g_free (font_callback);
}
return G_SOURCE_REMOVE;
}

View File

@@ -1,46 +0,0 @@
/* LIBGIMP - The GIMP Library
* Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
*
* gimpfontselect.h
*
* This library is free software: you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see
* <https://www.gnu.org/licenses/>.
*/
#if !defined (__GIMP_H_INSIDE__) && !defined (GIMP_COMPILATION)
#error "Only <libgimp/gimp.h> can be included directly."
#endif
#ifndef __GIMP_FONT_SELECT_H__
#define __GIMP_FONT_SELECT_H__
G_BEGIN_DECLS
typedef void (* GimpRunFontCallback) (const gchar *font_name,
gboolean dialog_closing,
gpointer user_data);
const gchar * gimp_font_select_new (const gchar *title,
const gchar *font_name,
GimpRunFontCallback callback,
gpointer data,
GDestroyNotify data_destroy);
void gimp_font_select_destroy (const gchar *font_callback);
G_END_DECLS
#endif /* __GIMP_FONT_SELECT_H__ */

View File

@@ -30,28 +30,37 @@
/**
* SECTION: gimpfontselect
* @title: gimpfontselect
* @short_description: Functions providing a font selection dialog.
* @short_description: Methods of a font chooser dialog.
*
* Functions providing a font selection dialog.
* A font chooser dialog shows installed fonts.
* The dialog is non-modal with its owning dialog,
* which is usually a plugin procedure's dialog.
* When a user selects a font,
* the dialog calls back but the dialog remains open.
* The chosen font is only a choice for the owning widget
* and does not select the font for the context.
* The user can close but not cancel the dialog.
* The owning dialog can close the font chooser dialog
* when the user closes or cancels the owning dialog.
**/
/**
* gimp_fonts_popup:
* @font_callback: The callback PDB proc to call when font selection is made.
* @font_callback: The callback PDB proc to call when user chooses a font.
* @popup_title: Title of the font selection dialog.
* @initial_font: The name of the font to set as the first selected.
* @initial_font_name: The name of the initial font choice.
*
* Invokes the Gimp font selection.
* Invokes the Gimp font selection dialog.
*
* This procedure opens the font selection dialog.
* Opens a dialog letting a user choose a font.
*
* Returns: TRUE on success.
**/
gboolean
gimp_fonts_popup (const gchar *font_callback,
const gchar *popup_title,
const gchar *initial_font)
const gchar *initial_font_name)
{
GimpValueArray *args;
GimpValueArray *return_vals;
@@ -60,7 +69,7 @@ gimp_fonts_popup (const gchar *font_callback,
args = gimp_value_array_new_from_types (NULL,
G_TYPE_STRING, font_callback,
G_TYPE_STRING, popup_title,
G_TYPE_STRING, initial_font,
G_TYPE_STRING, initial_font_name,
G_TYPE_NONE);
return_vals = gimp_pdb_run_procedure_array (gimp_get_pdb (),
@@ -77,11 +86,11 @@ gimp_fonts_popup (const gchar *font_callback,
/**
* gimp_fonts_close_popup:
* @font_callback: The name of the callback registered for this pop-up.
* @font_callback: The name of the callback registered in the PDB for this dialog.
*
* Close the font selection dialog.
*
* This procedure closes an opened font selection dialog.
* Closes an open font selection dialog.
*
* Returns: TRUE on success.
**/
@@ -110,7 +119,7 @@ gimp_fonts_close_popup (const gchar *font_callback)
/**
* gimp_fonts_set_popup:
* @font_callback: The name of the callback registered for this pop-up.
* @font_callback: The name of the callback registered in the PDB for the dialog.
* @font_name: The name of the font to set as selected.
*
* Sets the current font in a font selection dialog.

View File

@@ -34,7 +34,7 @@ G_BEGIN_DECLS
gboolean gimp_fonts_popup (const gchar *font_callback,
const gchar *popup_title,
const gchar *initial_font);
const gchar *initial_font_name);
gboolean gimp_fonts_close_popup (const gchar *font_callback);
gboolean gimp_fonts_set_popup (const gchar *font_callback,
const gchar *font_name);

View File

@@ -43,233 +43,193 @@
* A button which pops up a font selection dialog.
**/
enum
struct _GimpFontSelectButton
{
FONT_SET,
LAST_SIGNAL
/* !! Not a pointer, is contained. */
GimpResourceSelectButton parent_instance;
GtkWidget *font_name_label;
GtkWidget *drag_region_widget;
GtkWidget *button;
};
enum
{
PROP_0,
PROP_TITLE,
PROP_FONT_NAME,
N_PROPS
};
/* local */
/* implement virtual */
static void gimp_font_select_button_finalize (GObject *object);
static void gimp_font_select_button_draw_interior (GimpResourceSelectButton *self);
struct _GimpFontSelectButtonPrivate
{
gchar *title;
/* Called at init. */
static GtkWidget *gimp_font_select_button_create_interior (GimpFontSelectButton *self);
gchar *font_name; /* local copy */
/* A GtkTargetEntry has a string and two ints. This is one, but treat as an array.*/
static const GtkTargetEntry drag_target = { "application/x-gimp-font-name", 0, 0 };
GtkWidget *inside;
GtkWidget *label;
};
/* local function prototypes */
static void gimp_font_select_button_finalize (GObject *object);
static void gimp_font_select_button_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec);
static void gimp_font_select_button_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec);
static void gimp_font_select_button_clicked (GimpFontSelectButton *button);
static void gimp_font_select_button_callback (const gchar *font_name,
gboolean dialog_closing,
gpointer user_data);
static void gimp_font_select_drag_data_received (GimpFontSelectButton *button,
GdkDragContext *context,
gint x,
gint y,
GtkSelectionData *selection,
guint info,
guint time);
static GtkWidget * gimp_font_select_button_create_inside (GimpFontSelectButton *button);
static const GtkTargetEntry target = { "application/x-gimp-font-name", 0 };
static guint font_button_signals[LAST_SIGNAL] = { 0 };
static GParamSpec *font_button_props[N_PROPS] = { NULL, };
G_DEFINE_TYPE_WITH_PRIVATE (GimpFontSelectButton, gimp_font_select_button,
GIMP_TYPE_SELECT_BUTTON)
G_DEFINE_FINAL_TYPE (GimpFontSelectButton,
gimp_font_select_button,
GIMP_TYPE_RESOURCE_SELECT_BUTTON)
static void
gimp_font_select_button_class_init (GimpFontSelectButtonClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GimpSelectButtonClass *select_button_class = GIMP_SELECT_BUTTON_CLASS (klass);
/* Alias cast klass to super classes. */
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GimpResourceSelectButtonClass *superclass = GIMP_RESOURCE_SELECT_BUTTON_CLASS (klass);
g_debug ("%s called", G_STRFUNC);
/* Override virtual. */
object_class->finalize = gimp_font_select_button_finalize;
object_class->set_property = gimp_font_select_button_set_property;
object_class->get_property = gimp_font_select_button_get_property;
select_button_class->select_destroy = gimp_font_select_destroy;
/* Implement pure virtual functions. */
superclass->draw_interior = gimp_font_select_button_draw_interior;
klass->font_set = NULL;
/* Set data member of class. */
superclass->resource_type = GIMP_TYPE_FONT;
/**
* GimpFontSelectButton:title:
*
* The title to be used for the font selection popup dialog.
*
* Since: 2.4
/* We don't define property getter/setters: use superclass getter/setters.
* But super property name is "resource", not "font"
*/
font_button_props[PROP_TITLE] = g_param_spec_string ("title",
"Title",
"The title to be used for the font selection popup dialog",
_("Font Selection"),
GIMP_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY);
/**
* GimpFontSelectButton:font-name:
*
* The name of the currently selected font.
*
* Since: 2.4
*/
font_button_props[PROP_FONT_NAME] = g_param_spec_string ("font-name",
"Font name",
"The name of the currently selected font",
"Sans-serif",
GIMP_PARAM_READWRITE);
g_object_class_install_properties (object_class, N_PROPS, font_button_props);
/**
* GimpFontSelectButton::font-set:
* @widget: the object which received the signal.
* @font_name: the name of the currently selected font.
* @dialog_closing: whether the dialog was closed or not.
*
* The ::font-set signal is emitted when the user selects a font.
*
* Since: 2.4
*/
font_button_signals[FONT_SET] =
g_signal_new ("font-set",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (GimpFontSelectButtonClass, font_set),
NULL, NULL,
_gimpui_marshal_VOID__STRING_BOOLEAN,
G_TYPE_NONE, 2,
G_TYPE_STRING,
G_TYPE_BOOLEAN);
}
static void
gimp_font_select_button_init (GimpFontSelectButton *button)
gimp_font_select_button_init (GimpFontSelectButton *self)
{
button->priv = gimp_font_select_button_get_instance_private (button);
GtkWidget *interior;
button->priv->inside = gimp_font_select_button_create_inside (button);
gtk_container_add (GTK_CONTAINER (button), button->priv->inside);
g_debug ("%s called", G_STRFUNC);
/* Specialize super:
* - embed our widget interior instance to super widget instance.
* - tell super our dnd widget
* - tell super our clickable button
* Call superclass methods, with upcasts.
* These are on instance, not our subclass.
*/
interior = gimp_font_select_button_create_interior (self);
/* require self has sub widgets initialized. */
/* Embed the whole button.*/
gimp_resource_select_button_embed_interior (GIMP_RESOURCE_SELECT_BUTTON (self), interior);
/* Self knows the GtkTargetEntry, super creates target and handles receive drag. */
gimp_resource_select_button_set_drag_target (GIMP_RESOURCE_SELECT_BUTTON (self),
self->drag_region_widget,
&drag_target);
/* Super handles button clicks. */
gimp_resource_select_button_set_clickable (GIMP_RESOURCE_SELECT_BUTTON (self),
self->button);
}
/**
* gimp_font_select_button_new:
* @title: (nullable): Title of the dialog to use or %NULL to use the default title.
* @font_name: (nullable): Initial font name.
* @resource: (nullable): Initial font.
*
* Creates a new #GtkWidget that completely controls the selection of
* a font. This widget is suitable for placement in a table in a
* plug-in dialog.
* Creates a new #GtkWidget that lets a user choose a font.
* You can put this widget in a plug-in dialog.
*
* When font is NULL, initial choice is from context.
*
* Returns: A #GtkWidget that you can use in your UI.
*
* Since: 2.4
*/
GtkWidget *
gimp_font_select_button_new (const gchar *title,
const gchar *font_name)
gimp_font_select_button_new (const gchar *title,
GimpResource *resource)
{
GtkWidget *button;
GtkWidget *self;
if (title)
button = g_object_new (GIMP_TYPE_FONT_SELECT_BUTTON,
"title", title,
"font-name", font_name,
NULL);
else
button = g_object_new (GIMP_TYPE_FONT_SELECT_BUTTON,
"font-name", font_name,
NULL);
g_debug ("%s called", G_STRFUNC);
return button;
if (resource == NULL)
{
g_debug ("%s defaulting font from context", G_STRFUNC);
resource = GIMP_RESOURCE (gimp_context_get_font ());
}
g_assert (resource != NULL);
/* This method is polymorphic, so a factory can call it, but requires Font. */
g_return_val_if_fail (GIMP_IS_FONT (resource), NULL);
/* Create instance of self (not super.)
* This will call superclass init, self class init, superclass init, and instance init.
* Self subclass class_init will specialize by implementing virtual funcs
* that open and set remote chooser dialog, and that draw self interior.
*
* !!! property belongs to superclass and is named "resource"
*/
if (title)
self = g_object_new (GIMP_TYPE_FONT_SELECT_BUTTON,
"title", title,
"resource", resource,
NULL);
else
self = g_object_new (GIMP_TYPE_FONT_SELECT_BUTTON,
"resource", resource,
NULL);
/* We don't subscribe to events from super (such as draw events.)
* Super will call our draw method when it's resource changes.
* Except that the above setting of property happens too late,
* so we now draw the initial resource.
*/
/* Draw with the initial resource. Cast self from Widget. */
gimp_font_select_button_draw_interior (GIMP_RESOURCE_SELECT_BUTTON (self));
g_debug ("%s returns", G_STRFUNC);
return self;
}
/* Getter and setter.
* We could omit these, and use only the superclass methods.
* But script-fu-interface.c uses these, until FUTURE.
*/
/**
* gimp_font_select_button_get_font:
* @button: A #GimpFontSelectButton
* @self: A #GimpFontSelectButton
*
* Retrieves the name of currently selected font.
* Gets the currently selected font.
*
* Returns: an internal copy of the font name which must not be freed.
* Returns: (transfer none): an internal copy of the font which must not be freed.
*
* Since: 2.4
*/
const gchar *
gimp_font_select_button_get_font (GimpFontSelectButton *button)
GimpFont *
gimp_font_select_button_get_font (GimpFontSelectButton *self)
{
g_return_val_if_fail (GIMP_IS_FONT_SELECT_BUTTON (button), NULL);
g_return_val_if_fail (GIMP_IS_FONT_SELECT_BUTTON (self), NULL);
return button->priv->font_name;
/* Delegate to super w upcast arg and downcast result. */
return (GimpFont *) gimp_resource_select_button_get_resource ((GimpResourceSelectButton*) self);
}
/**
* gimp_font_select_button_set_font:
* @button: A #GimpFontSelectButton
* @font_name: (nullable): Font name to set; %NULL means no change.
* @self: A #GimpFontSelectButton
* @font: Font to set.
*
* Sets the current font for the font select button.
* Sets the currently selected font.
* Usually you should not call this; the user is in charge.
* Changes the selection in both the button and it's popup chooser.
*
* Since: 2.4
*/
void
gimp_font_select_button_set_font (GimpFontSelectButton *button,
const gchar *font_name)
gimp_font_select_button_set_font (GimpFontSelectButton *self,
GimpFont *font)
{
GimpSelectButton *select_button;
g_return_if_fail (GIMP_IS_FONT_SELECT_BUTTON (self));
g_return_if_fail (GIMP_IS_FONT_SELECT_BUTTON (button));
g_debug ("%s", G_STRFUNC);
select_button = GIMP_SELECT_BUTTON (button);
if (select_button->temp_callback)
{
gimp_fonts_set_popup (select_button->temp_callback, font_name);
}
else
{
gchar *name;
if (font_name && *font_name)
name = g_strdup (font_name);
else
name = gimp_context_get_font ();
gimp_font_select_button_callback (name, FALSE, button);
g_free (name);
}
/* Delegate to super with upcasts */
gimp_resource_select_button_set_resource (GIMP_RESOURCE_SELECT_BUTTON (self), GIMP_RESOURCE (font));
}
@@ -278,181 +238,98 @@ gimp_font_select_button_set_font (GimpFontSelectButton *button,
static void
gimp_font_select_button_finalize (GObject *object)
{
GimpFontSelectButton *button = GIMP_FONT_SELECT_BUTTON (object);
g_debug ("%s called", G_STRFUNC);
g_clear_pointer (&button->priv->font_name, g_free);
g_clear_pointer (&button->priv->title, g_free);
/* Has no allocations.*/
/* Chain up. */
G_OBJECT_CLASS (gimp_font_select_button_parent_class)->finalize (object);
}
static void
gimp_font_select_button_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec)
/* This is NOT an implementation of virtual function.
*
* Create a widget that is the interior of a button.
* Super creates the button, self creates interior.
* Button is-a container and self calls super to add interior to the container.
*
* Special: an hbox containing a general icon for a font and
* a label that is the name of the font family and style.
* FUTURE: label styled in the current font family and style.
*/
static GtkWidget*
gimp_font_select_button_create_interior (GimpFontSelectButton *self)
{
GimpFontSelectButton *button = GIMP_FONT_SELECT_BUTTON (object);
GtkWidget *button;
GtkWidget *hbox;
GtkWidget *image;
GtkWidget *label;
gchar *font_name = "unknown";
switch (property_id)
{
case PROP_TITLE:
button->priv->title = g_value_dup_string (value);
break;
case PROP_FONT_NAME:
gimp_font_select_button_set_font (button,
g_value_get_string (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void
gimp_font_select_button_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec)
{
GimpFontSelectButton *button = GIMP_FONT_SELECT_BUTTON (object);
switch (property_id)
{
case PROP_TITLE:
g_value_set_string (value, button->priv->title);
break;
case PROP_FONT_NAME:
g_value_set_string (value, button->priv->font_name);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void
gimp_font_select_button_callback (const gchar *font_name,
gboolean dialog_closing,
gpointer user_data)
{
GimpFontSelectButton *button = GIMP_FONT_SELECT_BUTTON (user_data);
GimpFontSelectButtonPrivate *priv = button->priv;
GimpSelectButton *select_button = GIMP_SELECT_BUTTON (button);
g_free (priv->font_name);
priv->font_name = g_strdup (font_name);
gtk_label_set_text (GTK_LABEL (priv->label), font_name);
if (dialog_closing)
select_button->temp_callback = NULL;
g_signal_emit (button, font_button_signals[FONT_SET], 0,
font_name, dialog_closing);
g_object_notify_by_pspec (G_OBJECT (button), font_button_props[PROP_FONT_NAME]);
}
static void
gimp_font_select_button_clicked (GimpFontSelectButton *button)
{
GimpSelectButton *select_button = GIMP_SELECT_BUTTON (button);
if (select_button->temp_callback)
{
/* calling gimp_fonts_set_popup() raises the dialog */
gimp_fonts_set_popup (select_button->temp_callback,
button->priv->font_name);
}
else
{
select_button->temp_callback =
gimp_font_select_new (button->priv->title,
button->priv->font_name,
gimp_font_select_button_callback,
button, NULL);
}
}
static void
gimp_font_select_drag_data_received (GimpFontSelectButton *button,
GdkDragContext *context,
gint x,
gint y,
GtkSelectionData *selection,
guint info,
guint time)
{
gint length = gtk_selection_data_get_length (selection);
gchar *str;
if (gtk_selection_data_get_format (selection) != 8 || length < 1)
{
g_warning ("%s: received invalid font data", G_STRFUNC);
return;
}
str = g_strndup ((const gchar *) gtk_selection_data_get_data (selection),
length);
if (g_utf8_validate (str, -1, NULL))
{
gint pid;
gpointer unused;
gint name_offset = 0;
if (sscanf (str, "%i:%p:%n", &pid, &unused, &name_offset) >= 2 &&
pid == gimp_getpid () && name_offset > 0)
{
gchar *name = str + name_offset;
gimp_font_select_button_set_font (button, name);
}
}
g_free (str);
}
static GtkWidget *
gimp_font_select_button_create_inside (GimpFontSelectButton *font_button)
{
GimpFontSelectButtonPrivate *priv = font_button->priv;
GtkWidget *button;
GtkWidget *hbox;
GtkWidget *image;
g_debug ("%s", G_STRFUNC);
/* Outermost is-a button. */
button = gtk_button_new ();
/* inside the button is hbox. */
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 4);
gtk_container_add (GTK_CONTAINER (button), hbox);
/* first item in hbox is an icon. */
image = gtk_image_new_from_icon_name (GIMP_ICON_FONT,
GTK_ICON_SIZE_BUTTON);
gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, FALSE, 0);
priv->label = gtk_label_new (priv->font_name);
gtk_box_pack_start (GTK_BOX (hbox), priv->label, TRUE, TRUE, 4);
/* Second item in hbox is font name.
* The initial text is dummy, a draw will soon refresh it.
* This function does not know the resource/font.
*/
label = gtk_label_new (font_name);
gtk_box_pack_start (GTK_BOX (hbox), label, TRUE, TRUE, 4);
gtk_widget_show_all (button);
/* Ensure sub widgets saved for subsequent use. */
g_signal_connect_swapped (button, "clicked",
G_CALLBACK (gimp_font_select_button_clicked),
font_button);
self->font_name_label = label; /* Save label for redraw. */
self->drag_region_widget = hbox;
self->button = button;
gtk_drag_dest_set (GTK_WIDGET (button),
GTK_DEST_DEFAULT_HIGHLIGHT |
GTK_DEST_DEFAULT_MOTION |
GTK_DEST_DEFAULT_DROP,
&target, 1,
GDK_ACTION_COPY);
g_signal_connect_swapped (button, "drag-data-received",
G_CALLBACK (gimp_font_select_drag_data_received),
font_button);
/* This subclass does not connect to draw signal on interior widget. */
/* Return the whole interior, which is-a button. */
return button;
}
/* Knows how to draw self interior.
* Self knows resource, it is not passed.
*
* Overrides virtual method in super, so it is generic on Resource.
*/
static void
gimp_font_select_button_draw_interior (GimpResourceSelectButton *self)
{
gchar *font_name;
GimpResource *resource;
GimpFontSelectButton *self_as_font_select;
g_debug ("%s", G_STRFUNC);
g_return_if_fail (GIMP_IS_FONT_SELECT_BUTTON (self));
self_as_font_select = GIMP_FONT_SELECT_BUTTON (self);
g_object_get (self, "resource", &resource, NULL);
/* For now, the "id" property of the resource is the name.
* FUTURE: core will support name distinct from ID.
*/
g_object_get (resource, "id", &font_name, NULL);
/* We are not keeping a copy of font name, nothing to free. */
/* Not styling the text using the chosen font,
* just replacing the text with the name of the chosen font.
*/
gtk_label_set_text (GTK_LABEL (self_as_font_select->font_name_label), font_name);
}

View File

@@ -25,61 +25,35 @@
#ifndef __GIMP_FONT_SELECT_BUTTON_H__
#define __GIMP_FONT_SELECT_BUTTON_H__
#include <libgimp/gimpselectbutton.h>
#include <libgimp/gimpresourceselectbutton.h>
G_BEGIN_DECLS
/* For information look into the C source or the html documentation */
/* This defines certain structs and the usual macros.
* A final type has no private.
*/
#define GIMP_TYPE_FONT_SELECT_BUTTON (gimp_font_select_button_get_type ())
G_DECLARE_FINAL_TYPE (GimpFontSelectButton,
gimp_font_select_button,
GIMP, FONT_SELECT_BUTTON,
GimpResourceSelectButton)
#define GIMP_TYPE_FONT_SELECT_BUTTON (gimp_font_select_button_get_type ())
#define GIMP_FONT_SELECT_BUTTON(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_FONT_SELECT_BUTTON, GimpFontSelectButton))
#define GIMP_FONT_SELECT_BUTTON_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_FONT_SELECT_BUTTON, GimpFontSelectButtonClass))
#define GIMP_IS_FONT_SELECT_BUTTON(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_FONT_SELECT_BUTTON))
#define GIMP_IS_FONT_SELECT_BUTTON_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_FONT_SELECT_BUTTON))
#define GIMP_FONT_SELECT_BUTTON_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_FONT_SELECT_BUTTON, GimpFontSelectButtonClass))
typedef struct _GimpFontSelectButtonPrivate GimpFontSelectButtonPrivate;
typedef struct _GimpFontSelectButtonClass GimpFontSelectButtonClass;
struct _GimpFontSelectButton
{
GimpSelectButton parent_instance;
GimpFontSelectButtonPrivate *priv;
};
struct _GimpFontSelectButtonClass
{
GimpSelectButtonClass parent_class;
GimpResourceSelectButtonClass parent_class;
/* font_set signal is emitted when font is chosen */
void (* font_set) (GimpFontSelectButton *button,
const gchar *font_name,
gboolean dialog_closing);
/* Padding for future expansion */
void (*_gimp_reserved1) (void);
void (*_gimp_reserved2) (void);
void (*_gimp_reserved3) (void);
void (*_gimp_reserved4) (void);
void (*_gimp_reserved5) (void);
void (*_gimp_reserved6) (void);
void (*_gimp_reserved7) (void);
void (*_gimp_reserved8) (void);
/* _set signal is not defined. Use resource_set signal from superclass */
};
GType gimp_font_select_button_get_type (void) G_GNUC_CONST;
GtkWidget * gimp_font_select_button_new (const gchar *title,
const gchar *font_name);
const gchar * gimp_font_select_button_get_font (GimpFontSelectButton *button);
void gimp_font_select_button_set_font (GimpFontSelectButton *button,
const gchar *font_name);
GimpResource *resource);
/* FUTURE eliminate. Use superclass method get_resource */
GimpFont * gimp_font_select_button_get_font (GimpFontSelectButton *self);
void gimp_font_select_button_set_font (GimpFontSelectButton *self,
GimpFont *font);
G_END_DECLS

View File

@@ -1,199 +0,0 @@
/* LIBGIMP - The GIMP Library
* Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
*
* gimpgradientselect.c
*
* This library is free software: you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see
* <https://www.gnu.org/licenses/>.
*/
#include "config.h"
#include "gimp.h"
typedef struct
{
gchar *gradient_callback;
guint idle_id;
gchar *gradient_name;
gint width;
gdouble *gradient_data;
GimpRunGradientCallback callback;
gboolean closing;
gpointer data;
GDestroyNotify data_destroy;
} GimpGradientData;
/* local function prototypes */
static void gimp_gradient_data_free (GimpGradientData *data);
static GimpValueArray * gimp_temp_gradient_run (GimpProcedure *procedure,
const GimpValueArray *args,
gpointer run_data);
static gboolean gimp_temp_gradient_idle (GimpGradientData *data);
/* public functions */
const gchar *
gimp_gradient_select_new (const gchar *title,
const gchar *gradient_name,
gint sample_size,
GimpRunGradientCallback callback,
gpointer data,
GDestroyNotify data_destroy)
{
GimpPlugIn *plug_in = gimp_get_plug_in ();
GimpProcedure *procedure;
gchar *gradient_callback;
GimpGradientData *gradient_data;
gradient_callback = gimp_pdb_temp_procedure_name (gimp_get_pdb ());
gradient_data = g_slice_new0 (GimpGradientData);
gradient_data->gradient_callback = gradient_callback;
gradient_data->callback = callback;
gradient_data->data = data;
gradient_data->data_destroy = data_destroy;
procedure = gimp_procedure_new (plug_in,
gradient_callback,
GIMP_PDB_PROC_TYPE_TEMPORARY,
gimp_temp_gradient_run,
gradient_data,
(GDestroyNotify)
gimp_gradient_data_free);
GIMP_PROC_ARG_STRING (procedure, "gradient-name",
"Gradient name",
"The gradient name",
NULL,
G_PARAM_READWRITE);
GIMP_PROC_ARG_INT (procedure, "gradient-width",
"Gradient width",
"The gradient width",
0, G_MAXINT, 0,
G_PARAM_READWRITE);
GIMP_PROC_ARG_FLOAT_ARRAY (procedure, "gradient-data",
"Gradient data",
"The gradient data",
G_PARAM_READWRITE);
GIMP_PROC_ARG_BOOLEAN (procedure, "closing",
"Closing",
"If the dialog was closing",
FALSE,
G_PARAM_READWRITE);
gimp_plug_in_add_temp_procedure (plug_in, procedure);
g_object_unref (procedure);
if (gimp_gradients_popup (gradient_callback, title, gradient_name,
sample_size))
{
/* Allow callbacks to be watched */
gimp_plug_in_extension_enable (plug_in);
return gradient_callback;
}
gimp_plug_in_remove_temp_procedure (plug_in, gradient_callback);
return NULL;
}
void
gimp_gradient_select_destroy (const gchar *gradient_callback)
{
GimpPlugIn *plug_in = gimp_get_plug_in ();
g_return_if_fail (gradient_callback != NULL);
gimp_plug_in_remove_temp_procedure (plug_in, gradient_callback);
}
/* private functions */
static void
gimp_gradient_data_free (GimpGradientData *data)
{
if (data->idle_id)
g_source_remove (data->idle_id);
if (data->gradient_callback)
{
gimp_gradients_close_popup (data->gradient_callback);
g_free (data->gradient_callback);
}
g_free (data->gradient_name);
g_free (data->gradient_data);
if (data->data_destroy)
data->data_destroy (data->data);
g_slice_free (GimpGradientData, data);
}
static GimpValueArray *
gimp_temp_gradient_run (GimpProcedure *procedure,
const GimpValueArray *args,
gpointer run_data)
{
GimpGradientData *data = run_data;
g_free (data->gradient_name);
g_free (data->gradient_data);
data->gradient_name = GIMP_VALUES_DUP_STRING (args, 0);
data->width = GIMP_VALUES_GET_INT (args, 1);
data->gradient_data = GIMP_VALUES_DUP_FLOAT_ARRAY (args, 2);
data->closing = GIMP_VALUES_GET_BOOLEAN (args, 3);
if (! data->idle_id)
data->idle_id = g_idle_add ((GSourceFunc) gimp_temp_gradient_idle, data);
return gimp_procedure_new_return_values (procedure, GIMP_PDB_SUCCESS, NULL);
}
static gboolean
gimp_temp_gradient_idle (GimpGradientData *data)
{
data->idle_id = 0;
if (data->callback)
data->callback (data->gradient_name,
data->width,
data->gradient_data,
data->closing,
data->data);
if (data->closing)
{
gchar *gradient_callback = data->gradient_callback;
data->gradient_callback = NULL;
gimp_gradient_select_destroy (gradient_callback);
g_free (gradient_callback);
}
return G_SOURCE_REMOVE;
}

View File

@@ -1,49 +0,0 @@
/* LIBGIMP - The GIMP Library
* Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
*
* gimpgradientselect.h
*
* This library is free software: you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see
* <https://www.gnu.org/licenses/>.
*/
#if !defined (__GIMP_H_INSIDE__) && !defined (GIMP_COMPILATION)
#error "Only <libgimp/gimp.h> can be included directly."
#endif
#ifndef __GIMP_GRADIENT_SELECT_H__
#define __GIMP_GRADIENT_SELECT_H__
G_BEGIN_DECLS
typedef void (* GimpRunGradientCallback) (const gchar *gradient_name,
gint width,
const gdouble *grad_data,
gboolean dialog_closing,
gpointer user_data);
const gchar * gimp_gradient_select_new (const gchar *title,
const gchar *gradient_name,
gint sample_size,
GimpRunGradientCallback callback,
gpointer data,
GDestroyNotify data_destroy);
void gimp_gradient_select_destroy (const gchar *gradient_callback);
G_END_DECLS
#endif /* __GIMP_GRADIENT_SELECT_H__ */

View File

@@ -30,30 +30,29 @@
/**
* SECTION: gimpgradientselect
* @title: gimpgradientselect
* @short_description: Functions providing a gradient selection dialog.
* @short_description: Methods of a gradient chooser dialog
*
* Functions providing a gradient selection dialog.
* A dialog letting a user choose a gradient. Read more at
* gimpfontselect.
**/
/**
* gimp_gradients_popup:
* @gradient_callback: The callback PDB proc to call when gradient selection is made.
* @gradient_callback: The callback PDB proc to call when user chooses a gradient.
* @popup_title: Title of the gradient selection dialog.
* @initial_gradient: The name of the gradient to set as the first selected.
* @sample_size: Size of the sample to return when the gradient is changed.
* @initial_gradient_name: The name of the initial gradient choice.
*
* Invokes the Gimp gradients selection.
* Invokes the Gimp gradients selection dialog.
*
* This procedure opens the gradient selection dialog.
* Opens a dialog letting a user choose a gradient.
*
* Returns: TRUE on success.
**/
gboolean
gimp_gradients_popup (const gchar *gradient_callback,
const gchar *popup_title,
const gchar *initial_gradient,
gint sample_size)
const gchar *initial_gradient_name)
{
GimpValueArray *args;
GimpValueArray *return_vals;
@@ -62,8 +61,7 @@ gimp_gradients_popup (const gchar *gradient_callback,
args = gimp_value_array_new_from_types (NULL,
G_TYPE_STRING, gradient_callback,
G_TYPE_STRING, popup_title,
G_TYPE_STRING, initial_gradient,
G_TYPE_INT, sample_size,
G_TYPE_STRING, initial_gradient_name,
G_TYPE_NONE);
return_vals = gimp_pdb_run_procedure_array (gimp_get_pdb (),
@@ -84,7 +82,7 @@ gimp_gradients_popup (const gchar *gradient_callback,
*
* Close the gradient selection dialog.
*
* This procedure closes an opened gradient selection dialog.
* Closes an open gradient selection dialog.
*
* Returns: TRUE on success.
**/

View File

@@ -34,8 +34,7 @@ G_BEGIN_DECLS
gboolean gimp_gradients_popup (const gchar *gradient_callback,
const gchar *popup_title,
const gchar *initial_gradient,
gint sample_size);
const gchar *initial_gradient_name);
gboolean gimp_gradients_close_popup (const gchar *gradient_callback);
gboolean gimp_gradients_set_popup (const gchar *gradient_callback,
const gchar *gradient_name);

View File

@@ -44,271 +44,157 @@
**/
#define CELL_HEIGHT 18
#define CELL_WIDTH 84
enum
struct _GimpGradientSelectButton
{
GRADIENT_SET,
LAST_SIGNAL
/* !! Not a pointer, is contained. */
GimpResourceSelectButton parent_instance;
GtkWidget *button;
GtkWidget *drag_region_widget;
GtkWidget *preview; /* needed by draw. */
};
enum
{
PROP_0,
PROP_TITLE,
PROP_GRADIENT_NAME,
N_PROPS
};
struct _GimpGradientSelectButtonPrivate
{
gchar *title;
gchar *gradient_name; /* Local copy */
gint sample_size;
gboolean reverse;
gint n_samples;
gdouble *gradient_data; /* Local copy */
GtkWidget *inside;
GtkWidget *preview;
};
/* local function prototypes */
static void gimp_gradient_select_button_finalize (GObject *object);
static void gimp_gradient_select_button_finalize (GObject *object);
static void gimp_gradient_select_button_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec);
static void gimp_gradient_select_button_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec);
static void gimp_gradient_select_button_embed_interior (GimpGradientSelectButton *self);
static void gimp_gradient_select_button_draw_interior (GimpResourceSelectButton *self);
static void gimp_gradient_select_button_set_drag_target (GimpGradientSelectButton *self);
static void gimp_gradient_select_button_clicked (GimpGradientSelectButton *button);
static void gimp_gradient_select_button_callback (const gchar *gradient_name,
gint n_samples,
const gdouble *gradient_data,
gboolean dialog_closing,
gpointer user_data);
static void gimp_gradient_select_preview_size_allocate
(GtkWidget *widget,
GtkAllocation *allocation,
GimpGradientSelectButton *button);
static gboolean gimp_gradient_select_preview_draw (GtkWidget *preview,
cairo_t *cr,
GimpGradientSelectButton *button);
static void gimp_gradient_select_drag_data_received (GimpGradientSelectButton *button,
GdkDragContext *context,
gint x,
gint y,
GtkSelectionData *selection,
guint info,
guint time);
static GtkWidget * gimp_gradient_select_button_create_inside (GimpGradientSelectButton *button);
static void gimp_gradient_select_preview_size_allocate (GtkWidget *widget,
GtkAllocation *allocation,
GimpGradientSelectButton *self);
static gboolean gimp_gradient_select_preview_draw_handler (GtkWidget *preview,
cairo_t *cr,
GimpGradientSelectButton *self);
static const GtkTargetEntry target = { "application/x-gimp-gradient-name", 0 };
static const GtkTargetEntry drag_target = { "application/x-gimp-gradient-name", 0 };
static guint gradient_button_signals[LAST_SIGNAL] = { 0 };
static GParamSpec *gradient_button_props[N_PROPS] = { NULL, };
G_DEFINE_TYPE_WITH_PRIVATE (GimpGradientSelectButton,
gimp_gradient_select_button,
GIMP_TYPE_SELECT_BUTTON)
G_DEFINE_FINAL_TYPE (GimpGradientSelectButton,
gimp_gradient_select_button,
GIMP_TYPE_RESOURCE_SELECT_BUTTON)
/* Initial dimensions of widget. */
#define CELL_HEIGHT 18
#define CELL_WIDTH 84
static void
gimp_gradient_select_button_class_init (GimpGradientSelectButtonClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GimpSelectButtonClass *select_button_class = GIMP_SELECT_BUTTON_CLASS (klass);
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GimpResourceSelectButtonClass *superclass = GIMP_RESOURCE_SELECT_BUTTON_CLASS (klass);
g_debug ("%s", G_STRFUNC);
object_class->finalize = gimp_gradient_select_button_finalize;
object_class->set_property = gimp_gradient_select_button_set_property;
object_class->get_property = gimp_gradient_select_button_get_property;
select_button_class->select_destroy = gimp_gradient_select_destroy;
/* Implement pure virtual functions. */
superclass->draw_interior = gimp_gradient_select_button_draw_interior;
klass->gradient_set = NULL;
/**
* GimpGradientSelectButton:title:
*
* The title to be used for the gradient selection popup dialog.
*
* Since: 2.4
*/
gradient_button_props[PROP_TITLE] = g_param_spec_string ("title",
"Title",
"The title to be used for the gradient selection popup dialog",
_("Gradient Selection"),
GIMP_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY);
/**
* GimpGradientSelectButton:gradient-name:
*
* The name of the currently selected gradient.
*
* Since: 2.4
*/
gradient_button_props[PROP_GRADIENT_NAME] = g_param_spec_string ("gradient-name",
"Gradient name",
"The name of the currently selected gradient",
NULL,
GIMP_PARAM_READWRITE);
g_object_class_install_properties (object_class, N_PROPS, gradient_button_props);
/**
* GimpGradientSelectButton::gradient-set:
* @widget: the object which received the signal.
* @gradient_name: the name of the currently selected gradient.
* @width: width of the gradient
* @grad_data: gradient data
* @dialog_closing: whether the dialog was closed or not.
*
* The ::gradient-set signal is emitted when the user selects a gradient.
*
* Since: 2.4
*/
gradient_button_signals[GRADIENT_SET] =
g_signal_new ("gradient-set",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (GimpGradientSelectButtonClass, gradient_set),
NULL, NULL,
_gimpui_marshal_VOID__STRING_INT_POINTER_BOOLEAN,
G_TYPE_NONE, 4,
G_TYPE_STRING,
G_TYPE_INT,
G_TYPE_POINTER,
G_TYPE_BOOLEAN);
/* Set data member of class. */
superclass->resource_type = GIMP_TYPE_GRADIENT;
}
static void
gimp_gradient_select_button_init (GimpGradientSelectButton *button)
gimp_gradient_select_button_init (GimpGradientSelectButton *self)
{
button->priv = gimp_gradient_select_button_get_instance_private (button);
g_debug ("%s", G_STRFUNC);
button->priv->gradient_name = gimp_context_get_gradient ();
button->priv->sample_size = CELL_WIDTH;
button->priv->reverse = FALSE;
gimp_gradient_select_button_embed_interior (self);
button->priv->inside = gimp_gradient_select_button_create_inside (button);
gtk_container_add (GTK_CONTAINER (button), button->priv->inside);
gimp_gradient_select_button_set_drag_target (self);
gimp_resource_select_button_set_clickable (GIMP_RESOURCE_SELECT_BUTTON (self),
self->button);
}
/**
* gimp_gradient_select_button_new:
* @title: (nullable): Title of the dialog to use or %NULL to use the default title.
* @gradient_name: (nullable): Initial gradient name.
* @gradient: (nullable): Initial gradient.
*
* Creates a new #GtkWidget that completely controls the selection of
* a gradient. This widget is suitable for placement in a table in a
* plug-in dialog.
* Creates a new #GtkWidget that lets a user choose a gradient.
* You can use this widget in a table in a plug-in dialog.
*
* Returns: A #GtkWidget that you can use in your UI.
*
* Since: 2.4
*/
GtkWidget *
gimp_gradient_select_button_new (const gchar *title,
const gchar *gradient_name)
gimp_gradient_select_button_new (const gchar *title,
GimpResource *gradient)
{
GtkWidget *button;
GtkWidget *self;
if (gradient == NULL)
{
g_debug ("%s defaulting gradient from context", G_STRFUNC);
gradient = GIMP_RESOURCE (gimp_context_get_gradient ());
}
g_assert (gradient != NULL);
/* This method is polymorphic, so a factory can call it, but requires gradient. */
g_return_val_if_fail (GIMP_IS_GRADIENT (gradient), NULL);
g_debug ("%s", G_STRFUNC);
if (title)
button = g_object_new (GIMP_TYPE_GRADIENT_SELECT_BUTTON,
"title", title,
"gradient-name", gradient_name,
NULL);
self = g_object_new (GIMP_TYPE_GRADIENT_SELECT_BUTTON,
"title", title,
"resource", gradient,
NULL);
else
button = g_object_new (GIMP_TYPE_GRADIENT_SELECT_BUTTON,
"gradient-name", gradient_name,
NULL);
self = g_object_new (GIMP_TYPE_GRADIENT_SELECT_BUTTON,
"resource", gradient,
NULL);
return button;
gimp_gradient_select_button_draw_interior (GIMP_RESOURCE_SELECT_BUTTON (self));
return self;
}
/**
* gimp_gradient_select_button_get_gradient:
* @button: A #GimpGradientSelectButton
* @self: A #GimpGradientSelectButton
*
* Retrieves the name of currently selected gradient.
* Gets the currently selected gradient.
*
* Returns: an internal copy of the gradient name which must not be freed.
* Returns: (transfer none): an internal copy of the gradient, which you must not free.
*
* Since: 2.4
*/
const gchar *
gimp_gradient_select_button_get_gradient (GimpGradientSelectButton *button)
GimpGradient *
gimp_gradient_select_button_get_gradient (GimpGradientSelectButton *self)
{
g_return_val_if_fail (GIMP_IS_GRADIENT_SELECT_BUTTON (button), NULL);
g_debug ("%s", G_STRFUNC);
return button->priv->gradient_name;
g_return_val_if_fail (GIMP_IS_GRADIENT_SELECT_BUTTON (self), NULL);
/* Delegate to super w upcast arg and downcast result. */
return (GimpGradient *) gimp_resource_select_button_get_resource ((GimpResourceSelectButton*) self);
}
/**
* gimp_gradient_select_button_set_gradient:
* @button: A #GimpGradientSelectButton
* @gradient_name: (nullable): Gradient name to set.
* @self: A #GimpGradientSelectButton
* @gradient: (nullable): Gradient to set.
*
* Sets the current gradient for the gradient select button.
*
* Since: 2.4
*/
void
gimp_gradient_select_button_set_gradient (GimpGradientSelectButton *button,
const gchar *gradient_name)
gimp_gradient_select_button_set_gradient (GimpGradientSelectButton *self,
GimpGradient *gradient)
{
GimpSelectButton *select_button;
g_return_if_fail (GIMP_IS_GRADIENT_SELECT_BUTTON (self));
g_return_if_fail (GIMP_IS_GRADIENT_SELECT_BUTTON (button));
g_debug ("%s", G_STRFUNC);
select_button = GIMP_SELECT_BUTTON (button);
if (select_button->temp_callback)
{
gimp_gradients_set_popup (select_button->temp_callback, gradient_name);
}
else
{
gchar *name;
gdouble *samples;
gint n_samples;
if (gradient_name && *gradient_name)
name = g_strdup (gradient_name);
else
name = gimp_context_get_gradient ();
if (gimp_gradient_get_uniform_samples (name,
button->priv->sample_size,
button->priv->reverse,
&n_samples,
&samples))
{
gimp_gradient_select_button_callback (name,
n_samples, samples,
FALSE, button);
g_free (samples);
}
g_free (name);
}
/* Delegate to super with upcasts */
gimp_resource_select_button_set_resource (GIMP_RESOURCE_SELECT_BUTTON (self), GIMP_RESOURCE (gradient));
}
@@ -317,167 +203,117 @@ gimp_gradient_select_button_set_gradient (GimpGradientSelectButton *button,
static void
gimp_gradient_select_button_finalize (GObject *object)
{
GimpGradientSelectButton *button = GIMP_GRADIENT_SELECT_BUTTON (object);
g_debug ("%s", G_STRFUNC);
g_clear_pointer (&button->priv->gradient_name, g_free);
g_clear_pointer (&button->priv->gradient_data, g_free);
g_clear_pointer (&button->priv->title, g_free);
/* Nothing was allocated. */
G_OBJECT_CLASS (gimp_gradient_select_button_parent_class)->finalize (object);
}
static void
gimp_gradient_select_button_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec)
gimp_gradient_select_button_draw_interior (GimpResourceSelectButton *self)
{
GimpGradientSelectButton *button = GIMP_GRADIENT_SELECT_BUTTON (object);
GimpGradientSelectButton *self_as_gradient_select;
switch (property_id)
{
case PROP_TITLE:
button->priv->title = g_value_dup_string (value);
break;
g_debug ("%s", G_STRFUNC);
case PROP_GRADIENT_NAME:
gimp_gradient_select_button_set_gradient (button,
g_value_get_string (value));
break;
g_return_if_fail (GIMP_IS_GRADIENT_SELECT_BUTTON (self));
self_as_gradient_select = GIMP_GRADIENT_SELECT_BUTTON (self);
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
/* Not actually draw, just queue. Continuation is the handler. */
gtk_widget_queue_draw (self_as_gradient_select->preview);
}
static void
gimp_gradient_select_button_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec)
{
GimpGradientSelectButton *button = GIMP_GRADIENT_SELECT_BUTTON (object);
switch (property_id)
{
case PROP_TITLE:
g_value_set_string (value, button->priv->title);
break;
case PROP_GRADIENT_NAME:
g_value_set_string (value, button->priv->gradient_name);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void
gimp_gradient_select_button_callback (const gchar *gradient_name,
gint n_samples,
const gdouble *gradient_data,
gboolean dialog_closing,
gpointer user_data)
{
GimpGradientSelectButton *button = user_data;
GimpSelectButton *select_button = GIMP_SELECT_BUTTON (button);
g_free (button->priv->gradient_name);
g_free (button->priv->gradient_data);
button->priv->gradient_name = g_strdup (gradient_name);
button->priv->n_samples = n_samples;
button->priv->gradient_data = g_memdup2 (gradient_data,
n_samples * sizeof (gdouble));
gtk_widget_queue_draw (button->priv->preview);
if (dialog_closing)
select_button->temp_callback = NULL;
g_signal_emit (button, gradient_button_signals[GRADIENT_SET], 0,
gradient_name, n_samples, gradient_data, dialog_closing);
g_object_notify_by_pspec (G_OBJECT (button), gradient_button_props[PROP_GRADIENT_NAME]);
}
static void
gimp_gradient_select_button_clicked (GimpGradientSelectButton *button)
{
GimpSelectButton *select_button = GIMP_SELECT_BUTTON (button);
if (select_button->temp_callback)
{
/* calling gimp_gradients_set_popup() raises the dialog */
gimp_gradients_set_popup (select_button->temp_callback,
button->priv->gradient_name);
}
else
{
select_button->temp_callback =
gimp_gradient_select_new (button->priv->title,
button->priv->gradient_name,
button->priv->sample_size,
gimp_gradient_select_button_callback,
button, NULL);
}
}
static void
gimp_gradient_select_preview_size_allocate (GtkWidget *widget,
GtkAllocation *allocation,
GimpGradientSelectButton *button)
/* Get array of samples from self's gradient.
* Return array and size at given handles.
* Return success.
*/
static gboolean
get_gradient_data (GimpGradientSelectButton *self,
gint allocation_width,
gint *sample_count,
gdouble **sample_array
)
{
gboolean result;
gdouble *samples;
gint n_samples;
if (gimp_gradient_get_uniform_samples (button->priv->gradient_name,
allocation->width,
button->priv->reverse,
&n_samples,
&samples))
{
g_free (button->priv->gradient_data);
GimpGradient *gradient;
button->priv->sample_size = allocation->width;
button->priv->n_samples = n_samples;
button->priv->gradient_data = samples;
g_debug ("%s", G_STRFUNC);
/* Self's gradient is property "resource"
* (resource field of super is private.)
*/
g_object_get (self, "resource", &gradient, NULL);
g_return_val_if_fail (GIMP_IS_GRADIENT (gradient), FALSE);
result = gimp_gradient_get_uniform_samples (
gradient,
allocation_width,
FALSE, /* not reversed. */
&n_samples,
&samples);
if (result)
{
/* Return array of samples to dereferenced handles. */
*sample_array = samples;
*sample_count = n_samples;
}
/* When result is true, caller must free the array. */
return result;
}
static gboolean
gimp_gradient_select_preview_draw (GtkWidget *widget,
cairo_t *cr,
GimpGradientSelectButton *button)
/* Called on widget resized. */
static void
gimp_gradient_select_preview_size_allocate (GtkWidget *widget,
GtkAllocation *allocation,
GimpGradientSelectButton *self)
{
g_debug ("%s", G_STRFUNC);
/* Do nothing.
*
* In former code, we cached the gradient data in self, on allocate event.
* But allocate event always seems to be paired with a draw event,
* so there is no point in caching the gradient data.
* And caching gradient data is a premature optimization,
* without deep knowledge of Gtk and actual performance testing,
* you can't know caching helps performance.
*/
}
/* Draw array of samples.
* This understands mostly cairo, and little about gradient.
*/
static void
gimp_gradient_select_preview_draw (
cairo_t *cr,
gint src_width,
gint dest_width,
gdouble *src)
{
GtkAllocation allocation;
cairo_pattern_t *pattern;
cairo_surface_t *surface;
const gdouble *src;
guchar *dest;
gint width;
gint x;
src = button->priv->gradient_data;
if (! src)
return FALSE;
gtk_widget_get_allocation (widget, &allocation);
pattern = gimp_cairo_checkerboard_create (cr, GIMP_CHECK_SIZE_SM, NULL, NULL);
cairo_set_source (cr, pattern);
cairo_pattern_destroy (pattern);
cairo_paint (cr);
width = button->priv->n_samples / 4;
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, 1);
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, src_width, 1);
for (x = 0, dest = cairo_image_surface_get_data (surface);
x < width;
x < src_width;
x++, src += 4, dest += 4)
{
GimpRGB color;
@@ -486,7 +322,7 @@ gimp_gradient_select_preview_draw (GtkWidget *widget,
gimp_rgba_set (&color, src[0], src[1], src[2], src[3]);
gimp_rgba_get_uchar (&color, &r, &g, &b, &a);
GIMP_CAIRO_ARGB32_SET_PIXEL(dest, r, g, b, a);
GIMP_CAIRO_ARGB32_SET_PIXEL (dest, r, g, b, a);
}
cairo_surface_mark_dirty (surface);
@@ -495,91 +331,94 @@ gimp_gradient_select_preview_draw (GtkWidget *widget,
cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REFLECT);
cairo_surface_destroy (surface);
cairo_scale (cr, (gdouble) allocation.width / (gdouble) width, 1.0);
cairo_scale (cr, (gdouble) dest_width / (gdouble) src_width, 1.0);
cairo_set_source (cr, pattern);
cairo_pattern_destroy (pattern);
cairo_paint (cr);
}
/* Handles a draw signal.
* Draw self, i.e. interior of button.
*
* Always returns FALSE, but doesn't draw when fail to get gradient data.
*
* Is passed neither gradient nor attributes of gradient: get them now from self.
*/
static gboolean
gimp_gradient_select_preview_draw_handler (
GtkWidget *widget,
cairo_t *cr,
GimpGradientSelectButton *self)
{
GtkAllocation allocation;
/* Attributes of the source.*/
gdouble *src;
gint n_samples;
gint src_width;
g_debug ("%s", G_STRFUNC);
gtk_widget_get_allocation (widget, &allocation);
if (!get_gradient_data (self, allocation.width, &n_samples, &src))
return FALSE;
/* Width in pixels of src, since BPP is 4. */
src_width = n_samples / 4;
gimp_gradient_select_preview_draw (cr, src_width, allocation.width, src);
g_free (src);
return FALSE;
}
static void
gimp_gradient_select_drag_data_received (GimpGradientSelectButton *button,
GdkDragContext *context,
gint x,
gint y,
GtkSelectionData *selection,
guint info,
guint time)
gimp_gradient_select_button_embed_interior (GimpGradientSelectButton *self)
{
gint length = gtk_selection_data_get_length (selection);
gchar *str;
GtkWidget *button;
GtkWidget *preview;
if (gtk_selection_data_get_format (selection) != 8 || length < 1)
{
g_warning ("%s: received invalid gradient data", G_STRFUNC);
return;
}
str = g_strndup ((const gchar *) gtk_selection_data_get_data (selection),
length);
if (g_utf8_validate (str, -1, NULL))
{
gint pid;
gpointer unused;
gint name_offset = 0;
if (sscanf (str, "%i:%p:%n", &pid, &unused, &name_offset) >= 2 &&
pid == gimp_getpid () && name_offset > 0)
{
gchar *name = str + name_offset;
gimp_gradient_select_button_set_gradient (button, name);
}
}
g_free (str);
}
static GtkWidget *
gimp_gradient_select_button_create_inside (GimpGradientSelectButton *gradient_button)
{
GimpGradientSelectButtonPrivate *priv = gradient_button->priv;
GtkWidget *button;
g_debug ("%s", G_STRFUNC);
/* Outermost is button. */
button = gtk_button_new ();
priv->preview = gtk_drawing_area_new ();
gtk_widget_set_size_request (priv->preview, CELL_WIDTH, CELL_HEIGHT);
gtk_container_add (GTK_CONTAINER (button), priv->preview);
/* Entire interior of button is a preview image. */
preview = gtk_drawing_area_new ();
gtk_widget_set_size_request (preview, CELL_WIDTH, CELL_HEIGHT);
gtk_container_add (GTK_CONTAINER (button), preview);
g_signal_connect (priv->preview, "size-allocate",
g_signal_connect (preview, "size-allocate",
G_CALLBACK (gimp_gradient_select_preview_size_allocate),
gradient_button);
self);
g_signal_connect (priv->preview, "draw",
G_CALLBACK (gimp_gradient_select_preview_draw),
gradient_button);
g_signal_connect (preview, "draw",
G_CALLBACK (gimp_gradient_select_preview_draw_handler),
self);
gtk_widget_show_all (button);
g_signal_connect_swapped (button, "clicked",
G_CALLBACK (gimp_gradient_select_button_clicked),
gradient_button);
/* Remember widgets needed later. */
self->drag_region_widget = preview;
self->button = button;
self->preview = preview;
gtk_drag_dest_set (GTK_WIDGET (button),
GTK_DEST_DEFAULT_HIGHLIGHT |
GTK_DEST_DEFAULT_MOTION |
GTK_DEST_DEFAULT_DROP,
&target, 1,
GDK_ACTION_COPY);
g_signal_connect_swapped (button, "drag-data-received",
G_CALLBACK (gimp_gradient_select_drag_data_received),
gradient_button);
return button;
/* Call super with upcasts. */
gimp_resource_select_button_embed_interior (GIMP_RESOURCE_SELECT_BUTTON (self), button);
}
static void
gimp_gradient_select_button_set_drag_target (GimpGradientSelectButton *self)
{
/* Self knows the GtkTargetEntry, super knows how to create target and receive drag. */
gimp_resource_select_button_set_drag_target (GIMP_RESOURCE_SELECT_BUTTON (self),
self->drag_region_widget,
&drag_target);
}

View File

@@ -25,62 +25,28 @@
#ifndef __GIMP_GRADIENT_SELECT_BUTTON_H__
#define __GIMP_GRADIENT_SELECT_BUTTON_H__
#include <libgimp/gimpselectbutton.h>
#include <libgimp/gimpresourceselectbutton.h>
G_BEGIN_DECLS
/* For information look into the C source or the html documentation */
#define GIMP_TYPE_GRADIENT_SELECT_BUTTON (gimp_gradient_select_button_get_type ())
#define GIMP_GRADIENT_SELECT_BUTTON(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_GRADIENT_SELECT_BUTTON, GimpGradientSelectButton))
#define GIMP_GRADIENT_SELECT_BUTTON_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_GRADIENT_SELECT_BUTTON, GimpGradientSelectButtonClass))
#define GIMP_IS_GRADIENT_SELECT_BUTTON(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_GRADIENT_SELECT_BUTTON))
#define GIMP_IS_GRADIENT_SELECT_BUTTON_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_GRADIENT_SELECT_BUTTON))
#define GIMP_GRADIENT_SELECT_BUTTON_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_GRADIENT_SELECT_BUTTON, GimpGradientSelectButtonClass))
typedef struct _GimpGradientSelectButtonPrivate GimpGradientSelectButtonPrivate;
typedef struct _GimpGradientSelectButtonClass GimpGradientSelectButtonClass;
struct _GimpGradientSelectButton
{
GimpSelectButton parent_instance;
GimpGradientSelectButtonPrivate *priv;
};
#define GIMP_TYPE_GRADIENT_SELECT_BUTTON (gimp_gradient_select_button_get_type ())
G_DECLARE_FINAL_TYPE (GimpGradientSelectButton,
gimp_gradient_select_button,
GIMP,
GRADIENT_SELECT_BUTTON,
GimpResourceSelectButton)
struct _GimpGradientSelectButtonClass
{
GimpSelectButtonClass parent_class;
/* gradient_set signal is emitted when gradient is chosen */
void (* gradient_set) (GimpGradientSelectButton *button,
const gchar *gradient_name,
gint width,
const gdouble *gradient_data,
gboolean dialog_closing);
/* Padding for future expansion */
void (*_gimp_reserved1) (void);
void (*_gimp_reserved2) (void);
void (*_gimp_reserved3) (void);
void (*_gimp_reserved4) (void);
void (*_gimp_reserved5) (void);
void (*_gimp_reserved6) (void);
void (*_gimp_reserved7) (void);
void (*_gimp_reserved8) (void);
GimpResourceSelectButtonClass parent_class;
};
GtkWidget * gimp_gradient_select_button_new (const gchar *title,
GimpResource *gradient);
GType gimp_gradient_select_button_get_type (void) G_GNUC_CONST;
GtkWidget * gimp_gradient_select_button_new (const gchar *title,
const gchar *gradient_name);
const gchar * gimp_gradient_select_button_get_gradient (GimpGradientSelectButton *button);
void gimp_gradient_select_button_set_gradient (GimpGradientSelectButton *button,
const gchar *gradient_name);
GimpGradient *gimp_gradient_select_button_get_gradient (GimpGradientSelectButton *self);
void gimp_gradient_select_button_set_gradient (GimpGradientSelectButton *self,
GimpGradient *gradient);
G_END_DECLS

View File

@@ -1,187 +0,0 @@
/* LIBGIMP - The GIMP Library
* Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
*
* gimppaletteselect.c
*
* This library is free software: you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see
* <https://www.gnu.org/licenses/>.
*/
#include "config.h"
#include "gimp.h"
typedef struct
{
gchar *palette_callback;
guint idle_id;
gchar *palette_name;
gint num_colors;
GimpRunPaletteCallback callback;
gboolean closing;
gpointer data;
GDestroyNotify data_destroy;
} GimpPaletteData;
/* local function prototypes */
static void gimp_palette_data_free (GimpPaletteData *data);
static GimpValueArray * gimp_temp_palette_run (GimpProcedure *procedure,
const GimpValueArray *args,
gpointer run_data);
static gboolean gimp_temp_palette_idle (GimpPaletteData *data);
/* public functions */
const gchar *
gimp_palette_select_new (const gchar *title,
const gchar *palette_name,
GimpRunPaletteCallback callback,
gpointer data,
GDestroyNotify data_destroy)
{
GimpPlugIn *plug_in = gimp_get_plug_in ();
GimpProcedure *procedure;
gchar *palette_callback;
GimpPaletteData *palette_data;
palette_callback = gimp_pdb_temp_procedure_name (gimp_get_pdb ());
palette_data = g_slice_new0 (GimpPaletteData);
palette_data->palette_callback = palette_callback;
palette_data->callback = callback;
palette_data->data = data;
palette_data->data_destroy = data_destroy;
procedure = gimp_procedure_new (plug_in,
palette_callback,
GIMP_PDB_PROC_TYPE_TEMPORARY,
gimp_temp_palette_run,
palette_data,
(GDestroyNotify)
gimp_palette_data_free);
GIMP_PROC_ARG_STRING (procedure, "palette-name",
"Palette name",
"The palette name",
NULL,
G_PARAM_READWRITE);
GIMP_PROC_ARG_INT (procedure, "num-colors",
"Num colors",
"Number of colors",
0, G_MAXINT, 0,
G_PARAM_READWRITE);
GIMP_PROC_ARG_BOOLEAN (procedure, "closing",
"Closing",
"If the dialog was closing",
FALSE,
G_PARAM_READWRITE);
gimp_plug_in_add_temp_procedure (plug_in, procedure);
g_object_unref (procedure);
if (gimp_palettes_popup (palette_callback, title, palette_name))
{
/* Allow callbacks to be watched */
gimp_plug_in_extension_enable (plug_in);
return palette_callback;
}
gimp_plug_in_remove_temp_procedure (plug_in, palette_callback);
return NULL;
}
void
gimp_palette_select_destroy (const gchar *palette_callback)
{
GimpPlugIn *plug_in = gimp_get_plug_in ();
g_return_if_fail (palette_callback != NULL);
gimp_plug_in_remove_temp_procedure (plug_in, palette_callback);
}
/* private functions */
static void
gimp_palette_data_free (GimpPaletteData *data)
{
if (data->idle_id)
g_source_remove (data->idle_id);
if (data->palette_callback)
{
gimp_palettes_close_popup (data->palette_callback);
g_free (data->palette_callback);
}
g_free (data->palette_name);
if (data->data_destroy)
data->data_destroy (data->data);
g_slice_free (GimpPaletteData, data);
}
static GimpValueArray *
gimp_temp_palette_run (GimpProcedure *procedure,
const GimpValueArray *args,
gpointer run_data)
{
GimpPaletteData *data = run_data;
g_free (data->palette_name);
data->palette_name = GIMP_VALUES_DUP_STRING (args, 0);
data->num_colors = GIMP_VALUES_GET_INT (args, 1);
data->closing = GIMP_VALUES_GET_BOOLEAN (args, 2);
if (! data->idle_id)
data->idle_id = g_idle_add ((GSourceFunc) gimp_temp_palette_idle,
data);
return gimp_procedure_new_return_values (procedure, GIMP_PDB_SUCCESS, NULL);
}
static gboolean
gimp_temp_palette_idle (GimpPaletteData *data)
{
data->idle_id = 0;
if (data->callback)
data->callback (data->palette_name,
data->closing,
data->data);
if (data->closing)
{
gchar *palette_callback = data->palette_callback;
data->palette_callback = NULL;
gimp_palette_select_destroy (palette_callback);
g_free (palette_callback);
}
return G_SOURCE_REMOVE;
}

View File

@@ -1,46 +0,0 @@
/* LIBGIMP - The GIMP Library
* Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
*
* gimppaletteselect.h
*
* This library is free software: you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see
* <https://www.gnu.org/licenses/>.
*/
#if !defined (__GIMP_H_INSIDE__) && !defined (GIMP_COMPILATION)
#error "Only <libgimp/gimp.h> can be included directly."
#endif
#ifndef __GIMP_PALETTE_SELECT_H__
#define __GIMP_PALETTE_SELECT_H__
G_BEGIN_DECLS
typedef void (* GimpRunPaletteCallback) (const gchar *palette_name,
gboolean dialog_closing,
gpointer user_data);
const gchar * gimp_palette_select_new (const gchar *title,
const gchar *palette_name,
GimpRunPaletteCallback callback,
gpointer data,
GDestroyNotify data_destroy);
void gimp_palette_select_destroy (const gchar *palette_callback);
G_END_DECLS
#endif /* __GIMP_PALETTE_SELECT_H__ */

View File

@@ -30,28 +30,29 @@
/**
* SECTION: gimppaletteselect
* @title: gimppaletteselect
* @short_description: Functions providing a palette selection dialog.
* @short_description: Methods of a palette chooser dialog
*
* Functions providing a palette selection dialog.
* A dialog letting a user choose a palette. Read more at
* gimpfontselect.
**/
/**
* gimp_palettes_popup:
* @palette_callback: The callback PDB proc to call when palette selection is made.
* @palette_callback: The callback PDB proc to call when user chooses a palette.
* @popup_title: Title of the palette selection dialog.
* @initial_palette: The name of the palette to set as the first selected.
* @initial_palette_name: The palette to set as the initial choice.
*
* Invokes the Gimp palette selection.
* Invokes the Gimp palette selection dialog.
*
* This procedure opens the palette selection dialog.
* Opens a dialog letting a user choose a palette.
*
* Returns: TRUE on success.
**/
gboolean
gimp_palettes_popup (const gchar *palette_callback,
const gchar *popup_title,
const gchar *initial_palette)
const gchar *initial_palette_name)
{
GimpValueArray *args;
GimpValueArray *return_vals;
@@ -60,7 +61,7 @@ gimp_palettes_popup (const gchar *palette_callback,
args = gimp_value_array_new_from_types (NULL,
G_TYPE_STRING, palette_callback,
G_TYPE_STRING, popup_title,
G_TYPE_STRING, initial_palette,
G_TYPE_STRING, initial_palette_name,
G_TYPE_NONE);
return_vals = gimp_pdb_run_procedure_array (gimp_get_pdb (),
@@ -81,7 +82,7 @@ gimp_palettes_popup (const gchar *palette_callback,
*
* Close the palette selection dialog.
*
* This procedure closes an opened palette selection dialog.
* Closes an open palette selection dialog.
*
* Returns: TRUE on success.
**/

View File

@@ -34,7 +34,7 @@ G_BEGIN_DECLS
gboolean gimp_palettes_popup (const gchar *palette_callback,
const gchar *popup_title,
const gchar *initial_palette);
const gchar *initial_palette_name);
gboolean gimp_palettes_close_popup (const gchar *palette_callback);
gboolean gimp_palettes_set_popup (const gchar *palette_callback,
const gchar *palette_name);

View File

@@ -19,6 +19,8 @@
* <https://www.gnu.org/licenses/>.
*/
/* Similar to gimpfontselectbutton.c, initially created by simple substitution. */
#include "config.h"
#include <gegl.h>
@@ -37,241 +39,199 @@
/**
* SECTION: gimppaletteselectbutton
* @title: GimpPaletteSelect
* @short_description: A button which pops up a palette select dialog.
* @title: GimpPaletteSelectButton
* @short_description: A button which pops up a palette selection dialog.
*
* A button which pops up a palette select dialog.
* A button which pops up a palette selection dialog.
**/
struct _GimpPaletteSelectButtonPrivate
struct _GimpPaletteSelectButton
{
gchar *title;
/* !! Not a pointer, is contained. */
GimpResourceSelectButton parent_instance;
gchar *palette_name; /* Local copy */
GtkWidget *inside;
GtkWidget *label;
GtkWidget *palette_name_label;
GtkWidget *drag_region_widget;
GtkWidget *button;
};
enum
{
PALETTE_SET,
LAST_SIGNAL
};
/* local */
enum
{
PROP_0,
PROP_TITLE,
PROP_PALETTE_NAME,
N_PROPS
};
/* implement virtual */
static void gimp_palette_select_button_finalize (GObject *object);
static void gimp_palette_select_button_draw_interior (GimpResourceSelectButton *self);
/* Called at init. */
static GtkWidget *gimp_palette_select_button_create_interior (GimpPaletteSelectButton *self);
/* local function prototypes */
/* A GtkTargetEntry has a string and two ints. This is one, but treat as an array.*/
static const GtkTargetEntry drag_target = { "application/x-gimp-palette-name", 0, 0 };
static void gimp_palette_select_button_finalize (GObject *object);
static void gimp_palette_select_button_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec);
static void gimp_palette_select_button_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec);
static void gimp_palette_select_button_clicked (GimpPaletteSelectButton *button);
static void gimp_palette_select_button_callback (const gchar *palette_name,
gboolean dialog_closing,
gpointer user_data);
static void gimp_palette_select_drag_data_received (GimpPaletteSelectButton *button,
GdkDragContext *context,
gint x,
gint y,
GtkSelectionData *selection,
guint info,
guint time);
static GtkWidget * gimp_palette_select_button_create_inside (GimpPaletteSelectButton *palette_button);
static const GtkTargetEntry target = { "application/x-gimp-palette-name", 0 };
static guint palette_button_signals[LAST_SIGNAL] = { 0 };
static GParamSpec *palette_button_props[N_PROPS] = { NULL, };
G_DEFINE_TYPE_WITH_PRIVATE (GimpPaletteSelectButton, gimp_palette_select_button,
GIMP_TYPE_SELECT_BUTTON)
G_DEFINE_FINAL_TYPE (GimpPaletteSelectButton,
gimp_palette_select_button,
GIMP_TYPE_RESOURCE_SELECT_BUTTON)
static void
gimp_palette_select_button_class_init (GimpPaletteSelectButtonClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GimpSelectButtonClass *select_button_class = GIMP_SELECT_BUTTON_CLASS (klass);
/* Alias cast klass to super classes. */
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GimpResourceSelectButtonClass *superclass = GIMP_RESOURCE_SELECT_BUTTON_CLASS (klass);
g_debug ("%s called", G_STRFUNC);
/* Override virtual. */
object_class->finalize = gimp_palette_select_button_finalize;
object_class->set_property = gimp_palette_select_button_set_property;
object_class->get_property = gimp_palette_select_button_get_property;
select_button_class->select_destroy = gimp_palette_select_destroy;
/* Implement pure virtual functions. */
superclass->draw_interior = gimp_palette_select_button_draw_interior;
klass->palette_set = NULL;
/* Set data member of class. */
superclass->resource_type = GIMP_TYPE_PALETTE;
/**
* GimpPaletteSelectButton:title:
*
* The title to be used for the palette selection popup dialog.
*
* Since: 2.4
/* We don't define property getter/setters: use superclass getter/setters.
* But super property name is "resource", not "palette"
*/
palette_button_props[PROP_TITLE] = g_param_spec_string ("title",
"Title",
"The title to be used for the palette selection popup dialog",
_("Palette Selection"),
GIMP_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY);
/**
* GimpPaletteSelectButton:palette-name:
*
* The name of the currently selected palette.
*
* Since: 2.4
*/
palette_button_props[PROP_PALETTE_NAME] = g_param_spec_string ("palette-name",
"Palette name",
"The name of the currently selected palette",
NULL,
GIMP_PARAM_READWRITE);
g_object_class_install_properties (object_class, N_PROPS, palette_button_props);
/**
* GimpPaletteSelectButton::palette-set:
* @widget: the object which received the signal.
* @palette_name: the name of the currently selected palette.
* @dialog_closing: whether the dialog was closed or not.
*
* The ::palette-set signal is emitted when the user selects a palette.
*
* Since: 2.4
*/
palette_button_signals[PALETTE_SET] =
g_signal_new ("palette-set",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (GimpPaletteSelectButtonClass, palette_set),
NULL, NULL,
_gimpui_marshal_VOID__STRING_BOOLEAN,
G_TYPE_NONE, 2,
G_TYPE_STRING,
G_TYPE_BOOLEAN);
}
static void
gimp_palette_select_button_init (GimpPaletteSelectButton *button)
gimp_palette_select_button_init (GimpPaletteSelectButton *self)
{
button->priv = gimp_palette_select_button_get_instance_private (button);
GtkWidget *interior;
button->priv->inside = gimp_palette_select_button_create_inside (button);
gtk_container_add (GTK_CONTAINER (button), button->priv->inside);
g_debug ("%s called", G_STRFUNC);
/* Specialize super:
* - embed our widget interior instance to super widget instance.
* - tell super our dnd widget
* - tell super our clickable button
* Call superclass methods, with upcasts.
* These are on instance, not our subclass.
*/
interior = gimp_palette_select_button_create_interior (self);
/* require self has sub widgets initialized. */
/* Embed the whole button.*/
gimp_resource_select_button_embed_interior (GIMP_RESOURCE_SELECT_BUTTON (self), interior);
/* Self knows the GtkTargetEntry, super creates target and handles receive drag. */
gimp_resource_select_button_set_drag_target (GIMP_RESOURCE_SELECT_BUTTON (self),
self->drag_region_widget,
&drag_target);
/* Super handles button clicks. */
gimp_resource_select_button_set_clickable (GIMP_RESOURCE_SELECT_BUTTON (self),
self->button);
}
/**
* gimp_palette_select_button_new:
* @title: (nullable): Title of the dialog to use or %NULL to use the default title.
* @palette_name: (nullable): Initial palette name.
* @resource: (nullable): Initial palette.
*
* Creates a new #GtkWidget that completely controls the selection of
* a palette. This widget is suitable for placement in a table in a
* plug-in dialog.
* Creates a new #GtkWidget that lets a user choose a palette.
* You can put this widget in a table in a plug-in dialog.
*
* When palette is NULL, initial choice is from context.
*
* Returns: A #GtkWidget that you can use in your UI.
*
* Since: 2.4
*/
GtkWidget *
gimp_palette_select_button_new (const gchar *title,
const gchar *palette_name)
gimp_palette_select_button_new (const gchar *title,
GimpResource *resource)
{
GtkWidget *button;
GtkWidget *self;
if (title)
button = g_object_new (GIMP_TYPE_PALETTE_SELECT_BUTTON,
"title", title,
"palette-name", palette_name,
NULL);
else
button = g_object_new (GIMP_TYPE_PALETTE_SELECT_BUTTON,
"palette-name", palette_name,
NULL);
g_debug ("%s called", G_STRFUNC);
return button;
if (resource == NULL)
{
g_debug ("%s defaulting palette from context", G_STRFUNC);
resource = GIMP_RESOURCE (gimp_context_get_palette ());
}
g_assert (resource != NULL);
/* This method is polymorphic, so a factory can call it, but requires Palette. */
g_return_val_if_fail (GIMP_IS_PALETTE (resource), NULL);
/* Create instance of self (not super.)
* This will call superclass init, self class init, superclass init, and instance init.
* Self subclass class_init will specialize by implementing virtual funcs
* that open and set remote chooser dialog, and that draw self interior.
*
* !!! property belongs to superclass and is named "resource"
*/
if (title)
self = g_object_new (GIMP_TYPE_PALETTE_SELECT_BUTTON,
"title", title,
"resource", resource,
NULL);
else
self = g_object_new (GIMP_TYPE_PALETTE_SELECT_BUTTON,
"resource", resource,
NULL);
/* We don't subscribe to events from super (such as draw events.)
* Super will call our draw method when it's resource changes.
* Except that the above setting of property happens too late,
* so we now draw the initial resource.
*/
/* Draw with the initial resource. Cast self from Widget. */
gimp_palette_select_button_draw_interior (GIMP_RESOURCE_SELECT_BUTTON (self));
g_debug ("%s returns", G_STRFUNC);
return self;
}
/* Getter and setter.
* We could omit these, and use only the superclass methods.
* But script-fu-interface.c uses these, until FUTURE.
*/
/**
* gimp_palette_select_button_get_palette:
* @button: A #GimpPaletteSelectButton
* @self: A #GimpPaletteSelectButton
*
* Retrieves the name of currently selected palette.
* Gets the currently selected palette.
*
* Returns: an internal copy of the palette name which must not be freed.
* Returns: (transfer none): an internal copy of the palette which must not be freed.
*
* Since: 2.4
*/
const gchar *
gimp_palette_select_button_get_palette (GimpPaletteSelectButton *button)
GimpPalette *
gimp_palette_select_button_get_palette (GimpPaletteSelectButton *self)
{
g_return_val_if_fail (GIMP_IS_PALETTE_SELECT_BUTTON (button), NULL);
g_return_val_if_fail (GIMP_IS_PALETTE_SELECT_BUTTON (self), NULL);
return button->priv->palette_name;
/* Delegate to super w upcast arg and downcast result. */
return (GimpPalette *) gimp_resource_select_button_get_resource ((GimpResourceSelectButton*) self);
}
/**
* gimp_palette_select_button_set_palette:
* @button: A #GimpPaletteSelectButton
* @palette_name: (nullable): Palette name to set; %NULL means set to palette in context.
* @self: A #GimpPaletteSelectButton
* @palette: Palette to set.
*
* Sets the current palette for the palette select button.
* Sets the currently selected palette.
* Usually you should not call this; the user is in charge.
* Changes the selection in both the button and it's popup chooser.
*
* Since: 2.4
*/
void
gimp_palette_select_button_set_palette (GimpPaletteSelectButton *button,
const gchar *palette_name)
gimp_palette_select_button_set_palette (GimpPaletteSelectButton *self,
GimpPalette *palette)
{
GimpSelectButton *select_button;
g_return_if_fail (GIMP_IS_PALETTE_SELECT_BUTTON (self));
g_return_if_fail (GIMP_IS_PALETTE_SELECT_BUTTON (button));
g_debug ("%s", G_STRFUNC);
select_button = GIMP_SELECT_BUTTON (button);
if (select_button->temp_callback)
{
gimp_palettes_set_popup (select_button->temp_callback, palette_name);
}
else
{
gchar *name;
/* If not NULL and not empty string. */
if (palette_name && *palette_name)
name = palette_name;
else
{
GimpPalette * palette = gimp_context_get_palette ();
name = gimp_resource_get_id (GIMP_RESOURCE (palette));
}
gimp_palette_select_button_callback (name, FALSE, button);
}
/* Delegate to super with upcasts */
gimp_resource_select_button_set_resource (GIMP_RESOURCE_SELECT_BUTTON (self), GIMP_RESOURCE (palette));
}
@@ -280,179 +240,98 @@ gimp_palette_select_button_set_palette (GimpPaletteSelectButton *button,
static void
gimp_palette_select_button_finalize (GObject *object)
{
GimpPaletteSelectButton *button = GIMP_PALETTE_SELECT_BUTTON (object);
g_debug ("%s called", G_STRFUNC);
g_clear_pointer (&button->priv->palette_name, g_free);
g_clear_pointer (&button->priv->title, g_free);
/* Has no allocations.*/
/* Chain up. */
G_OBJECT_CLASS (gimp_palette_select_button_parent_class)->finalize (object);
}
static void
gimp_palette_select_button_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec)
/* This is NOT an implementation of virtual function.
*
* Create a widget that is the interior of a button.
* Super creates the button, self creates interior.
* Button is-a container and self calls super to add interior to the container.
*
* Special: an hbox containing a general icon for a palette and
* a label that is the name of the palette family and style.
* FUTURE: label styled in the current palette family and style.
*/
static GtkWidget*
gimp_palette_select_button_create_interior (GimpPaletteSelectButton *self)
{
GimpPaletteSelectButton *button = GIMP_PALETTE_SELECT_BUTTON (object);
GtkWidget *button;
GtkWidget *hbox;
GtkWidget *image;
GtkWidget *label;
gchar *palette_name = "unknown";
switch (property_id)
{
case PROP_TITLE:
button->priv->title = g_value_dup_string (value);
break;
case PROP_PALETTE_NAME:
gimp_palette_select_button_set_palette (button,
g_value_get_string (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void
gimp_palette_select_button_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec)
{
GimpPaletteSelectButton *button = GIMP_PALETTE_SELECT_BUTTON (object);
switch (property_id)
{
case PROP_TITLE:
g_value_set_string (value, button->priv->title);
break;
case PROP_PALETTE_NAME:
g_value_set_string (value, button->priv->palette_name);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void
gimp_palette_select_button_callback (const gchar *palette_name,
gboolean dialog_closing,
gpointer user_data)
{
GimpPaletteSelectButton *button = user_data;
GimpSelectButton *select_button = GIMP_SELECT_BUTTON (button);
g_free (button->priv->palette_name);
button->priv->palette_name = g_strdup (palette_name);
gtk_label_set_text (GTK_LABEL (button->priv->label), palette_name);
if (dialog_closing)
select_button->temp_callback = NULL;
g_signal_emit (button, palette_button_signals[PALETTE_SET], 0,
palette_name, dialog_closing);
g_object_notify_by_pspec (G_OBJECT (button), palette_button_props[PROP_PALETTE_NAME]);
}
static void
gimp_palette_select_button_clicked (GimpPaletteSelectButton *button)
{
GimpSelectButton *select_button = GIMP_SELECT_BUTTON (button);
if (select_button->temp_callback)
{
/* calling gimp_palettes_set_popup() raises the dialog */
gimp_palettes_set_popup (select_button->temp_callback,
button->priv->palette_name);
}
else
{
select_button->temp_callback =
gimp_palette_select_new (button->priv->title,
button->priv->palette_name,
gimp_palette_select_button_callback,
button, NULL);
}
}
static void
gimp_palette_select_drag_data_received (GimpPaletteSelectButton *button,
GdkDragContext *context,
gint x,
gint y,
GtkSelectionData *selection,
guint info,
guint time)
{
gint length = gtk_selection_data_get_length (selection);
gchar *str;
if (gtk_selection_data_get_format (selection) != 8 || length < 1)
{
g_warning ("%s: received invalid palette data", G_STRFUNC);
return;
}
str = g_strndup ((const gchar *) gtk_selection_data_get_data (selection),
length);
if (g_utf8_validate (str, -1, NULL))
{
gint pid;
gpointer unused;
gint name_offset = 0;
if (sscanf (str, "%i:%p:%n", &pid, &unused, &name_offset) >= 2 &&
pid == gimp_getpid () && name_offset > 0)
{
gchar *name = str + name_offset;
gimp_palette_select_button_set_palette (button, name);
}
}
g_free (str);
}
static GtkWidget *
gimp_palette_select_button_create_inside (GimpPaletteSelectButton *palette_button)
{
GtkWidget *button;
GtkWidget *hbox;
GtkWidget *image;
g_debug ("%s", G_STRFUNC);
/* Outermost is-a button. */
button = gtk_button_new ();
/* inside the button is hbox. */
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 4);
gtk_container_add (GTK_CONTAINER (button), hbox);
/* first item in hbox is an icon. */
image = gtk_image_new_from_icon_name (GIMP_ICON_PALETTE,
GTK_ICON_SIZE_BUTTON);
gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, FALSE, 0);
palette_button->priv->label = gtk_label_new (palette_button->priv->palette_name);
gtk_box_pack_start (GTK_BOX (hbox), palette_button->priv->label, TRUE, TRUE, 4);
/* Second item in hbox is palette name.
* The initial text is dummy, a draw will soon refresh it.
* This function does not know the resource/palette.
*/
label = gtk_label_new (palette_name);
gtk_box_pack_start (GTK_BOX (hbox), label, TRUE, TRUE, 4);
gtk_widget_show_all (button);
/* Ensure sub widgets saved for subsequent use. */
g_signal_connect_swapped (button, "clicked",
G_CALLBACK (gimp_palette_select_button_clicked),
palette_button);
self->palette_name_label = label; /* Save label for redraw. */
self->drag_region_widget = hbox;
self->button = button;
gtk_drag_dest_set (GTK_WIDGET (button),
GTK_DEST_DEFAULT_HIGHLIGHT |
GTK_DEST_DEFAULT_MOTION |
GTK_DEST_DEFAULT_DROP,
&target, 1,
GDK_ACTION_COPY);
g_signal_connect_swapped (button, "drag-data-received",
G_CALLBACK (gimp_palette_select_drag_data_received),
palette_button);
/* This subclass does not connect to draw signal on interior widget. */
/* Return the whole interior, which is-a button. */
return button;
}
/* Knows how to draw self interior.
* Self knows resource, it is not passed.
*
* Overrides virtual method in super, so it is generic on Resource.
*/
static void
gimp_palette_select_button_draw_interior (GimpResourceSelectButton *self)
{
gchar *palette_name;
GimpResource *resource;
GimpPaletteSelectButton *self_as_palette_select;
g_debug ("%s", G_STRFUNC);
g_return_if_fail (GIMP_IS_PALETTE_SELECT_BUTTON (self));
self_as_palette_select = GIMP_PALETTE_SELECT_BUTTON (self);
g_object_get (self, "resource", &resource, NULL);
/* For now, the "id" property of the resource is the name.
* FUTURE: core will support name distinct from ID.
*/
g_object_get (resource, "id", &palette_name, NULL);
/* We are not keeping a copy of palette name, nothing to free. */
/* Not styling the text using the chosen palette,
* just replacing the text with the name of the chosen palette.
*/
gtk_label_set_text (GTK_LABEL (self_as_palette_select->palette_name_label), palette_name);
}

View File

@@ -25,61 +25,35 @@
#ifndef __GIMP_PALETTE_SELECT_BUTTON_H__
#define __GIMP_PALETTE_SELECT_BUTTON_H__
#include <libgimp/gimpselectbutton.h>
#include <libgimp/gimpresourceselectbutton.h>
G_BEGIN_DECLS
/* For information look into the C source or the html documentation */
/* This defines certain structs and the usual macros.
* A final type has no private.
*/
#define GIMP_TYPE_PALETTE_SELECT_BUTTON (gimp_palette_select_button_get_type ())
G_DECLARE_FINAL_TYPE (GimpPaletteSelectButton,
gimp_palette_select_button,
GIMP, PALETTE_SELECT_BUTTON,
GimpResourceSelectButton)
#define GIMP_TYPE_PALETTE_SELECT_BUTTON (gimp_palette_select_button_get_type ())
#define GIMP_PALETTE_SELECT_BUTTON(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_PALETTE_SELECT_BUTTON, GimpPaletteSelectButton))
#define GIMP_PALETTE_SELECT_BUTTON_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_PALETTE_SELECT_BUTTON, GimpPaletteSelectButtonClass))
#define GIMP_IS_PALETTE_SELECT_BUTTON(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_PALETTE_SELECT_BUTTON))
#define GIMP_IS_PALETTE_SELECT_BUTTON_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_PALETTE_SELECT_BUTTON))
#define GIMP_PALETTE_SELECT_BUTTON_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_PALETTE_SELECT_BUTTON, GimpPaletteSelectButtonClass))
typedef struct _GimpPaletteSelectButtonPrivate GimpPaletteSelectButtonPrivate;
typedef struct _GimpPaletteSelectButtonClass GimpPaletteSelectButtonClass;
struct _GimpPaletteSelectButton
{
GimpSelectButton parent_instance;
GimpPaletteSelectButtonPrivate *priv;
};
struct _GimpPaletteSelectButtonClass
{
GimpSelectButtonClass parent_class;
GimpResourceSelectButtonClass parent_class;
/* palette_set signal is emitted when palette is chosen */
void (* palette_set) (GimpPaletteSelectButton *button,
const gchar *palette_name,
gboolean dialog_closing);
/* Padding for future expansion */
void (*_gimp_reserved1) (void);
void (*_gimp_reserved2) (void);
void (*_gimp_reserved3) (void);
void (*_gimp_reserved4) (void);
void (*_gimp_reserved5) (void);
void (*_gimp_reserved6) (void);
void (*_gimp_reserved7) (void);
void (*_gimp_reserved8) (void);
/* _set signal is not defined. Use resource_set signal from superclass */
};
GType gimp_palette_select_button_get_type (void) G_GNUC_CONST;
GtkWidget * gimp_palette_select_button_new (const gchar *title,
const gchar *palette_name);
const gchar * gimp_palette_select_button_get_palette (GimpPaletteSelectButton *button);
void gimp_palette_select_button_set_palette (GimpPaletteSelectButton *button,
const gchar *palette_name);
GtkWidget * gimp_palette_select_button_new (const gchar *title,
GimpResource *resource);
/* FUTURE eliminate. Use superclass method get_resource */
GimpPalette *gimp_palette_select_button_get_palette (GimpPaletteSelectButton *self);
void gimp_palette_select_button_set_palette (GimpPaletteSelectButton *self,
GimpPalette *palette);
G_END_DECLS

View File

@@ -25,6 +25,139 @@
*/
/*
* GIMP_TYPE_PARAM_RESOURCE
*/
static void gimp_param_resource_class_init (GParamSpecClass *klass);
static void gimp_param_resource_init (GParamSpec *pspec);
static gboolean gimp_param_resource_validate (GParamSpec *pspec,
GValue *value);
GType
gimp_param_resource_get_type (void)
{
static GType type = 0;
if (! type)
{
const GTypeInfo info =
{
sizeof (GParamSpecClass),
NULL, NULL,
(GClassInitFunc) gimp_param_resource_class_init,
NULL, NULL,
sizeof (GimpParamSpecResource),
0,
(GInstanceInitFunc) gimp_param_resource_init
};
type = g_type_register_static (G_TYPE_PARAM_OBJECT,
"GimpParamResource", &info, 0);
}
return type;
}
static void
gimp_param_resource_class_init (GParamSpecClass *klass)
{
klass->value_type = GIMP_TYPE_RESOURCE;
klass->value_validate = gimp_param_resource_validate;
}
static void
gimp_param_resource_init (GParamSpec *pspec)
{
GimpParamSpecResource *ispec = GIMP_PARAM_SPEC_RESOURCE (pspec);
ispec->none_ok = FALSE;
}
/* Return TRUE when value is invalid!!!
* FIXME: should be named is_invalid.
*/
static gboolean
gimp_param_resource_validate (GParamSpec *pspec,
GValue *value)
{
GimpParamSpecResource *ispec = GIMP_PARAM_SPEC_RESOURCE (pspec);
GimpResource *resource = value->data[0].v_pointer;
g_debug (">>>>>%s", G_STRFUNC);
if (! ispec->none_ok && resource == NULL)
/* NULL when NULL not allowed is invalid. */
return TRUE;
if (resource != NULL)
{
if (GIMP_IS_BRUSH (resource) && gimp_brush_is_valid (GIMP_BRUSH (resource)))
return FALSE;
else if (GIMP_IS_FONT (resource) && gimp_font_is_valid (GIMP_FONT (resource)))
return FALSE;
else if (GIMP_IS_GRADIENT (resource) && gimp_gradient_is_valid (GIMP_GRADIENT (resource)))
return FALSE;
else if (GIMP_IS_PALETTE (resource) && gimp_palette_is_valid (GIMP_PALETTE (resource)))
return FALSE;
else if (GIMP_IS_PATTERN (resource) && gimp_pattern_is_valid (GIMP_PATTERN (resource)))
return FALSE;
else
{
/* Not a resource type or is invalid reference to core resource.
* Plugin might be using a resource that was uninstalled.
*/
g_object_unref (resource);
value->data[0].v_pointer = NULL;
return TRUE;
}
}
else
{
/* resource is NULL but null is valid.*/
return FALSE;
}
}
/**
* gimp_param_spec_resource:
* @name: Canonical name of the property specified.
* @nick: Nick name of the property specified.
* @blurb: Description of the property specified.
* @none_ok: Whether no is a valid value.
* @flags: Flags for the property specified.
*
* Creates a new #GimpParamSpecResource specifying a
* #GIMP_TYPE_RESOURCE property.
*
* See g_param_spec_internal() for details on property names.
*
* Returns: (transfer full): The newly created #GimpParamSpecResource.
*
* Since: 3.0
**/
GParamSpec *
gimp_param_spec_resource (const gchar *name,
const gchar *nick,
const gchar *blurb,
gboolean none_ok,
GParamFlags flags)
{
GimpParamSpecResource *ispec;
ispec = g_param_spec_internal (GIMP_TYPE_PARAM_RESOURCE,
name, nick, blurb, flags);
g_return_val_if_fail (ispec, NULL);
ispec->none_ok = none_ok ? TRUE : FALSE;
return G_PARAM_SPEC (ispec);
}
/*
* GIMP_TYPE_PARAM_BRUSH
*/

View File

@@ -27,6 +27,34 @@
G_BEGIN_DECLS
/*
* GIMP_TYPE_PARAM_RESOURCE
*/
/* See bottom of this file for definition of GIMP_VALUE_HOLDS_RESOURCE(value) */
#define GIMP_TYPE_PARAM_RESOURCE (gimp_param_resource_get_type ())
#define GIMP_PARAM_SPEC_RESOURCE(pspec) (G_TYPE_CHECK_INSTANCE_CAST ((pspec), GIMP_TYPE_PARAM_RESOURCE, GimpParamSpecResource))
#define GIMP_IS_PARAM_SPEC_RESOURCE(pspec) (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), GIMP_TYPE_PARAM_RESOURCE))
typedef struct _GimpParamSpecResource GimpParamSpecResource;
struct _GimpParamSpecResource
{
GParamSpecObject parent_instance;
gboolean none_ok;
};
GType gimp_param_resource_get_type (void) G_GNUC_CONST;
GParamSpec * gimp_param_spec_resource (
const gchar *name,
const gchar *nick,
const gchar *blurb,
gboolean none_ok,
GParamFlags flags);
/*
* GIMP_TYPE_PARAM_BRUSH
@@ -164,7 +192,11 @@ GParamSpec * gimp_param_spec_pattern (const gchar *name,
#define GIMP_VALUE_HOLDS_RESOURCE(value) (GIMP_VALUE_HOLDS_BRUSH (value) || GIMP_VALUE_HOLDS_FONT (value) || GIMP_VALUE_HOLDS_GRADIENT (value) || GIMP_VALUE_HOLDS_PALETTE (value) || GIMP_VALUE_HOLDS_PATTERN (value) )
#define GIMP_VALUE_HOLDS_RESOURCE(value) (GIMP_VALUE_HOLDS_BRUSH (value) || \
GIMP_VALUE_HOLDS_FONT (value) || \
GIMP_VALUE_HOLDS_GRADIENT (value) || \
GIMP_VALUE_HOLDS_PALETTE (value) || \
GIMP_VALUE_HOLDS_PATTERN (value) )

View File

@@ -1,221 +0,0 @@
/* LIBGIMP - The GIMP Library
* Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
*
* gimppatternselect.c
*
* This library is free software: you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see
* <https://www.gnu.org/licenses/>.
*/
#include "config.h"
#include "gimp.h"
typedef struct
{
gchar *pattern_callback;
guint idle_id;
gchar *pattern_name;
gint width;
gint height;
gint bytes;
guchar *pattern_mask_data;
GimpRunPatternCallback callback;
gboolean closing;
gpointer data;
GDestroyNotify data_destroy;
} GimpPatternData;
/* local function prototypes */
static void gimp_pattern_data_free (GimpPatternData *data);
static GimpValueArray * gimp_temp_pattern_run (GimpProcedure *procedure,
const GimpValueArray *args,
gpointer run_data);
static gboolean gimp_temp_pattern_idle (GimpPatternData *data);
/* public functions */
const gchar *
gimp_pattern_select_new (const gchar *title,
const gchar *pattern_name,
GimpRunPatternCallback callback,
gpointer data,
GDestroyNotify data_destroy)
{
GimpPlugIn *plug_in = gimp_get_plug_in ();
GimpProcedure *procedure;
gchar *pattern_callback;
GimpPatternData *pattern_data;
pattern_callback = gimp_pdb_temp_procedure_name (gimp_get_pdb ());
pattern_data = g_slice_new0 (GimpPatternData);
pattern_data->pattern_callback = pattern_callback;
pattern_data->callback = callback;
pattern_data->data = data;
pattern_data->data_destroy = data_destroy;
procedure = gimp_procedure_new (plug_in,
pattern_callback,
GIMP_PDB_PROC_TYPE_TEMPORARY,
gimp_temp_pattern_run,
pattern_data,
(GDestroyNotify)
gimp_pattern_data_free);
GIMP_PROC_ARG_STRING (procedure, "pattern-name",
"Pattern name",
"The pattern name",
NULL,
G_PARAM_READWRITE);
GIMP_PROC_ARG_INT (procedure, "mask-width",
"Mask width",
"Pattern width",
0, 10000, 0,
G_PARAM_READWRITE);
GIMP_PROC_ARG_INT (procedure, "mask-height",
"Mask height",
"Pattern height",
0, 10000, 0,
G_PARAM_READWRITE);
GIMP_PROC_ARG_INT (procedure, "mask-bpp",
"Mask bpp",
"Pattern bytes per pixel",
0, 10000, 0,
G_PARAM_READWRITE);
GIMP_PROC_ARG_INT (procedure, "mask-len",
"Mask length",
"Length of pattern mask data",
0, G_MAXINT, 0,
G_PARAM_READWRITE);
GIMP_PROC_ARG_UINT8_ARRAY (procedure, "mask-data",
"Mask data",
"The pattern mask data",
G_PARAM_READWRITE);
GIMP_PROC_ARG_BOOLEAN (procedure, "closing",
"Closing",
"If the dialog was cloaing",
FALSE,
G_PARAM_READWRITE);
gimp_plug_in_add_temp_procedure (plug_in, procedure);
g_object_unref (procedure);
if (gimp_patterns_popup (pattern_callback, title, pattern_name))
{
/* Allow callbacks to be watched */
gimp_plug_in_extension_enable (plug_in);
return pattern_callback;
}
gimp_plug_in_remove_temp_procedure (plug_in, pattern_callback);
return NULL;
}
void
gimp_pattern_select_destroy (const gchar *pattern_callback)
{
GimpPlugIn *plug_in = gimp_get_plug_in ();
g_return_if_fail (pattern_callback != NULL);
gimp_plug_in_remove_temp_procedure (plug_in, pattern_callback);
}
/* private functions */
static void
gimp_pattern_data_free (GimpPatternData *data)
{
if (data->idle_id)
g_source_remove (data->idle_id);
if (data->pattern_callback)
{
gimp_patterns_close_popup (data->pattern_callback);
g_free (data->pattern_callback);
}
g_free (data->pattern_name);
g_free (data->pattern_mask_data);
if (data->data_destroy)
data->data_destroy (data->data);
g_slice_free (GimpPatternData, data);
}
static GimpValueArray *
gimp_temp_pattern_run (GimpProcedure *procedure,
const GimpValueArray *args,
gpointer run_data)
{
GimpPatternData *data = run_data;
g_free (data->pattern_name);
g_free (data->pattern_mask_data);
data->pattern_name = GIMP_VALUES_DUP_STRING (args, 0);
data->width = GIMP_VALUES_GET_INT (args, 1);
data->height = GIMP_VALUES_GET_INT (args, 2);
data->bytes = GIMP_VALUES_GET_INT (args, 3);
data->pattern_mask_data = GIMP_VALUES_DUP_UINT8_ARRAY (args, 5);
data->closing = GIMP_VALUES_GET_BOOLEAN (args, 6);
if (! data->idle_id)
data->idle_id = g_idle_add ((GSourceFunc) gimp_temp_pattern_idle, data);
return gimp_procedure_new_return_values (procedure, GIMP_PDB_SUCCESS, NULL);
}
static gboolean
gimp_temp_pattern_idle (GimpPatternData *data)
{
data->idle_id = 0;
if (data->callback)
data->callback (data->pattern_name,
data->width,
data->height,
data->bytes,
data->pattern_mask_data,
data->closing,
data->data);
if (data->closing)
{
gchar *pattern_callback = data->pattern_callback;
data->pattern_callback = NULL;
gimp_pattern_select_destroy (pattern_callback);
g_free (pattern_callback);
}
return G_SOURCE_REMOVE;
}

View File

@@ -1,59 +0,0 @@
/* LIBGIMP - The GIMP Library
* Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
*
* gimppatternselect.h
*
* This library is free software: you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see
* <https://www.gnu.org/licenses/>.
*/
#if !defined (__GIMP_H_INSIDE__) && !defined (GIMP_COMPILATION)
#error "Only <libgimp/gimp.h> can be included directly."
#endif
#ifndef __GIMP_PATTERN_SELECT_H__
#define __GIMP_PATTERN_SELECT_H__
G_BEGIN_DECLS
/**
* GimpRunPatternCallback:
* @pattern_name: Name of the pattern
* @width: width
* @height: height
* @bpp: bytes per pixel
* @mask_data: (array): Mask data
* @dialog_closing: Dialog closing?
* @user_data: (closure): user data
*/
typedef void (* GimpRunPatternCallback) (const gchar *pattern_name,
gint width,
gint height,
gint bpp,
const guchar *mask_data,
gboolean dialog_closing,
gpointer user_data);
const gchar * gimp_pattern_select_new (const gchar *title,
const gchar *pattern_name,
GimpRunPatternCallback callback,
gpointer data,
GDestroyNotify data_destroy);
void gimp_pattern_select_destroy (const gchar *pattern_callback);
G_END_DECLS
#endif /* __GIMP_PATTERN_SELECT_H__ */

View File

@@ -30,28 +30,29 @@
/**
* SECTION: gimppatternselect
* @title: gimppatternselect
* @short_description: Functions providing a pattern selection dialog.
* @short_description: Methods of a pattern chooser dialog
*
* Functions providing a pattern selection dialog.
* A dialog letting a user choose a pattern. Read more at
* gimpfontselect.
**/
/**
* gimp_patterns_popup:
* @pattern_callback: The callback PDB proc to call when pattern selection is made.
* @pattern_callback: The callback PDB proc to call when the user chooses a pattern.
* @popup_title: Title of the pattern selection dialog.
* @initial_pattern: The name of the pattern to set as the first selected.
* @initial_pattern_name: The name of the pattern to set as the initial choice.
*
* Invokes the Gimp pattern selection.
*
* This procedure opens the pattern selection dialog.
* Opens the pattern selection dialog.
*
* Returns: TRUE on success.
**/
gboolean
gimp_patterns_popup (const gchar *pattern_callback,
const gchar *popup_title,
const gchar *initial_pattern)
const gchar *initial_pattern_name)
{
GimpValueArray *args;
GimpValueArray *return_vals;
@@ -60,7 +61,7 @@ gimp_patterns_popup (const gchar *pattern_callback,
args = gimp_value_array_new_from_types (NULL,
G_TYPE_STRING, pattern_callback,
G_TYPE_STRING, popup_title,
G_TYPE_STRING, initial_pattern,
G_TYPE_STRING, initial_pattern_name,
G_TYPE_NONE);
return_vals = gimp_pdb_run_procedure_array (gimp_get_pdb (),
@@ -81,7 +82,7 @@ gimp_patterns_popup (const gchar *pattern_callback,
*
* Close the pattern selection dialog.
*
* This procedure closes an opened pattern selection dialog.
* Closes an open pattern selection dialog.
*
* Returns: TRUE on success.
**/

View File

@@ -34,7 +34,7 @@ G_BEGIN_DECLS
gboolean gimp_patterns_popup (const gchar *pattern_callback,
const gchar *popup_title,
const gchar *initial_pattern);
const gchar *initial_pattern_name);
gboolean gimp_patterns_close_popup (const gchar *pattern_callback);
gboolean gimp_patterns_set_popup (const gchar *pattern_callback,
const gchar *pattern_name);

File diff suppressed because it is too large Load Diff

View File

@@ -25,65 +25,35 @@
#ifndef __GIMP_PATTERN_SELECT_BUTTON_H__
#define __GIMP_PATTERN_SELECT_BUTTON_H__
#include <libgimp/gimpselectbutton.h>
#include <libgimp/gimpresourceselectbutton.h>
G_BEGIN_DECLS
/* For information look into the C source or the html documentation */
/* This defines certain structs and the usual macros.
* A final type has no private.
*/
#define GIMP_TYPE_PATTERN_SELECT_BUTTON (gimp_pattern_select_button_get_type ())
G_DECLARE_FINAL_TYPE (GimpPatternSelectButton,
gimp_pattern_select_button,
GIMP, PATTERN_SELECT_BUTTON,
GimpResourceSelectButton)
#define GIMP_TYPE_PATTERN_SELECT_BUTTON (gimp_pattern_select_button_get_type ())
#define GIMP_PATTERN_SELECT_BUTTON(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_PATTERN_SELECT_BUTTON, GimpPatternSelectButton))
#define GIMP_PATTERN_SELECT_BUTTON_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_PATTERN_SELECT_BUTTON, GimpPatternSelectButtonClass))
#define GIMP_IS_PATTERN_SELECT_BUTTON(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_PATTERN_SELECT_BUTTON))
#define GIMP_IS_PATTERN_SELECT_BUTTON_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_PATTERN_SELECT_BUTTON))
#define GIMP_PATTERN_SELECT_BUTTON_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_PATTERN_SELECT_BUTTON, GimpPatternSelectButtonClass))
typedef struct _GimpPatternSelectButtonPrivate GimpPatternSelectButtonPrivate;
typedef struct _GimpPatternSelectButtonClass GimpPatternSelectButtonClass;
struct _GimpPatternSelectButton
{
GimpSelectButton parent_instance;
GimpPatternSelectButtonPrivate *priv;
};
struct _GimpPatternSelectButtonClass
{
GimpSelectButtonClass parent_class;
GimpResourceSelectButtonClass parent_class;
/* pattern_set signal is emitted when pattern is chosen */
void (* pattern_set) (GimpPatternSelectButton *button,
const gchar *pattern_name,
gint width,
gint height,
gint bpp,
const guchar *mask_data,
gboolean dialog_closing);
/* Padding for future expansion */
void (*_gimp_reserved1) (void);
void (*_gimp_reserved2) (void);
void (*_gimp_reserved3) (void);
void (*_gimp_reserved4) (void);
void (*_gimp_reserved5) (void);
void (*_gimp_reserved6) (void);
void (*_gimp_reserved7) (void);
void (*_gimp_reserved8) (void);
/* _set signal is not defined. Use resource_set signal from superclass */
};
GType gimp_pattern_select_button_get_type (void) G_GNUC_CONST;
GtkWidget * gimp_pattern_select_button_new (const gchar *title,
const gchar *pattern_name);
const gchar * gimp_pattern_select_button_get_pattern (GimpPatternSelectButton *button);
void gimp_pattern_select_button_set_pattern (GimpPatternSelectButton *button,
const gchar *pattern_name);
GtkWidget * gimp_pattern_select_button_new (const gchar *title,
GimpResource *resource);
/* FUTURE eliminate. Use superclass method get_resource */
GimpPattern *gimp_pattern_select_button_get_pattern (GimpPatternSelectButton *self);
void gimp_pattern_select_button_set_pattern (GimpPatternSelectButton *self,
GimpPattern *pattern);
G_END_DECLS

View File

@@ -861,6 +861,32 @@ G_BEGIN_DECLS
/* Resource */
#define GIMP_PROC_ARG_BRUSH(procedure, name, nick, blurb, flags) \
gimp_procedure_add_argument (procedure,\
gimp_param_spec_brush (name, nick, blurb,\
GIMP_TYPE_BRUSH,\
flags))
#define GIMP_PROC_ARG_FONT(procedure, name, nick, blurb, flags) \
gimp_procedure_add_argument (procedure,\
gimp_param_spec_font (name, nick, blurb,\
GIMP_TYPE_FONT,\
flags))
#define GIMP_PROC_ARG_GRADIENT(procedure, name, nick, blurb, flags) \
gimp_procedure_add_argument (procedure,\
gimp_param_spec_gradient (name, nick, blurb,\
GIMP_TYPE_GRADIENT,\
flags))
#define GIMP_PROC_ARG_PALETTE(procedure, name, nick, blurb, flags) \
gimp_procedure_add_argument (procedure,\
gimp_param_spec_palette (name, nick, blurb,\
GIMP_TYPE_PALETTE,\
flags))
#define GIMP_PROC_ARG_PATTERN(procedure, name, nick, blurb, flags) \
gimp_procedure_add_argument (procedure,\
gimp_param_spec_pattern (name, nick, blurb,\
GIMP_TYPE_PATTERN,\
flags))
#define GIMP_VALUES_GET_BRUSH(args, n) \
g_value_get_object (gimp_value_array_index (args, n))
#define GIMP_VALUES_SET_BRUSH(args, n, value) \

View File

@@ -725,12 +725,28 @@ gimp_procedure_dialog_get_widget (GimpProcedureDialog *dialog,
property, NULL,
GTK_FILE_CHOOSER_ACTION_OPEN);
}
/* GimpResource subclasses */
/* FUTURE: title the chooser more specifically, with a prefix that is the nick of the property. */
else if (G_IS_PARAM_SPEC_OBJECT (pspec) && pspec->value_type == GIMP_TYPE_BRUSH)
{
widget = gimp_prop_brush_chooser_button_new (G_OBJECT (dialog->priv->config),
property, NULL);
widget = gimp_prop_chooser_brush_new (G_OBJECT (dialog->priv->config), property, _("Brush Chooser"));
}
else if (G_IS_PARAM_SPEC_OBJECT (pspec) && pspec->value_type == GIMP_TYPE_FONT)
{
widget = gimp_prop_chooser_font_new (G_OBJECT (dialog->priv->config), property, _("Font Chooser"));
}
else if (G_IS_PARAM_SPEC_OBJECT (pspec) && pspec->value_type == GIMP_TYPE_GRADIENT)
{
widget = gimp_prop_chooser_gradient_new (G_OBJECT (dialog->priv->config), property, _("Gradient Chooser"));
}
else if (G_IS_PARAM_SPEC_OBJECT (pspec) && pspec->value_type == GIMP_TYPE_PALETTE)
{
widget = gimp_prop_chooser_palette_new (G_OBJECT (dialog->priv->config), property, _("Palette Chooser"));
}
else if (G_IS_PARAM_SPEC_OBJECT (pspec) && pspec->value_type == GIMP_TYPE_PATTERN)
{
widget = gimp_prop_chooser_pattern_new (G_OBJECT (dialog->priv->config), property, _("Pattern Chooser"));
}
/* FIXME add cases for other resources. */
else if (G_PARAM_SPEC_TYPE (pspec) == G_TYPE_PARAM_ENUM)
{
GimpIntStore *store;

View File

@@ -1,299 +0,0 @@
/* LIBGIMP - The GIMP Library
* Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
*
* This library is free software: you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see
* <https://www.gnu.org/licenses/>.
*/
#include "config.h"
#include <gegl.h>
#include <gegl-paramspecs.h>
#include <gtk/gtk.h>
#include "gimpui.h"
/* Several of these local functions were copied from gimppropwidgets.
* FUTURE: make utility functions shared by prop widgets.
*/
/* When property_name of object changes, call the callback passing callback_data. */
static void
connect_notify_property_changed (GObject *object,
const gchar *property_name,
GCallback callback,
gpointer callback_data)
{
gchar *notify_name;
notify_name = g_strconcat ("notify::", property_name, NULL);
g_signal_connect_object (object, notify_name, callback, callback_data, 0);
g_free (notify_name);
}
/* Setter and getters for a config property bound to a widget.
*
* A prop widget is responsible for knowing the config property it is bound to.
* The config property is a pair [config, property_name]
*
* The property name is unique among properties of the config.
* But it is not constant, and the config can have many similarly named properties,
* when the config has many properties each a value of type say GimpBrush.
* For example, the widget may have property "brush" but the config have "brush2"
*
* We arbitrarily store it in data, not in yet another property.
*/
static void
gimp_widget_set_bound_property (GtkWidget *widget,
GObject *config,
const gchar *property_name)
{
g_debug ("%s: %s", G_STRFUNC, property_name);
g_return_if_fail (GTK_IS_WIDGET (widget));
/* Widget destruction notifies this and frees the string. */
g_object_set_data_full (G_OBJECT (widget),
"gimp-widget-property-name",
g_strdup (property_name),
(GDestroyNotify) g_free);
g_object_set_data_full (G_OBJECT (widget),
"gimp-widget-property-config",
g_object_ref (config),
(GDestroyNotify) g_object_unref);
}
/* The result string is owned by the widget and is destroyed with the widget.
* Caller must copy it if caller needs it after the widget is destroyed.
*/
static const gchar *
gimp_widget_get_bound_property_name (GtkWidget *widget)
{
gchar * result=NULL;
g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
result = (gchar *) g_object_get_data (G_OBJECT (widget),
"gimp-widget-property-name");
/* Ensure result is NULL when set_bound_property was not called prior. */
g_debug ("bound to %s", result);
return result;
}
static GObject *
gimp_widget_get_bound_property_owner (GtkWidget *widget)
{
GObject * result=NULL;
g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
result = g_object_get_data (G_OBJECT (widget),
"gimp-widget-property-config");
/* Ensure result is NULL if the widget lacks the property.
* When set_bound_property was not called prior.
*/
g_debug("bound to owner %p", result);
return result;
}
static GParamSpec *
find_param_spec (GObject *object,
const gchar *property_name,
const gchar *strloc)
{
GParamSpec *param_spec;
param_spec = g_object_class_find_property (G_OBJECT_GET_CLASS (object),
property_name);
if (! param_spec)
g_warning ("%s: %s has no property named '%s'",
strloc,
g_type_name (G_TYPE_FROM_INSTANCE (object)),
property_name);
return param_spec;
}
#ifdef DEBUG
/* Print the ID of a GimpResource */
static void
debug_resource_id(GimpBrush *property_value)
{
gchar * id;
g_object_get (GIMP_RESOURCE(property_value), "id", &id, NULL);
g_debug ("brush's id: %s", id);
}
#else
static void debug_resource_id(GimpBrush *property_value) {}
#endif
/* Called when the "brush" property of the widget changes.
*
* Do a prop widget's essential behavior:
* copy from widget property to GimpProcedureConfig property.
*
* Require the widget to have previously bound the config's property to itself.
* We don't compare current value with new value:
* that is an optimization to reduce signals.
* Only we are subscribed to this notify signal.
* The config is only being used to marshall args to a procedure call.
*/
static void
gimp_prop_brush_chooser_button_notify (GtkWidget *button)
{
GimpBrush *widget_property_value = NULL;
GimpBrush *config_property_value = NULL;
/* This pair designates a property of a GimpProcedureConfig. */
GObject *config;
const gchar *config_property_name;
/* Get changed value of the widget's property */
g_object_get (button, "brush", &widget_property_value, NULL);
debug_resource_id (widget_property_value);
/* Get the name of the config property the widget is bound to. */
config = gimp_widget_get_bound_property_owner (button);
config_property_name = gimp_widget_get_bound_property_name (button);
g_assert (config_property_name != NULL);
/* FUTURE: migrate much of this code to a new method
* GimpProcedureConfig.replace_object_value(property_name, new_value)
* It would know to free the existing value.
*/
/* Free the existing config property.
*
* Properties of type GObject might not have default value,
* so expect it can be NULL, when the config (settings) have never been serialized.
*
* Here we get a pointer to the object, and g_object_clear it.
* The config still points to the freed object, but we soon replace it.
*/
g_debug ("notify callback, get property: %s from config. ", config_property_name);
g_object_get (config, config_property_name, &config_property_value, NULL);
g_clear_object (&config_property_value);
/* Set the config's property to the widget's property */
g_object_set (config, config_property_name, widget_property_value, NULL);
/* Assert that g_object_set refs the value,
* so value won't be freed when widget closes.
*/
}
/**
* gimp_prop_brush_chooser_button_new:
* @config: Object to which property is attached.
* @property_name: Name of property controlled by button.
*
* Creates a #GimpBrushSelectButton that displays and sets the property,
* which is a GimpBrush.
*
* The button is labeled with the @property_name's nick.
*
* When pushed, the button shows a dialog that lets the user choose a brush.
*
* Returns: (transfer full): The newly created #GimpBrushSelectButton widget.
*
* Since: 3.0
*/
GtkWidget *
gimp_prop_brush_chooser_button_new (GObject *config,
const gchar *property_name,
const gchar *title)
{
GParamSpec *param_spec;
GtkWidget *button;
GimpBrush *brush;
g_return_val_if_fail (G_IS_OBJECT (config), NULL);
g_return_val_if_fail (property_name != NULL, NULL);
g_debug ("config is %p", config);
g_debug ("property name is %s", property_name);
param_spec = find_param_spec (config, property_name, G_STRFUNC);
if (! param_spec)
{
g_warning ("%s: %s has no property named '%s'",
G_STRFUNC, g_type_name (G_TYPE_FROM_INSTANCE (config)),
property_name);
return NULL;
}
if (! G_IS_PARAM_SPEC_OBJECT (param_spec) || param_spec->value_type != GIMP_TYPE_BRUSH)
{
g_warning ("%s: property '%s' of %s is not a G_PARAM_SPEC_OBJECT of value type GIMP_TYPE_BRUSH.",
G_STRFUNC, param_spec->name,
g_type_name (param_spec->owner_type));
return NULL;
}
if (! title)
title = g_param_spec_get_nick (param_spec);
/* Initial choice in chooser is the brush of the config. */
/* Assert the property exists, but might be NULL. */
g_object_get (config, property_name, &brush, NULL);
if (brush == NULL)
{
/* Property has no default.
* Get a reasonable value from context.
* The widget will show some value selected,
* ensure it is the the value in context.
*/
g_warning ("No brush property in config. Using brush from context.");
brush = gimp_context_get_brush();
}
debug_resource_id (brush);
/* FIXME: use a widget that chooses only a brush,
* and not opacity, spacing, layer_mode.
*/
button = gimp_brush_select_button_new (title, brush,
1.0, 2, GIMP_LAYER_MODE_NORMAL);
/* Unlike other prop widgets, we don't use a callback for a signal of the widget.
* And we don't bind directly to a property.
* Instead get a callback for the notify signal of the widget "brush" property.
* Handler will copy widget's property to config's property.
*/
connect_notify_property_changed (
(GObject *)button, "brush", /* Source of signal. */
G_CALLBACK (gimp_prop_brush_chooser_button_notify), /* signal handler. */
button); /* Data passed to handler. */
/* widget knows what config property it is bound to. */
gimp_widget_set_bound_property (button, config, property_name);
/* FIXME: label the widget with the nick of the paramspec. */
gtk_widget_show (button);
return button;
}

View File

@@ -1,35 +0,0 @@
/* LIBGIMP - The GIMP Library
* Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
*
* This library is free software: you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see
* <https://www.gnu.org/licenses/>.
*/
#if !defined (__GIMP_UI_H_INSIDE__) && !defined (GIMP_COMPILATION)
#error "Only <libgimp/gimpui.h> can be included directly."
#endif
#ifndef __GIMP_PROP_BRUSH_CHOOSER_H__
#define __GIMP_PROP_BRUSH_CHOOSER_H__
G_BEGIN_DECLS
GtkWidget * gimp_prop_brush_chooser_button_new (GObject *config,
const gchar *property_name,
const gchar *title);
G_END_DECLS
#endif /* __GIMP_PROP_BRUSH_CHOOSER_H__ */

105
libgimp/gimppropchooser.c Normal file
View File

@@ -0,0 +1,105 @@
/* LIBGIMP - The GIMP Library
* Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
*
* This library is free software: you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see
* <https://www.gnu.org/licenses/>.
*/
#include "config.h"
#include <gegl.h>
#include <gegl-paramspecs.h>
#include <gtk/gtk.h>
#include "gimpui.h"
/* PropChooser
* A GtkWidget, more specifically a GtkButtonWidget.
* Pops up a chooser widget.
* Has Prop widget trait, i.e. binds property of the chooser widget
* to a property of a ProcedureConfig.
*
* For now, only for Resource choosers,
* which are named GimpResourceSelectButton ("select" means "choose")
*
* Call a factory to create PropWidgets, passing a creator function of
* a kind of wrapped widget.
*
* Stack of objects:
* PropWidget<Resource> (this file)
* <Resource>SelectButton button pops up a
* <Resource>Select dialog lets user choose <resource>
* libgimp wire protocol to core
* PDBDialog (app/widgets/gimppdbdialog.c)
*/
/* Only brush is annotated.
* Usually these are created by GimpProcedureDialog.
* FIXME: It is not clear that these need to be public API,
* unless a plugin creates its own dialog.
*/
/**
* gimp_prop_chooser_brush_new:
* @config: Object to which property is attached.
* @property_name: Name of property controlled by button.
* @chooser_title: Title for the popup chooser dialog.
*
* Creates a #GimpBrushSelectButton that displays and sets the property.
*
* @config is usually a GimpProcedureConfig (but it could be otherwise.)
* The @config must have a property with name @property_name.
* The property must be type #GimpBrush.
* The @property_name need not be "brush",
* since the @config may have more than one property of type #GimpBrush.
*
* The button is labeled with the @property_name's nick.
*
* When pushed, the button pops up a dialog that lets the user choose a brush.
* The dialog will have the given title.
*
* Returns: (transfer full): The newly created #GimpBrushSelectButton widget.
*
* Since: 3.0
*/
GtkWidget *
gimp_prop_chooser_brush_new (GObject *config, const gchar *property_name, const gchar *title)
{
return gimp_prop_chooser_factory (gimp_brush_select_button_new, config, property_name, title);
};
GtkWidget *
gimp_prop_chooser_font_new (GObject *config, const gchar *property_name, const gchar *title)
{
return gimp_prop_chooser_factory (gimp_font_select_button_new, config, property_name, title);
};
GtkWidget *
gimp_prop_chooser_gradient_new (GObject *config, const gchar *property_name, const gchar *title)
{
return gimp_prop_chooser_factory (gimp_gradient_select_button_new, config, property_name, title);
};
GtkWidget *
gimp_prop_chooser_palette_new (GObject *config, const gchar *property_name, const gchar *title)
{
return gimp_prop_chooser_factory (gimp_palette_select_button_new, config, property_name, title);
};
GtkWidget *
gimp_prop_chooser_pattern_new (GObject *config, const gchar *property_name, const gchar *title)
{
return gimp_prop_chooser_factory (gimp_pattern_select_button_new, config, property_name, title);
};

47
libgimp/gimppropchooser.h Normal file
View File

@@ -0,0 +1,47 @@
/* LIBGIMP - The GIMP Library
* Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
*
* This library is free software: you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see
* <https://www.gnu.org/licenses/>.
*/
#if !defined (__GIMP_UI_H_INSIDE__) && !defined (GIMP_COMPILATION)
#error "Only <libgimp/gimpui.h> can be included directly."
#endif
#ifndef __GIMP_PROP_CHOOSER_H__
#define __GIMP_PROP_CHOOSER_H__
G_BEGIN_DECLS
GtkWidget *gimp_prop_chooser_brush_new (GObject *config,
const gchar *property_name,
const gchar *chooser_title);
GtkWidget *gimp_prop_chooser_font_new (GObject *config,
const gchar *property_name,
const gchar *chooser_title);
GtkWidget *gimp_prop_chooser_gradient_new (GObject *config,
const gchar *property_name,
const gchar *chooser_title);
GtkWidget *gimp_prop_chooser_palette_new (GObject *config,
const gchar *property_name,
const gchar *chooser_title);
GtkWidget *gimp_prop_chooser_pattern_new (GObject *config,
const gchar *property_name,
const gchar *chooser_title);
G_END_DECLS
#endif /* __GIMP_PROP_CHOOSER_H__ */

View File

@@ -0,0 +1,118 @@
/* LIBGIMP - The GIMP Library
* Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
*
* This library is free software: you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see
* <https://www.gnu.org/licenses/>.
*/
#include "config.h"
#include <gegl.h>
#include <gtk/gtk.h>
#include "libgimp/gimp.h"
#include "libgimp/gimpui.h"
static GimpResource * get_initial_resource_from_config (GObject *config,
const gchar *property_name);
/**
* gimp_prop_chooser_factory:
* @widget_creator_func: (scope async): Function that creates a chooser widget
* @config: Object to which property is attached.
* @property_name: Name of property set by the widget.
* @chooser_title: Title for the popup chooser dialog.
*
* Creates a #GimpResourceSelectButton that displays
* and sets the named property of the config.
*
* The factory makes many kinds of widgets.
* Parameterized by passing a creator function for a kind of widget.
* E.G. creator function is gimp_brush_select_button_new.
* The created widget must have a property named "resource".
*
* The factory wraps the widget so that it is a *prop* widget.
* A prop widget gets the initial choice from the @config
* and binds the property named @property_name
* of the @config to the widget's "resource" property.
*
* @config is usually a #GimpProcedureConfig (but it could be otherwise.)
* The @config must have a property with name @property_name.
* The property must be of type that matches that of the @widget_creator_func,
* e.g. #GimpBrush.
* The @property_name need not be "brush",
* since the @config may have more than one property of the same type e.g. #GimpBrush.
*
* Returns: (transfer full): The newly created #GimpResourceSelectButton widget.
*
* Since: 3.0
*/
GtkWidget *
gimp_prop_chooser_factory (GimpResourceWidgetCreator widget_creator_func,
GObject *config,
const gchar *property_name,
const gchar *chooser_title)
{
GtkWidget *result_widget;
GimpResource *initial_resource;
g_debug ("%s called", G_STRFUNC);
initial_resource = get_initial_resource_from_config (config, property_name);
/* initial_resource may be NULL.
* When NULL, the widget creator will set it's resource property from context.
* We bind with G_BINDING_SYNC_CREATE which immediately flows widget to config.
* So the config property is not NULL after this.
*/
/* Create the wrapped widget. For example, call gimp_font_select_button_new.*/
result_widget = widget_creator_func (chooser_title,
initial_resource);
/* Bind the wrapped widget's property to the config's property.
*
* The property name of the config can vary, e.g. "font" or "font1"
* The property name on widget is generic "resource" not specific e.g. "font"
*
* We bind G_BINDING_BIDIRECTIONAL.
* But we expect no other actor beside widget will change the config,
* (at least while the widget lives.)
* Bind from widget source to config target,
* because G_BINDING_SYNC_CREATE initially flows that way.
*/
g_object_bind_property (result_widget, /* Source for initial transfer */
"resource",
config, /* Target of initial transfer. */
property_name,
G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
return result_widget;
}
static GimpResource *
get_initial_resource_from_config (GObject *config,
const gchar *property_name)
{
GimpResource *initial_resource;
g_debug ("%s called", G_STRFUNC);
g_object_get (config,
property_name, &initial_resource,
NULL);
return initial_resource;
}

View File

@@ -0,0 +1,46 @@
/* LIBGIMP - The GIMP Library
* Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
*
* This library is free software: you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see
* <https://www.gnu.org/licenses/>.
*/
#if !defined (__GIMP_UI_H_INSIDE__) && !defined (GIMP_COMPILATION)
#error "Only <libgimp/gimpui.h> can be included directly."
#endif
#ifndef __GIMP_PROP_CHOOSER_FACTORY_H__
#define __GIMP_PROP_CHOOSER_FACTORY_H__
G_BEGIN_DECLS
/**
* GimpResourceWidgetCreator:
* @title: title of the popup chooser dialog
* @initial_resource: Resource to show as initial choice
*
* Function producing a chooser widget for a specific GimpResource object type.
* e.g. gimp_font_select_button_new
* Widgets for resource subclass choosers all have the same signature.
**/
typedef GtkWidget* (*GimpResourceWidgetCreator)(const gchar* title, GimpResource * initial_resource);
GtkWidget *gimp_prop_chooser_factory (GimpResourceWidgetCreator widget_creator_func,
GObject *config,
const gchar *property_name,
const gchar *chooser_title);
G_END_DECLS
#endif /* __GIMP_PROP_CHOOSER_FACTORY_H__ */

View File

@@ -0,0 +1,622 @@
/* LIBGIMP - The GIMP Library
* Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
*
* This library is free software: you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see
* <https://www.gnu.org/licenses/>.
*/
#include "config.h"
#include "gimp.h"
/* Data bounced back and forth to/from core and libgimp,
* and here from the temp PDB procedure to the idle func.
* But it is opaque to core, passed and returned unaltered.
*
* Not all fields are meaningful in each direction or transfer.
* !!! We don't pass resource to core in this struct,
* only from the temp callback to the idle func.
*
* Lifetime is as long as the remote dialog is open.
* Closing the chooser dialog frees the adaption struct.
*/
typedef struct
{
/* This portion is passed to and from idle. */
/* !!! resource is not long lived, only during a transfer to idle. */
guint idle_id;
GimpResource *resource;
GType resource_type;
gboolean closing;
/* This portion is passed to and from core, and to idle. */
gchar *temp_PDB_callback_name;
GimpResourceChoosedCallback callback;
gpointer owner_data;
GDestroyNotify data_destroy;
} GimpResourceAdaption;
/* local */
static void gimp_resource_data_free (GimpResourceAdaption *adaption);
static GimpValueArray * gimp_temp_resource_run (GimpProcedure *procedure,
const GimpValueArray *args,
gpointer run_data);
static gboolean gimp_temp_resource_idle (GimpResourceAdaption *adaption);
/* public */
/* Annotation, which appears in the libgimp API doc.
* Not a class, only functions.
* The functions appear as class methods of GimpResource class.
* Formerly, API had separate functions for each resource subclass.
*/
/**
* SECTION: gimpresourceselect
* @title: GimpResourceSelect
* @short_description: A resource selection dialog.
*
* A resource selection dialog.
*
* An adapter and proxy between libgimp and core.
* (see Adapter and Proxy patterns in programming literature.)
*
* Proxy: to a remote dialog in core.
* Is a dialog, but the dialog is remote (another process.)
* Remote dialog is a chooser dialog of subclass of GimpResource,
* e.g. GimpBrush, GimpFont, etc.
*
* Adapter: gets a callback via PDB procedure from remote dialog
* and shuffles parameters to call a owner's callback on libgimp side.
*
* Generic on type of GimpResource subclass.
* That is, the type of GimpResource subclass is passed.
*
* Responsibilities:
*
* - implement a proxy to a chooser widget in core
*
* Collaborations:
*
* - called by GimpResourceSelectButton to popup as a sibling widget
* - PDB procedures to/from core, which implements the remote dialog
* (from via PDB temp callback, to via PDB procs such as gimp_fonts_popup)
* - plugins implementing their own GUI
**/
/* This was extracted from gimpbrushselect.c, gimpfontselect.c, etc.
* and those were deleted.
*/
/* Functions that dispatch on resource type.
*
* For now, the design is that core callbacks pass
* attributes of the resource (not just the resource.)
* FUTURE: core will use the same signature for all remote dialogs,
* regardless of resource type.
* Then all this dispatching code can be deleted.
*/
/* Create args for temp PDB callback.
* Must match signature that core hardcodes in a subclass of gimp_pdb_dialog.
*
* For example, see app/widgets/paletteselect.c
*
* When testing, the error "Unable to run callback... temp_proc... wrong type"
* means a signature mismatch.
*
* Note the signature from core might be from an old design where
* the core sent all data needed to draw the resource.
* In the new design, libgimp gets the attributes of the resource
* from core in a separate PDB proc call back to core.
* While core uses the old design and libgimp uses the new design,
* libgimp simply ignores the extra args (adapts the signature.)
*/
static void
create_callback_PDB_procedure_params (
GimpProcedure *procedure,
GType resource_type)
{
/* Order of args is important. */
/* Prefix of args is same across resource_type. */
/* !!! core gimp_pdb_dialog is still passing string. */
GIMP_PROC_ARG_STRING (procedure, "resource-name",
"Resource name",
"The resource name",
NULL,
G_PARAM_READWRITE);
/* Create args for the extra, superfluous args that core is passing.*/
if (g_type_is_a (resource_type, GIMP_TYPE_FONT))
{
/* No other args. */
}
else if (g_type_is_a (resource_type, GIMP_TYPE_GRADIENT))
{
GIMP_PROC_ARG_INT (procedure, "gradient-width",
"Gradient width",
"The gradient width",
0, G_MAXINT, 0,
G_PARAM_READWRITE);
GIMP_PROC_ARG_FLOAT_ARRAY (procedure, "gradient-data",
"Gradient data",
"The gradient data",
G_PARAM_READWRITE);
}
else if (g_type_is_a (resource_type, GIMP_TYPE_BRUSH))
{
GIMP_PROC_ARG_DOUBLE (procedure, "opacity",
"Opacity",
NULL,
0.0, 100.0, 100.0,
G_PARAM_READWRITE);
GIMP_PROC_ARG_INT (procedure, "spacing",
"Spacing",
NULL,
-1, 1000, 20,
G_PARAM_READWRITE);
GIMP_PROC_ARG_ENUM (procedure, "paint-mode",
"Paint mode",
NULL,
GIMP_TYPE_LAYER_MODE,
GIMP_LAYER_MODE_NORMAL,
G_PARAM_READWRITE);
GIMP_PROC_ARG_INT (procedure, "mask-width",
"Brush width",
NULL,
0, 10000, 0,
G_PARAM_READWRITE);
GIMP_PROC_ARG_INT (procedure, "mask-height",
"Brush height",
NULL,
0, 10000, 0,
G_PARAM_READWRITE);
GIMP_PROC_ARG_INT (procedure, "mask-len",
"Mask length",
"Length of brush mask data",
0, G_MAXINT, 0,
G_PARAM_READWRITE);
GIMP_PROC_ARG_UINT8_ARRAY (procedure, "mask-data",
"Mask data",
"The brush mask data",
G_PARAM_READWRITE);
}
else if (g_type_is_a (resource_type, GIMP_TYPE_PALETTE))
{
GIMP_PROC_ARG_INT (procedure, "num-colors",
"Num colors",
"Number of colors",
0, G_MAXINT, 0,
G_PARAM_READWRITE);
}
else if (g_type_is_a (resource_type, GIMP_TYPE_PATTERN))
{
GIMP_PROC_ARG_INT (procedure, "mask-width",
"Mask width",
"Pattern width",
0, 10000, 0,
G_PARAM_READWRITE);
GIMP_PROC_ARG_INT (procedure, "mask-height",
"Mask height",
"Pattern height",
0, 10000, 0,
G_PARAM_READWRITE);
GIMP_PROC_ARG_INT (procedure, "mask-bpp",
"Mask bpp",
"Pattern bytes per pixel",
0, 10000, 0,
G_PARAM_READWRITE);
GIMP_PROC_ARG_INT (procedure, "mask-len",
"Mask length",
"Length of pattern mask data",
0, G_MAXINT, 0,
G_PARAM_READWRITE);
GIMP_PROC_ARG_UINT8_ARRAY (procedure, "mask-data",
"Mask data",
"The pattern mask data",
G_PARAM_READWRITE);
}
else
{
g_warning ("%s: unhandled resource type", G_STRFUNC);
}
/* Suffix of args is same across resource_type. */
GIMP_PROC_ARG_BOOLEAN (procedure, "closing",
"Closing",
"If the dialog was closing",
FALSE,
G_PARAM_READWRITE);
}
/* Open (create) a remote chooser dialog of resource.
*
* Dispatch on subclass of GimpResource.
* Call a PDB procedure that communicates with core to create remote dialog.
*/
static gboolean
popup_remote_chooser (
const gchar *title,
GimpResource *resource,
gchar *temp_PDB_callback_name,
GType resource_type)
{
gboolean result = FALSE;
gchar *resource_name;
g_debug ("%s", G_STRFUNC);
/* The PDB procedure still takes a name aka ID instead of a resource object. */
g_object_get (resource, "id", &resource_name, NULL);
if (g_type_is_a (resource_type, GIMP_TYPE_BRUSH))
{
result = gimp_brushes_popup (temp_PDB_callback_name, title, resource_name);
}
else if (g_type_is_a (resource_type, GIMP_TYPE_FONT))
{
result = gimp_fonts_popup (temp_PDB_callback_name, title, resource_name);
}
else if (g_type_is_a (resource_type, GIMP_TYPE_GRADIENT))
{
result = gimp_gradients_popup (temp_PDB_callback_name, title, resource_name);
}
else if (g_type_is_a (resource_type, GIMP_TYPE_PALETTE))
{
result = gimp_palettes_popup (temp_PDB_callback_name, title, resource_name);
}
else if (g_type_is_a (resource_type, GIMP_TYPE_PATTERN))
{
result = gimp_patterns_popup (temp_PDB_callback_name, title, resource_name);
}
else
{
g_warning ("%s: unhandled resource type", G_STRFUNC);
}
return result;
}
/*Does nothing, quietly, when the remote dialog is not open. */
static void
close_remote_chooser (
gchar *temp_PDB_callback_name,
GType resource_type)
{
if (g_type_is_a (resource_type, GIMP_TYPE_FONT))
{
gimp_fonts_close_popup (temp_PDB_callback_name);
}
else if (g_type_is_a (resource_type, GIMP_TYPE_GRADIENT))
{
gimp_gradients_close_popup (temp_PDB_callback_name);
}
else if (g_type_is_a (resource_type, GIMP_TYPE_BRUSH))
{
gimp_brushes_close_popup (temp_PDB_callback_name);
}
else if (g_type_is_a (resource_type, GIMP_TYPE_PALETTE))
{
gimp_palettes_close_popup (temp_PDB_callback_name);
}
else if (g_type_is_a (resource_type, GIMP_TYPE_PATTERN))
{
gimp_patterns_close_popup (temp_PDB_callback_name);
}
else
{
g_warning ("%s: unhandled resource type", G_STRFUNC);
}
}
/* Get the index of the is_closing arg in a GimpValueArray of the tempPDBproc.
* Count the extra args above, and add that to 1.
*/
static gint
index_of_is_closing_arg (GType resource_type)
{
if (g_type_is_a (resource_type, GIMP_TYPE_FONT))
{
return 1;
}
else if (g_type_is_a (resource_type, GIMP_TYPE_GRADIENT))
{
return 3;
}
else if (g_type_is_a (resource_type, GIMP_TYPE_BRUSH))
{
return 8;
}
else if (g_type_is_a (resource_type, GIMP_TYPE_PALETTE))
{
return 2;
}
else if (g_type_is_a (resource_type, GIMP_TYPE_PATTERN))
{
return 6;
}
else
{
g_warning ("%s: unhandled resource type", G_STRFUNC);
return 0;
}
}
/**
* gimp_resource_select_new:
* @title: Title of the resource selection dialog.
* @resource: The resource to set as the initial choice.
* @resource_type: The type of the subclass of resource.
* @callback: (scope notified): The callback function to call when a user chooses a resource.
* @owner_data: (closure callback): The run_data given to @callback.
* @data_destroy: (destroy owner_data): The destroy function for @owner_data.
*
* Invoke a resource chooser dialog which may call @callback with the chosen
* resource and owner's @data.
*
* A proxy to a remote dialog in core, which knows the model i.e. installed resources.
*
* Generic on type of #GimpResource subclass passed in @resource_type.
*
* Returns: (transfer none): the name of a temporary PDB procedure. The
* string belongs to the resource selection dialog and will be
* freed automatically when the dialog is closed.
**/
const gchar *
gimp_resource_select_new (
const gchar *title,
GimpResource *resource,
GType resource_type,
GimpResourceChoosedCallback callback,
gpointer owner_data,
GDestroyNotify data_destroy)
{
GimpPlugIn *plug_in = gimp_get_plug_in ();
GimpProcedure *procedure;
gchar *temp_PDB_callback_name;
GimpResourceAdaption *adaption;
g_debug ("%s", G_STRFUNC);
g_return_val_if_fail (resource != NULL, NULL);
g_return_val_if_fail (callback != NULL, NULL);
g_return_val_if_fail (resource_type != 0, NULL);
temp_PDB_callback_name = gimp_pdb_temp_procedure_name (gimp_get_pdb ());
adaption = g_slice_new0 (GimpResourceAdaption);
adaption->temp_PDB_callback_name = temp_PDB_callback_name;
adaption->callback = callback;
adaption->owner_data = owner_data;
adaption->data_destroy = data_destroy;
adaption->resource_type = resource_type;
/* !!! Only part of the adaption has been initialized. */
procedure = gimp_procedure_new (plug_in,
temp_PDB_callback_name,
GIMP_PDB_PROC_TYPE_TEMPORARY,
gimp_temp_resource_run,
adaption,
(GDestroyNotify) gimp_resource_data_free);
create_callback_PDB_procedure_params (procedure, resource_type);
gimp_plug_in_add_temp_procedure (plug_in, procedure);
g_object_unref (procedure);
if (popup_remote_chooser (title, resource, temp_PDB_callback_name, resource_type))
{
/* Allow callbacks to be watched */
gimp_plug_in_extension_enable (plug_in);
return temp_PDB_callback_name;
}
else
{
g_warning ("Failed to open remote resource select dialog.");
gimp_plug_in_remove_temp_procedure (plug_in, temp_PDB_callback_name);
return NULL;
}
}
void
gimp_resource_select_destroy (const gchar *temp_PDB_callback_name)
{
GimpPlugIn *plug_in = gimp_get_plug_in ();
g_debug ("%s", G_STRFUNC);
g_return_if_fail (temp_PDB_callback_name != NULL);
gimp_plug_in_remove_temp_procedure (plug_in, temp_PDB_callback_name);
/* Assert that removing temp procedure will callback the destroy function
* gimp_resource_data_free.
* The allocated adaption must not be used again.
*/
}
/* Set currently selected resource in remote chooser.
*
* Calls a PDB procedure.
*
* Note core is still using string name of resource,
* so pdb/groups/<foo>_select.pdb, <foo>_set_popup must have type string.
*/
void
gimp_resource_select_set (
const gchar *temp_pdb_callback,
GimpResource *resource,
GType resource_type)
{
gchar * resource_name;
g_debug ("%s", G_STRFUNC);
/* The remote setter is e.g. gimp_fonts_set_popup, a PDB procedure.
* It still takes a name aka ID instead of a resource object.
*/
g_object_get (resource, "id", &resource_name, NULL);
if (g_type_is_a (resource_type, GIMP_TYPE_FONT))
{
gimp_fonts_set_popup (temp_pdb_callback, resource_name);
}
else if (g_type_is_a (resource_type, GIMP_TYPE_GRADIENT))
{
gimp_gradients_set_popup (temp_pdb_callback, resource_name);
}
else if (g_type_is_a (resource_type, GIMP_TYPE_BRUSH))
{
gimp_brushes_set_popup (temp_pdb_callback, resource_name);
}
else if (g_type_is_a (resource_type, GIMP_TYPE_PALETTE))
{
gimp_palettes_set_popup (temp_pdb_callback, resource_name);
}
else if (g_type_is_a (resource_type, GIMP_TYPE_PATTERN))
{
gimp_patterns_set_popup (temp_pdb_callback, resource_name);
}
else
{
g_warning ("%s: unhandled resource type", G_STRFUNC);
}
}
/* private functions */
/* Free a GimpResourceAdaption struct.
* A GimpResourceAdaption and this func are passed to a GimpProcedure
* and this func is called back when the procedure is removed.
*
* This can be called for the exception: failed to open remote dialog.
*
* Each allocated field must be safely freed (not assuming it is valid pointer.)
*/
static void
gimp_resource_data_free (GimpResourceAdaption *adaption)
{
g_debug ("%s", G_STRFUNC);
if (adaption->idle_id)
g_source_remove (adaption->idle_id);
/* adaption->resource should be NULL, else we failed to transfer to the owner. */
g_clear_object (&adaption->resource);
if (adaption->temp_PDB_callback_name)
{
close_remote_chooser (adaption->temp_PDB_callback_name, adaption->resource_type);
g_free (adaption->temp_PDB_callback_name);
}
/* Destroy any inner generic data passed by the owner. */
if (adaption->data_destroy)
adaption->data_destroy (adaption->owner_data);
g_slice_free (GimpResourceAdaption, adaption);
}
/* Run func for the temporary PDB procedure.
* Called when user chooses a resource in remote dialog.
*/
static GimpValueArray *
gimp_temp_resource_run (
GimpProcedure *procedure,
const GimpValueArray *args,
gpointer run_data) /* is-a adaption */
{
GimpResourceAdaption *adaption = run_data;
const gchar *resource_name;
GimpResource *resource;
g_debug ("%s", G_STRFUNC);
/* Convert name string to object. */
resource_name = GIMP_VALUES_GET_STRING(args, 0);
resource = g_object_new (adaption->resource_type, "id", resource_name, NULL);
/* Pass the new resource object to the idle func, which will transfer ownership.
* and clear adaption->resource.
* Thus assert that adaption->resource is NULL, and this is not a leak.
*/
adaption->resource = resource;
/* !!! Adapting the temp PDB callback signature to simplified libgimp callback.
* I.E. discarding args that are attributes of the resource.
*/
adaption->closing = GIMP_VALUES_GET_BOOLEAN (args, index_of_is_closing_arg (adaption->resource_type));
/* Set idle_id to remember an idle source exists,
* but idle_id is not used by the idle func.
*/
if (! adaption->idle_id)
adaption->idle_id = g_idle_add ((GSourceFunc) gimp_temp_resource_idle,
adaption);
return gimp_procedure_new_return_values (procedure, GIMP_PDB_SUCCESS, NULL);
}
static gboolean
gimp_temp_resource_idle (GimpResourceAdaption *adaption)
{
adaption->idle_id = 0;
g_debug ("%s", G_STRFUNC);
/* We don't expect callback to be NULL, but check anyway.
* This is asynchronous so there could be a race.
*/
if (adaption->callback)
adaption->callback (adaption->resource,
adaption->closing,
adaption->owner_data);
/* Ownership of resource transfers to whom we are calling back. */
adaption->resource = NULL;
if (adaption->closing)
{
gchar *temp_PDB_callback_name = adaption->temp_PDB_callback_name;
adaption->temp_PDB_callback_name = NULL;
gimp_resource_select_destroy (temp_PDB_callback_name);
g_free (temp_PDB_callback_name);
}
return G_SOURCE_REMOVE;
}

View File

@@ -0,0 +1,55 @@
/* LIBGIMP - The GIMP Library
* Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
*
* This library is free software: you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see
* <https://www.gnu.org/licenses/>.
*/
#if !defined (__GIMP_H_INSIDE__) && !defined (GIMP_COMPILATION)
#error "Only <libgimp/gimp.h> can be included directly."
#endif
#ifndef __GIMP_RESOURCE_SELECT_H__
#define __GIMP_RESOURCE_SELECT_H__
G_BEGIN_DECLS
/**
* GimpResourceChoosedCallback:
* @resource: Chosen resource
* @is_dialog_closing: Did user click Close button of dialog?
* @owner_data: (closure): Owner's data
*
* Callback from libgimp GimpResourceSelect adapter to owner.
**/
typedef void (* GimpResourceChoosedCallback) (GimpResource *resource,
gboolean is_dialog_closing,
gpointer owner_data);
const gchar * gimp_resource_select_new (const gchar *title,
GimpResource *resource,
GType resource_type,
GimpResourceChoosedCallback callback,
gpointer owner_data,
GDestroyNotify data_destroy);
void gimp_resource_select_destroy (const gchar *temp_pdb_callback);
void gimp_resource_select_set (const gchar *temp_pdb_callback,
GimpResource *resource,
GType resource_type);
G_END_DECLS
#endif /* __GIMP_RESOURCE_SELECT_H__ */

View File

@@ -0,0 +1,731 @@
/* LIBGIMP - The GIMP Library
* Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
*
* This library is free software: you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see
* <https://www.gnu.org/licenses/>.
*/
#include "config.h"
#include <gegl.h>
#include <gtk/gtk.h>
#include "libgimpwidgets/gimpwidgets.h"
#include "gimp.h"
#include "gimpuitypes.h"
#include "gimpresourceselectbutton.h"
#include "gimpuimarshal.h"
#include "libgimp-intl.h"
/* Annotation for the class, which appears in the GimpUi doc. */
/**
* SECTION: gimpresourceselectbutton
* @title: GimpResourceSelectButton
* @short_description: Base class for buttons that popup a resource selection dialog.
*
* A button which pops up a resource selection dialog.
*
* Subclasses: GimpFontSelectButton is a minimal one.
* A subclass provides button trait (clickable),
* but possibly not a GtkButton and may have many sub widgets.
*
* Responsibilities:
*
* - implementing outer container widget,
* - managing clicks and popping up a remote chooser,
* - having a resource property,
* - signaling when user selects resource
* - receiving drag,
* - triggering draws of the button interior (by subclass) and draws of remote popup chooser.
*
* Collaborations:
*
* - owned by GimpProcedureDialog via GimpPropWidget
* - resource property usually bound to a GimpConfig for a GimpPluginProcedure.
* - communicates using GimpResourceSelect with remote GimpPDBDialog,
* to choose an installed GimpResource owned by core.
*
* Subclass responsibilities:
*
* - creating interior widgets
* - drawing the interior (a preview of the chosen resource)
* - declaring which interior widgets are drag destinations
* - declaring which interior widgets are clickable (generate "clicked" signal)
* - generate "clicked" (delegating to GtkButton or implementing from mouse events)
*
* Class is abstract and cannot be instantiated: no new () method.
* Instead, instantiate a subclass.
*
* Since: 3.0
**/
/* This class was derived from GimpSelectButton and its subclass GimpPatternSelectButton.
* By moving things from the subclass to the super class, generalizing.
* I.E. refactored by inheriting methods that are the same across subclasses.
*/
enum
{
RESOURCE_SET,
LAST_SIGNAL
};
enum
{
PROP_0,
PROP_TITLE,
PROP_RESOURCE,
N_PROPS
};
/* Private structure definition. */
typedef struct
{
GimpResource *resource; /* Thing self widget chooses*/
/* Type of resource is known by the class, not instance.
* e.g. GimpFont, some subclass of GimpResource
*/
/* Self collaborates with a remote widget, a popup chooser dialog. */
const gchar *title; /* Title of remote widget. */
/* Interface functions to remote dialog.
* Instance knows a temporary PDB procedure which the remote dialog callbacks self.
* This specializes us, and is returned by a call to e.g. gimp_pattern_select_new,
* a libgimp function that talks to remote dialog.
*
* It does not need to be freed, owned by the PDB.
*/
const gchar *temp_callback_from_remote_dialog;
/* Self is-a GtkContainer widget to which subclasses will embed. */
/* Widget interior to self, created and drawn by subclass. */
GtkWidget *interior_widget;
} GimpResourceSelectButtonPrivate;
/* local function prototypes */
/* Overridden GObject methods. */
static void gimp_resource_select_button_dispose (GObject *object);
static void gimp_resource_select_button_finalize (GObject *object);
static void gimp_resource_select_button_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec);
static void gimp_resource_select_button_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec);
static void gimp_resource_select_button_clicked (GimpResourceSelectButton *self);
static void gimp_resource_select_button_callback (GimpResource *resource,
gboolean dialog_closing,
gpointer user_data);
static void gimp_resource_select_drag_data_received (GimpResourceSelectButton *self,
GdkDragContext *context,
gint x,
gint y,
GtkSelectionData *selection,
guint info,
guint time);
static void gimp_resource_select_button_set_remote_dialog (GimpResourceSelectButton *self,
GimpResource *resource);
static guint resource_button_signals[LAST_SIGNAL] = { 0 };
static GParamSpec *resource_button_props[N_PROPS] = { NULL, };
G_DEFINE_TYPE_WITH_PRIVATE (GimpResourceSelectButton, gimp_resource_select_button,
GTK_TYPE_BOX)
static void
gimp_resource_select_button_class_init (GimpResourceSelectButtonClass *klass)
{
/* Root super class */
GObjectClass *object_class = G_OBJECT_CLASS (klass);
g_debug ("%s", G_STRFUNC);
/* Override to root super class GObject. */
object_class->dispose = gimp_resource_select_button_dispose;
object_class->finalize = gimp_resource_select_button_finalize;
object_class->set_property = gimp_resource_select_button_set_property;
object_class->get_property = gimp_resource_select_button_get_property;
/* Signals */
klass->resource_set = NULL;
/**
* GimpResourceSelectButton:title:
*
* The title to be used for the resource selection popup dialog.
*
* Since: 2.4
*/
/* Default is not localized i18n since caller should provide a value. */
resource_button_props[PROP_TITLE]
= g_param_spec_string ("title",
"Title",
"The title to be used for the resource selection popup dialog",
"Resource Selection", /* default */
GIMP_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY);
/**
* GimpResourceSelectButton:resource:
*
* The currently selected resource.
*
* Since: 2.4
*/
/* Has no default. */
resource_button_props[PROP_RESOURCE]
= gimp_param_spec_resource ("resource", /* name */
"Resource", /* nick */
"The currently selected resource",
TRUE, /* none_ok */
GIMP_PARAM_READWRITE);
g_object_class_install_properties (object_class, N_PROPS, resource_button_props);
/**
* GimpResourceSelectButton::resource-set:
* @widget: the object which received the signal.
* @resource: the currently selected resource.
* @dialog_closing: whether the dialog was closed or not.
*
* The ::resource-set signal is emitted when the user selects a resource.
*
* Since: 2.4
*/
resource_button_signals[RESOURCE_SET] =
g_signal_new ("resource-set",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (GimpResourceSelectButtonClass, resource_set),
NULL, NULL,
_gimpui_marshal_VOID__POINTER_BOOLEAN,
G_TYPE_NONE, 2,
G_TYPE_OBJECT,
G_TYPE_BOOLEAN);
}
static void
gimp_resource_select_button_init (GimpResourceSelectButton *self)
{
GimpResourceSelectButtonPrivate *priv = gimp_resource_select_button_get_instance_private (self);
g_debug ("%s", G_STRFUNC);
g_return_if_fail (GIMP_IS_RESOURCE_SELECT_BUTTON (self));
gtk_orientable_set_orientation (GTK_ORIENTABLE (self), GTK_ORIENTATION_HORIZONTAL);
/* No need to initialize interior_widget. A subclass will add it, which must have a clickable.*/
/* Remote dialog not exist yet. */
priv->temp_callback_from_remote_dialog = NULL;
}
/**
* gimp_resource_select_button_set_drag_target:
* @self: A #GimpResourceSelectButton
* @drag_region_widget: An interior widget to be a droppable region and emit "drag-data-received" signal
* @drag_target: The drag target to accept
*
* Called by a subclass init to specialize the instance.
*
* Subclass knows its interior widget whose region is a drop zone.
* Subclass knows what things can be dropped (target.)
* Self (super) handles the drop.
*
* Since: 3.0
**/
void
gimp_resource_select_button_set_drag_target (
GimpResourceSelectButton *self,
GtkWidget *drag_region_widget,
const GtkTargetEntry *drag_target)
{
g_debug ("%s", G_STRFUNC);
g_return_if_fail (GIMP_IS_RESOURCE_SELECT_BUTTON (self));
g_return_if_fail (drag_target != NULL);
g_return_if_fail (drag_region_widget != NULL);
gtk_drag_dest_set (drag_region_widget,
GTK_DEST_DEFAULT_HIGHLIGHT |
GTK_DEST_DEFAULT_MOTION |
GTK_DEST_DEFAULT_DROP,
drag_target, 1, /* Pass array of size 1 */
GDK_ACTION_COPY);
/* connect drag_region_widget's drag_received signal to self's callback. */
g_signal_connect_swapped (drag_region_widget, "drag-data-received",
G_CALLBACK (gimp_resource_select_drag_data_received),
self);
}
/**
* gimp_resource_select_button_set_clickable:
* @self: A #GimpResourceSelectButton
* @widget: An interior widget that emits "clicked" signal
*
* Called by a subclass init to specialize the instance.
*
* Subclass knows its interior widget whose region when clicked
* should popup remote chooser.
* Self handles the click event.
*
* Since: 3.0
**/
void
gimp_resource_select_button_set_clickable (GimpResourceSelectButton *self,
GtkWidget *widget)
{
g_debug ("%s", G_STRFUNC);
g_return_if_fail (GIMP_IS_RESOURCE_SELECT_BUTTON (self));
g_return_if_fail (widget != NULL);
g_return_if_fail (GTK_IS_WIDGET (widget));
/* Require the widget have a signal "clicked", usually a button. */
g_signal_connect_swapped (widget, "clicked",
G_CALLBACK (gimp_resource_select_button_clicked),
self);
}
/**
* gimp_resource_select_button_get_resource:
* @self: A #GimpResourceSelectButton
*
* Gets the currently selected resource.
*
* Returns: (transfer none): an internal copy of the resource which must not be freed.
* You should ref and unref it when you want to own the resource.
*
* Since: 2.4
*/
GimpResource *
gimp_resource_select_button_get_resource (GimpResourceSelectButton *self)
{
GimpResourceSelectButtonPrivate *priv;
g_return_val_if_fail (GIMP_IS_RESOURCE_SELECT_BUTTON (self), NULL);
priv = gimp_resource_select_button_get_instance_private (self);
return priv->resource;
}
/**
* gimp_resource_select_button_set_resource:
* @self: A #GimpResourceSelectButton
* @resource: Resource to set.
*
* Sets the currently selected resource.
* This will select the resource in both the button and any chooser popup.
*
* Since: 2.4
*/
void
gimp_resource_select_button_set_resource (GimpResourceSelectButton *self,
GimpResource *resource)
{
GimpResourceSelectButtonPrivate *priv;
g_return_if_fail (GIMP_IS_RESOURCE_SELECT_BUTTON (self));
g_return_if_fail (resource != NULL);
priv = gimp_resource_select_button_get_instance_private (self);
g_debug ("%s", G_STRFUNC);
if (priv->temp_callback_from_remote_dialog)
{
/* A popup chooser dialog is already shown.
* Call its setter to change the selection there
* (since all views of the resource must be consistent.)
* That will call back, which will change our own view of the resource.
*/
gimp_resource_select_button_set_remote_dialog (self, resource);
}
else
{
/* Call our own setter. */
gimp_resource_select_button_callback (resource, FALSE, self);
}
}
/**
* gimp_resource_select_button_embed_interior:
* @self: A #GimpResourceSelectButton
* @interior: Interior widget to embed into the exterior container widget.
*
* Called by subclasses init to specialize the instance.
*
* Embed an interior widget into self's outer container widget.
*
* Since: 3.0
*/
void
gimp_resource_select_button_embed_interior (GimpResourceSelectButton *self, GtkWidget * interior)
{
g_return_if_fail (GIMP_IS_RESOURCE_SELECT_BUTTON (self));
g_return_if_fail (GTK_IS_WIDGET (interior));
g_return_if_fail (GTK_IS_CONTAINER (self));
gtk_container_add (GTK_CONTAINER (self), interior);
/* Show self as widget, now it is complete. */
gtk_widget_show_all (GTK_WIDGET (self));
/* We can't draw the interior until self property "resource" is set. */
}
/**
* gimp_resource_select_button_draw_interior:
* @self: A #GimpResourceSelectButton
* @resource: A resource instance whose attributes should be drawn.
*
* Calls the virtual method of a similar name, which subclasses must override.
*
* A subclass knows how to draw its interior.
* Called by super when the view is invalidated (needs to be redrawn.)
* Public, but subclasses do not ordinarily call this function.
*
* Since: 3.0
**/
void
gimp_resource_select_button_draw_interior (GimpResourceSelectButton *self, GimpResource *resource)
{
GimpResourceSelectButtonClass *klass;
g_debug ("%s", G_STRFUNC);
g_return_if_fail (GIMP_IS_RESOURCE_SELECT_BUTTON (self));
g_return_if_fail (GIMP_IS_RESOURCE (resource));
klass = GIMP_RESOURCE_SELECT_BUTTON_GET_CLASS (self);
/* Check subclass has overridden before calling it. */
g_return_if_fail (klass->draw_interior != NULL);
/* Call the subclass drawing method. */
klass->draw_interior (self);
/* Note that gtk_widget_queue_draw is specific to cairo drawing areas,
* and is not a general method of forcing a refresh of a wiget.
* We always call the subclass draw method via its implementation
* of our virtual draw method.
* The subclass may use gtk_widget_queue_draw, but we don't.
*/
}
/* private functions */
static void
gimp_resource_select_button_set_remote_dialog (GimpResourceSelectButton *self,
GimpResource *resource)
{
GimpResourceSelectButtonPrivate *priv;
GimpResourceSelectButtonClass *klass;
g_debug ("%s", G_STRFUNC);
g_return_if_fail (GIMP_IS_RESOURCE_SELECT_BUTTON (self));
g_return_if_fail (resource != NULL);
priv = gimp_resource_select_button_get_instance_private (self);
klass = GIMP_RESOURCE_SELECT_BUTTON_GET_CLASS (self);
/* Require virtual method was overridden by subclass. */
g_return_if_fail (klass->resource_type != G_TYPE_INVALID);
/* The ultimate remote setter is e.g. gimp_fonts_set_popup, a PDB procedure.
*
* !!! Use the passed resource, not priv->resource.
* Expect a callback which will change priv->resource.
*/
gimp_resource_select_set (priv->temp_callback_from_remote_dialog,
resource,
klass->resource_type);
}
/* Setter for property.
* Overrides setter of base class GObject.
* The underlying field may be NULL after init,
* but after that, do not allow it to be set to NULL.
* I.E. invariant is (priv->resource != NULL) after new ()
*/
static void
gimp_resource_select_button_set_property (GObject *object,
guint property_id,
const GValue *gvalue,
GParamSpec *pspec)
{
GimpResourceSelectButton *self = GIMP_RESOURCE_SELECT_BUTTON (object);
GimpResourceSelectButtonPrivate *priv = gimp_resource_select_button_get_instance_private (self);
g_debug ("%s, id: %i", G_STRFUNC, property_id);
switch (property_id)
{
case PROP_TITLE:
priv->title = g_value_dup_string (gvalue);
break;
case PROP_RESOURCE:
/* Do not use the exported method set_resource.
* That is internal and less safe
* because it is agnostic of NULL values passed,
* and does not unref any existing value.
*/
GimpResource * specific_value;
specific_value = g_value_get_object (gvalue);
g_assert (specific_value != NULL);
priv->resource = specific_value;
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void
gimp_resource_select_button_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec)
{
GimpResourceSelectButton *self = GIMP_RESOURCE_SELECT_BUTTON (object);
GimpResourceSelectButtonPrivate *priv = gimp_resource_select_button_get_instance_private (self);
switch (property_id)
{
case PROP_TITLE:
g_value_set_string (value, priv->title);
break;
case PROP_RESOURCE:
g_value_set_object (value, priv->resource);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
/* A callback from the remote resource select popup.
* When user chooses a resource.
* Via a temporary PDB procedure.
*
* Set self's model (priv->resource)
* Notify any parent widget subscribed on the "resource" property
* typically a prop widget.
* Update the view, since model changed.
*/
static void
gimp_resource_select_button_callback (GimpResource *resource,
gboolean dialog_closing,
gpointer user_data)
{
GimpResourceSelectButton *self = GIMP_RESOURCE_SELECT_BUTTON (user_data);
GimpResourceSelectButtonPrivate *priv = gimp_resource_select_button_get_instance_private (self);
g_debug ("%s, id: %s", G_STRFUNC, gimp_resource_get_id (resource));
g_object_unref (priv->resource);
priv->resource = resource;
/* Feedback user choice of resource into the look of the widget interior.
* Call virtual method overridden by subclass.
*/
gimp_resource_select_button_draw_interior (self, resource);
if (dialog_closing)
priv->temp_callback_from_remote_dialog = NULL;
g_signal_emit (self, resource_button_signals[RESOURCE_SET], 0, resource, dialog_closing);
g_object_notify_by_pspec (G_OBJECT (self), resource_button_props[PROP_RESOURCE]);
}
static void
gimp_resource_select_button_clicked (GimpResourceSelectButton *self)
{
GimpResourceSelectButtonPrivate *priv = gimp_resource_select_button_get_instance_private (self);
GimpResourceSelectButtonClass *klass = GIMP_RESOURCE_SELECT_BUTTON_GET_CLASS (self);
g_debug ("%s called", G_STRFUNC);
if (priv->temp_callback_from_remote_dialog)
{
/* Popup already created. Calling setter raises the popup. */
gimp_resource_select_button_set_remote_dialog (self, priv->resource);
}
else
{
g_debug ("%s calling newer of remote dialog", G_STRFUNC);
/* Call GimpResourceSelect which dispatches on resource_type. */
priv->temp_callback_from_remote_dialog =
gimp_resource_select_new (priv->title,
priv->resource,
klass->resource_type,
gimp_resource_select_button_callback,
self,
NULL); /* No func to free data. */
}
g_debug ("%s returns", G_STRFUNC);
}
/* Drag methods. */
static void
gimp_resource_select_drag_data_received (GimpResourceSelectButton *self,
GdkDragContext *context,
gint x,
gint y,
GtkSelectionData *selection,
guint info,
guint time)
{
gint length = gtk_selection_data_get_length (selection);
gchar *str;
GimpResourceSelectButtonClass *klass;
g_debug ("%s called", G_STRFUNC);
klass = GIMP_RESOURCE_SELECT_BUTTON_GET_CLASS (self);
/* Require class resource_type was initialized. */
g_assert (klass->resource_type != 0);
/* Drag data is a string that is the ID of the resource. */
if (gtk_selection_data_get_format (selection) != 8 || length < 1)
{
g_warning ("%s: received invalid resource data", G_STRFUNC);
return;
}
str = g_strndup ((const gchar *) gtk_selection_data_get_data (selection),
length);
if (g_utf8_validate (str, -1, NULL))
{
gint pid;
gpointer unused;
gint name_offset = 0;
if (sscanf (str, "%i:%p:%n", &pid, &unused, &name_offset) >= 2 &&
pid == gimp_getpid () && name_offset > 0)
{
gchar *name = str + name_offset;
GimpResource *resource;
/* Create just a proxy object, not a new resource in core.
* Create an instance of the type (e.g. GimpFont) that this class creates.
*/
resource = g_object_new (klass->resource_type, "id", name, NULL);
gimp_resource_select_button_set_resource (self, resource);
}
}
g_free (str);
}
/* Dispose, finalize, destroy. */
/* When self is disposed, e.g. when user Cancels owning dialog,
* close the remote popup, which will destroy it.
* Dispose is first phase to break possible cycle of the popup referencing self.
*/
static void
gimp_resource_select_button_dispose (GObject *self)
{
g_debug ("%s", G_STRFUNC);
gimp_resource_select_button_close_popup (GIMP_RESOURCE_SELECT_BUTTON (self));
/* Chain up. */
G_OBJECT_CLASS (gimp_resource_select_button_parent_class)->dispose (self);
}
/**
* gimp_resource_select_button_close_popup:
* @self: A #GimpResourceSelectButton
*
* Closes the popup resource chooser dialog associated with @self.
*
* FUTURE: Possibly obsolete this by making it private,
* since only called by script-fu-interface.c.
* Might be needed if we allow plugins to implement their own dialogs.
*
* Since: 2.4
*/
void
gimp_resource_select_button_close_popup (GimpResourceSelectButton *self)
{
GimpResourceSelectButtonPrivate *priv;
g_debug ("%s", G_STRFUNC);
g_return_if_fail (GIMP_IS_RESOURCE_SELECT_BUTTON (self));
priv = gimp_resource_select_button_get_instance_private (self);
if (priv->temp_callback_from_remote_dialog)
{
gimp_resource_select_destroy (priv->temp_callback_from_remote_dialog);
priv->temp_callback_from_remote_dialog = NULL;
}
/* Else already closed. */
}
static void
gimp_resource_select_button_finalize (GObject *object)
{
GimpResourceSelectButton *self = GIMP_RESOURCE_SELECT_BUTTON (object);
GimpResourceSelectButtonPrivate *priv = gimp_resource_select_button_get_instance_private (self);
g_debug ("%s", G_STRFUNC);
g_clear_pointer (&priv->resource, g_free);
g_free ((gpointer) priv->title);
/* Chain up. */
G_OBJECT_CLASS (gimp_resource_select_button_parent_class)->finalize (object);
}

View File

@@ -0,0 +1,85 @@
/* LIBGIMP - The GIMP Library
* Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
*
* This library is free software: you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see
* <https://www.gnu.org/licenses/>.
*/
#if !defined (__GIMP_UI_H_INSIDE__) && !defined (GIMP_COMPILATION)
#error "Only <libgimp/gimpui.h> can be included directly."
#endif
#ifndef __GIMP_RESOURCE_SELECT_BUTTON_H__
#define __GIMP_RESOURCE_SELECT_BUTTON_H__
G_BEGIN_DECLS
/* Inherits GtkBox
* Inheritable by e.g. GimpBrushSelectButton.
*/
#define GIMP_TYPE_RESOURCE_SELECT_BUTTON gimp_resource_select_button_get_type ()
G_DECLARE_DERIVABLE_TYPE (GimpResourceSelectButton, gimp_resource_select_button, GIMP, RESOURCE_SELECT_BUTTON, GtkBox)
struct _GimpResourceSelectButtonClass
{
GtkBoxClass parent_class;
/* Signal resource_set. Emitted when user chooses a resource.
* The signal carries only the resource (a proxy having an ID).
* The resource knows its own attributes needed for drawing it.
* Such attributes are NOT in the signal.
*
* Seems to be unused by GIMP internal code,
* instead GimpPropChooser binds to property.
*/
/* FIXME: should be an annotation. */
void (* resource_set) (GimpResourceSelectButton *self,
GimpResource *resource,
gboolean dialog_closing);
/* virtual methods. */
void (*draw_interior) (GimpResourceSelectButton *self);
/* Specialized by subclass. */
GType resource_type; /* e.g. GimpBrush */
/* Padding for future expansion */
gpointer padding[8];
};
/* Abstract, no new(), instead new a subclass. */
/* API from above, e.g. used by GimpPropChooser */
GimpResource *gimp_resource_select_button_get_resource (GimpResourceSelectButton *self);
void gimp_resource_select_button_set_resource (GimpResourceSelectButton *self,
GimpResource *resource);
/* Public, but called by super. */
void gimp_resource_select_button_draw_interior (GimpResourceSelectButton *self,
GimpResource *resource);
/* API from below, used by subclasses e.g. GimpBrushSelectButton */
void gimp_resource_select_button_embed_interior (GimpResourceSelectButton *self,
GtkWidget *interior);
void gimp_resource_select_button_set_drag_target (GimpResourceSelectButton *self,
GtkWidget *drag_region_widget,
const GtkTargetEntry *drag_target);
void gimp_resource_select_button_set_clickable (GimpResourceSelectButton *self,
GtkWidget *widget);
void gimp_resource_select_button_close_popup (GimpResourceSelectButton *self);
G_END_DECLS
#endif /* __GIMP_RESOURCE_SELECT_BUTTON_H__ */

View File

@@ -1,94 +0,0 @@
/* LIBGIMP - The GIMP Library
* Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
*
* gimpselectbutton.c
* Copyright (C) 2003 Sven Neumann <sven@gimp.org>
*
* This library is free software: you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see
* <https://www.gnu.org/licenses/>.
*/
#include "config.h"
#include <gtk/gtk.h>
#include "gimp.h"
#include "gimpuitypes.h"
#include "gimpselectbutton.h"
/**
* SECTION: gimpselectbutton
* @title: GimpSelectButton
* @short_description: The base class of the data select buttons.
*
* The base class of the brush, pattern, gradient, palette and font
* select buttons.
**/
/* local function prototypes */
static void gimp_select_button_dispose (GObject *object);
G_DEFINE_TYPE (GimpSelectButton, gimp_select_button, GTK_TYPE_BOX)
static void
gimp_select_button_class_init (GimpSelectButtonClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->dispose = gimp_select_button_dispose;
}
static void
gimp_select_button_init (GimpSelectButton *select_button)
{
gtk_orientable_set_orientation (GTK_ORIENTABLE (select_button),
GTK_ORIENTATION_HORIZONTAL);
}
static void
gimp_select_button_dispose (GObject *object)
{
gimp_select_button_close_popup (GIMP_SELECT_BUTTON (object));
G_OBJECT_CLASS (gimp_select_button_parent_class)->dispose (object);
}
/**
* gimp_select_button_close_popup:
* @button: A #GimpSelectButton
*
* Closes the popup window associated with @button.
*
* Since: 2.4
*/
void
gimp_select_button_close_popup (GimpSelectButton *button)
{
g_return_if_fail (GIMP_IS_SELECT_BUTTON (button));
if (button->temp_callback)
{
GimpSelectButtonClass *klass = GIMP_SELECT_BUTTON_GET_CLASS (button);
klass->select_destroy (button->temp_callback);
button->temp_callback = NULL;
}
}

View File

@@ -1,81 +0,0 @@
/* LIBGIMP - The GIMP Library
* Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
*
* gimpselectbutton.h
*
* This library is free software: you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see
* <https://www.gnu.org/licenses/>.
*/
#if !defined (__GIMP_UI_H_INSIDE__) && !defined (GIMP_COMPILATION)
#error "Only <libgimp/gimpui.h> can be included directly."
#endif
#ifndef __GIMP_SELECT_BUTTON_H__
#define __GIMP_SELECT_BUTTON_H__
G_BEGIN_DECLS
/* For information look into the C source or the html documentation */
#define GIMP_TYPE_SELECT_BUTTON (gimp_select_button_get_type ())
#define GIMP_SELECT_BUTTON(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_SELECT_BUTTON, GimpSelectButton))
#define GIMP_SELECT_BUTTON_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_SELECT_BUTTON, GimpSelectButtonClass))
#define GIMP_IS_SELECT_BUTTON(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_SELECT_BUTTON))
#define GIMP_IS_SELECT_BUTTON_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_SELECT_BUTTON))
#define GIMP_SELECT_BUTTON_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_SELECT_BUTTON, GimpSelectButtonClass))
typedef struct _GimpSelectButtonPrivate GimpSelectButtonPrivate;
typedef struct _GimpSelectButtonClass GimpSelectButtonClass;
struct _GimpSelectButton
{
GtkBox parent_instance;
GimpSelectButtonPrivate *priv;
/* FIXME MOVE TO PRIVATE */
const gchar *temp_callback;
};
struct _GimpSelectButtonClass
{
GtkBoxClass parent_class;
gchar *default_title;
void (* select_destroy) (const gchar *callback);
/* Padding for future expansion */
void (*_gimp_reserved1) (void);
void (*_gimp_reserved2) (void);
void (*_gimp_reserved3) (void);
void (*_gimp_reserved4) (void);
void (*_gimp_reserved5) (void);
void (*_gimp_reserved6) (void);
void (*_gimp_reserved7) (void);
void (*_gimp_reserved8) (void);
};
GType gimp_select_button_get_type (void) G_GNUC_CONST;
void gimp_select_button_close_popup (GimpSelectButton *button);
G_END_DECLS
#endif /* __GIMP_SELECT_BUTTON_H__ */

View File

@@ -61,12 +61,23 @@ EXPORTS
gimp_procedure_dialog_set_sensitive
gimp_progress_bar_get_type
gimp_progress_bar_new
gimp_prop_brush_chooser_button_new
gimp_prop_chooser_brush_new
gimp_prop_chooser_factory
gimp_prop_chooser_font_new
gimp_prop_chooser_gradient_new
gimp_prop_chooser_palette_new
gimp_prop_chooser_pattern_new
gimp_resource_select_button_close_popup
gimp_resource_select_button_draw_interior
gimp_resource_select_button_embed_interior
gimp_resource_select_button_get_resource
gimp_resource_select_button_get_type
gimp_resource_select_button_set_clickable
gimp_resource_select_button_set_drag_target
gimp_resource_select_button_set_resource
gimp_save_procedure_dialog_add_metadata
gimp_save_procedure_dialog_get_type
gimp_save_procedure_dialog_new
gimp_select_button_close_popup
gimp_select_button_get_type
gimp_ui_get_display_window
gimp_ui_get_progress_window
gimp_ui_init

View File

@@ -33,6 +33,7 @@
#include <libgimp/gimpbrushselectbutton.h>
#include <libgimp/gimpdrawablepreview.h>
#include <libgimp/gimpexport.h>
#include <libgimp/gimpresourceselectbutton.h>
#include <libgimp/gimpfontselectbutton.h>
#include <libgimp/gimpgradientselectbutton.h>
#include <libgimp/gimpimagecombobox.h>
@@ -43,10 +44,10 @@
#include <libgimp/gimpproceduredialog.h>
#include <libgimp/gimpprocview.h>
#include <libgimp/gimpprogressbar.h>
#include <libgimp/gimppropchooser.h>
#include <libgimp/gimppropchooserfactory.h>
#include <libgimp/gimpsaveproceduredialog.h>
#include <libgimp/gimpselectbutton.h>
#include <libgimp/gimpzoompreview.h>
#include <libgimp/gimppropbrushchooser.h>
#undef __GIMP_UI_H_INSIDE__

View File

@@ -23,6 +23,4 @@
# BOOL deprecated alias for BOOLEAN
VOID: STRING, BOOLEAN
VOID: STRING, INT, POINTER, BOOLEAN
VOID: STRING, INT, INT, INT, POINTER, BOOLEAN
VOID: STRING, DOUBLE, INT, INT, INT, INT, POINTER, BOOLEAN
VOID: POINTER, BOOLEAN

View File

@@ -166,14 +166,11 @@ pdb_wrappers_headers = [
libgimp_sources_introspectable = [
'gimp.c',
'gimpbatchprocedure.c',
'gimpbrushselect.c',
'gimpchannel.c',
'gimpdisplay.c',
'gimpdrawable.c',
'gimpfileprocedure.c',
'gimpfontselect.c',
'gimpgimprc.c',
'gimpgradientselect.c',
'gimpimage.c',
'gimpimagecolorprofile.c',
'gimpimagemetadata.c',
@@ -183,15 +180,14 @@ libgimp_sources_introspectable = [
'gimplayer.c',
'gimplayermask.c',
'gimploadprocedure.c',
'gimppaletteselect.c',
'gimpparamspecs.c',
'gimppatternselect.c',
'gimppdb.c',
'gimpplugin.c',
'gimpprocedure.c',
'gimpprocedureconfig.c',
'gimpprogress.c',
'gimpresource.c',
'gimpresourceselect.c',
'gimpresource-subclass.c',
'gimpsaveprocedure.c',
'gimpselection.c',
@@ -225,14 +221,11 @@ libgimp_headers_introspectable = [
# Other headers
'gimpbatchprocedure.h',
'gimpbrushselect.h',
'gimpchannel.h',
'gimpdisplay.h',
'gimpdrawable.h',
'gimpfileprocedure.h',
'gimpfontselect.h',
'gimpgimprc.h',
'gimpgradientselect.h',
'gimpimage.h',
'gimpimagecolorprofile.h',
'gimpimagemetadata.h',
@@ -241,16 +234,15 @@ libgimp_headers_introspectable = [
'gimplayer.h',
'gimplayermask.h',
'gimploadprocedure.h',
'gimppaletteselect.h',
'gimpparamspecs.h',
'gimpparamspecs-resource.h',
'gimppatternselect.h',
'gimppdb.h',
'gimpplugin.h',
'gimpprocedure.h',
'gimpprocedureconfig.h',
'gimpprogress.h',
'gimpresource.h',
'gimpresourceselect.h',
'gimpresource-subclass.h',
'gimpsaveprocedure.h',
'gimpselection.h',
@@ -267,7 +259,6 @@ libgimp_headers = [
libgimpui_sources_introspectable = [
'gimpaspectpreview.c',
'gimppropbrushchooser.c',
'gimpbrushselectbutton.c',
'gimpdrawablepreview.c',
'gimpexport.c',
@@ -281,8 +272,10 @@ libgimpui_sources_introspectable = [
'gimpproceduredialog.c',
'gimpprocview.c',
'gimpprogressbar.c',
'gimppropchooser.c',
'gimppropchooserfactory.c',
'gimpresourceselectbutton.c',
'gimpsaveproceduredialog.c',
'gimpselectbutton.c',
'gimpui.c',
'gimpzoompreview.c',
]
@@ -312,8 +305,10 @@ libgimpui_headers_introspectable = [
'gimpproceduredialog.h',
'gimpprocview.h',
'gimpprogressbar.h',
'gimppropchooser.h',
'gimppropchooserfactory.h',
'gimpresourceselectbutton.h',
'gimpsaveproceduredialog.h',
'gimpselectbutton.h',
'gimpzoompreview.h',
]

View File

@@ -352,6 +352,10 @@ gimp_config_param_spec_duplicate (GParamSpec *pspec)
g_strcmp0 (type_name, "GimpChannel") == 0 ||
g_strcmp0 (type_name, "GimpSelection") == 0 ||
g_strcmp0 (type_name, "GimpBrush") == 0 ||
g_strcmp0 (type_name, "GimpFont") == 0 ||
g_strcmp0 (type_name, "GimpGradient") == 0 ||
g_strcmp0 (type_name, "GimpPalette") == 0 ||
g_strcmp0 (type_name, "GimpPattern") == 0 ||
g_strcmp0 (type_name, "GimpVectors") == 0)
{
copy = g_param_spec_object (name, nick, blurb,

View File

@@ -17,43 +17,28 @@
# "Perlized" from C source by Manish Singh <yosh@gimp.org>
sub brushes_popup {
$blurb = 'Invokes the Gimp brush selection.';
$help = 'This procedure opens the brush selection dialog.';
$blurb = 'Invokes the GIMP brush selection dialog.';
$help = 'Opens a dialog letting a user choose a brush.';
&andy_pdb_misc('1998');
@inargs = (
{ name => 'brush_callback', type => 'string', non_empty => 1,
desc => 'The callback PDB proc to call when brush selection is
made' },
{ name => 'popup_title', type => 'string',
desc => 'Title of the brush selection dialog' },
{ name => 'initial_brush', type => 'string', null_ok => 1,
desc => 'The name of the brush to set as the first selected' },
{ name => 'opacity', type => '0 <= float <= 100',
desc => 'The initial opacity of the brush' },
{ name => 'spacing', type => 'int32 <= 1000',
desc => 'The initial spacing of the brush (if < 0 then use brush
default spacing)' },
{ name => 'paint_mode', type => 'enum GimpLayerMode',
default => 'GIMP_LAYER_MODE_NORMAL',
desc => 'The initial paint mode' }
{ name => 'brush_callback', type => 'string', non_empty => 1,
desc => 'The callback PDB proc to call when user chooses a brush' },
{ name => 'popup_title', type => 'string',
desc => 'Title of the brush selection dialog' },
{ name => 'initial_brush_name', type => 'string', null_ok => 1,
desc => 'The name of the brush to set as the initial choice' }
);
%invoke = (
code => <<'CODE'
{
if (paint_mode == GIMP_LAYER_MODE_OVERLAY_LEGACY)
paint_mode = GIMP_LAYER_MODE_SOFTLIGHT_LEGACY;
if (gimp->no_interface ||
if (gimp->no_interface ||
! gimp_pdb_lookup_procedure (gimp->pdb, brush_callback) ||
! gimp_pdb_dialog_new (gimp, context, progress,
gimp_data_factory_get_container (gimp->brush_factory),
popup_title, brush_callback, initial_brush,
"opacity", opacity / 100.0,
"paint-mode", paint_mode,
"spacing", spacing,
popup_title, brush_callback, initial_brush_name,
NULL))
success = FALSE;
}
@@ -63,13 +48,13 @@ CODE
sub brushes_close_popup {
$blurb = 'Close the brush selection dialog.';
$help = 'This procedure closes an opened brush selection dialog.';
$help = 'Closes an open brush selection dialog.';
&andy_pdb_misc('1998');
@inargs = (
{ name => 'brush_callback', type => 'string', non_empty => 1,
desc => 'The name of the callback registered for this pop-up' }
{ name => 'brush_callback', type => 'string', non_empty => 1,
desc => 'The name of the callback registered for this pop-up' }
);
%invoke = (
@@ -86,39 +71,25 @@ CODE
}
sub brushes_set_popup {
$blurb = 'Sets the current brush in a brush selection dialog.';
$blurb = 'Sets the selected brush in a brush selection dialog.';
$help = $blurb;
&andy_pdb_misc('1998');
@inargs = (
{ name => 'brush_callback', type => 'string', non_empty => 1,
desc => 'The name of the callback registered for this pop-up' },
{ name => 'brush_name', type => 'string',
desc => 'The name of the brush to set as selected' },
{ name => 'opacity', type => '0 <= float <= 100',
desc => 'The initial opacity of the brush' },
{ name => 'spacing', type => 'int32 <= 1000',
desc => 'The initial spacing of the brush (if < 0 then use brush
default spacing)' },
{ name => 'paint_mode', type => 'enum GimpLayerMode',
default => 'GIMP_LAYER_MODE_NORMAL',
desc => 'The initial paint mode' }
{ name => 'brush_callback', type => 'string', non_empty => 1,
desc => 'The name of the callback registered for this pop-up' },
{ name => 'brush_name', type => 'string',
desc => 'The name of the brush to set as selected' }
);
%invoke = (
code => <<'CODE'
{
if (paint_mode == GIMP_LAYER_MODE_OVERLAY_LEGACY)
paint_mode = GIMP_LAYER_MODE_SOFTLIGHT_LEGACY;
if (gimp->no_interface ||
! gimp_pdb_lookup_procedure (gimp->pdb, brush_callback) ||
! gimp_pdb_dialog_set (gimp, gimp_data_factory_get_container (gimp->brush_factory),
brush_callback, brush_name,
"opacity", opacity / 100.0,
"paint-mode", paint_mode,
"spacing", spacing,
NULL))
success = FALSE;
}
@@ -138,7 +109,7 @@ CODE
$desc = 'Brush UI';
$doc_title = 'gimpbrushselect';
$doc_short_desc = 'Functions providing a brush selection dialog.';
$doc_long_desc = 'Functions providing a brush selection dialog.';
$doc_short_desc = 'Methods of a font chooser dialog';
$doc_long_desc = 'A dialog letting a user choose a brush. Read more at gimpfontselect.';
1;

View File

@@ -16,19 +16,20 @@
# "Perlized" from C source by Manish Singh <yosh@gimp.org>
sub fonts_popup {
$blurb = 'Invokes the Gimp font selection.';
$help = 'This procedure opens the font selection dialog.';
$blurb = 'Invokes the Gimp font selection dialog.';
$help = 'Opens a dialog letting a user choose a font.';
&neo_pdb_misc('2003');
@inargs = (
{ name => 'font_callback', type => 'string', non_empty => 1,
desc => 'The callback PDB proc to call when font selection is made' },
{ name => 'popup_title', type => 'string',
desc => 'Title of the font selection dialog' },
{ name => 'initial_font', type => 'string', null_ok => 1,
desc => 'The name of the font to set as the first selected' }
{ name => 'font_callback', type => 'string', non_empty => 1,
desc => 'The callback PDB proc to call when user chooses a font' },
{ name => 'popup_title', type => 'string',
desc => 'Title of the font selection dialog' },
{ name => 'initial_font_name', type => 'string', null_ok => 1,
desc => 'The name of the initial font choice.' }
);
%invoke = (
@@ -39,7 +40,7 @@ sub fonts_popup {
! gimp_data_factory_data_wait (gimp->font_factory) ||
! gimp_pdb_dialog_new (gimp, context, progress,
gimp_data_factory_get_container (gimp->font_factory),
popup_title, font_callback, initial_font,
popup_title, font_callback, initial_font_name,
NULL))
success = FALSE;
}
@@ -49,13 +50,13 @@ CODE
sub fonts_close_popup {
$blurb = 'Close the font selection dialog.';
$help = 'This procedure closes an opened font selection dialog.';
$help = 'Closes an open font selection dialog.';
&neo_pdb_misc('2003');
@inargs = (
{ name => 'font_callback', type => 'string', non_empty => 1,
desc => 'The name of the callback registered for this pop-up' }
{ name => 'font_callback', type => 'string', non_empty => 1,
desc => 'The name of the callback registered in the PDB for this dialog' }
);
%invoke = (
@@ -65,7 +66,7 @@ sub fonts_close_popup {
! gimp_pdb_lookup_procedure (gimp->pdb, font_callback) ||
! gimp_pdb_dialog_close (gimp,
gimp_data_factory_get_container (gimp->font_factory),
font_callback))
font_callback))
success = FALSE;
}
CODE
@@ -79,10 +80,10 @@ sub fonts_set_popup {
&neo_pdb_misc('2003');
@inargs = (
{ name => 'font_callback', type => 'string', non_empty => 1,
desc => 'The name of the callback registered for this pop-up' },
{ name => 'font_name', type => 'string',
desc => 'The name of the font to set as selected' }
{ name => 'font_callback', type => 'string', non_empty => 1,
desc => 'The name of the callback registered in the PDB for the dialog.' },
{ name => 'font_name', type => 'string',
desc => 'The name of the font to set as selected' }
);
%invoke = (
@@ -93,7 +94,7 @@ sub fonts_set_popup {
! gimp_data_factory_data_wait (gimp->font_factory) ||
! gimp_pdb_dialog_set (gimp,
gimp_data_factory_get_container (gimp->font_factory),
font_callback, font_name,
font_callback, font_name,
NULL))
success = FALSE;
}
@@ -113,7 +114,18 @@ CODE
$desc = 'Font UI';
$doc_title = 'gimpfontselect';
$doc_short_desc = 'Functions providing a font selection dialog.';
$doc_long_desc = 'Functions providing a font selection dialog.';
$doc_short_desc = 'Methods of a font chooser dialog.';
$doc_long_desc = <<'LONG_DESC';
A font chooser dialog shows installed fonts.
The dialog is non-modal with its owning dialog,
which is usually a plugin procedure's dialog.
When a user selects a font,
the dialog calls back but the dialog remains open.
The chosen font is only a choice for the owning widget
and does not select the font for the context.
The user can close but not cancel the dialog.
The owning dialog can close the font chooser dialog
when the user closes or cancels the owning dialog.
LONG_DESC
1;

View File

@@ -16,36 +16,36 @@
# "Perlized" from C source by Manish Singh <yosh@gimp.org>
sub gradients_popup {
$blurb = 'Invokes the Gimp gradients selection.';
$help = 'This procedure opens the gradient selection dialog.';
$blurb = 'Invokes the Gimp gradients selection dialog.';
$help = 'Opens a dialog letting a user choose a gradient.';
&andy_pdb_misc('1998');
@inargs = (
{ name => 'gradient_callback', type => 'string', non_empty => 1,
desc => 'The callback PDB proc to call when gradient selection is
made' },
{ name => 'popup_title', type => 'string',
desc => 'Title of the gradient selection dialog' },
{ name => 'initial_gradient', type => 'string', null_ok => 1,
desc => 'The name of the gradient to set as the first selected' },
{ name => 'sample_size', type => '1 <= int32 <= 10000', no_validate => 1,
desc => 'Size of the sample to return when the gradient is changed' }
);
{ name => 'gradient_callback', type => 'string', non_empty => 1,
desc => 'The callback PDB proc to call when user chooses a gradient' },
{ name => 'popup_title', type => 'string',
desc => 'Title of the gradient selection dialog' },
{ name => 'initial_gradient_name', type => 'string', null_ok => 1,
desc => 'The name of the initial gradient choice' }
);
%invoke = (
code => <<'CODE'
{
if (sample_size < 1 || sample_size > 10000)
sample_size = GIMP_GRADIENT_DEFAULT_SAMPLE_SIZE;
/* Formerly, this procedure had another parameter:
* the sample size of the gradient's data passed in the changed callback.
* Now the sample size is determined by core, and in the future,
* the callback won't return a sample of the data at all.
*/
if (gimp->no_interface ||
! gimp_pdb_lookup_procedure (gimp->pdb, gradient_callback) ||
! gimp_pdb_dialog_new (gimp, context, progress,
gimp_data_factory_get_container (gimp->gradient_factory),
popup_title, gradient_callback, initial_gradient,
"sample-size", sample_size,
popup_title, gradient_callback, initial_gradient_name,
NULL))
success = FALSE;
}
@@ -55,13 +55,13 @@ CODE
sub gradients_close_popup {
$blurb = 'Close the gradient selection dialog.';
$help = 'This procedure closes an opened gradient selection dialog.';
$help = 'Closes an open gradient selection dialog.';
&andy_pdb_misc('1998');
@inargs = (
{ name => 'gradient_callback', type => 'string', non_empty => 1,
desc => 'The name of the callback registered for this pop-up' }
{ name => 'gradient_callback', type => 'string', non_empty => 1,
desc => 'The name of the callback registered for this pop-up' }
);
%invoke = (
@@ -84,10 +84,10 @@ sub gradients_set_popup {
&andy_pdb_misc('1998');
@inargs = (
{ name => 'gradient_callback', type => 'string', non_empty => 1,
desc => 'The name of the callback registered for this pop-up' },
{ name => 'gradient_name', type => 'string',
desc => 'The name of the gradient to set as selected' }
{ name => 'gradient_callback', type => 'string', non_empty => 1,
desc => 'The name of the callback registered for this pop-up' },
{ name => 'gradient_name', type => 'string',
desc => 'The name of the gradient to set as selected' }
);
%invoke = (
@@ -117,7 +117,7 @@ CODE
$desc = 'Gradient UI';
$doc_title = 'gimpgradientselect';
$doc_short_desc = 'Functions providing a gradient selection dialog.';
$doc_long_desc = 'Functions providing a gradient selection dialog.';
$doc_short_desc = 'Methods of a gradient chooser dialog';
$doc_long_desc = 'A dialog letting a user choose a gradient. Read more at gimpfontselect.';
1;

View File

@@ -17,19 +17,18 @@
# "Perlized" from C source by Manish Singh <yosh@gimp.org>
sub palettes_popup {
$blurb = 'Invokes the Gimp palette selection.';
$help = 'This procedure opens the palette selection dialog.';
$blurb = 'Invokes the Gimp palette selection dialog.';
$help = 'Opens a dialog letting a user choose a palette.';
&mitch_pdb_misc('2002');
@inargs = (
{ name => 'palette_callback', type => 'string', non_empty => 1,
desc => 'The callback PDB proc to call when palette selection is
made' },
{ name => 'popup_title', type => 'string',
desc => 'Title of the palette selection dialog' },
{ name => 'initial_palette', type => 'string', null_ok => 1,
desc => 'The name of the palette to set as the first selected' }
{ name => 'palette_callback', type => 'string', non_empty => 1,
desc => 'The callback PDB proc to call when user chooses a palette' },
{ name => 'popup_title', type => 'string',
desc => 'Title of the palette selection dialog' },
{ name => 'initial_palette_name', type => 'string', null_ok => 1,
desc => 'The palette to set as the initial choice.' }
);
%invoke = (
@@ -39,7 +38,7 @@ sub palettes_popup {
! gimp_pdb_lookup_procedure (gimp->pdb, palette_callback) ||
! gimp_pdb_dialog_new (gimp, context, progress,
gimp_data_factory_get_container (gimp->palette_factory),
popup_title, palette_callback, initial_palette,
popup_title, palette_callback, initial_palette_name,
NULL))
success = FALSE;
}
@@ -49,13 +48,13 @@ CODE
sub palettes_close_popup {
$blurb = 'Close the palette selection dialog.';
$help = 'This procedure closes an opened palette selection dialog.';
$help = 'Closes an open palette selection dialog.';
&mitch_pdb_misc('2002');
@inargs = (
{ name => 'palette_callback', type => 'string', non_empty => 1,
desc => 'The name of the callback registered for this pop-up' }
{ name => 'palette_callback', type => 'string', non_empty => 1,
desc => 'The name of the callback registered for this pop-up' }
);
%invoke = (
@@ -78,10 +77,10 @@ sub palettes_set_popup {
&mitch_pdb_misc('2002');
@inargs = (
{ name => 'palette_callback', type => 'string', non_empty => 1,
desc => 'The name of the callback registered for this pop-up' },
{ name => 'palette_name', type => 'string',
desc => 'The name of the palette to set as selected' },
{ name => 'palette_callback', type => 'string', non_empty => 1,
desc => 'The name of the callback registered for this pop-up' },
{ name => 'palette_name', type => 'string',
desc => 'The name of the palette to set as selected' },
);
%invoke = (
@@ -110,7 +109,7 @@ CODE
$desc = 'Palette UI';
$doc_title = 'gimppaletteselect';
$doc_short_desc = 'Functions providing a palette selection dialog.';
$doc_long_desc = 'Functions providing a palette selection dialog.';
$doc_short_desc = 'Methods of a palette chooser dialog';
$doc_long_desc = 'A dialog letting a user choose a palette. Read more at gimpfontselect.';
1;

View File

@@ -18,18 +18,17 @@
sub patterns_popup {
$blurb = 'Invokes the Gimp pattern selection.';
$help = 'This procedure opens the pattern selection dialog.';
$help = 'Opens the pattern selection dialog.';
&andy_pdb_misc('1998');
@inargs = (
{ name => 'pattern_callback', type => 'string', non_empty => 1,
desc => 'The callback PDB proc to call when pattern selection is
made' },
{ name => 'popup_title', type => 'string',
desc => 'Title of the pattern selection dialog' },
{ name => 'initial_pattern', type => 'string', null_ok => 1,
desc => 'The name of the pattern to set as the first selected' }
{ name => 'pattern_callback', type => 'string', non_empty => 1,
desc => 'The callback PDB proc to call when the user chooses a pattern' },
{ name => 'popup_title', type => 'string',
desc => 'Title of the pattern selection dialog' },
{ name => 'initial_pattern_name', type => 'string', null_ok => 1,
desc => 'The name of the pattern to set as the initial choice' }
);
%invoke = (
@@ -39,7 +38,7 @@ sub patterns_popup {
! gimp_pdb_lookup_procedure (gimp->pdb, pattern_callback) ||
! gimp_pdb_dialog_new (gimp, context, progress,
gimp_data_factory_get_container (gimp->pattern_factory),
popup_title, pattern_callback, initial_pattern,
popup_title, pattern_callback, initial_pattern_name,
NULL))
success = FALSE;
}
@@ -49,13 +48,13 @@ CODE
sub patterns_close_popup {
$blurb = 'Close the pattern selection dialog.';
$help = 'This procedure closes an opened pattern selection dialog.';
$help = 'Closes an open pattern selection dialog.';
&andy_pdb_misc('1998');
@inargs = (
{ name => 'pattern_callback', type => 'string', non_empty => 1,
desc => 'The name of the callback registered for this pop-up' }
{ name => 'pattern_callback', type => 'string', non_empty => 1,
desc => 'The name of the callback registered for this pop-up' }
);
%invoke = (
@@ -78,10 +77,10 @@ sub patterns_set_popup {
&andy_pdb_misc('1998');
@inargs = (
{ name => 'pattern_callback', type => 'string', non_empty => 1,
desc => 'The name of the callback registered for this pop-up' },
{ name => 'pattern_name', type => 'string',
desc => 'The name of the pattern to set as selected' }
{ name => 'pattern_callback', type => 'string', non_empty => 1,
desc => 'The name of the callback registered for this pop-up' },
{ name => 'pattern_name', type => 'string',
desc => 'The name of the pattern to set as selected' }
);
%invoke = (
@@ -110,7 +109,7 @@ CODE
$desc = 'Pattern UI';
$doc_title = 'gimppatternselect';
$doc_short_desc = 'Functions providing a pattern selection dialog.';
$doc_long_desc = 'Functions providing a pattern selection dialog.';
$doc_short_desc = 'Methods of a pattern chooser dialog';
$doc_long_desc = 'A dialog letting a user choose a pattern. Read more at gimpfontselect.';
1;

View File

@@ -24,6 +24,10 @@ if HAVE_WEBP
file_webp = file-webp
endif
# lkk temporarily not making these plugins until next commit fixes them for Resource
# gfig
# pagecurl
SUBDIRS = \
script-fu \
file-bmp \
@@ -43,7 +47,6 @@ SUBDIRS = \
$(file_webp) \
flame \
fractal-explorer \
gfig \
gimpressionist \
gradient-flare \
help \
@@ -53,7 +56,6 @@ SUBDIRS = \
lighting \
map-object \
metadata \
pagecurl \
$(print) \
$(python) \
screenshot \

View File

@@ -394,8 +394,7 @@ gfig_dialog (void)
/* brush selector in Stroke frame */
gfig_context->brush_select
= gimp_brush_select_button_new ("Brush",
gfig_context->default_style.brush_name,
-1.0, -1, -1);
gfig_context->default_style.brush);
g_signal_connect (gfig_context->brush_select, "brush-set",
G_CALLBACK (gfig_brush_changed_callback), NULL);
gtk_box_pack_start (GTK_BOX (vbox), gfig_context->brush_select,

View File

@@ -255,9 +255,9 @@ gfig_load_style (Style *style,
}
gfig_read_parameter_string (style_text, nitems, "BrushName",
&style->brush_name);
&style->brush);
if (style->brush_name == NULL)
if (style->brush == NULL)
g_message ("Error loading style: got NULL for brush name.");
gfig_read_parameter_string (style_text, nitems, "Pattern", &style->pattern);
@@ -353,11 +353,11 @@ gfig_save_style (Style *style,
gint blen = G_ASCII_DTOSTR_BUF_SIZE;
if (gfig_context->debug_styles)
g_printerr ("Saving style %s, brush name '%s'\n", style->name, style->brush_name);
g_printerr ("Saving style %s, brush name '%s'\n", style->name, style->brush);
g_string_append_printf (string, "<Style %s>\n", style->name);
g_string_append_printf (string, "BrushName: %s\n", style->brush_name);
if (!style->brush_name)
g_string_append_printf (string, "BrushName: %s\n", style->brush);
if (!style->brush)
g_message ("Error saving style %s: saving NULL for brush name", style->name);
g_string_append_printf (string, "PaintType: %d\n", style->paint_type);
@@ -399,7 +399,7 @@ gfig_style_save_as_attributes (Style *style,
if (gfig_context->debug_styles)
g_printerr ("Saving style %s as attributes\n", style->name);
g_string_append_printf (string, "BrushName=\"%s\" ", style->brush_name);
g_string_append_printf (string, "BrushName=\"%s\" ", style->brush);
g_string_append_printf (string, "Foreground=\"%s %s %s %s\" ",
g_ascii_dtostr (buffer_r, blen, style->foreground.r),
@@ -501,10 +501,7 @@ set_paint_type_callback (GtkToggleButton *toggle,
*/
void
gfig_brush_changed_callback (GimpBrushSelectButton *button,
const gchar *brush_name,
gdouble opacity,
gint spacing,
GimpLayerMode paint_mode,
const GimpBrush *brush,
gint width,
gint height,
const guchar *mask_data,
@@ -514,13 +511,13 @@ gfig_brush_changed_callback (GimpBrushSelectButton *button,
Style *current_style;
current_style = gfig_context_get_current_style ();
current_style->brush_name = g_strdup (brush_name);
current_style->brush = brush;
/* this will soon be unneeded. How soon? */
gfig_context->bdesc.name = g_strdup (brush_name);
gfig_context->bdesc.name = g_strdup (brush);
gfig_context->bdesc.width = width;
gfig_context->bdesc.height = height;
gimp_context_set_brush (brush_name);
gimp_context_set_brush (brush);
gimp_context_set_brush_default_size ();
gfig_paint_callback ();
@@ -586,10 +583,10 @@ gfig_style_copy (Style *style1,
gfig_rgba_copy (&style1->foreground, &style0->foreground);
gfig_rgba_copy (&style1->background, &style0->background);
if (!style0->brush_name)
if (!style0->brush)
g_message ("Error copying style %s: brush name is NULL.", style0->name);
style1->brush_name = g_strdup (style0->brush_name);
style1->brush = g_strdup (style0->brush);
style1->gradient = g_strdup (style0->gradient);
style1->pattern = g_strdup (style0->pattern);
style1->fill_type = style0->fill_type;
@@ -612,9 +609,9 @@ gfig_style_apply (Style *style)
gimp_context_set_background (&style->background);
if (! gimp_context_set_brush (style->brush_name))
if (! gimp_context_set_brush (style->brush))
g_message ("Style apply: Failed to set brush to '%s' in style '%s'",
style->brush_name, style->name);
style->brush, style->name);
gimp_context_set_brush_default_size ();
@@ -648,18 +645,18 @@ gfig_read_gimp_style (Style *style,
gimp_context_get_foreground (&style->foreground);
gimp_context_get_background (&style->background);
style->brush_name = gimp_context_get_brush ();
gimp_brush_get_info (style->brush_name,
style->brush = gimp_context_get_brush ();
gimp_brush_get_info (style->brush,
&style->brush_width, &style->brush_height,
&dummy, &dummy);
style->brush_spacing = gimp_brush_get_spacing (style->brush_name);
style->brush_spacing = gimp_brush_get_spacing (style->brush);
style->gradient = gimp_context_get_gradient ();
style->pattern = gimp_context_get_pattern ();
style->fill_opacity = 100.;
gfig_context->bdesc.name = style->brush_name;
gfig_context->bdesc.name = style->brush;
gfig_context->bdesc.width = style->brush_width;
gfig_context->bdesc.height = style->brush_height;
}
@@ -686,14 +683,13 @@ gfig_style_set_context_from_style (Style *style)
&style->foreground);
gimp_color_button_set_color (GIMP_COLOR_BUTTON (gfig_context->bg_color_button),
&style->background);
if (! gimp_context_set_brush (style->brush_name))
g_message ("Style from context: Failed to set brush to '%s'",
style->brush_name);
if (! gimp_context_set_brush (style->brush))
g_message ("Style from context: Failed to set brush");
gimp_context_set_brush_default_size ();
gimp_brush_select_button_set_brush (GIMP_BRUSH_SELECT_BUTTON (gfig_context->brush_select),
style->brush_name, -1.0, -1, -1); /* FIXME */
style->brush); /* FIXME */
gimp_pattern_select_button_set_pattern (GIMP_PATTERN_SELECT_BUTTON (gfig_context->pattern_select),
style->pattern);
@@ -701,7 +697,7 @@ gfig_style_set_context_from_style (Style *style)
gimp_gradient_select_button_set_gradient (GIMP_GRADIENT_SELECT_BUTTON (gfig_context->gradient_select),
style->gradient);
gfig_context->bdesc.name = style->brush_name;
gfig_context->bdesc.name = style->brush;
if (gfig_context->debug_styles)
g_printerr ("done.\n");
@@ -738,7 +734,7 @@ gfig_style_set_style_from_context (Style *style)
&color);
gfig_rgba_copy (&style->background, &color);
style->brush_name = current_style->brush_name;
style->brush = current_style->brush;
if (!style->pattern || strcmp (style->pattern, current_style->pattern))
{

View File

@@ -30,7 +30,7 @@
struct _Style
{
gchar *name;
gchar *brush_name;
GimpBrush *brush;
gint brush_width;
gint brush_height;
gint brush_spacing;

View File

@@ -15,7 +15,8 @@ subdir('file-tiff')
subdir('file-webp')
subdir('flame')
subdir('fractal-explorer')
subdir('gfig')
# lkk temporarily not built
# subdir('gfig')
subdir('gimpressionist')
subdir('gradient-flare')
subdir('help')
@@ -25,7 +26,8 @@ subdir('imagemap')
subdir('lighting')
subdir('map-object')
subdir('metadata')
subdir('pagecurl')
# lkk temporarily not built
# subdir('pagecurl')
subdir('print')
subdir('python')
subdir('screenshot')

View File

@@ -45,6 +45,12 @@ EXTRA_DIST = \
python-eval.py \
spyro-plus.py
if GIMP_UNSTABLE
test_dialogdir = $(gimpplugindir)/plug-ins/test-dialog
test_dialog_SCRIPTS = test-dialog.py
EXTRA_DIST += test-dialog.py
endif
# Python interpreter file.
pyinterpdir = $(gimpplugindir)/interpreters

View File

@@ -38,14 +38,46 @@ Not localized, no i18n
'''
def process_args(brush):
def process_args(brush, font, gradient, palette, pattern):
'''
Test the args are sane.
'''
assert brush is not None
assert isinstance(brush, Gimp.Brush)
assert brush.get_id() is not None
print( "Brush id is:", brush.get_id())
id = brush.get_id()
assert id is not None
print("Brush id is:", id)
Gimp.message(id)
assert font is not None
assert isinstance(font, Gimp.Font)
id = font.get_id()
assert id is not None
print("font id is:", id)
Gimp.message(id)
assert gradient is not None
assert isinstance(gradient, Gimp.Gradient)
id = gradient.get_id()
assert id is not None
print("gradient id is:", id)
Gimp.message(id)
assert palette is not None
assert isinstance(palette, Gimp.Palette)
id = palette.get_id()
assert id is not None
print("palette id is:", id)
Gimp.message(id)
assert pattern is not None
assert isinstance(pattern, Gimp.Pattern)
id = pattern.get_id()
assert id is not None
print("pattern id is:", id)
Gimp.message(id)
return
@@ -69,13 +101,15 @@ def test_dialog(procedure, run_mode, image, n_drawables, drawables, args, data):
dialog.destroy()
brush = config.get_property('brush')
# opacity = config.get_property('opacity')
font = config.get_property('font')
gradient = config.get_property('gradient')
palette = config.get_property('palette')
pattern = config.get_property('pattern')
Gimp.context_push()
image.undo_group_start()
process_args(brush)
process_args(brush, font, gradient, palette, pattern)
Gimp.displays_flush()
@@ -96,9 +130,20 @@ class TestDialogPlugin (Gimp.PlugIn):
# See comments about this in foggify.py, from which we borrowed
brush = GObject.Property(type =Gimp.Brush,
# no default?
nick ="Brush",
blurb="Brush")
font = GObject.Property(type =Gimp.Font,
nick ="Font",
blurb="Font")
gradient = GObject.Property(type =Gimp.Gradient,
nick ="Gradient",
blurb="Gradient")
palette = GObject.Property(type =Gimp.Palette,
nick ="Palette",
blurb="Palette")
pattern = GObject.Property(type =Gimp.Pattern,
nick ="Pattern",
blurb="Pattern")
# FUTURE all other Gimp classes that have GimpParamSpecs
@@ -127,6 +172,10 @@ class TestDialogPlugin (Gimp.PlugIn):
procedure.add_menu_path ("<Image>/Test")
procedure.add_argument_from_property(self, "brush")
procedure.add_argument_from_property(self, "font")
procedure.add_argument_from_property(self, "gradient")
procedure.add_argument_from_property(self, "palette")
procedure.add_argument_from_property(self, "pattern")
return procedure

View File

@@ -516,11 +516,7 @@ script_fu_interface (SFScript *script,
case SF_BRUSH:
left_align = TRUE;
widget = gimp_brush_select_button_new (_("Script-Fu Brush Selection"),
arg->value.sfa_brush.name,
arg->value.sfa_brush.opacity,
arg->value.sfa_brush.spacing,
arg->value.sfa_brush.paint_mode);
widget = gimp_brush_select_button_new (_("Script-Fu Brush Selection"), NULL);
g_signal_connect_swapped (widget, "brush-set",
G_CALLBACK (script_fu_brush_callback),
&arg->value.sfa_brush);
@@ -640,8 +636,8 @@ script_fu_interface_quit (SFScript *script)
case SF_PATTERN:
case SF_GRADIENT:
case SF_BRUSH:
gimp_select_button_close_popup
(GIMP_SELECT_BUTTON (sf_interface->widgets[i]));
gimp_resource_select_button_close_popup
(GIMP_RESOURCE_SELECT_BUTTON (sf_interface->widgets[i]));
break;
default:
@@ -1016,11 +1012,7 @@ script_fu_reset (SFScript *script)
break;
case SF_BRUSH:
gimp_brush_select_button_set_brush (GIMP_BRUSH_SELECT_BUTTON (widget),
value->sfa_brush.name,
value->sfa_brush.opacity,
value->sfa_brush.spacing,
value->sfa_brush.paint_mode);
gimp_brush_select_button_set_brush (GIMP_BRUSH_SELECT_BUTTON (widget), NULL);
break;
case SF_OPTION:

View File

@@ -4,11 +4,8 @@
libgimp/gimp.c
libgimp/gimpbrushselectbutton.c
libgimp/gimpexport.c
libgimp/gimpfontselectbutton.c
libgimp/gimpgradientselectbutton.c
libgimp/gimpimagemetadata.c
libgimp/gimpimagemetadata-save.c
libgimp/gimppaletteselectbutton.c
libgimp/gimppatternselectbutton.c
libgimp/gimppdb.c
libgimp/gimpprocbrowserdialog.c