diff --git a/app/core/Makefile.am b/app/core/Makefile.am
index 05504e5a2d..53c3188db9 100644
--- a/app/core/Makefile.am
+++ b/app/core/Makefile.am
@@ -433,6 +433,8 @@ libappcore_a_sources = \
gimpprojectable.h \
gimpprojection.c \
gimpprojection.h \
+ gimpresource.c \
+ gimpresource.h \
gimpsamplepoint.c \
gimpsamplepoint.h \
gimpsamplepointundo.c \
diff --git a/app/core/gimpparamspecs.c b/app/core/gimpparamspecs.c
index b93adb8c76..f96399b949 100644
--- a/app/core/gimpparamspecs.c
+++ b/app/core/gimpparamspecs.c
@@ -37,6 +37,7 @@
#include "vectors/gimpvectors.h"
/* resource types */
+#include "gimpresource.h"
#include "gimpbrush.h"
#include "gimpgradient.h"
#include "gimppalette.h"
diff --git a/app/core/gimpresource.c b/app/core/gimpresource.c
new file mode 100644
index 0000000000..19a709a1db
--- /dev/null
+++ b/app/core/gimpresource.c
@@ -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
+ * .
+ */
+
+#include "config.h"
+
+#include
+#include
+#include
+
+#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");
+}
diff --git a/app/core/gimpresource.h b/app/core/gimpresource.h
new file mode 100644
index 0000000000..5e593f4769
--- /dev/null
+++ b/app/core/gimpresource.h
@@ -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 .
+ */
+
+#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__ */
diff --git a/app/core/meson.build b/app/core/meson.build
index 6a8313025a..c7155729f9 100644
--- a/app/core/meson.build
+++ b/app/core/meson.build
@@ -217,6 +217,7 @@ libappcore_sources = [
'gimpprogress.c',
'gimpprojectable.c',
'gimpprojection.c',
+ 'gimpresource.c',
'gimpsamplepoint.c',
'gimpsamplepointundo.c',
'gimpscanconvert.c',
diff --git a/app/pdb/brush-select-cmds.c b/app/pdb/brush-select-cmds.c
index 6e5b038867..554504ccab 100644
--- a/app/pdb/brush-select-cmds.c
+++ b/app/pdb/brush-select-cmds.c
@@ -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);
}
diff --git a/app/pdb/font-select-cmds.c b/app/pdb/font-select-cmds.c
index 93878ac93f..bca497e57a 100644
--- a/app/pdb/font-select-cmds.c
+++ b/app/pdb/font-select-cmds.c
@@ -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 ",
@@ -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 ",
@@ -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));
diff --git a/app/pdb/gradient-select-cmds.c b/app/pdb/gradient-select-cmds.c
index ca83f48fa8..9e5880a0c8 100644
--- a/app/pdb/gradient-select-cmds.c
+++ b/app/pdb/gradient-select-cmds.c
@@ -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",
diff --git a/app/pdb/palette-select-cmds.c b/app/pdb/palette-select-cmds.c
index 01e0c84a66..2b8b095abe 100644
--- a/app/pdb/palette-select-cmds.c
+++ b/app/pdb/palette-select-cmds.c
@@ -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 ",
@@ -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 ",
diff --git a/app/pdb/pattern-select-cmds.c b/app/pdb/pattern-select-cmds.c
index 284b4f924c..7790d3ac1a 100644
--- a/app/pdb/pattern-select-cmds.c
+++ b/app/pdb/pattern-select-cmds.c
@@ -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",
diff --git a/libgimp/Makefile.gi b/libgimp/Makefile.gi
index e4217d64f0..61f85a8b71 100644
--- a/libgimp/Makefile.gi
+++ b/libgimp/Makefile.gi
@@ -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
diff --git a/libgimp/gimp.def b/libgimp/gimp.def
index 4c185fadf4..6659774f40 100644
--- a/libgimp/gimp.def
+++ b/libgimp/gimp.def
@@ -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
diff --git a/libgimp/gimp.h b/libgimp/gimp.h
index 5197f295d2..197954e3bb 100644
--- a/libgimp/gimp.h
+++ b/libgimp/gimp.h
@@ -37,13 +37,10 @@
#include
#include
-#include
#include
#include
#include
-#include
#include
-#include
#include
#include
#include
@@ -52,10 +49,8 @@
#include
#include
#include
-#include
#include
#include
-#include
#include
#include
#include
@@ -69,6 +64,11 @@
#include
#include
+/* Resources and their widgets. Order important. */
+#include
+#include
+#include
+
#include
#undef __GIMP_H_INSIDE__
diff --git a/libgimp/gimpbrushselect.c b/libgimp/gimpbrushselect.c
deleted file mode 100644
index 101f5a1b18..0000000000
--- a/libgimp/gimpbrushselect.c
+++ /dev/null
@@ -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
- * .
- */
-
-#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;
-}
diff --git a/libgimp/gimpbrushselect.h b/libgimp/gimpbrushselect.h
deleted file mode 100644
index 6ed7916653..0000000000
--- a/libgimp/gimpbrushselect.h
+++ /dev/null
@@ -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
- * .
- */
-
-#if !defined (__GIMP_H_INSIDE__) && !defined (GIMP_COMPILATION)
-#error "Only 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__ */
diff --git a/libgimp/gimpbrushselect_pdb.c b/libgimp/gimpbrushselect_pdb.c
index 0ab224b9dc..8719854f11 100644
--- a/libgimp/gimpbrushselect_pdb.c
+++ b/libgimp/gimpbrushselect_pdb.c
@@ -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 (),
diff --git a/libgimp/gimpbrushselect_pdb.h b/libgimp/gimpbrushselect_pdb.h
index ae401f2d59..f47165bdf0 100644
--- a/libgimp/gimpbrushselect_pdb.h
+++ b/libgimp/gimpbrushselect_pdb.h
@@ -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
diff --git a/libgimp/gimpbrushselectbutton.c b/libgimp/gimpbrushselectbutton.c
index 6c89d67770..d529ebc273 100644
--- a/libgimp/gimpbrushselectbutton.c
+++ b/libgimp/gimpbrushselectbutton.c
@@ -37,437 +37,239 @@
/**
* SECTION: gimpbrushselectbutton
- * @title: gimpbrushselectbutton
- * @short_description: A button that pops up a brush selection dialog.
+ * @title: GimpBrushSelectButton
+ * @short_description: A button which pops up a brush selection dialog.
*
- * A button that pops up a brush selection dialog.
+ * A button which pops up a brush selection dialog.
**/
-
#define CELL_SIZE 20
-
-enum
+/* A B&W image. mask_data is allocated and must be freed. */
+typedef struct _PreviewBitmap
{
- BRUSH_SET,
- LAST_SIGNAL
-};
-
-enum
-{
- PROP_0,
- PROP_TITLE,
- PROP_BRUSH_NAME,
- PROP_BRUSH_OPACITY,
- PROP_BRUSH_SPACING,
- PROP_BRUSH_PAINT_MODE,
- N_PROPS
-};
-
-
-struct _GimpBrushSelectButtonPrivate
-{
- gchar *title;
-
- gchar *brush_name; /* Local copy */
- gdouble opacity;
- gint spacing;
- GimpLayerMode paint_mode;
gint width;
gint height;
- guchar *mask_data; /* local copy */
+ guchar *mask_data;
+} _PreviewBitmap;
- GtkWidget *inside;
- GtkWidget *preview;
- GtkWidget *popup;
+struct _GimpBrushSelectButton
+{
+ /* !! Not a pointer, is contained. */
+ GimpResourceSelectButton parent_instance;
+
+ /* Partial view of brush image. Receives drag. Receives mouse down to popup zoom. */
+ GtkWidget *peephole_view;
+ GtkWidget *popup; /* Popup showing entire, full-size brush image. */
+ GtkWidget *browse_button; /* Clickable area that popups remote chooser. */
};
+/* local */
-/* local function prototypes */
+/* implement virtual. */
+static void gimp_brush_select_button_finalize (GObject *object);
+static void gimp_brush_select_button_draw_interior (GimpResourceSelectButton *self);
-static void gimp_brush_select_button_finalize (GObject *object);
+/* init methods. */
+static void gimp_brush_select_button_embed_interior (GimpBrushSelectButton *self);
+static void gimp_brush_select_button_set_drag_target (GimpBrushSelectButton *self);
-static void gimp_brush_select_button_set_property (GObject *object,
- guint property_id,
- const GValue *value,
- GParamSpec *pspec);
-static void gimp_brush_select_button_get_property (GObject *object,
- guint property_id,
- GValue *value,
- GParamSpec *pspec);
+static GtkWidget *gimp_brush_select_button_create_interior (GimpBrushSelectButton *self);
-static void gimp_brush_select_button_clicked (GimpBrushSelectButton *button);
+/* Event handlers. */
+static void gimp_brush_select_on_preview_resize (GimpBrushSelectButton *button);
+static gboolean gimp_brush_select_on_preview_events (GtkWidget *widget,
+ GdkEvent *event,
+ GimpBrushSelectButton *button);
-static void gimp_brush_select_button_callback (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);
+/* local drawing methods. */
+static void gimp_brush_select_preview_draw (GimpPreviewArea *area,
+ gint x,
+ gint y,
+ _PreviewBitmap mask,
+ gint rowstride);
+static void gimp_brush_select_preview_fill_draw (GtkWidget *preview,
+ _PreviewBitmap mask);
-static void gimp_brush_select_preview_resize (GimpBrushSelectButton *button);
-static gboolean gimp_brush_select_preview_events (GtkWidget *widget,
- GdkEvent *event,
- GimpBrushSelectButton *button);
-static void gimp_brush_select_preview_draw (GimpPreviewArea *area,
- gint x,
- gint y,
- gint width,
- gint height,
- const guchar *mask_data,
- gint rowstride);
-static void gimp_brush_select_preview_update (GtkWidget *preview,
- gint brush_width,
- gint brush_height,
- const guchar *mask_data);
+static void gimp_brush_select_button_draw (GimpBrushSelectButton *self);
+static _PreviewBitmap gimp_brush_select_button_get_brush_bitmap (GimpBrushSelectButton *self);
+/* Popup methods. */
static void gimp_brush_select_button_open_popup (GimpBrushSelectButton *button,
gint x,
gint y);
static void gimp_brush_select_button_close_popup (GimpBrushSelectButton *button);
-static void gimp_brush_select_drag_data_received (GimpBrushSelectButton *button,
- GdkDragContext *context,
- gint x,
- gint y,
- GtkSelectionData *selection,
- guint info,
- guint time);
-
-static GtkWidget * gimp_brush_select_button_create_inside (GimpBrushSelectButton *button);
-static const GtkTargetEntry target = { "application/x-gimp-brush-name", 0 };
-static guint brush_button_signals[LAST_SIGNAL] = { 0 };
-static GParamSpec *brush_button_props[N_PROPS] = { NULL, };
+/* A GtkTargetEntry has a string and two ints.
+ * This is one, but we treat it as an array.
+ */
+static const GtkTargetEntry drag_target = { "application/x-gimp-brush-name", 0, 0 };
-
-G_DEFINE_TYPE_WITH_PRIVATE (GimpBrushSelectButton, gimp_brush_select_button,
- GIMP_TYPE_SELECT_BUTTON)
+G_DEFINE_FINAL_TYPE (GimpBrushSelectButton,
+ gimp_brush_select_button,
+ GIMP_TYPE_RESOURCE_SELECT_BUTTON)
static void
gimp_brush_select_button_class_init (GimpBrushSelectButtonClass *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);
object_class->finalize = gimp_brush_select_button_finalize;
- object_class->set_property = gimp_brush_select_button_set_property;
- object_class->get_property = gimp_brush_select_button_get_property;
- select_button_class->select_destroy = gimp_brush_select_destroy;
+ /* Implement pure virtual functions. */
+ superclass->draw_interior = gimp_brush_select_button_draw_interior;
- klass->brush_set = NULL;
+ /* Set data member of class. */
+ superclass->resource_type = GIMP_TYPE_BRUSH;
- /**
- * GimpBrushSelectButton:title:
- *
- * The title to be used for the brush selection popup dialog.
- *
- * Since: 2.4
+ /* We don't define property getter/setters: use superclass getter/setters.
+ * But super property name is "resource", not "brush"
*/
- brush_button_props[PROP_TITLE] = g_param_spec_string ("title",
- "Title",
- "The title to be used for the brush selection popup dialog",
- _("Brush Selection"),
- GIMP_PARAM_READWRITE |
- G_PARAM_CONSTRUCT_ONLY);
-
- /**
- * GimpBrushSelectButton:brush-name:
- *
- * The name of the currently selected brush.
- *
- * Since: 2.4
- */
- brush_button_props[PROP_BRUSH_NAME] = g_param_spec_string ("brush-name",
- "Brush name",
- "The name of the currently selected brush",
- NULL,
- GIMP_PARAM_READWRITE);
-
- /**
- * GimpBrushSelectButton:opacity:
- *
- * The opacity of the currently selected brush.
- *
- * Since: 2.4
- */
- brush_button_props[PROP_BRUSH_OPACITY] = g_param_spec_double ("brush-opacity",
- "Brush opacity",
- "The opacity of the currently selected brush",
- -1.0, 100.0, -1.0,
- GIMP_PARAM_READWRITE);
-
- /**
- * GimpBrushSelectButton:spacing:
- *
- * The spacing of the currently selected brush.
- *
- * Since: 2.4
- */
- brush_button_props[PROP_BRUSH_SPACING] = g_param_spec_int ("brush-spacing",
- "Brush spacing",
- "The spacing of the currently selected brush",
- -G_MAXINT, 1000, -1,
- GIMP_PARAM_READWRITE);
-
- /**
- * GimpBrushSelectButton:paint-mode:
- *
- * The paint mode.
- *
- * Since: 2.4
- */
- brush_button_props[PROP_BRUSH_PAINT_MODE] = g_param_spec_int ("brush-paint-mode",
- "Brush paint mode",
- "The paint mode of the currently selected brush",
- -1, GIMP_LAYER_MODE_LUMINANCE,
- -1,
- GIMP_PARAM_READWRITE);
-
- g_object_class_install_properties (object_class, N_PROPS, brush_button_props);
-
- /**
- * GimpBrushSelectButton::brush-set:
- * @widget: the object which received the signal.
- * @brush_name: the name of the currently selected brush.
- * @opacity: opacity of the brush
- * @spacing: spacing of the brush
- * @paint_mode: paint mode of the brush
- * @width: width of the brush
- * @height: height of the brush
- * @mask_data: (array) (element-type guchar): brush mask data
- * @dialog_closing: whether the dialog was closed or not.
- *
- * The ::brush-set signal is emitted when the user selects a brush.
- *
- * Since: 2.4
- */
- brush_button_signals[BRUSH_SET] =
- g_signal_new ("brush-set",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_FIRST,
- G_STRUCT_OFFSET (GimpBrushSelectButtonClass, brush_set),
- NULL, NULL,
- _gimpui_marshal_VOID__STRING_DOUBLE_INT_INT_INT_INT_POINTER_BOOLEAN,
- G_TYPE_NONE, 8,
- G_TYPE_STRING,
- G_TYPE_DOUBLE,
- G_TYPE_INT,
- G_TYPE_INT,
- G_TYPE_INT,
- G_TYPE_INT,
- G_TYPE_POINTER,
- G_TYPE_BOOLEAN);
}
static void
-gimp_brush_select_button_init (GimpBrushSelectButton *button)
+gimp_brush_select_button_init (GimpBrushSelectButton *self)
{
- GimpBrushSelectButtonPrivate *priv;
- gint mask_bpp;
- gint mask_data_size;
- gint color_bpp;
- gint color_data_size;
- guint8 *color_data;
+ g_debug ("%s called", G_STRFUNC);
- button->priv = gimp_brush_select_button_get_instance_private (button);
+ /* Specialize:
+ * - embed our widget interior instance to super widget instance.
+ * - connect our widget to dnd
+ * These will call superclass methods.
+ * These are on instance, not our subclass.
+ */
+ gimp_brush_select_button_embed_interior (self);
- priv = button->priv;
+ gimp_brush_select_button_set_drag_target (self);
- priv->brush_name = gimp_context_get_brush ();
- gimp_brush_get_pixels (priv->brush_name,
- &priv->width,
- &priv->height,
- &mask_bpp,
- &mask_data_size,
- &priv->mask_data,
- &color_bpp,
- &color_data_size,
- &color_data);
-
- if (color_data)
- g_free (color_data);
-
- priv->inside = gimp_brush_select_button_create_inside (button);
- gtk_container_add (GTK_CONTAINER (button), priv->inside);
+ /* Tell super which sub widget pops up remote chooser.
+ * Only the browse_button.
+ * A click in the peephole_view does something else: popup a zoom.
+ */
+ gimp_resource_select_button_set_clickable (GIMP_RESOURCE_SELECT_BUTTON (self),
+ self->browse_button);
}
/**
* gimp_brush_select_button_new:
- * @title: (nullable): Title of the dialog to use or %NULL means to use the default
- * title.
- * @brush_name: (nullable): Initial brush name or %NULL to use current selection.
- * @opacity: Initial opacity. -1 means to use current opacity.
- * @spacing: Initial spacing. -1 means to use current spacing.
- * @paint_mode: Initial paint mode. -1 means to use current paint mode.
+ * @title: (nullable): Title of the dialog to use or %NULL to use the default title.
+ * @resource: (nullable): Initial brush.
*
- * Creates a new #GtkWidget that completely controls the selection of
- * a brush. This widget is suitable for placement in a table in a
- * plug-in dialog.
+ * Creates a new #GtkWidget that lets a user choose a brush.
+ * You can put this widget in a plug-in dialog.
+ *
+ * When brush is NULL, initial choice is from context.
*
* Returns: A #GtkWidget that you can use in your UI.
*
* Since: 2.4
*/
GtkWidget *
-gimp_brush_select_button_new (const gchar *title,
- const gchar *brush_name,
- gdouble opacity,
- gint spacing,
- GimpLayerMode paint_mode)
+gimp_brush_select_button_new (const gchar *title,
+ GimpResource *resource)
{
- GtkWidget *button;
+ GtkWidget *self;
- if (title)
- button = g_object_new (GIMP_TYPE_BRUSH_SELECT_BUTTON,
- "title", title,
- "brush-name", brush_name,
- "brush-opacity", opacity,
- "brush-spacing", spacing,
- "brush-paint-mode", paint_mode,
- NULL);
- else
- button = g_object_new (GIMP_TYPE_BRUSH_SELECT_BUTTON,
- "brush-name", brush_name,
- "brush-opacity", opacity,
- "brush-spacing", spacing,
- "brush-paint-mode", paint_mode,
- NULL);
+ g_debug ("%s called", G_STRFUNC);
- return button;
+ if (resource == NULL)
+ {
+ g_debug ("%s defaulting brush from context", G_STRFUNC);
+ resource = GIMP_RESOURCE (gimp_context_get_brush ());
+ }
+ g_assert (resource != NULL);
+ /* This method is polymorphic, so a factory can call it, but requires Brush. */
+ g_return_val_if_fail (GIMP_IS_BRUSH (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_BRUSH_SELECT_BUTTON,
+ "title", title,
+ "resource", resource,
+ NULL);
+ else
+ self = g_object_new (GIMP_TYPE_BRUSH_SELECT_BUTTON,
+ "resource", resource,
+ NULL);
+
+ /* We don't subscribe to events from super.
+ * Super will queue a draw when it's resource changes.
+ * Except that the above setting of property happens too late,
+ * so we now draw the initial resource.
+ */
+
+ /* Draw it with the initial resource.
+ * Easier to call draw method than to queue a draw.
+ *
+ * Cast self from Widget.
+ */
+ gimp_brush_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_brush_select_button_get_brush:
- * @button: A #GimpBrushSelectButton
- * @opacity: (out) (optional): Opacity of the selected brush.
- * @spacing: (out) (optional): Spacing of the selected brush.
- * @paint_mode: (out) (optional): Paint mode of the selected brush.
+ * @self: A #GimpBrushSelectButton
*
- * Retrieves the properties of currently selected brush.
+ * Gets the currently selected brush.
*
- * Returns: an internal copy of the brush name which must not be freed.
+ * Returns: (transfer none): an internal copy of the brush which must not be freed.
*
* Since: 2.4
*/
-const gchar *
-gimp_brush_select_button_get_brush (GimpBrushSelectButton *button,
- gdouble *opacity,
- gint *spacing,
- GimpLayerMode *paint_mode)
+GimpBrush *
+gimp_brush_select_button_get_brush (GimpBrushSelectButton *self)
{
- g_return_val_if_fail (GIMP_IS_BRUSH_SELECT_BUTTON (button), NULL);
+ g_return_val_if_fail (GIMP_IS_BRUSH_SELECT_BUTTON (self), NULL);
- if (opacity)
- *opacity = button->priv->opacity;
-
- if (spacing)
- *spacing = button->priv->spacing;
-
- if (paint_mode)
- *paint_mode = button->priv->paint_mode;
-
- return button->priv->brush_name;
+ /* Delegate to super w upcast arg and downcast result. */
+ return (GimpBrush *) gimp_resource_select_button_get_resource ((GimpResourceSelectButton*) self);
}
/**
* gimp_brush_select_button_set_brush:
- * @button: A #GimpBrushSelectButton
- * @brush_name: (nullable): Brush name to set; %NULL means no change.
- * @opacity: Opacity to set. -1.0 means no change.
- * @spacing: Spacing to set. -1 means no change.
- * @paint_mode: Paint mode to set. -1 means no change.
+ * @self: A #GimpBrushSelectButton
+ * @brush: Brush to set.
*
- * Sets the current brush and other values for the brush select
- * button.
+ * Sets the currently selected brush.
+ * 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_brush_select_button_set_brush (GimpBrushSelectButton *button,
- const gchar *brush_name,
- gdouble opacity,
- gint spacing,
- GimpLayerMode paint_mode)
+gimp_brush_select_button_set_brush (GimpBrushSelectButton *self,
+ GimpBrush *brush)
{
- GimpSelectButton *select_button;
+ g_return_if_fail (GIMP_IS_BRUSH_SELECT_BUTTON (self));
- g_return_if_fail (GIMP_IS_BRUSH_SELECT_BUTTON (button));
+ g_debug ("%s", G_STRFUNC);
- select_button = GIMP_SELECT_BUTTON (button);
-
- if (select_button->temp_callback)
- {
- gimp_brushes_set_popup (select_button->temp_callback, brush_name,
- opacity, spacing, paint_mode);
- }
- else
- {
- gchar *name;
- gint width;
- gint height;
- gint bytes;
- gint mask_data_size;
- guint8 *mask_data;
- gint color_bpp;
- gint color_data_size;
- guint8 *color_data;
-
- if (brush_name && *brush_name)
- name = g_strdup (brush_name);
- else
- name = gimp_context_get_brush ();
-
- if (gimp_brush_get_pixels (name,
- &width,
- &height,
- &bytes,
- &mask_data_size,
- &mask_data,
- &color_bpp,
- &color_data_size,
- &color_data))
- {
- if (color_data)
- g_free (color_data);
-
- if (opacity < 0.0)
- opacity = gimp_context_get_opacity ();
-
- if (spacing == -1)
- {
- /* GimpBrush now a class. get_spacing is now an instance method.
- * FIXME: when this widget takes a brush instance instead of a name,
- * the next two lines should be deleted.
- */
- GimpBrush *brush = g_object_new (GIMP_TYPE_BRUSH, NULL);
- g_object_set (brush, "id", name, NULL);
-
- spacing = gimp_brush_get_spacing (brush);
- }
-
- if (paint_mode == -1)
- paint_mode = gimp_context_get_paint_mode ();
-
- gimp_brush_select_button_callback (name,
- opacity, spacing, paint_mode,
- width, height, width * height,
- mask_data,
- FALSE, button);
-
- g_free (mask_data);
- }
-
- g_free (name);
- }
+ /* Delegate to super with upcasts */
+ gimp_resource_select_button_set_resource (GIMP_RESOURCE_SELECT_BUTTON (self), GIMP_RESOURCE (brush));
}
@@ -476,221 +278,217 @@ gimp_brush_select_button_set_brush (GimpBrushSelectButton *button,
static void
gimp_brush_select_button_finalize (GObject *object)
{
- GimpBrushSelectButton *button = GIMP_BRUSH_SELECT_BUTTON (object);
+ g_debug ("%s called", G_STRFUNC);
- g_clear_pointer (&button->priv->brush_name, g_free);
- g_clear_pointer (&button->priv->mask_data, g_free);
- g_clear_pointer (&button->priv->title, g_free);
+ /* Has no allocations.*/
+ /* Chain up. */
G_OBJECT_CLASS (gimp_brush_select_button_parent_class)->finalize (object);
}
-static void
-gimp_brush_select_button_set_property (GObject *object,
- guint property_id,
- const GValue *value,
- GParamSpec *pspec)
+
+/* Create a widget that is the interior of another widget, a GimpBrushSelectButton.
+ * Super creates the exterior, self creates interior.
+ * Exterior is-a container and self calls super to add interior to the container.
+ */
+static GtkWidget *
+gimp_brush_select_button_create_interior (GimpBrushSelectButton *self)
{
- GimpBrushSelectButton *button = GIMP_BRUSH_SELECT_BUTTON (object);
- gdouble opacity;
- gint32 spacing;
- gint32 paint_mode;
+ GtkWidget *hbox;
+ GtkWidget *frame;
+ GtkWidget *peephole_view;
+ GtkWidget *browse_button;
- switch (property_id)
- {
- case PROP_TITLE:
- button->priv->title = g_value_dup_string (value);
- break;
+ g_debug ("%s", G_STRFUNC);
- case PROP_BRUSH_NAME:
- gimp_brush_select_button_set_brush (button,
- g_value_get_string (value),
- -1.0, -1, -1);
- break;
+ hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
- case PROP_BRUSH_OPACITY:
- opacity = g_value_get_double (value);
- if (opacity >= 0.0)
- button->priv->opacity = opacity;
- break;
+ frame = gtk_frame_new (NULL);
+ gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
+ gtk_box_pack_start (GTK_BOX (hbox), frame, FALSE, FALSE, 0);
- case PROP_BRUSH_SPACING:
- spacing = g_value_get_int (value);
- if (spacing != -1)
- button->priv->spacing = spacing;
- break;
+ peephole_view = gimp_preview_area_new ();
+ gtk_widget_add_events (peephole_view,
+ GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK);
+ gtk_widget_set_size_request (peephole_view, CELL_SIZE, CELL_SIZE);
+ gtk_container_add (GTK_CONTAINER (frame), peephole_view);
- case PROP_BRUSH_PAINT_MODE:
- paint_mode = g_value_get_int (value);
- if (paint_mode != -1)
- button->priv->paint_mode = paint_mode;
- break;
+ g_signal_connect_swapped (peephole_view, "size-allocate",
+ G_CALLBACK (gimp_brush_select_on_preview_resize),
+ self);
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- break;
- }
+ /* preview receives mouse events to popup and down. */
+ g_signal_connect (peephole_view, "event",
+ G_CALLBACK (gimp_brush_select_on_preview_events),
+ self);
+
+ browse_button = gtk_button_new_with_mnemonic (_("_Browse..."));
+ gtk_box_pack_start (GTK_BOX (hbox), browse_button, TRUE, TRUE, 0);
+
+ gtk_widget_show_all (hbox);
+
+ /* Ensure self knows sub widgets. */
+ self->peephole_view = peephole_view;
+ self->browse_button = browse_button;
+
+ /* Return the whole, it is not a button, only contains a button. */
+ return hbox;
+}
+
+/* This is NOT an implementation of virtual function. */
+static void
+gimp_brush_select_button_embed_interior (GimpBrushSelectButton *self)
+{
+ GtkWidget *interior;
+
+ g_debug ("%s", G_STRFUNC);
+
+ interior = gimp_brush_select_button_create_interior (self);
+
+ /* This subclass does not connect to draw signal on interior widget. */
+
+ /* Call super with upcasts. */
+ gimp_resource_select_button_embed_interior (GIMP_RESOURCE_SELECT_BUTTON (self), interior);
}
static void
-gimp_brush_select_button_get_property (GObject *object,
- guint property_id,
- GValue *value,
- GParamSpec *pspec)
+gimp_brush_select_button_set_drag_target (GimpBrushSelectButton *self)
{
- GimpBrushSelectButton *button = GIMP_BRUSH_SELECT_BUTTON (object);
-
- switch (property_id)
- {
- case PROP_TITLE:
- g_value_set_string (value, button->priv->title);
- break;
-
- case PROP_BRUSH_NAME:
- g_value_set_string (value, button->priv->brush_name);
- break;
-
- case PROP_BRUSH_OPACITY:
- g_value_set_double (value, button->priv->opacity);
- break;
-
- case PROP_BRUSH_SPACING:
- g_value_set_int (value, button->priv->spacing);
- break;
-
- case PROP_BRUSH_PAINT_MODE:
- g_value_set_int (value, button->priv->paint_mode);
- break;
-
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- break;
- }
+ /* Self knows the GtkTargetEntry, super knows how to create target and receive drag. */
+ /* Only the peephole_view receives drag. */
+ gimp_resource_select_button_set_drag_target (GIMP_RESOURCE_SELECT_BUTTON (self),
+ self->peephole_view,
+ &drag_target);
}
+
+/* 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_brush_select_button_callback (const gchar *name,
- gdouble opacity,
- gint spacing,
- GimpLayerMode paint_mode,
- gint width,
- gint height,
- gint mask_size,
- const guchar *mask_data,
- gboolean dialog_closing,
- gpointer data)
+gimp_brush_select_button_draw_interior (GimpResourceSelectButton *self)
{
- GimpBrushSelectButton *button = GIMP_BRUSH_SELECT_BUTTON (data);
- GimpSelectButton *select_button = GIMP_SELECT_BUTTON (button);
+ g_debug ("%s", G_STRFUNC);
- g_free (button->priv->brush_name);
- g_free (button->priv->mask_data);
+ g_return_if_fail (GIMP_IS_BRUSH_SELECT_BUTTON (self));
- button->priv->brush_name = g_strdup (name);
- button->priv->width = width;
- button->priv->height = height;
- button->priv->mask_data = g_memdup2 (mask_data, width * height);
- button->priv->opacity = opacity;
- button->priv->spacing = spacing;
- button->priv->paint_mode = paint_mode;
-
- gimp_brush_select_preview_update (button->priv->preview,
- width, height, mask_data);
-
- if (dialog_closing)
- select_button->temp_callback = NULL;
-
- g_signal_emit (button, brush_button_signals[BRUSH_SET], 0,
- name, opacity, spacing, paint_mode, width, height, mask_data,
- dialog_closing);
- g_object_notify_by_pspec (G_OBJECT (button), brush_button_props[PROP_BRUSH_NAME]);
+ gimp_brush_select_button_draw (GIMP_BRUSH_SELECT_BUTTON (self));
}
+
+/* Draw self.
+ *
+ * This knows that we only draw the peephole_view. Gtk draws the browse button.
+ */
static void
-gimp_brush_select_button_clicked (GimpBrushSelectButton *button)
+gimp_brush_select_button_draw (GimpBrushSelectButton *self)
{
- GimpSelectButton *select_button = GIMP_SELECT_BUTTON (button);
+ _PreviewBitmap mask;
- if (select_button->temp_callback)
- {
- /* calling gimp_brushes_set_popup() raises the dialog */
- gimp_brushes_set_popup (select_button->temp_callback,
- button->priv->brush_name,
- button->priv->opacity,
- button->priv->spacing,
- button->priv->paint_mode);
- }
- else
- {
- select_button->temp_callback =
- gimp_brush_select_new (button->priv->title,
- button->priv->brush_name,
- button->priv->opacity,
- button->priv->spacing,
- button->priv->paint_mode,
- gimp_brush_select_button_callback,
- button, NULL);
- }
+ g_debug ("%s", G_STRFUNC);
+
+ /* Draw the peephole. */
+ mask = gimp_brush_select_button_get_brush_bitmap (self);
+ gimp_brush_select_preview_fill_draw (self->peephole_view, mask);
+ g_free (mask.mask_data);
}
+
+
+/* Return the mask portion of self's brush's data.
+ * Caller must free mask_data.
+ */
+static _PreviewBitmap
+gimp_brush_select_button_get_brush_bitmap (GimpBrushSelectButton *self)
+{
+ GimpBrush *brush;
+ gint mask_bpp;
+ gint mask_data_size;
+ gint color_bpp;
+ gint color_data_size;
+ guint8 *color_data;
+ _PreviewBitmap result;
+
+ g_debug ("%s", G_STRFUNC);
+
+ g_object_get (self, "resource", &brush, NULL);
+
+ gimp_brush_get_pixels (brush,
+ &result.width,
+ &result.height,
+ &mask_bpp,
+ &mask_data_size,
+ &result.mask_data,
+ &color_bpp,
+ &color_data_size,
+ &color_data);
+
+ /* Discard any color data, bitmap is B&W i.e. i.e. depth one i.e. a mask */
+ if (color_data)
+ g_free (color_data);
+
+ return result;
+}
+
+
+/* On resize event, redraw. */
static void
-gimp_brush_select_preview_resize (GimpBrushSelectButton *button)
+gimp_brush_select_on_preview_resize (GimpBrushSelectButton *self)
{
- if (button->priv->width > 0 &&
- button->priv->height > 0)
- gimp_brush_select_preview_update (button->priv->preview,
- button->priv->width,
- button->priv->height,
- button->priv->mask_data);
+ g_debug ("%s", G_STRFUNC);
+
+ gimp_brush_select_button_draw (self);
}
+
+/* On mouse events in self's peephole_view, popup a zoom view of entire brush */
static gboolean
-gimp_brush_select_preview_events (GtkWidget *widget,
- GdkEvent *event,
- GimpBrushSelectButton *button)
+gimp_brush_select_on_preview_events (GtkWidget *widget,
+ GdkEvent *event,
+ GimpBrushSelectButton *self)
{
GdkEventButton *bevent;
- if (button->priv->mask_data)
+ g_debug ("%s", G_STRFUNC);
+
+ switch (event->type)
{
- switch (event->type)
+ case GDK_BUTTON_PRESS:
+ bevent = (GdkEventButton *) event;
+
+ if (bevent->button == 1)
{
- case GDK_BUTTON_PRESS:
- bevent = (GdkEventButton *) event;
-
- if (bevent->button == 1)
- {
- gtk_grab_add (widget);
- gimp_brush_select_button_open_popup (button,
- bevent->x, bevent->y);
- }
- break;
-
- case GDK_BUTTON_RELEASE:
- bevent = (GdkEventButton *) event;
-
- if (bevent->button == 1)
- {
- gtk_grab_remove (widget);
- gimp_brush_select_button_close_popup (button);
- }
- break;
-
- default:
- break;
+ gtk_grab_add (widget);
+ gimp_brush_select_button_open_popup (self,
+ bevent->x, bevent->y);
}
+ break;
+
+ case GDK_BUTTON_RELEASE:
+ bevent = (GdkEventButton *) event;
+
+ if (bevent->button == 1)
+ {
+ gtk_grab_remove (widget);
+ gimp_brush_select_button_close_popup (self);
+ }
+ break;
+
+ default:
+ break;
}
return FALSE;
}
+/* Draw a GimpPreviewArea with a given bitmap. */
static void
gimp_brush_select_preview_draw (GimpPreviewArea *area,
gint x,
gint y,
- gint width,
- gint height,
- const guchar *mask_data,
+ _PreviewBitmap mask,
gint rowstride)
{
const guchar *src;
@@ -698,45 +496,49 @@ gimp_brush_select_preview_draw (GimpPreviewArea *area,
guchar *buf;
gint i, j;
- buf = g_new (guchar, width * height);
+ g_debug ("%s", G_STRFUNC);
- src = mask_data;
+ buf = g_new (guchar, mask.width * mask.height);
+
+ src = mask.mask_data;
dest = buf;
- for (j = 0; j < height; j++)
+ for (j = 0; j < mask.height; j++)
{
const guchar *s = src;
- for (i = 0; i < width; i++, s++, dest++)
+ for (i = 0; i < mask.width; i++, s++, dest++)
*dest = 255 - *s;
src += rowstride;
}
gimp_preview_area_draw (area,
- x, y, width, height,
+ x, y, mask.width, mask.height,
GIMP_GRAY_IMAGE,
buf,
- width);
+ mask.width);
g_free (buf);
}
+/* Fill a GimpPreviewArea with a bitmap then draw. */
static void
-gimp_brush_select_preview_update (GtkWidget *preview,
- gint brush_width,
- gint brush_height,
- const guchar *mask_data)
+gimp_brush_select_preview_fill_draw (GtkWidget *preview,
+ _PreviewBitmap mask)
{
GimpPreviewArea *area = GIMP_PREVIEW_AREA (preview);
GtkAllocation allocation;
gint x, y;
gint width, height;
+ _PreviewBitmap drawn_mask;
+
+ g_debug ("%s", G_STRFUNC);
gtk_widget_get_allocation (preview, &allocation);
- width = MIN (brush_width, allocation.width);
- height = MIN (brush_height, allocation.height);
+ width = MIN (mask.width, allocation.width);
+ height = MIN (mask.height, allocation.height);
x = ((allocation.width - width) / 2);
y = ((allocation.height - height) / 2);
@@ -748,159 +550,92 @@ gimp_brush_select_preview_update (GtkWidget *preview,
allocation.height,
0xFF, 0xFF, 0xFF);
+ /* Draw same data to new bounds.
+ * drawn_mask.mask_data points to same array.
+ */
+ drawn_mask.width = width;
+ drawn_mask.height = height;
+ drawn_mask.mask_data = mask.mask_data;
+
gimp_brush_select_preview_draw (area,
- x, y, width, height,
- mask_data, brush_width);
+ x, y,
+ drawn_mask,
+ mask.width); /* row stride */
+ /* Caller will free mask.mask_data */
}
+/* popup methods. */
+
static void
-gimp_brush_select_button_open_popup (GimpBrushSelectButton *button,
+gimp_brush_select_button_open_popup (GimpBrushSelectButton *self,
gint x,
gint y)
{
- GimpBrushSelectButtonPrivate *priv = button->priv;
GtkWidget *frame;
GtkWidget *preview;
GdkMonitor *monitor;
GdkRectangle workarea;
gint x_org;
gint y_org;
+ _PreviewBitmap mask;
- if (priv->popup)
- gimp_brush_select_button_close_popup (button);
+ g_debug ("%s", G_STRFUNC);
- if (priv->width <= CELL_SIZE && priv->height <= CELL_SIZE)
- return;
+ if (self->popup)
+ gimp_brush_select_button_close_popup (self);
- priv->popup = gtk_window_new (GTK_WINDOW_POPUP);
- gtk_window_set_type_hint (GTK_WINDOW (priv->popup), GDK_WINDOW_TYPE_HINT_DND);
- gtk_window_set_screen (GTK_WINDOW (priv->popup),
- gtk_widget_get_screen (GTK_WIDGET (button)));
+ mask = gimp_brush_select_button_get_brush_bitmap (self);
- frame = gtk_frame_new (NULL);
- gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT);
- gtk_container_add (GTK_CONTAINER (priv->popup), frame);
- gtk_widget_show (frame);
-
- preview = gimp_preview_area_new ();
- gtk_widget_set_size_request (preview, priv->width, priv->height);
- gtk_container_add (GTK_CONTAINER (frame), preview);
- gtk_widget_show (preview);
-
- /* decide where to put the popup */
- gdk_window_get_origin (gtk_widget_get_window (priv->preview),
- &x_org, &y_org);
-
- monitor = gimp_widget_get_monitor (GTK_WIDGET (button));
- gdk_monitor_get_workarea (monitor, &workarea);
-
- x = x_org + x - (priv->width / 2);
- y = y_org + y - (priv->height / 2);
-
- x = CLAMP (x, workarea.x, workarea.x + workarea.width - priv->width);
- y = CLAMP (y, workarea.y, workarea.y + workarea.height - priv->height);
-
- gtk_window_move (GTK_WINDOW (priv->popup), x, y);
-
- gtk_widget_show (priv->popup);
-
- /* Draw the brush */
- gimp_brush_select_preview_draw (GIMP_PREVIEW_AREA (preview),
- 0, 0, priv->width, priv->height,
- priv->mask_data, priv->width);
-}
-
-static void
-gimp_brush_select_button_close_popup (GimpBrushSelectButton *button)
-{
- g_clear_pointer (&button->priv->popup, gtk_widget_destroy);
-}
-
-static void
-gimp_brush_select_drag_data_received (GimpBrushSelectButton *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)
+ if (mask.width <= CELL_SIZE && mask.height <= CELL_SIZE)
{
- g_warning ("%s: received invalid brush data", G_STRFUNC);
+ g_debug ("%s: omit popup smaller than peephole.", 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_brush_select_button_set_brush (button, name, -1.0, -1, -1);
- }
- }
-
- g_free (str);
-}
-
-static GtkWidget *
-gimp_brush_select_button_create_inside (GimpBrushSelectButton *brush_button)
-{
- GimpBrushSelectButtonPrivate *priv = brush_button->priv;
- GtkWidget *hbox;
- GtkWidget *frame;
- GtkWidget *button;
-
- hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+ self->popup = gtk_window_new (GTK_WINDOW_POPUP);
+ gtk_window_set_type_hint (GTK_WINDOW (self->popup), GDK_WINDOW_TYPE_HINT_DND);
+ gtk_window_set_screen (GTK_WINDOW (self->popup),
+ gtk_widget_get_screen (GTK_WIDGET (self)));
frame = gtk_frame_new (NULL);
- gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
- gtk_box_pack_start (GTK_BOX (hbox), frame, FALSE, FALSE, 0);
+ gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT);
+ gtk_container_add (GTK_CONTAINER (self->popup), frame);
+ gtk_widget_show (frame);
- priv->preview = gimp_preview_area_new ();
- gtk_widget_add_events (priv->preview,
- GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK);
- gtk_widget_set_size_request (priv->preview, CELL_SIZE, CELL_SIZE);
- gtk_container_add (GTK_CONTAINER (frame), priv->preview);
+ preview = gimp_preview_area_new ();
+ gtk_widget_set_size_request (preview, mask.width, mask.height);
+ gtk_container_add (GTK_CONTAINER (frame), preview);
+ gtk_widget_show (preview);
- g_signal_connect_swapped (priv->preview, "size-allocate",
- G_CALLBACK (gimp_brush_select_preview_resize),
- brush_button);
- g_signal_connect (priv->preview, "event",
- G_CALLBACK (gimp_brush_select_preview_events),
- brush_button);
+ /* decide where to put the popup: near the peephole_view i.e. at mousedown coords */
+ gdk_window_get_origin (gtk_widget_get_window (self->peephole_view),
+ &x_org, &y_org);
- gtk_drag_dest_set (GTK_WIDGET (priv->preview),
- GTK_DEST_DEFAULT_HIGHLIGHT |
- GTK_DEST_DEFAULT_MOTION |
- GTK_DEST_DEFAULT_DROP,
- &target, 1,
- GDK_ACTION_COPY);
+ monitor = gimp_widget_get_monitor (GTK_WIDGET (self));
+ gdk_monitor_get_workarea (monitor, &workarea);
- g_signal_connect_swapped (priv->preview, "drag-data-received",
- G_CALLBACK (gimp_brush_select_drag_data_received),
- brush_button);
+ x = x_org + x - (mask.width / 2);
+ y = y_org + y - (mask.height / 2);
- button = gtk_button_new_with_mnemonic (_("_Browse..."));
- gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
+ x = CLAMP (x, workarea.x, workarea.x + workarea.width - mask.width);
+ y = CLAMP (y, workarea.y, workarea.y + workarea.height - mask.height);
- g_signal_connect_swapped (button, "clicked",
- G_CALLBACK (gimp_brush_select_button_clicked),
- brush_button);
+ gtk_window_move (GTK_WINDOW (self->popup), x, y);
- gtk_widget_show_all (hbox);
+ gtk_widget_show (self->popup);
- return hbox;
+ /* Draw popup now. Usual events do not cause a draw. */
+ gimp_brush_select_preview_draw (GIMP_PREVIEW_AREA (preview),
+ 0, 0,
+ mask,
+ mask.width);
+ g_free (mask.mask_data);
+}
+
+static void
+gimp_brush_select_button_close_popup (GimpBrushSelectButton *self)
+{
+ g_debug ("%s", G_STRFUNC);
+
+ g_clear_pointer (&self->popup, gtk_widget_destroy);
}
diff --git a/libgimp/gimpbrushselectbutton.h b/libgimp/gimpbrushselectbutton.h
index 95be946d0d..6a16a90ea6 100644
--- a/libgimp/gimpbrushselectbutton.h
+++ b/libgimp/gimpbrushselectbutton.h
@@ -25,76 +25,35 @@
#ifndef __GIMP_BRUSH_SELECT_BUTTON_H__
#define __GIMP_BRUSH_SELECT_BUTTON_H__
-#include
+#include
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
diff --git a/libgimp/gimpfontselect.c b/libgimp/gimpfontselect.c
deleted file mode 100644
index 5c4714fda5..0000000000
--- a/libgimp/gimpfontselect.c
+++ /dev/null
@@ -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
- * .
- */
-
-#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;
-}
diff --git a/libgimp/gimpfontselect.h b/libgimp/gimpfontselect.h
deleted file mode 100644
index 6a41c31422..0000000000
--- a/libgimp/gimpfontselect.h
+++ /dev/null
@@ -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
- * .
- */
-
-#if !defined (__GIMP_H_INSIDE__) && !defined (GIMP_COMPILATION)
-#error "Only 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__ */
diff --git a/libgimp/gimpfontselect_pdb.c b/libgimp/gimpfontselect_pdb.c
index 10223193ff..65c9a11a55 100644
--- a/libgimp/gimpfontselect_pdb.c
+++ b/libgimp/gimpfontselect_pdb.c
@@ -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.
diff --git a/libgimp/gimpfontselect_pdb.h b/libgimp/gimpfontselect_pdb.h
index 1685e351a3..c0456c632f 100644
--- a/libgimp/gimpfontselect_pdb.h
+++ b/libgimp/gimpfontselect_pdb.h
@@ -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);
diff --git a/libgimp/gimpfontselectbutton.c b/libgimp/gimpfontselectbutton.c
index 5f994eccdc..9e47e17f29 100644
--- a/libgimp/gimpfontselectbutton.c
+++ b/libgimp/gimpfontselectbutton.c
@@ -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);
+}
diff --git a/libgimp/gimpfontselectbutton.h b/libgimp/gimpfontselectbutton.h
index ac816092aa..7adde5bdad 100644
--- a/libgimp/gimpfontselectbutton.h
+++ b/libgimp/gimpfontselectbutton.h
@@ -25,61 +25,35 @@
#ifndef __GIMP_FONT_SELECT_BUTTON_H__
#define __GIMP_FONT_SELECT_BUTTON_H__
-#include
+#include
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
diff --git a/libgimp/gimpgradientselect.c b/libgimp/gimpgradientselect.c
deleted file mode 100644
index 3982aea0df..0000000000
--- a/libgimp/gimpgradientselect.c
+++ /dev/null
@@ -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
- * .
- */
-
-#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;
-}
diff --git a/libgimp/gimpgradientselect.h b/libgimp/gimpgradientselect.h
deleted file mode 100644
index 972e7eb18b..0000000000
--- a/libgimp/gimpgradientselect.h
+++ /dev/null
@@ -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
- * .
- */
-
-#if !defined (__GIMP_H_INSIDE__) && !defined (GIMP_COMPILATION)
-#error "Only 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__ */
diff --git a/libgimp/gimpgradientselect_pdb.c b/libgimp/gimpgradientselect_pdb.c
index c55c341bf2..67a47d217a 100644
--- a/libgimp/gimpgradientselect_pdb.c
+++ b/libgimp/gimpgradientselect_pdb.c
@@ -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.
**/
diff --git a/libgimp/gimpgradientselect_pdb.h b/libgimp/gimpgradientselect_pdb.h
index e3b85937d6..c283ac5aeb 100644
--- a/libgimp/gimpgradientselect_pdb.h
+++ b/libgimp/gimpgradientselect_pdb.h
@@ -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);
diff --git a/libgimp/gimpgradientselectbutton.c b/libgimp/gimpgradientselectbutton.c
index c464edc885..b24f9ea40b 100644
--- a/libgimp/gimpgradientselectbutton.c
+++ b/libgimp/gimpgradientselectbutton.c
@@ -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);
}
diff --git a/libgimp/gimpgradientselectbutton.h b/libgimp/gimpgradientselectbutton.h
index 2d0549385a..e2bfbe5e4f 100644
--- a/libgimp/gimpgradientselectbutton.h
+++ b/libgimp/gimpgradientselectbutton.h
@@ -25,62 +25,28 @@
#ifndef __GIMP_GRADIENT_SELECT_BUTTON_H__
#define __GIMP_GRADIENT_SELECT_BUTTON_H__
-#include
+#include
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
diff --git a/libgimp/gimppaletteselect.c b/libgimp/gimppaletteselect.c
deleted file mode 100644
index 0df01c3f4c..0000000000
--- a/libgimp/gimppaletteselect.c
+++ /dev/null
@@ -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
- * .
- */
-
-#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;
-}
diff --git a/libgimp/gimppaletteselect.h b/libgimp/gimppaletteselect.h
deleted file mode 100644
index 505ee1d9eb..0000000000
--- a/libgimp/gimppaletteselect.h
+++ /dev/null
@@ -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
- * .
- */
-
-#if !defined (__GIMP_H_INSIDE__) && !defined (GIMP_COMPILATION)
-#error "Only 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__ */
diff --git a/libgimp/gimppaletteselect_pdb.c b/libgimp/gimppaletteselect_pdb.c
index 6a1ebaa9c6..72c9cd0730 100644
--- a/libgimp/gimppaletteselect_pdb.c
+++ b/libgimp/gimppaletteselect_pdb.c
@@ -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.
**/
diff --git a/libgimp/gimppaletteselect_pdb.h b/libgimp/gimppaletteselect_pdb.h
index 221ec4b7b3..840108db9d 100644
--- a/libgimp/gimppaletteselect_pdb.h
+++ b/libgimp/gimppaletteselect_pdb.h
@@ -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);
diff --git a/libgimp/gimppaletteselectbutton.c b/libgimp/gimppaletteselectbutton.c
index b4a57197c8..ef782f5ab6 100644
--- a/libgimp/gimppaletteselectbutton.c
+++ b/libgimp/gimppaletteselectbutton.c
@@ -19,6 +19,8 @@
* .
*/
+/* Similar to gimpfontselectbutton.c, initially created by simple substitution. */
+
#include "config.h"
#include
@@ -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);
+}
diff --git a/libgimp/gimppaletteselectbutton.h b/libgimp/gimppaletteselectbutton.h
index 23cf63264e..1d2a1c57d2 100644
--- a/libgimp/gimppaletteselectbutton.h
+++ b/libgimp/gimppaletteselectbutton.h
@@ -25,61 +25,35 @@
#ifndef __GIMP_PALETTE_SELECT_BUTTON_H__
#define __GIMP_PALETTE_SELECT_BUTTON_H__
-#include
+#include
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
diff --git a/libgimp/gimpparamspecs-body-resource.c b/libgimp/gimpparamspecs-body-resource.c
index 3ae744d0c7..e53770ab00 100644
--- a/libgimp/gimpparamspecs-body-resource.c
+++ b/libgimp/gimpparamspecs-body-resource.c
@@ -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
*/
diff --git a/libgimp/gimpparamspecs-resource.h b/libgimp/gimpparamspecs-resource.h
index 978b82aa39..83fc4943a8 100644
--- a/libgimp/gimpparamspecs-resource.h
+++ b/libgimp/gimpparamspecs-resource.h
@@ -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) )
diff --git a/libgimp/gimppatternselect.c b/libgimp/gimppatternselect.c
deleted file mode 100644
index da53110a06..0000000000
--- a/libgimp/gimppatternselect.c
+++ /dev/null
@@ -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
- * .
- */
-
-#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;
-}
diff --git a/libgimp/gimppatternselect.h b/libgimp/gimppatternselect.h
deleted file mode 100644
index 024257732f..0000000000
--- a/libgimp/gimppatternselect.h
+++ /dev/null
@@ -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
- * .
- */
-
-#if !defined (__GIMP_H_INSIDE__) && !defined (GIMP_COMPILATION)
-#error "Only 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__ */
diff --git a/libgimp/gimppatternselect_pdb.c b/libgimp/gimppatternselect_pdb.c
index d1f9fbde90..02657e28f8 100644
--- a/libgimp/gimppatternselect_pdb.c
+++ b/libgimp/gimppatternselect_pdb.c
@@ -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.
**/
diff --git a/libgimp/gimppatternselect_pdb.h b/libgimp/gimppatternselect_pdb.h
index 50a04287b4..b56f4be488 100644
--- a/libgimp/gimppatternselect_pdb.h
+++ b/libgimp/gimppatternselect_pdb.h
@@ -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);
diff --git a/libgimp/gimppatternselectbutton.c b/libgimp/gimppatternselectbutton.c
index 46cc6ef306..444f1f8367 100644
--- a/libgimp/gimppatternselectbutton.c
+++ b/libgimp/gimppatternselectbutton.c
@@ -19,6 +19,10 @@
* .
*/
+/* Similar to gimpbrushselectbutton.c.
+ * FUTURE: inherit or share common code.
+ */
+
#include "config.h"
#include
@@ -38,301 +42,244 @@
/**
* SECTION: gimppatternselectbutton
* @title: GimpPatternSelectButton
- * @short_description: A button which pops up a pattern select dialog.
+ * @short_description: A button which pops up a pattern selection dialog.
*
- * A button which pops up a pattern select dialog.
+ * A button which pops up a pattern selection dialog.
**/
-
#define CELL_SIZE 20
-
-#define GET_PRIVATE(obj) (((GimpPatternSelectButtonPrivate *) (obj))->priv)
-
-struct _GimpPatternSelectButtonPrivate
+/* An image. pixelels is allocated and must be freed. */
+typedef struct _PreviewImage
{
- gchar *title;
+ gint width;
+ gint height;
+ gint bpp;
+ guchar *pixelels;
+} _PreviewImage;
- gchar *pattern_name; /* Local copy */
- gint width;
- gint height;
- gint bytes;
- guchar *mask_data; /* local copy */
+struct _GimpPatternSelectButton
+{
+ /* !! Not a pointer, is contained. */
+ GimpResourceSelectButton parent_instance;
- GtkWidget *inside;
- GtkWidget *preview;
- GtkWidget *popup;
+ /* Partial view of pattern image. Receives drag. Receives mouse down to popup zoom. */
+ GtkWidget *peephole_view;
+ GtkWidget *popup; /* Popup showing entire, full-size pattern image. */
+ GtkWidget *browse_button; /* Clickable area that popups remote chooser. */
};
-enum
-{
- PATTERN_SET,
- LAST_SIGNAL
-};
+/* local */
-enum
-{
- PROP_0,
- PROP_TITLE,
- PROP_PATTERN_NAME,
- N_PROPS
-};
+/* implement virtual. */
+static void gimp_pattern_select_button_finalize (GObject *object);
+static void gimp_pattern_select_button_draw_interior (GimpResourceSelectButton *self);
+/* init methods. */
+static GtkWidget *gimp_pattern_select_button_create_interior (GimpPatternSelectButton *self);
-/* local function prototypes */
+/* Event handlers. */
+static void gimp_pattern_select_on_preview_resize (GimpPatternSelectButton *button);
+static gboolean gimp_pattern_select_on_preview_events (GtkWidget *widget,
+ GdkEvent *event,
+ GimpPatternSelectButton *button);
-static void gimp_pattern_select_button_finalize (GObject *object);
+/* local drawing methods. */
+static void gimp_pattern_select_preview_draw (GimpPreviewArea *area,
+ gint x,
+ gint y,
+ _PreviewImage image,
+ gint rowstride);
+static void gimp_pattern_select_preview_fill_draw (GtkWidget *preview,
+ _PreviewImage image);
-static void gimp_pattern_select_button_set_property (GObject *object,
- guint property_id,
- const GValue *value,
- GParamSpec *pspec);
-static void gimp_pattern_select_button_get_property (GObject *object,
- guint property_id,
- GValue *value,
- GParamSpec *pspec);
-
-static void gimp_pattern_select_button_clicked (GimpPatternSelectButton *button);
-
-static void gimp_pattern_select_button_callback (const gchar *pattern_name,
- gint width,
- gint height,
- gint bytes,
- const guchar *mask_data,
- gboolean dialog_closing,
- gpointer user_data);
-
-static void gimp_pattern_select_preview_resize (GimpPatternSelectButton *button);
-static gboolean gimp_pattern_select_preview_events (GtkWidget *widget,
- GdkEvent *event,
- GimpPatternSelectButton *button);
-static void gimp_pattern_select_preview_update (GtkWidget *preview,
- gint width,
- gint height,
- gint bytes,
- const guchar *mask_data);
+static void gimp_pattern_select_button_draw (GimpPatternSelectButton *self);
+static _PreviewImage gimp_pattern_select_button_get_pattern_image (GimpPatternSelectButton *self);
+/* Popup methods. */
static void gimp_pattern_select_button_open_popup (GimpPatternSelectButton *button,
gint x,
gint y);
static void gimp_pattern_select_button_close_popup (GimpPatternSelectButton *button);
-static void gimp_pattern_select_drag_data_received (GimpPatternSelectButton *button,
- GdkDragContext *context,
- gint x,
- gint y,
- GtkSelectionData *selection,
- guint info,
- guint time);
-
-static GtkWidget * gimp_pattern_select_button_create_inside (GimpPatternSelectButton *button);
-static const GtkTargetEntry target = { "application/x-gimp-pattern-name", 0 };
-static guint pattern_button_signals[LAST_SIGNAL] = { 0 };
-static GParamSpec *pattern_button_props[N_PROPS] = { NULL, };
+/* A GtkTargetEntry has a string and two ints.
+ * This is one, but we treat it as an array.
+ */
+static const GtkTargetEntry drag_target = { "application/x-gimp-pattern-name", 0, 0 };
-
-G_DEFINE_TYPE_WITH_PRIVATE (GimpPatternSelectButton, gimp_pattern_select_button,
- GIMP_TYPE_SELECT_BUTTON)
+G_DEFINE_FINAL_TYPE (GimpPatternSelectButton,
+ gimp_pattern_select_button,
+ GIMP_TYPE_RESOURCE_SELECT_BUTTON)
static void
gimp_pattern_select_button_class_init (GimpPatternSelectButtonClass *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);
object_class->finalize = gimp_pattern_select_button_finalize;
- object_class->set_property = gimp_pattern_select_button_set_property;
- object_class->get_property = gimp_pattern_select_button_get_property;
- select_button_class->select_destroy = gimp_pattern_select_destroy;
+ /* Implement pure virtual functions. */
+ superclass->draw_interior = gimp_pattern_select_button_draw_interior;
- klass->pattern_set = NULL;
+ /* Set data member of class. */
+ superclass->resource_type = GIMP_TYPE_PATTERN;
- /**
- * GimpPatternSelectButton:title:
- *
- * The title to be used for the pattern selection popup dialog.
- *
- * Since: 2.4
+ /* We don't define property getter/setters: use superclass getter/setters.
+ * But super property name is "resource", not "pattern"
*/
- pattern_button_props[PROP_TITLE] = g_param_spec_string ("title",
- "Title",
- "The title to be used for the pattern selection popup dialog",
- _("Pattern Selection"),
- GIMP_PARAM_READWRITE |
- G_PARAM_CONSTRUCT_ONLY);
-
- /**
- * GimpPatternSelectButton:pattern-name:
- *
- * The name of the currently selected pattern.
- *
- * Since: 2.4
- */
- pattern_button_props[PROP_PATTERN_NAME] = g_param_spec_string ("pattern-name",
- "Pattern name",
- "The name of the currently selected pattern",
- NULL,
- GIMP_PARAM_READWRITE);
-
- g_object_class_install_properties (object_class, N_PROPS, pattern_button_props);
-
- /**
- * GimpPatternSelectButton::pattern-set:
- * @widget: the object which received the signal.
- * @pattern_name: the name of the currently selected pattern.
- * @width: width of the pattern
- * @height: height of the pattern
- * @bpp: bpp of the pattern
- * @mask_data: pattern mask data
- * @dialog_closing: whether the dialog was closed or not.
- *
- * The ::pattern-set signal is emitted when the user selects a pattern.
- *
- * Since: 2.4
- */
- pattern_button_signals[PATTERN_SET] =
- g_signal_new ("pattern-set",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_FIRST,
- G_STRUCT_OFFSET (GimpPatternSelectButtonClass, pattern_set),
- NULL, NULL,
- _gimpui_marshal_VOID__STRING_INT_INT_INT_POINTER_BOOLEAN,
- G_TYPE_NONE, 6,
- G_TYPE_STRING,
- G_TYPE_INT,
- G_TYPE_INT,
- G_TYPE_INT,
- G_TYPE_POINTER,
- G_TYPE_BOOLEAN);
}
static void
-gimp_pattern_select_button_init (GimpPatternSelectButton *button)
+gimp_pattern_select_button_init (GimpPatternSelectButton *self)
{
- gint mask_data_size;
+ GtkWidget *interior;
- button->priv = gimp_pattern_select_button_get_instance_private (button);
+ g_debug ("%s called", G_STRFUNC);
- button->priv->pattern_name = gimp_context_get_pattern ();
- gimp_pattern_get_pixels (button->priv->pattern_name,
- &button->priv->width,
- &button->priv->height,
- &button->priv->bytes,
- &mask_data_size,
- &button->priv->mask_data);
+ /* Specialize:
+ * - embed our widget interior instance to super widget instance.
+ * - connect our widget to dnd
+ * These will call superclass methods.
+ * These are on instance, not our subclass.
+ */
+ interior = gimp_pattern_select_button_create_interior (self);
- button->priv->inside = gimp_pattern_select_button_create_inside (button);
- gtk_container_add (GTK_CONTAINER (button), button->priv->inside);
+ gimp_resource_select_button_embed_interior (GIMP_RESOURCE_SELECT_BUTTON (self), interior);
+
+ /* Self knows the GtkTargetEntry, super knows how to create target and receive drag. */
+ /* Only the peephole_view receives drag. */
+ gimp_resource_select_button_set_drag_target (GIMP_RESOURCE_SELECT_BUTTON (self),
+ self->peephole_view,
+ &drag_target);
+
+ /* Tell super which sub widget pops up remote chooser.
+ * Only the browse_button.
+ * A click in the peephole_view does something else: popup a zoom.
+ */
+ gimp_resource_select_button_set_clickable (GIMP_RESOURCE_SELECT_BUTTON (self),
+ self->browse_button);
}
/**
* gimp_pattern_select_button_new:
* @title: (nullable): Title of the dialog to use or %NULL to use the default title.
- * @pattern_name: (nullable): Initial pattern name or %NULL to use current selection.
+ * @resource: (nullable): Initial pattern.
*
- * Creates a new #GtkWidget that completely controls the selection of
- * a pattern. This widget is suitable for placement in a table in a
- * plug-in dialog.
+ * Creates a new #GtkWidget that lets a user choose a pattern.
+ * You can put this widget in a table in a plug-in dialog.
+ *
+ * When pattern is NULL, initial choice is from context.
*
* Returns: A #GtkWidget that you can use in your UI.
*
* Since: 2.4
*/
GtkWidget *
-gimp_pattern_select_button_new (const gchar *title,
- const gchar *pattern_name)
+gimp_pattern_select_button_new (const gchar *title,
+ GimpResource *resource)
{
- GtkWidget *button;
+ GtkWidget *self;
- if (title)
- button = g_object_new (GIMP_TYPE_PATTERN_SELECT_BUTTON,
- "title", title,
- "pattern-name", pattern_name,
- NULL);
- else
- button = g_object_new (GIMP_TYPE_PATTERN_SELECT_BUTTON,
- "pattern-name", pattern_name,
- NULL);
+ g_debug ("%s called", G_STRFUNC);
- return button;
+ if (resource == NULL)
+ {
+ g_debug ("%s defaulting pattern from context", G_STRFUNC);
+ resource = GIMP_RESOURCE (gimp_context_get_pattern ());
+ }
+ g_assert (resource != NULL);
+ /* This method is polymorphic, so a factory can call it, but requires Pattern. */
+ g_return_val_if_fail (GIMP_IS_PATTERN (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_PATTERN_SELECT_BUTTON,
+ "title", title,
+ "resource", resource,
+ NULL);
+ else
+ self = g_object_new (GIMP_TYPE_PATTERN_SELECT_BUTTON,
+ "resource", resource,
+ NULL);
+
+ /* We don't subscribe to events from super.
+ * Super will queue a draw when it's resource changes.
+ * Except that the above setting of property happens too late,
+ * so we now draw the initial resource.
+ */
+
+ /* Draw it with the initial resource.
+ * Easier to call draw method than to queue a draw.
+ *
+ * Cast self from Widget.
+ */
+ gimp_pattern_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_pattern_select_button_get_pattern:
- * @button: A #GimpPatternSelectButton
+ * @self: A #GimpPatternSelectButton
*
- * Retrieves the name of currently selected pattern.
+ * Gets the currently selected pattern.
*
- * Returns: an internal copy of the pattern name which must not be freed.
+ * Returns: (transfer none): an internal copy of the pattern which must not be freed.
*
* Since: 2.4
*/
-const gchar *
-gimp_pattern_select_button_get_pattern (GimpPatternSelectButton *button)
+GimpPattern *
+gimp_pattern_select_button_get_pattern (GimpPatternSelectButton *self)
{
- g_return_val_if_fail (GIMP_IS_PATTERN_SELECT_BUTTON (button), NULL);
+ g_return_val_if_fail (GIMP_IS_PATTERN_SELECT_BUTTON (self), NULL);
- return button->priv->pattern_name;
+ /* Delegate to super w upcast arg and downcast result. */
+ return (GimpPattern *) gimp_resource_select_button_get_resource ((GimpResourceSelectButton*) self);
}
/**
* gimp_pattern_select_button_set_pattern:
- * @button: A #GimpPatternSelectButton
- * @pattern_name: (nullable): Pattern name to set; %NULL means no change.
+ * @self: A #GimpPatternSelectButton
+ * @pattern: Pattern to set.
*
- * Sets the current pattern for the pattern select button.
+ * Sets the currently selected pattern.
+ * 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_pattern_select_button_set_pattern (GimpPatternSelectButton *button,
- const gchar *pattern_name)
+gimp_pattern_select_button_set_pattern (GimpPatternSelectButton *self,
+ GimpPattern *pattern)
{
- GimpSelectButton *select_button;
+ g_return_if_fail (GIMP_IS_PATTERN_SELECT_BUTTON (self));
- g_return_if_fail (GIMP_IS_PATTERN_SELECT_BUTTON (button));
+ g_debug ("%s", G_STRFUNC);
- select_button = GIMP_SELECT_BUTTON (button);
-
- if (select_button->temp_callback)
- {
- gimp_patterns_set_popup (select_button->temp_callback, pattern_name);
- }
- else
- {
- gchar *name;
- gint width;
- gint height;
- gint bytes;
- gint mask_data_size;
- guint8 *mask_data;
-
- if (pattern_name && *pattern_name)
- name = g_strdup (pattern_name);
- else
- name = gimp_context_get_pattern ();
-
- if (gimp_pattern_get_pixels (name,
- &width,
- &height,
- &bytes,
- &mask_data_size,
- &mask_data))
- {
- gimp_pattern_select_button_callback (name,
- width, height, bytes, mask_data,
- FALSE, button);
-
- g_free (mask_data);
- }
-
- g_free (name);
- }
+ /* Delegate to super with upcasts */
+ gimp_resource_select_button_set_resource (GIMP_RESOURCE_SELECT_BUTTON (self), GIMP_RESOURCE (pattern));
}
@@ -341,305 +288,28 @@ gimp_pattern_select_button_set_pattern (GimpPatternSelectButton *button,
static void
gimp_pattern_select_button_finalize (GObject *object)
{
- GimpPatternSelectButton *button = GIMP_PATTERN_SELECT_BUTTON (object);
+ g_debug ("%s called", G_STRFUNC);
- g_clear_pointer (&button->priv->pattern_name, g_free);
- g_clear_pointer (&button->priv->mask_data, g_free);
- g_clear_pointer (&button->priv->title, g_free);
+ /* Has no allocations.*/
+ /* Chain up. */
G_OBJECT_CLASS (gimp_pattern_select_button_parent_class)->finalize (object);
}
-static void
-gimp_pattern_select_button_set_property (GObject *object,
- guint property_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- GimpPatternSelectButton *button = GIMP_PATTERN_SELECT_BUTTON (object);
-
- switch (property_id)
- {
- case PROP_TITLE:
- button->priv->title = g_value_dup_string (value);
- break;
-
- case PROP_PATTERN_NAME:
- gimp_pattern_select_button_set_pattern (button,
- g_value_get_string (value));
- break;
-
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- break;
- }
-}
-
-static void
-gimp_pattern_select_button_get_property (GObject *object,
- guint property_id,
- GValue *value,
- GParamSpec *pspec)
-{
- GimpPatternSelectButton *button = GIMP_PATTERN_SELECT_BUTTON (object);
-
- switch (property_id)
- {
- case PROP_TITLE:
- g_value_set_string (value, button->priv->title);
- break;
-
- case PROP_PATTERN_NAME:
- g_value_set_string (value, button->priv->pattern_name);
- break;
-
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- break;
- }
-}
-
-static void
-gimp_pattern_select_button_callback (const gchar *pattern_name,
- gint width,
- gint height,
- gint bytes,
- const guchar *mask_data,
- gboolean dialog_closing,
- gpointer user_data)
-{
- GimpPatternSelectButton *button = user_data;
- GimpSelectButton *select_button = GIMP_SELECT_BUTTON (button);
-
- g_free (button->priv->pattern_name);
- g_free (button->priv->mask_data);
-
- button->priv->pattern_name = g_strdup (pattern_name);
- button->priv->width = width;
- button->priv->height = height;
- button->priv->bytes = bytes;
- button->priv->mask_data = g_memdup2 (mask_data, width * height * bytes);
-
- gimp_pattern_select_preview_update (button->priv->preview,
- width, height, bytes, mask_data);
-
- if (dialog_closing)
- select_button->temp_callback = NULL;
-
- g_signal_emit (button, pattern_button_signals[PATTERN_SET], 0,
- pattern_name, width, height, bytes, dialog_closing);
- g_object_notify_by_pspec (G_OBJECT (button), pattern_button_props[PROP_PATTERN_NAME]);
-}
-
-static void
-gimp_pattern_select_button_clicked (GimpPatternSelectButton *button)
-{
- GimpSelectButton *select_button = GIMP_SELECT_BUTTON (button);
-
- if (select_button->temp_callback)
- {
- /* calling gimp_patterns_set_popup() raises the dialog */
- gimp_patterns_set_popup (select_button->temp_callback,
- button->priv->pattern_name);
- }
- else
- {
- select_button->temp_callback =
- gimp_pattern_select_new (button->priv->title,
- button->priv->pattern_name,
- gimp_pattern_select_button_callback,
- button, NULL);
- }
-}
-
-static void
-gimp_pattern_select_preview_resize (GimpPatternSelectButton *button)
-{
- if (button->priv->width > 0 && button->priv->height > 0)
- gimp_pattern_select_preview_update (button->priv->preview,
- button->priv->width,
- button->priv->height,
- button->priv->bytes,
- button->priv->mask_data);
-}
-
-static gboolean
-gimp_pattern_select_preview_events (GtkWidget *widget,
- GdkEvent *event,
- GimpPatternSelectButton *button)
-{
- GdkEventButton *bevent;
-
- if (button->priv->mask_data)
- {
- switch (event->type)
- {
- case GDK_BUTTON_PRESS:
- bevent = (GdkEventButton *) event;
-
- if (bevent->button == 1)
- {
- gtk_grab_add (widget);
- gimp_pattern_select_button_open_popup (button,
- bevent->x, bevent->y);
- }
- break;
-
- case GDK_BUTTON_RELEASE:
- bevent = (GdkEventButton *) event;
-
- if (bevent->button == 1)
- {
- gtk_grab_remove (widget);
- gimp_pattern_select_button_close_popup (button);
- }
- break;
-
- default:
- break;
- }
- }
-
- return FALSE;
-}
-
-static void
-gimp_pattern_select_preview_update (GtkWidget *preview,
- gint width,
- gint height,
- gint bytes,
- const guchar *mask_data)
-{
- GimpImageType type;
-
- switch (bytes)
- {
- case 1: type = GIMP_GRAY_IMAGE; break;
- case 2: type = GIMP_GRAYA_IMAGE; break;
- case 3: type = GIMP_RGB_IMAGE; break;
- case 4: type = GIMP_RGBA_IMAGE; break;
- default:
- return;
- }
-
- gimp_preview_area_draw (GIMP_PREVIEW_AREA (preview),
- 0, 0, width, height,
- type,
- mask_data,
- width * bytes);
-}
-
-static void
-gimp_pattern_select_button_open_popup (GimpPatternSelectButton *button,
- gint x,
- gint y)
-{
- GimpPatternSelectButtonPrivate *priv = button->priv;
- GtkWidget *frame;
- GtkWidget *preview;
- GdkMonitor *monitor;
- GdkRectangle workarea;
- gint x_org;
- gint y_org;
-
- if (priv->popup)
- gimp_pattern_select_button_close_popup (button);
-
- if (priv->width <= CELL_SIZE && priv->height <= CELL_SIZE)
- return;
-
- priv->popup = gtk_window_new (GTK_WINDOW_POPUP);
- gtk_window_set_type_hint (GTK_WINDOW (priv->popup), GDK_WINDOW_TYPE_HINT_DND);
- gtk_window_set_screen (GTK_WINDOW (priv->popup),
- gtk_widget_get_screen (GTK_WIDGET (button)));
-
- frame = gtk_frame_new (NULL);
- gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT);
- gtk_container_add (GTK_CONTAINER (priv->popup), frame);
- gtk_widget_show (frame);
-
- preview = gimp_preview_area_new ();
- gtk_widget_set_size_request (preview, priv->width, priv->height);
- gtk_container_add (GTK_CONTAINER (frame), preview);
- gtk_widget_show (preview);
-
- /* decide where to put the popup */
- gdk_window_get_origin (gtk_widget_get_window (priv->preview),
- &x_org, &y_org);
-
- monitor = gimp_widget_get_monitor (GTK_WIDGET (button));
- gdk_monitor_get_workarea (monitor, &workarea);
-
- x = x_org + x - (priv->width / 2);
- y = y_org + y - (priv->height / 2);
-
- x = CLAMP (x, workarea.x, workarea.x + workarea.width - priv->width);
- y = CLAMP (y, workarea.y, workarea.y + workarea.height - priv->height);
-
- gtk_window_move (GTK_WINDOW (priv->popup), x, y);
-
- gtk_widget_show (priv->popup);
-
- /* Draw the pattern */
- gimp_pattern_select_preview_update (preview,
- priv->width,
- priv->height,
- priv->bytes,
- priv->mask_data);
-}
-
-static void
-gimp_pattern_select_button_close_popup (GimpPatternSelectButton *button)
-{
- g_clear_pointer (&button->priv->popup, gtk_widget_destroy);
-}
-
-static void
-gimp_pattern_select_drag_data_received (GimpPatternSelectButton *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 ("Received invalid pattern data!");
- 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_pattern_select_button_set_pattern (button, name);
- }
- }
-
- g_free (str);
-}
+/* Create a widget that is the interior of another widget, a GimpPatternSelectButton.
+ * Super creates the exterior, self creates interior.
+ * Exterior is-a container and self calls super to add interior to the container.
+ */
static GtkWidget *
-gimp_pattern_select_button_create_inside (GimpPatternSelectButton *pattern_button)
+gimp_pattern_select_button_create_interior (GimpPatternSelectButton *self)
{
- GimpPatternSelectButtonPrivate *priv = pattern_button->priv;
- GtkWidget *hbox;
- GtkWidget *frame;
- GtkWidget *button;
+ GtkWidget *hbox;
+ GtkWidget *frame;
+ GtkWidget *peephole_view;
+ GtkWidget *browse_button;
+
+ g_debug ("%s", G_STRFUNC);
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
@@ -647,38 +317,291 @@ gimp_pattern_select_button_create_inside (GimpPatternSelectButton *pattern_butto
gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
gtk_box_pack_start (GTK_BOX (hbox), frame, FALSE, FALSE, 0);
- priv->preview = gimp_preview_area_new ();
- gtk_widget_add_events (priv->preview,
+ peephole_view = gimp_preview_area_new ();
+ gtk_widget_add_events (peephole_view,
GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK);
- gtk_widget_set_size_request (priv->preview, CELL_SIZE, CELL_SIZE);
- gtk_container_add (GTK_CONTAINER (frame), priv->preview);
+ gtk_widget_set_size_request (peephole_view, CELL_SIZE, CELL_SIZE);
+ gtk_container_add (GTK_CONTAINER (frame), peephole_view);
- g_signal_connect_swapped (priv->preview, "size-allocate",
- G_CALLBACK (gimp_pattern_select_preview_resize),
- pattern_button);
- g_signal_connect (priv->preview, "event",
- G_CALLBACK (gimp_pattern_select_preview_events),
- pattern_button);
+ g_signal_connect_swapped (peephole_view, "size-allocate",
+ G_CALLBACK (gimp_pattern_select_on_preview_resize),
+ self);
- gtk_drag_dest_set (GTK_WIDGET (priv->preview),
- GTK_DEST_DEFAULT_HIGHLIGHT |
- GTK_DEST_DEFAULT_MOTION |
- GTK_DEST_DEFAULT_DROP,
- &target, 1,
- GDK_ACTION_COPY);
+ /* preview receives mouse events to popup and down. */
+ g_signal_connect (peephole_view, "event",
+ G_CALLBACK (gimp_pattern_select_on_preview_events),
+ self);
- g_signal_connect_swapped (priv->preview, "drag-data-received",
- G_CALLBACK (gimp_pattern_select_drag_data_received),
- pattern_button);
-
- button = gtk_button_new_with_mnemonic (_("_Browse..."));
- gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
-
- g_signal_connect_swapped (button, "clicked",
- G_CALLBACK (gimp_pattern_select_button_clicked),
- pattern_button);
+ browse_button = gtk_button_new_with_mnemonic (_("_Browse..."));
+ gtk_box_pack_start (GTK_BOX (hbox), browse_button, TRUE, TRUE, 0);
gtk_widget_show_all (hbox);
+ /* Ensure self knows sub widgets. */
+ self->peephole_view = peephole_view;
+ self->browse_button = browse_button;
+
+ /* Return the whole, it is not a button, only contains a button. */
return hbox;
}
+
+
+/* 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_pattern_select_button_draw_interior (GimpResourceSelectButton *self)
+{
+ g_debug ("%s", G_STRFUNC);
+
+ g_return_if_fail (GIMP_IS_PATTERN_SELECT_BUTTON (self));
+
+ gimp_pattern_select_button_draw (GIMP_PATTERN_SELECT_BUTTON (self));
+}
+
+
+/* Draw self.
+ *
+ * This knows that we only draw the peephole_view. Gtk draws the browse button.
+ */
+static void
+gimp_pattern_select_button_draw (GimpPatternSelectButton *self)
+{
+ _PreviewImage image;
+
+ g_debug ("%s", G_STRFUNC);
+
+ /* Draw the peephole. */
+ image = gimp_pattern_select_button_get_pattern_image (self);
+ gimp_pattern_select_preview_fill_draw (self->peephole_view, image);
+ g_free (image.pixelels);
+}
+
+
+
+/* Return the image of self's pattern.
+ * Caller must free pixelels.
+ */
+static _PreviewImage
+gimp_pattern_select_button_get_pattern_image (GimpPatternSelectButton *self)
+{
+ GimpPattern *pattern;
+ gint pixelels_size;
+ _PreviewImage result;
+
+ g_debug ("%s", G_STRFUNC);
+
+ g_object_get (self, "resource", &pattern, NULL);
+
+ gimp_pattern_get_pixels (pattern,
+ &result.width,
+ &result.height,
+ &result.bpp,
+ &pixelels_size, /* discarded. */
+ &result.pixelels);
+
+ return result;
+}
+
+
+/* On resize event, redraw. */
+static void
+gimp_pattern_select_on_preview_resize (GimpPatternSelectButton *self)
+{
+ g_debug ("%s", G_STRFUNC);
+
+ gimp_pattern_select_button_draw (self);
+}
+
+
+/* On mouse events in self's peephole_view, popup a zoom view of entire pattern */
+static gboolean
+gimp_pattern_select_on_preview_events (GtkWidget *widget,
+ GdkEvent *event,
+ GimpPatternSelectButton *self)
+{
+ GdkEventButton *bevent;
+
+ g_debug ("%s", G_STRFUNC);
+
+ switch (event->type)
+ {
+ case GDK_BUTTON_PRESS:
+ bevent = (GdkEventButton *) event;
+
+ if (bevent->button == 1)
+ {
+ gtk_grab_add (widget);
+ gimp_pattern_select_button_open_popup (self,
+ bevent->x, bevent->y);
+ }
+ break;
+
+ case GDK_BUTTON_RELEASE:
+ bevent = (GdkEventButton *) event;
+
+ if (bevent->button == 1)
+ {
+ gtk_grab_remove (widget);
+ gimp_pattern_select_button_close_popup (self);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return FALSE;
+}
+
+/* Draw a GimpPreviewArea with a given image. */
+static void
+gimp_pattern_select_preview_draw (GimpPreviewArea *area,
+ gint x,
+ gint y,
+ _PreviewImage image,
+ gint rowstride)
+{
+ GimpImageType type;
+
+ g_debug ("%s", G_STRFUNC);
+
+ switch (image.bpp)
+ {
+ case 1: type = GIMP_GRAY_IMAGE; break;
+ case 2: type = GIMP_GRAYA_IMAGE; break;
+ case 3: type = GIMP_RGB_IMAGE; break;
+ case 4: type = GIMP_RGBA_IMAGE; break;
+ default:
+ g_warning ("Invalid bpp");
+ return;
+ }
+
+ gimp_preview_area_draw (area,
+ x, y,
+ image.width, image.height,
+ type,
+ image.pixelels,
+ rowstride);
+}
+
+/* Fill a GimpPreviewArea with a image then draw. */
+static void
+gimp_pattern_select_preview_fill_draw (GtkWidget *preview,
+ _PreviewImage image)
+{
+ GimpPreviewArea *area = GIMP_PREVIEW_AREA (preview);
+ GtkAllocation allocation;
+ gint x, y;
+ gint width, height;
+ _PreviewImage drawn_image;
+
+ g_debug ("%s", G_STRFUNC);
+
+ gtk_widget_get_allocation (preview, &allocation);
+
+ width = MIN (image.width, allocation.width);
+ height = MIN (image.height, allocation.height);
+
+ x = ((allocation.width - width) / 2);
+ y = ((allocation.height - height) / 2);
+
+ if (x || y)
+ gimp_preview_area_fill (area,
+ 0, 0,
+ allocation.width,
+ allocation.height,
+ 0xFF, 0xFF, 0xFF);
+
+ /* Draw same data to new bounds.
+ * drawn_image.pixelels points to same array.
+ */
+ drawn_image.width = width;
+ drawn_image.height = height;
+ drawn_image.pixelels = image.pixelels;
+ drawn_image.bpp = image.bpp;
+
+ gimp_pattern_select_preview_draw (area,
+ x, y,
+ drawn_image,
+ image.width * image.bpp ); /* row stride */
+ /* Caller will free image.pixelels */
+}
+
+/* popup methods. */
+
+static void
+gimp_pattern_select_button_open_popup (GimpPatternSelectButton *self,
+ gint x,
+ gint y)
+{
+ GtkWidget *frame;
+ GtkWidget *preview;
+ GdkMonitor *monitor;
+ GdkRectangle workarea;
+ gint x_org;
+ gint y_org;
+ _PreviewImage image;
+
+ g_debug ("%s", G_STRFUNC);
+
+ if (self->popup)
+ gimp_pattern_select_button_close_popup (self);
+
+ image = gimp_pattern_select_button_get_pattern_image (self);
+
+ if (image.width <= CELL_SIZE && image.height <= CELL_SIZE)
+ {
+ g_debug ("%s: omit popup smaller than peephole.", G_STRFUNC);
+ return;
+ }
+
+ self->popup = gtk_window_new (GTK_WINDOW_POPUP);
+ gtk_window_set_type_hint (GTK_WINDOW (self->popup), GDK_WINDOW_TYPE_HINT_DND);
+ gtk_window_set_screen (GTK_WINDOW (self->popup),
+ gtk_widget_get_screen (GTK_WIDGET (self)));
+
+ frame = gtk_frame_new (NULL);
+ gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT);
+ gtk_container_add (GTK_CONTAINER (self->popup), frame);
+ gtk_widget_show (frame);
+
+ preview = gimp_preview_area_new ();
+ gtk_widget_set_size_request (preview, image.width, image.height);
+ gtk_container_add (GTK_CONTAINER (frame), preview);
+ gtk_widget_show (preview);
+
+ /* decide where to put the popup: near the peephole_view i.e. at mousedown coords */
+ gdk_window_get_origin (gtk_widget_get_window (self->peephole_view),
+ &x_org, &y_org);
+
+ monitor = gimp_widget_get_monitor (GTK_WIDGET (self));
+ gdk_monitor_get_workarea (monitor, &workarea);
+
+ x = x_org + x - (image.width / 2);
+ y = y_org + y - (image.height / 2);
+
+ x = CLAMP (x, workarea.x, workarea.x + workarea.width - image.width);
+ y = CLAMP (y, workarea.y, workarea.y + workarea.height - image.height);
+
+ gtk_window_move (GTK_WINDOW (self->popup), x, y);
+
+ gtk_widget_show (self->popup);
+
+ /* Draw popup now. Usual events do not cause a draw. */
+ gimp_pattern_select_preview_draw (GIMP_PREVIEW_AREA (preview),
+ 0, 0,
+ image,
+ image.width * image.bpp);
+ g_free (image.pixelels);
+}
+
+static void
+gimp_pattern_select_button_close_popup (GimpPatternSelectButton *self)
+{
+ g_debug ("%s", G_STRFUNC);
+
+ g_clear_pointer (&self->popup, gtk_widget_destroy);
+}
diff --git a/libgimp/gimppatternselectbutton.h b/libgimp/gimppatternselectbutton.h
index 202f6920e9..dd42ff31e9 100644
--- a/libgimp/gimppatternselectbutton.h
+++ b/libgimp/gimppatternselectbutton.h
@@ -25,65 +25,35 @@
#ifndef __GIMP_PATTERN_SELECT_BUTTON_H__
#define __GIMP_PATTERN_SELECT_BUTTON_H__
-#include
+#include
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
diff --git a/libgimp/gimpprocedure-params.h b/libgimp/gimpprocedure-params.h
index 6a052435f9..597b5ee6a7 100644
--- a/libgimp/gimpprocedure-params.h
+++ b/libgimp/gimpprocedure-params.h
@@ -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) \
diff --git a/libgimp/gimpproceduredialog.c b/libgimp/gimpproceduredialog.c
index 4a52d17dbc..935679b9b5 100644
--- a/libgimp/gimpproceduredialog.c
+++ b/libgimp/gimpproceduredialog.c
@@ -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;
diff --git a/libgimp/gimppropbrushchooser.c b/libgimp/gimppropbrushchooser.c
deleted file mode 100644
index 9151ff795d..0000000000
--- a/libgimp/gimppropbrushchooser.c
+++ /dev/null
@@ -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
- * .
- */
-
-#include "config.h"
-
-#include
-#include
-#include
-
-#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;
-}
diff --git a/libgimp/gimppropbrushchooser.h b/libgimp/gimppropbrushchooser.h
deleted file mode 100644
index 72003cf91e..0000000000
--- a/libgimp/gimppropbrushchooser.h
+++ /dev/null
@@ -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
- * .
- */
-
- #if !defined (__GIMP_UI_H_INSIDE__) && !defined (GIMP_COMPILATION)
- #error "Only 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__ */
diff --git a/libgimp/gimppropchooser.c b/libgimp/gimppropchooser.c
new file mode 100644
index 0000000000..b9dd888116
--- /dev/null
+++ b/libgimp/gimppropchooser.c
@@ -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
+ * .
+ */
+
+#include "config.h"
+
+#include
+#include
+#include
+
+#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 (this file)
+ * SelectButton button pops up a
+ * Select dialog lets user choose
+ * 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);
+};
diff --git a/libgimp/gimppropchooser.h b/libgimp/gimppropchooser.h
new file mode 100644
index 0000000000..d4ffb7efb8
--- /dev/null
+++ b/libgimp/gimppropchooser.h
@@ -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
+ * .
+ */
+
+ #if !defined (__GIMP_UI_H_INSIDE__) && !defined (GIMP_COMPILATION)
+ #error "Only 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__ */
diff --git a/libgimp/gimppropchooserfactory.c b/libgimp/gimppropchooserfactory.c
new file mode 100644
index 0000000000..a61979f05e
--- /dev/null
+++ b/libgimp/gimppropchooserfactory.c
@@ -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
+ * .
+ */
+
+#include "config.h"
+
+#include
+#include
+
+#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;
+}
diff --git a/libgimp/gimppropchooserfactory.h b/libgimp/gimppropchooserfactory.h
new file mode 100644
index 0000000000..d012a151be
--- /dev/null
+++ b/libgimp/gimppropchooserfactory.h
@@ -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
+ * .
+ */
+
+ #if !defined (__GIMP_UI_H_INSIDE__) && !defined (GIMP_COMPILATION)
+ #error "Only 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__ */
diff --git a/libgimp/gimpresourceselect.c b/libgimp/gimpresourceselect.c
new file mode 100644
index 0000000000..071255c8ca
--- /dev/null
+++ b/libgimp/gimpresourceselect.c
@@ -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
+ * .
+ */
+
+#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/_select.pdb, _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;
+}
diff --git a/libgimp/gimpresourceselect.h b/libgimp/gimpresourceselect.h
new file mode 100644
index 0000000000..8ad8fe47a6
--- /dev/null
+++ b/libgimp/gimpresourceselect.h
@@ -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
+ * .
+ */
+
+#if !defined (__GIMP_H_INSIDE__) && !defined (GIMP_COMPILATION)
+#error "Only 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__ */
diff --git a/libgimp/gimpresourceselectbutton.c b/libgimp/gimpresourceselectbutton.c
new file mode 100644
index 0000000000..31ce8e1a75
--- /dev/null
+++ b/libgimp/gimpresourceselectbutton.c
@@ -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
+ * .
+ */
+
+#include "config.h"
+
+#include
+#include
+
+#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);
+}
diff --git a/libgimp/gimpresourceselectbutton.h b/libgimp/gimpresourceselectbutton.h
new file mode 100644
index 0000000000..2e73e30d1a
--- /dev/null
+++ b/libgimp/gimpresourceselectbutton.h
@@ -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
+ * .
+ */
+
+#if !defined (__GIMP_UI_H_INSIDE__) && !defined (GIMP_COMPILATION)
+#error "Only 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__ */
diff --git a/libgimp/gimpselectbutton.c b/libgimp/gimpselectbutton.c
deleted file mode 100644
index 36ca90c52d..0000000000
--- a/libgimp/gimpselectbutton.c
+++ /dev/null
@@ -1,94 +0,0 @@
-/* LIBGIMP - The GIMP Library
- * Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
- *
- * gimpselectbutton.c
- * Copyright (C) 2003 Sven Neumann
- *
- * 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
- * .
- */
-
-#include "config.h"
-
-#include
-
-#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;
- }
-}
diff --git a/libgimp/gimpselectbutton.h b/libgimp/gimpselectbutton.h
deleted file mode 100644
index 6b191f697d..0000000000
--- a/libgimp/gimpselectbutton.h
+++ /dev/null
@@ -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
- * .
- */
-
-#if !defined (__GIMP_UI_H_INSIDE__) && !defined (GIMP_COMPILATION)
-#error "Only 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__ */
diff --git a/libgimp/gimpui.def b/libgimp/gimpui.def
index 557d8b1308..ce71f3002a 100644
--- a/libgimp/gimpui.def
+++ b/libgimp/gimpui.def
@@ -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
diff --git a/libgimp/gimpui.h b/libgimp/gimpui.h
index 1dd189d990..d5675a5215 100644
--- a/libgimp/gimpui.h
+++ b/libgimp/gimpui.h
@@ -33,6 +33,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -43,10 +44,10 @@
#include
#include
#include
+#include
+#include
#include
-#include
#include
-#include
#undef __GIMP_UI_H_INSIDE__
diff --git a/libgimp/gimpuimarshal.list b/libgimp/gimpuimarshal.list
index 59ec674668..5e2b8e72c8 100644
--- a/libgimp/gimpuimarshal.list
+++ b/libgimp/gimpuimarshal.list
@@ -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
diff --git a/libgimp/meson.build b/libgimp/meson.build
index e15b53a838..c296a291ea 100644
--- a/libgimp/meson.build
+++ b/libgimp/meson.build
@@ -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',
]
diff --git a/libgimpconfig/gimpconfig-params.c b/libgimpconfig/gimpconfig-params.c
index 1b6e1fd81e..15f817bb7e 100644
--- a/libgimpconfig/gimpconfig-params.c
+++ b/libgimpconfig/gimpconfig-params.c
@@ -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,
diff --git a/pdb/groups/brush_select.pdb b/pdb/groups/brush_select.pdb
index f6002bd7cc..b61bbfefef 100644
--- a/pdb/groups/brush_select.pdb
+++ b/pdb/groups/brush_select.pdb
@@ -17,43 +17,28 @@
# "Perlized" from C source by Manish Singh
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;
diff --git a/pdb/groups/font_select.pdb b/pdb/groups/font_select.pdb
index 29cf362187..8f680d2d22 100644
--- a/pdb/groups/font_select.pdb
+++ b/pdb/groups/font_select.pdb
@@ -16,19 +16,20 @@
# "Perlized" from C source by Manish Singh
+
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;
diff --git a/pdb/groups/gradient_select.pdb b/pdb/groups/gradient_select.pdb
index a4f2ab153f..80aade519d 100644
--- a/pdb/groups/gradient_select.pdb
+++ b/pdb/groups/gradient_select.pdb
@@ -16,36 +16,36 @@
# "Perlized" from C source by Manish Singh
+
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;
diff --git a/pdb/groups/palette_select.pdb b/pdb/groups/palette_select.pdb
index b55d0a06ca..5394df853b 100644
--- a/pdb/groups/palette_select.pdb
+++ b/pdb/groups/palette_select.pdb
@@ -17,19 +17,18 @@
# "Perlized" from C source by Manish Singh
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;
diff --git a/pdb/groups/pattern_select.pdb b/pdb/groups/pattern_select.pdb
index 02e54c284e..8c334f9947 100644
--- a/pdb/groups/pattern_select.pdb
+++ b/pdb/groups/pattern_select.pdb
@@ -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;
diff --git a/plug-ins/Makefile.am b/plug-ins/Makefile.am
index 06d5cabfeb..a8c4869c27 100644
--- a/plug-ins/Makefile.am
+++ b/plug-ins/Makefile.am
@@ -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 \
diff --git a/plug-ins/gfig/gfig-dialog.c b/plug-ins/gfig/gfig-dialog.c
index 23209b0fbd..a856b13a7f 100644
--- a/plug-ins/gfig/gfig-dialog.c
+++ b/plug-ins/gfig/gfig-dialog.c
@@ -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,
diff --git a/plug-ins/gfig/gfig-style.c b/plug-ins/gfig/gfig-style.c
index a215ac3703..fc018b2a03 100644
--- a/plug-ins/gfig/gfig-style.c
+++ b/plug-ins/gfig/gfig-style.c
@@ -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, "