Fix plugins to use new GimpResource.

This commit is contained in:
lloyd konneker 2022-09-05 19:28:35 -04:00 committed by Jehan
parent 54db045f45
commit e00f2d7f50
40 changed files with 773 additions and 605 deletions

View file

@ -161,7 +161,7 @@ register_palette_select_procs (GimpPDB *pdb)
gimp_procedure_add_argument (procedure,
gimp_param_spec_string ("initial-palette-name",
"initial palette name",
"The palette to set as the initial choice.",
"The name of the palette to set as the initial choice.",
FALSE, TRUE, FALSE,
NULL,
GIMP_PARAM_READWRITE));

View file

@ -28,8 +28,8 @@ Now, there are methods on resource objects.
Methods take an instance of the object as the first argument,
often called "self."
This means that whenever you used a string name to refer to a resource object,
you usually should pass an instance of an object.
This means that where you formerly used a string name to refer to a resource object,
now you usually should pass an instance of an object.
### Changes to reference documents
@ -38,8 +38,23 @@ you usually should pass an instance of an object.
Shows classes Brush, Font, and so forth.
The classes have instance methods taking the instance as the first argument.
Example:
```
gboolean gboolean gimp_brush_delete(gcharray) => gboolean gimp_brush_delete ( GimpBrush*)
```
The classes may also have class methods still taking string names.
Example:
```
gboolean gimp_brush_id_is_valid (const gchar* id)
```
Is a class method (in the "Functions" section of the class) taking the ID
(same as the name) to test whether such a brush is installed in Gimp core.
#### PDB Browser
Remember the PDB Browser shows the C API. You must mentally convert
@ -51,6 +66,28 @@ where formerly they took type gcharray i.e. strings.
Shows some procedures that take a string name of a brush.
These are usually class methods.
#### Other changes to the API
Many of the Gimp functions dealing with the context
now take or return an instance of a resource.
Example:
```
gcharray* gimp_context_get_brush (void) => GimpBrush* gimp_context_get_brush (void)
```
A few functions have even more changed signature:
```
gint gimp_palette_get_info (gcharray) =>
gint gimp_palette_get_color_count (GimpPalette*)
```
The name and description of this function are changed
to accurately describe that the function only returns an integer
(formerly, the description said it also returned the name of the palette.)
### New resource objects
FUTURE

View file

@ -146,7 +146,9 @@ libgimpui_sources = \
libgimpui_built_sources = \
gimpuimarshal.c \
gimpuimarshal.h
gimpuimarshal.h \
gimppropchooser.c \
gimppropchooser.h
libgimpui_extra_sources = gimpuimarshal.list

View file

@ -193,7 +193,6 @@ libgimpui_introspectable_headers = \
../libgimp/gimpproceduredialog.h \
../libgimp/gimpprocview.h \
../libgimp/gimpprogressbar.h \
../libgimp/gimppropchooser.h \
../libgimp/gimppropchooserfactory.h \
../libgimp/gimpresourceselectbutton.h \
../libgimp/gimpsaveproceduredialog.h \
@ -215,7 +214,6 @@ libgimpui_introspectable = \
../libgimp/gimpprocbrowserdialog.c \
../libgimp/gimpproceduredialog.c \
../libgimp/gimpprocview.c \
../libgimp/gimppropchooser.c \
../libgimp/gimppropchooserfactory.c \
../libgimp/gimpsaveproceduredialog.c \
../libgimp/gimpprogressbar.c \

View file

@ -451,7 +451,13 @@ gimp_main (GType plug_in_type,
GIMP_TYPE_CHANNEL, GIMP_TYPE_PARAM_CHANNEL,
GIMP_TYPE_LAYER_MASK, GIMP_TYPE_PARAM_LAYER_MASK,
GIMP_TYPE_SELECTION, GIMP_TYPE_PARAM_SELECTION,
GIMP_TYPE_VECTORS, GIMP_TYPE_PARAM_VECTORS
GIMP_TYPE_VECTORS, GIMP_TYPE_PARAM_VECTORS,
GIMP_TYPE_BRUSH, GIMP_TYPE_PARAM_BRUSH,
GIMP_TYPE_FONT, GIMP_TYPE_PARAM_FONT,
GIMP_TYPE_GRADIENT, GIMP_TYPE_PARAM_GRADIENT,
GIMP_TYPE_PALETTE, GIMP_TYPE_PARAM_PALETTE,
GIMP_TYPE_PATTERN, GIMP_TYPE_PARAM_PATTERN
};
gint i;

View file

@ -56,8 +56,6 @@
#include <libgimp/gimpprocedureconfig.h>
#include <libgimp/gimpprocedure-params.h>
#include <libgimp/gimpprogress.h>
#include <libgimp/gimpresource.h>
#include <libgimp/gimpresource-subclass.h>
#include <libgimp/gimpsaveprocedure.h>
#include <libgimp/gimpselection.h>
#include <libgimp/gimptextlayer.h>

View file

@ -604,8 +604,13 @@ gimp_gp_param_to_value (gpointer gimp,
g_return_if_fail (param != NULL);
g_return_if_fail (value != NULL);
if (type == G_TYPE_NONE)
if (type == G_TYPE_NONE || type == G_TYPE_INVALID)
{
type = g_type_from_name (param->type_name);
if (type == 0)
g_critical ("%s: type name %s is not registered", G_STRFUNC, param->type_name);
}
/* assert type is not G_TYPE_NONE and type is not G_TYPE_INVALID. */
g_value_init (value, type);
@ -730,7 +735,9 @@ gimp_gp_param_to_value (gpointer gimp,
}
else if (GIMP_VALUE_HOLDS_RESOURCE (value))
{
g_value_set_object (value, get_resource_by_id (gimp, G_VALUE_TYPE (value), param->data.d_string));
gpointer resource; /* when compiled in app, use generic pointer. */
resource = get_resource_by_id (gimp, G_VALUE_TYPE (value), param->data.d_string);
g_value_set_object (value, resource);
}
else if (G_VALUE_HOLDS_PARAM (value))
{
@ -1054,9 +1061,27 @@ gimp_value_to_gp_param (const GValue *value,
{
GObject *resource = g_value_get_object (value);
/* Represent by a char*, which must be NULL when resource is NULL.
* resource may be NULL e.g. for return value of a canceled dialog.
*/
param->param_type = GP_PARAM_TYPE_STRING;
param->data.d_string = resource ? get_resource_id (resource) : "";
if (resource != NULL)
{
gchar * resource_id = get_resource_id (resource);
/* resource_id can be NULL if resource is invalid. */
if (full_copy)
param->data.d_string = g_strdup (resource_id);
else
param->data.d_string = resource_id;
}
else
{
param->data.d_string = NULL;
}
/* Ensure ( full_copy AND ( d_string==NULL OR points to new allocation ))
* OR ( not full copy AND ( d_string==NULL OR points to resource's ID char* )
*/
}
else if (G_VALUE_HOLDS_PARAM (value))
{

View file

@ -41,7 +41,7 @@
* gimp_palettes_popup:
* @palette_callback: The callback PDB proc to call when user chooses a palette.
* @popup_title: Title of the palette selection dialog.
* @initial_palette_name: The palette to set as the initial choice.
* @initial_palette_name: The name of the palette to set as the initial choice.
*
* Invokes the Gimp palette selection dialog.
*

View file

@ -24,7 +24,6 @@
#include "gimpui.h"
/* PropChooser
* A GtkWidget, more specifically a GtkButtonWidget.
* Pops up a chooser widget.
@ -34,28 +33,19 @@
* 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.
* A factory creates the widgets.
*/
/* Not public i.e. not annotated.
*
* Stack of objects:
* PropWidget<Resource> (this file)
* <Resource>SelectButton button pops up a
* <Resource>Select dialog lets user choose <resource>
* libgimp wire protocol to core
* PDBDialog (app/widgets/gimppdbdialog.c)
*/
* Used only by GimpProcedureDialog.
* These could be in the public API,
* if we want plugins to create their own widget that updates the plugin's own property.
*
* The following is in the style of GObject annotations, but is not public.
/* 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.
*
@ -67,13 +57,9 @@
*
* 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
* When pushed, the button shows a dialog that lets the user choose a brush.
*/
GtkWidget *
gimp_prop_chooser_brush_new (GObject *config, const gchar *property_name, const gchar *title)
{

View file

@ -24,7 +24,7 @@
#include "libgimp/gimp.h"
#include "libgimp/gimpui.h"
static GimpResource * get_initial_resource_from_config (GObject *config,
static GimpResource * get_initial_resource_from_config (GObject *config,
const gchar *property_name);
/**

View file

@ -129,8 +129,7 @@ static gboolean gimp_temp_resource_idle (GimpResourceAdaption *adaption)
* libgimp simply ignores the extra args (adapts the signature.)
*/
static void
create_callback_PDB_procedure_params (
GimpProcedure *procedure,
create_callback_PDB_procedure_params (GimpProcedure *procedure,
GType resource_type)
{
/* Order of args is important. */
@ -263,8 +262,7 @@ create_callback_PDB_procedure_params (
* Call a PDB procedure that communicates with core to create remote dialog.
*/
static gboolean
popup_remote_chooser (
const gchar *title,
popup_remote_chooser (const gchar *title,
GimpResource *resource,
gchar *temp_PDB_callback_name,
GType resource_type)
@ -306,8 +304,7 @@ popup_remote_chooser (
/*Does nothing, quietly, when the remote dialog is not open. */
static void
close_remote_chooser (
gchar *temp_PDB_callback_name,
close_remote_chooser (gchar *temp_PDB_callback_name,
GType resource_type)
{
if (g_type_is_a (resource_type, GIMP_TYPE_FONT))
@ -393,8 +390,7 @@ index_of_is_closing_arg (GType resource_type)
const gchar *
gimp_resource_select_new (
const gchar *title,
gimp_resource_select_new (const gchar *title,
GimpResource *resource,
GType resource_type,
GimpResourceChoosedCallback callback,
@ -478,8 +474,7 @@ gimp_resource_select_destroy (const gchar *temp_PDB_callback_name)
* so pdb/groups/<foo>_select.pdb, <foo>_set_popup must have type string.
*/
void
gimp_resource_select_set (
const gchar *temp_pdb_callback,
gimp_resource_select_set (const gchar *temp_pdb_callback,
GimpResource *resource,
GType resource_type)
{
@ -556,8 +551,7 @@ gimp_resource_data_free (GimpResourceAdaption *adaption)
* Called when user chooses a resource in remote dialog.
*/
static GimpValueArray *
gimp_temp_resource_run (
GimpProcedure *procedure,
gimp_temp_resource_run (GimpProcedure *procedure,
const GimpValueArray *args,
gpointer run_data) /* is-a adaption */
{
@ -585,8 +579,7 @@ gimp_temp_resource_run (
* 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);
adaption->idle_id = g_idle_add ((GSourceFunc) gimp_temp_resource_idle, adaption);
return gimp_procedure_new_return_values (procedure, GIMP_PDB_SUCCESS, NULL);
}

View file

@ -156,6 +156,9 @@ static void gimp_resource_select_drag_data_received (GimpResourceSelectButton
static void gimp_resource_select_button_set_remote_dialog (GimpResourceSelectButton *self,
GimpResource *resource);
static void gimp_resource_select_button_draw_interior (GimpResourceSelectButton *self,
GimpResource *resource);
static guint resource_button_signals[LAST_SIGNAL] = { 0 };
static GParamSpec *resource_button_props[N_PROPS] = { NULL, };
@ -409,20 +412,15 @@ gimp_resource_select_button_embed_interior (GimpResourceSelectButton *self, GtkW
/* 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.
*
* Calls the virtual method of a similar name, which subclasses must override.
* resource: The instance to be drawn.
*
* 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
* Not public.
*/
static void
gimp_resource_select_button_draw_interior (GimpResourceSelectButton *self, GimpResource *resource)
{
GimpResourceSelectButtonClass *klass;
@ -725,7 +723,7 @@ gimp_resource_select_button_finalize (GObject *object)
g_debug ("%s", G_STRFUNC);
g_clear_pointer (&priv->resource, g_free);
g_clear_pointer (&priv->resource, g_object_unref);
g_free ((gpointer) priv->title);
/* Chain up. */

View file

@ -65,10 +65,6 @@ GimpResource *gimp_resource_select_button_get_resource (GimpResourceSelectButton
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,

View file

@ -68,7 +68,6 @@ EXPORTS
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

View file

@ -272,7 +272,6 @@ libgimpui_sources_introspectable = [
'gimpproceduredialog.c',
'gimpprocview.c',
'gimpprogressbar.c',
'gimppropchooser.c',
'gimppropchooserfactory.c',
'gimpresourceselectbutton.c',
'gimpsaveproceduredialog.c',
@ -283,6 +282,7 @@ libgimpui_sources_introspectable = [
libgimpui_sources = [
libgimpui_sources_introspectable,
gimpuimarshal,
'gimppropchooser.c',
]
libgimpui_headers_introspectable = [
@ -305,7 +305,6 @@ libgimpui_headers_introspectable = [
'gimpproceduredialog.h',
'gimpprocview.h',
'gimpprogressbar.h',
'gimppropchooser.h',
'gimppropchooserfactory.h',
'gimpresourceselectbutton.h',
'gimpsaveproceduredialog.h',

View file

@ -28,7 +28,7 @@ sub palettes_popup {
{ 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.' }
desc => 'The name of the palette to set as the initial choice.' }
);
%invoke = (

View file

@ -24,10 +24,6 @@ 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 \
@ -47,6 +43,7 @@ SUBDIRS = \
$(file_webp) \
flame \
fractal-explorer \
gfig \
gimpressionist \
gradient-flare \
help \
@ -56,6 +53,7 @@ SUBDIRS = \
lighting \
map-object \
metadata \
pagecurl \
$(print) \
$(python) \
screenshot \

View file

@ -44,6 +44,7 @@
/* Define how the plug-in works. Values marked (r) are with regard */
/* to film_height (i.e. it should be a value from 0.0 to 1.0) */
/* Saved as settings. Must be trivially serializable; no pointers. */
typedef struct
{
gint film_height; /* height of the film */
@ -57,7 +58,8 @@ typedef struct
gdouble number_height; /* height of picture numbering (r) */
gint number_start; /* number for first picture */
GimpRGB number_color; /* color of number */
gchar number_font[FONT_LEN]; /* font family to use for numbering */
GimpFont *number_font; /* font family for numbering */
gchar font_name[FONT_LEN]; /* serializable name of font for numbering */
gint number_pos[2]; /* flags where to draw numbers (top/bottom) */
gint keep_height; /* flag if to keep max. image height */
gint num_images; /* number of images */
@ -142,13 +144,16 @@ static gboolean film_dialog (GimpImage *image);
static void film_reset_callback (GtkWidget *widget,
gpointer data);
static void film_font_select_callback (GimpFontSelectButton *button,
const gchar *name,
GimpResource *font,
gboolean closing,
gpointer data);
static void film_scale_entry_update_double (GimpLabelSpin *entry,
gdouble *value);
static void film_load_settings (void);
static void film_save_settings (void);
G_DEFINE_TYPE (Film, film, GIMP_TYPE_PLUG_IN)
GIMP_MAIN (FILM_TYPE)
@ -179,7 +184,8 @@ static FilmVals filmvals =
0.052, /* Image number height */
1, /* Start index of numbering */
{ 0.93, 0.61, 0.0, 1.0 }, /* Color of number */
"Monospace", /* Font family for numbering */
NULL, /* !!! No default, must be set later. */
"Monospace", /* Case sensitive, must be name of an installed font. */
{ TRUE, TRUE }, /* Numbering on top and bottom */
0, /* Don't keep max. image height */
0, /* Number of images */
@ -263,10 +269,9 @@ film_create_procedure (GimpPlugIn *plug_in,
G_MININT, G_MAXINT, 1,
G_PARAM_READWRITE);
GIMP_PROC_ARG_STRING (procedure, "number-font",
GIMP_PROC_ARG_FONT (procedure, "number-font",
"Number font",
"Font for drawing numbers",
NULL,
G_PARAM_READWRITE);
GIMP_PROC_ARG_RGB (procedure, "number-color",
@ -328,7 +333,7 @@ film_run (GimpProcedure *procedure,
switch (run_mode)
{
case GIMP_RUN_INTERACTIVE:
gimp_get_data (PLUG_IN_PROC, &filmvals);
film_load_settings();
if (! film_dialog (image))
{
@ -350,9 +355,7 @@ film_run (GimpProcedure *procedure,
}
GIMP_VALUES_GET_RGB (args, 1, &filmvals.film_color);
filmvals.number_start = GIMP_VALUES_GET_INT (args, 2);
g_strlcpy (filmvals.number_font,
GIMP_VALUES_GET_STRING (args, 3),
FONT_LEN);
filmvals.number_font = GIMP_VALUES_GET_FONT (args, 3);
GIMP_VALUES_GET_RGB (args, 4, &filmvals.number_color);
filmvals.number_pos[0] = GIMP_VALUES_GET_INT (args, 5);
filmvals.number_pos[1] = GIMP_VALUES_GET_INT (args, 6);
@ -364,7 +367,7 @@ film_run (GimpProcedure *procedure,
break;
case GIMP_RUN_WITH_LAST_VALS:
gimp_get_data (PLUG_IN_PROC, &filmvals);
film_load_settings();
break;
default:
@ -400,9 +403,8 @@ film_run (GimpProcedure *procedure,
gimp_display_new (image);
}
/* Store data */
if (run_mode == GIMP_RUN_INTERACTIVE)
gimp_set_data (PLUG_IN_PROC, &filmvals, sizeof (FilmVals));
film_save_settings();
}
if (! return_vals)
@ -646,8 +648,9 @@ check_filmvals (void)
if (filmvals.number_start < 0)
filmvals.number_start = 0;
if (filmvals.number_font[0] == '\0')
strcpy (filmvals.number_font, "Monospace");
if (filmvals.number_font == NULL)
filmvals.number_font = gimp_context_get_font ();
g_assert (GIMP_IS_FONT (filmvals.number_font));
for (i = 0, j = 0; i < filmvals.num_images; i++)
{
@ -737,7 +740,12 @@ draw_number (GimpLayer *layer,
GimpImage *image;
GimpLayer *text_layer;
gint text_width, text_height, text_ascent, descent;
gchar *fontname = filmvals.number_font;
GimpFont *font = filmvals.number_font;
gchar *fontname;
/* FIXME: gimp_text methods should take GimpFont font instead of font_name */
g_object_get (font, "id", &fontname, NULL);
g_snprintf (buf, sizeof (buf), "%d", num);
@ -1124,8 +1132,9 @@ create_selection_tab (GtkWidget *notebook,
&filmvals.number_start);
/* Fontfamily for numbering */
font_button = gimp_font_select_button_new (NULL, filmvals.number_font);
g_signal_connect (font_button, "font-set",
/* Require filmvals.number_font is NULL or a valid GimpFont. */
font_button = gimp_font_select_button_new (NULL, GIMP_RESOURCE (filmvals.number_font));
g_signal_connect (font_button, "resource-set",
G_CALLBACK (film_font_select_callback), &filmvals);
label = gimp_grid_attach_aligned (GTK_GRID (grid), 0, 1,
_("_Font:"), 0.0, 0.5,
@ -1388,13 +1397,13 @@ film_reset_callback (GtkWidget *widget,
static void
film_font_select_callback (GimpFontSelectButton *button,
const gchar *name,
GimpResource *resource,
gboolean closing,
gpointer data)
{
FilmVals *vals = (FilmVals *) data;
g_strlcpy (vals->number_font, name, FONT_LEN);
vals->number_font = GIMP_FONT (resource);
}
static void
@ -1403,3 +1412,32 @@ film_scale_entry_update_double (GimpLabelSpin *entry,
{
*value = gimp_label_spin_get_value (entry);
}
/* FIXME: use GimpProcedureConfig
*
* Now using the old method: get_data.
* And chunking the settings into global struct filmvals instead of properties.
*/
static void
film_load_settings (void)
{
(void) gimp_get_data (PLUG_IN_PROC, &filmvals);
/* When no data, returns false and filmvals is as statically initialized. */
/* The GimpFont pointer was unserialized but garbage.
* Restore pointer from the name which was also serialized.
* A hack that goes away when GimpProcedureConfig is used.
*/
filmvals.number_font = g_object_new (GIMP_TYPE_FONT, "id", filmvals.font_name, NULL);
}
static void
film_save_settings (void)
{
/* Copy font name from font, i.e. serialize string not pointer. */
g_strlcpy (filmvals.font_name,
gimp_resource_get_id (GIMP_RESOURCE (filmvals.number_font)),
FONT_LEN);
gimp_set_data (PLUG_IN_PROC, &filmvals, sizeof (FilmVals));
}

View file

@ -416,16 +416,16 @@ map (GeglBuffer *buffer,
static gdouble *
get_samples_gradient (GimpDrawable *drawable)
{
gchar *gradient_name;
GimpGradient *gradient;
gint n_d_samples;
gdouble *d_samples = NULL;
gradient_name = gimp_context_get_gradient ();
gradient = gimp_context_get_gradient ();
/* FIXME: "reverse" hardcoded to FALSE. */
gimp_gradient_get_uniform_samples (gradient_name, NSAMPLES, FALSE,
gimp_gradient_get_uniform_samples (gradient, NSAMPLES, FALSE,
&n_d_samples, &d_samples);
g_free (gradient_name);
if (! gimp_drawable_is_rgb (drawable))
{

View file

@ -2478,7 +2478,8 @@ fill_missing_colors (void)
static void
get_gradient (gint mode)
{
gchar *name;
GimpGradient *gradient;
gint n_f_samples;
gdouble *f_samples;
gdouble *f_samp; /* float samples */
@ -2486,14 +2487,12 @@ get_gradient (gint mode)
free_colors ();
name = gimp_context_get_gradient ();
gradient = gimp_context_get_gradient ();
gimp_gradient_get_uniform_samples (name, 256 /* n_samples */,
gimp_gradient_get_uniform_samples (gradient, 256 /* n_samples */,
mode == SMP_INV_GRADIENT,
&n_f_samples, &f_samples);
g_free (name);
for (lum = 0; lum < 256; lum++)
{
f_samp = &f_samples[lum * 4];

View file

@ -318,15 +318,15 @@ drawable_to_cmap (control_point *cp)
}
else if (GRADIENT_DRAWABLE == config.cmap_drawable_id)
{
gchar *name = gimp_context_get_gradient ();
GimpGradient *gradient = gimp_context_get_gradient ();
gint num;
gdouble *g;
/* FIXME: "reverse" hardcoded to FALSE. */
gimp_gradient_get_uniform_samples (name, 256, FALSE,
gimp_gradient_get_uniform_samples (gradient, 256, FALSE,
&num, &g);
g_free (name);
for (i = 0; i < 256; i++)
for (j = 0; j < 3; j++)

View file

@ -38,7 +38,7 @@
static gint n_gradient_samples = 0;
static gdouble *gradient_samples = NULL;
static gchar *gradient_name = NULL;
static GimpGradient *gradient = NULL;
static gboolean ready_now = FALSE;
static gchar *tpath = NULL;
static DialogElements *elements = NULL;
@ -286,10 +286,10 @@ explorer_number_of_colors_callback (GtkAdjustment *adjustment,
g_free (gradient_samples);
if (! gradient_name)
gradient_name = gimp_context_get_gradient ();
if (! gradient)
gradient = gimp_context_get_gradient ();
gimp_gradient_get_uniform_samples (gradient_name,
gimp_gradient_get_uniform_samples (gradient,
wvals.ncolors,
wvals.gradinvert,
&n_gradient_samples,
@ -299,20 +299,15 @@ explorer_number_of_colors_callback (GtkAdjustment *adjustment,
dialog_update_preview ();
}
/* Same signature as all GimpResourceSelectButton */
static void
explorer_gradient_select_callback (GimpGradientSelectButton *gradient_button,
const gchar *name,
gint width,
const gdouble *gradient_data,
gboolean dialog_closing,
gpointer data)
explorer_gradient_select_callback (gpointer data, /* widget */
GimpGradient *gradient,
gboolean dialog_closing)
{
g_free (gradient_name);
g_free (gradient_samples);
gradient_name = g_strdup (name);
gimp_gradient_get_uniform_samples (gradient_name,
gimp_gradient_get_uniform_samples (gradient,
wvals.ncolors,
wvals.gradinvert,
&n_gradient_samples,
@ -521,9 +516,9 @@ explorer_dialog (void)
GtkWidget *hbox;
GtkWidget *grid;
GtkWidget *button;
GtkWidget *gradient;
GtkWidget *gradient_button;
gchar *path;
gchar *gradient_name;
GimpGradient *gradient;
GSList *group = NULL;
gint i;
@ -1156,21 +1151,21 @@ explorer_dialog (void)
_("Create a color-map using a gradient from "
"the gradient editor"), NULL);
gradient_name = gimp_context_get_gradient ();
gradient = gimp_context_get_gradient ();
gimp_gradient_get_uniform_samples (gradient_name,
gimp_gradient_get_uniform_samples (gradient,
wvals.ncolors,
wvals.gradinvert,
&n_gradient_samples,
&gradient_samples);
gradient = gimp_gradient_select_button_new (_("FractalExplorer Gradient"),
gradient_name);
g_signal_connect (gradient, "gradient-set",
gradient_button = gimp_gradient_select_button_new (_("FractalExplorer Gradient"),
GIMP_RESOURCE (gradient));
g_signal_connect (gradient_button, "resource-set",
G_CALLBACK (explorer_gradient_select_callback), NULL);
g_free (gradient_name);
gtk_box_pack_start (GTK_BOX (hbox), gradient, FALSE, FALSE, 0);
gtk_widget_show (gradient);
gtk_box_pack_start (GTK_BOX (hbox), gradient_button, FALSE, FALSE, 0);
gtk_widget_show (gradient_button);
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
{
@ -1341,15 +1336,13 @@ make_color_map (void)
*/
if (gradient_samples == NULL)
{
gchar *gradient_name = gimp_context_get_gradient ();
GimpGradient *gradient = gimp_context_get_gradient ();
gimp_gradient_get_uniform_samples (gradient_name,
gimp_gradient_get_uniform_samples (gradient,
wvals.ncolors,
wvals.gradinvert,
&n_gradient_samples,
&gradient_samples);
g_free (gradient_name);
}
redstretch = wvals.redstretch * 127.5;

View file

@ -298,6 +298,8 @@ gfig_dialog (void)
NULL);
gimp_window_set_transient (GTK_WINDOW (top_level_dlg));
gimp_dialog_set_alternative_button_order (GTK_DIALOG (top_level_dlg),
GTK_RESPONSE_OK,
GTK_RESPONSE_CANCEL,
@ -394,8 +396,8 @@ gfig_dialog (void)
/* brush selector in Stroke frame */
gfig_context->brush_select
= gimp_brush_select_button_new ("Brush",
gfig_context->default_style.brush);
g_signal_connect (gfig_context->brush_select, "brush-set",
GIMP_RESOURCE (gfig_context->default_style.brush));
g_signal_connect (gfig_context->brush_select, "resource-set",
G_CALLBACK (gfig_brush_changed_callback), NULL);
gtk_box_pack_start (GTK_BOX (vbox), gfig_context->brush_select,
FALSE, FALSE, 0);
@ -459,8 +461,9 @@ gfig_dialog (void)
/* A page for the pattern selector */
gfig_context->pattern_select
= gimp_pattern_select_button_new ("Pattern", gfig_context->default_style.pattern);
g_signal_connect (gfig_context->pattern_select, "pattern-set",
= gimp_pattern_select_button_new ("Pattern",
GIMP_RESOURCE (gfig_context->default_style.pattern));
g_signal_connect (gfig_context->pattern_select, "resource-set",
G_CALLBACK (gfig_pattern_changed_callback), NULL);
gtk_widget_show (gfig_context->pattern_select);
gtk_notebook_append_page (GTK_NOTEBOOK (fill_type_notebook),
@ -468,8 +471,9 @@ gfig_dialog (void)
/* A page for the gradient selector */
gfig_context->gradient_select
= gimp_gradient_select_button_new ("Gradient", gfig_context->default_style.gradient);
g_signal_connect (gfig_context->gradient_select, "gradient-set",
= gimp_gradient_select_button_new ("Gradient",
GIMP_RESOURCE (gfig_context->default_style.gradient));
g_signal_connect (gfig_context->gradient_select, "resource-set",
G_CALLBACK (gfig_gradient_changed_callback), NULL);
gtk_widget_show (gfig_context->gradient_select);
gtk_notebook_append_page (GTK_NOTEBOOK (fill_type_notebook),
@ -518,8 +522,7 @@ gfig_dialog (void)
gfig_list_load_all (gfig_path);
/* Setup initial brush settings */
gfig_context->bdesc.name = gimp_context_get_brush ();
mygimp_brush_info (&gfig_context->bdesc.width, &gfig_context->bdesc.height);
set_context_bdesc (gimp_context_get_brush ());
gtk_widget_show (main_hbox);
@ -2031,7 +2034,13 @@ toggle_obj_type (GtkRadioAction *action,
GtkRadioAction *current,
gpointer data)
{
static GdkCursor *p_cursors[DEL_OBJ + 1];
/* cache of cursors.
* Must be larger than action values, i.e. NULL_OPER.
* Test by clicking the "select object" icon.
* C ensures is initialized to NULL.
*/
static GdkCursor *p_cursors[NULL_OPER];
GdkCursorType ctype = GDK_LAST_CURSOR;
DobjType new_type;
@ -2045,13 +2054,17 @@ toggle_obj_type (GtkRadioAction *action,
if (new_type < MOVE_OBJ) /* Eeeeek */
{
g_debug ("%s new_type < MOVE_OBJ", G_STRFUNC);
obj_show_single = -1; /* Cancel select preview */
}
/* Update draw areas */
gtk_widget_queue_draw (gfig_context->preview);
}
g_debug ("%s: old and new obj type %d %d", G_STRFUNC, selvals.otype, new_type);
selvals.otype = new_type;
gtk_notebook_set_current_page (GTK_NOTEBOOK (tool_options_notebook),
new_type - 1);
@ -2066,7 +2079,6 @@ toggle_obj_type (GtkRadioAction *action,
case STAR:
case SPIRAL:
case BEZIER:
default:
ctype = GDK_CROSSHAIR;
break;
case MOVE_OBJ:
@ -2078,14 +2090,26 @@ toggle_obj_type (GtkRadioAction *action,
case DEL_OBJ:
ctype = GDK_PIRATE;
break;
case OBJ_TYPE_NONE:
ctype = GDK_CROSSHAIR;
break;
default:
g_debug ("%s: default cursor for object type %d.", G_STRFUNC, selvals.otype);
ctype = GDK_CROSSHAIR;
break;
}
/* Get cached cursor. */
if (!p_cursors[selvals.otype])
{
GdkDisplay *display = gtk_widget_get_display (gfig_context->preview);
GdkCursor *cursor;
p_cursors[selvals.otype] = gdk_cursor_new_for_display (display, ctype);
GdkDisplay *display = gtk_widget_get_display (gfig_context->preview);
cursor = gdk_cursor_new_for_display (display, ctype);
p_cursors[selvals.otype] = cursor;
}
/* Require cursor (possibly from cache) is-a cursor. */
g_assert (GDK_IS_CURSOR (p_cursors[selvals.otype]));
gdk_window_set_cursor (gtk_widget_get_window (gfig_context->preview),
p_cursors[selvals.otype]);

View file

@ -37,10 +37,11 @@
#include "gfig-style.h"
static void gfig_read_parameter_string (gchar **text,
static void gfig_read_resource (gchar **text,
gint nitems,
const gchar *name,
gchar **style_entry);
const gchar *tag,
GimpResource **style_entry,
GType resource_type);
static void gfig_read_parameter_int (gchar **text,
gint nitems,
@ -57,18 +58,21 @@ static void gfig_read_parameter_gimp_rgb (gchar **text,
const gchar *name,
GimpRGB *style_entry);
/* From a style string, read a resource name,
* create a resource object, and put it in
* given entry of a style.
*/
static void
gfig_read_parameter_string (gchar **text,
gfig_read_resource (gchar **text,
gint nitems,
const gchar *name,
gchar **style_entry)
const gchar *tag,
GimpResource **style_entry,
GType resource_type)
{
gint n = 0;
gchar *ptr;
gchar *tmpstr;
*style_entry = NULL;
while (n < nitems)
{
ptr = strchr (text[n], ':');
@ -76,9 +80,21 @@ gfig_read_parameter_string (gchar **text,
{
tmpstr = g_strndup (text[n], ptr - text[n]);
ptr++;
if (!strcmp (tmpstr, name))
if (!strcmp (tmpstr, tag))
{
*style_entry = g_strdup (g_strchug (ptr));
/* Create a resource object, just a proxy for the thing in core. */
GimpResource *resource;
gchar *resource_id = g_strdup (g_strchug (ptr));
resource = g_object_new (resource_type, "id", resource_id, NULL);
/* We own the resource object, its refcount is one.
* The resource object owns its string ID.
*/
*style_entry = resource;
/* We are not checking the ID is valid.
* The user might have uninstalled the resource.
*/
g_free (tmpstr);
return;
}
@ -87,7 +103,9 @@ gfig_read_parameter_string (gchar **text,
++n;
}
g_message ("Parameter '%s' not found", name);
/* Fail */
*style_entry = NULL;
g_message ("Parameter '%s' not found", tag);
}
@ -254,14 +272,16 @@ gfig_load_style (Style *style,
return TRUE;
}
gfig_read_parameter_string (style_text, nitems, "BrushName",
&style->brush);
gfig_read_resource (style_text, nitems, "BrushName",
(GimpResource**) &style->brush, GIMP_TYPE_BRUSH);
if (style->brush == NULL)
g_message ("Error loading style: got NULL for brush name.");
g_message ("Error loading style: missing brush.");
gfig_read_parameter_string (style_text, nitems, "Pattern", &style->pattern);
gfig_read_parameter_string (style_text, nitems, "Gradient", &style->gradient);
gfig_read_resource (style_text, nitems, "Pattern",
(GimpResource**) &style->pattern, GIMP_TYPE_PATTERN);
gfig_read_resource (style_text, nitems, "Gradient",
(GimpResource**) &style->gradient, GIMP_TYPE_GRADIENT);
gfig_read_parameter_gimp_rgb (style_text, nitems, "Foreground",
&style->foreground);
@ -353,10 +373,12 @@ 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);
g_printerr ("Saving style %s, brush name '%s'\n", style->name,
gimp_resource_get_id (GIMP_RESOURCE (style->brush)));
g_string_append_printf (string, "<Style %s>\n", style->name);
g_string_append_printf (string, "BrushName: %s\n", style->brush);
g_string_append_printf (string, "BrushName: %s\n",
gimp_resource_get_id (GIMP_RESOURCE (style->brush)));
if (!style->brush)
g_message ("Error saving style %s: saving NULL for brush name", style->name);
@ -367,9 +389,10 @@ gfig_save_style (Style *style,
g_string_append_printf (string, "FillOpacity: %s\n",
g_ascii_dtostr (buffer, blen, style->fill_opacity));
g_string_append_printf (string, "Pattern: %s\n", style->pattern);
g_string_append_printf (string, "Gradient: %s\n", style->gradient);
g_string_append_printf (string, "Pattern: %s\n",
gimp_resource_get_id (GIMP_RESOURCE (style->pattern)));
g_string_append_printf (string, "Gradient: %s\n",
gimp_resource_get_id (GIMP_RESOURCE (style->gradient)));
g_string_append_printf (string, "Foreground: %s %s %s %s\n",
g_ascii_dtostr (buffer_r, blen, style->foreground.r),
@ -399,7 +422,11 @@ gfig_style_save_as_attributes (Style *style,
if (gfig_context->debug_styles)
g_printerr ("Saving style %s as attributes\n", style->name);
g_string_append_printf (string, "BrushName=\"%s\" ", style->brush);
/* Tags must match the ones written, see below in the code. */
g_string_append_printf (string, "BrushName=\"%s\" ",
gimp_resource_get_id (GIMP_RESOURCE (style->brush)));
/* Why only brush and not pattern and gradient? */
g_string_append_printf (string, "Foreground=\"%s %s %s %s\" ",
g_ascii_dtostr (buffer_r, blen, style->foreground.r),
@ -494,19 +521,15 @@ set_paint_type_callback (GtkToggleButton *toggle,
/*
* gfig_brush_changed_callback() is the callback for the brush
* selector widget. It reads the brush name from the widget, and
* applies this to the current style, as well as the gfig_context->bdesc
* selector widget. It receives the brush from the widget, and
* sets the brush in the current style, as well as the gfig_context->bdesc
* values. It then produces a repaint (which will be suppressed if
* gfig_context->enable_repaint is FALSE).
*/
void
gfig_brush_changed_callback (GimpBrushSelectButton *button,
const GimpBrush *brush,
gint width,
gint height,
const guchar *mask_data,
gboolean dialog_closing,
gpointer user_data)
gfig_brush_changed_callback (gpointer user_data,
GimpBrush *brush,
gboolean dialog_closing)
{
Style *current_style;
@ -514,9 +537,8 @@ gfig_brush_changed_callback (GimpBrushSelectButton *button,
current_style->brush = brush;
/* this will soon be unneeded. How soon? */
gfig_context->bdesc.name = g_strdup (brush);
gfig_context->bdesc.width = width;
gfig_context->bdesc.height = height;
set_context_bdesc (brush);
gimp_context_set_brush (brush);
gimp_context_set_brush_default_size ();
@ -524,35 +546,27 @@ gfig_brush_changed_callback (GimpBrushSelectButton *button,
}
void
gfig_pattern_changed_callback (GimpPatternSelectButton *button,
const gchar *pattern_name,
gint width,
gint height,
gint bpp,
const guchar *mask_data,
gboolean dialog_closing,
gpointer user_data)
gfig_pattern_changed_callback (gpointer user_data,
GimpPattern *pattern,
gboolean dialog_closing)
{
Style *current_style;
current_style = gfig_context_get_current_style ();
current_style->pattern = g_strdup (pattern_name);
current_style->pattern = pattern;
gfig_paint_callback ();
}
void
gfig_gradient_changed_callback (GimpGradientSelectButton *button,
const gchar *gradient_name,
gint width,
const gdouble *grad_data,
gboolean dialog_closing,
gpointer user_data)
gfig_gradient_changed_callback (gpointer user_data,
GimpGradient *gradient,
gboolean dialog_closing)
{
Style *current_style;
current_style = gfig_context_get_current_style ();
current_style->gradient = g_strdup (gradient_name);
current_style->gradient = gradient;
gfig_paint_callback ();
}
@ -586,9 +600,11 @@ gfig_style_copy (Style *style1,
if (!style0->brush)
g_message ("Error copying style %s: brush name is NULL.", style0->name);
style1->brush = g_strdup (style0->brush);
style1->gradient = g_strdup (style0->gradient);
style1->pattern = g_strdup (style0->pattern);
/* ownership issues ? */
style1->brush = style0->brush;
style1->gradient = style0->gradient;
style1->pattern = style0->pattern;
style1->fill_type = style0->fill_type;
style1->fill_opacity = style0->fill_opacity;
style1->paint_type = style0->paint_type;
@ -611,10 +627,12 @@ gfig_style_apply (Style *style)
if (! gimp_context_set_brush (style->brush))
g_message ("Style apply: Failed to set brush to '%s' in style '%s'",
style->brush, style->name);
gimp_resource_get_id (GIMP_RESOURCE (style->brush)),
style->name);
gimp_context_set_brush_default_size ();
g_assert (style->pattern != NULL);
gimp_context_set_pattern (style->pattern);
gimp_context_set_gradient (style->gradient);
@ -646,19 +664,18 @@ gfig_read_gimp_style (Style *style,
gimp_context_get_background (&style->background);
style->brush = gimp_context_get_brush ();
gimp_brush_get_info (style->brush,
&style->brush_width, &style->brush_height,
&dummy, &dummy);
style->brush_spacing = gimp_brush_get_spacing (style->brush);
style->gradient = gimp_context_get_gradient ();
style->pattern = gimp_context_get_pattern ();
style->fill_opacity = 100.;
gfig_context->bdesc.name = style->brush;
gfig_context->bdesc.width = style->brush_width;
gfig_context->bdesc.height = style->brush_height;
/* Cache attributes of brush. */
gimp_brush_get_info (style->brush,
&style->brush_width, &style->brush_height,
&dummy, &dummy);
style->brush_spacing = gimp_brush_get_spacing (style->brush);
set_context_bdesc (style->brush);
}
/*
@ -697,7 +714,8 @@ gfig_style_set_context_from_style (Style *style)
gimp_gradient_select_button_set_gradient (GIMP_GRADIENT_SELECT_BUTTON (gfig_context->gradient_select),
style->gradient);
gfig_context->bdesc.name = style->brush;
set_context_bdesc (style->brush);
if (gfig_context->debug_styles)
g_printerr ("done.\n");
@ -734,13 +752,16 @@ gfig_style_set_style_from_context (Style *style)
&color);
gfig_rgba_copy (&style->background, &color);
/* FIXME: issues of ownership.
* A resource is a pointer to an object.
* We own each resource object returned by gimp_context_get_<resource> and should unref it.
* Here this is possibly overwriting a reference that should be unreffed.
* Also, this is copying a reference, so we should ref the object.
*
* For now, its just a plugin, we don't care much about leaks.
*/
style->brush = current_style->brush;
if (!style->pattern || strcmp (style->pattern, current_style->pattern))
{
style->pattern = g_strdup (current_style->pattern); /* why strduping? */
}
style->pattern = current_style->pattern;
style->gradient = current_style->gradient;
if (gimp_int_combo_box_get_active (GIMP_INT_COMBO_BOX (gfig_context->fillstyle_combo), &value))
@ -752,25 +773,29 @@ gfig_style_set_style_from_context (Style *style)
style->paint_type = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (gfig_context->paint_type_toggle));
}
/* Set bdesc from brush. Side effects on gfig_context->bdesc */
void
mygimp_brush_info (gint *width,
gint *height)
set_context_bdesc (GimpBrush *brush)
{
gchar *name = gimp_context_get_brush ();
gint width;
gint height;
gint dummy;
if (name && gimp_brush_get_info (name, width, height, &dummy, &dummy))
g_return_if_fail (brush != NULL);
g_return_if_fail (GIMP_IS_BRUSH (brush));
if (brush && gimp_brush_get_info (brush, &width, &height, &dummy, &dummy))
{
*width = MAX (*width, 32);
*height = MAX (*height, 32);
gfig_context->bdesc.brush = brush;
gfig_context->bdesc.width = MAX (width, 32);
gfig_context->bdesc.height = MAX (height, 32);
}
else
{
g_message ("Failed to get brush info");
*width = *height = 48;
gfig_context->bdesc.width = 48;
gfig_context->bdesc.height = 48;
}
g_free (name);
}
Style *

View file

@ -30,7 +30,11 @@
struct _Style
{
gchar *name;
GimpBrush *brush;
GimpPattern *pattern;
GimpGradient *gradient;
gint brush_width;
gint brush_height;
gint brush_spacing;
@ -40,8 +44,7 @@ struct _Style
gdouble airbrushpressure;
FillType fill_type;
gdouble fill_opacity;
gchar *pattern;
gchar *gradient;
PaintType paint_type;
GimpRGB foreground;
GimpRGB background;
@ -75,32 +78,15 @@ void set_background_callback (GimpColorButton *button,
void set_paint_type_callback (GtkToggleButton *toggle,
gpointer data);
void gfig_brush_changed_callback (GimpBrushSelectButton *button,
const gchar *brush_name,
gdouble opacity,
gint spacing,
GimpLayerMode paint_mode,
gint width,
gint height,
const guchar *mask_data,
gboolean dialog_closing,
gpointer user_data);
void gfig_pattern_changed_callback (GimpPatternSelectButton *button,
const gchar *pattern_name,
gint width,
gint height,
gint bpp,
const guchar *mask_data,
gboolean dialog_closing,
gpointer user_data);
void gfig_gradient_changed_callback (GimpGradientSelectButton *button,
const gchar *gradient_name,
gint width,
const gdouble *grad_data,
gboolean dialog_closing,
gpointer user_data);
void gfig_brush_changed_callback (gpointer user_data,
GimpBrush *brush,
gboolean dialog_closing);
void gfig_pattern_changed_callback (gpointer user_data,
GimpPattern *pattern,
gboolean dialog_closing);
void gfig_gradient_changed_callback (gpointer user_data,
GimpGradient *gradient,
gboolean dialog_closing);
void gfig_rgba_copy (GimpRGB *color1,
GimpRGB *color2);
@ -118,8 +104,7 @@ void gfig_style_set_context_from_style (Style *style);
void gfig_style_set_style_from_context (Style *style);
void mygimp_brush_info (gint *width,
gint *height);
void set_context_bdesc (GimpBrush *brush);
Style *gfig_context_get_current_style (void);

View file

@ -115,7 +115,7 @@ struct _GFigObj
/* this is temp, should be able to get rid of */
typedef struct BrushDesc
{
gchar *name;
GimpBrush *brush;
gdouble opacity;
gint spacing;
GimpLayerMode paint_mode;

View file

@ -5062,7 +5062,12 @@ gradient_get_values_real_external (const gchar *gradient_name,
gint i;
gint j;
gimp_gradient_get_uniform_samples (gradient_name, nvalues, reverse,
GimpGradient *gradient;
/* New proxy for gradient. */
gradient = g_object_new (GIMP_TYPE_GRADIENT, "id", gradient_name, NULL);
gimp_gradient_get_uniform_samples (gradient, nvalues, reverse,
&n_tmp_values, &tmp_values);
for (i = 0; i < nvalues; i++)

View file

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

View file

@ -511,42 +511,6 @@ dialog (void)
vbox, TRUE, TRUE, 0);
gtk_widget_show (vbox);
frame = gimp_frame_new ("LibGimp Widget Testing Ground");
gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
gtk_widget_show (frame);
grid = gtk_grid_new ();
gtk_grid_set_row_spacing (GTK_GRID (grid), 6);
gtk_grid_set_column_spacing (GTK_GRID (grid), 6);
gtk_container_add (GTK_CONTAINER (frame), grid);
gtk_widget_show (grid);
button = gimp_brush_select_button_new ("Brush Test", NULL,
1.0, 20, GIMP_LAYER_MODE_NORMAL);
gimp_grid_attach_aligned (GTK_GRID (grid), 0, 0,
"Brush Select:", 0.0, 0.5,
button, 1);
button = gimp_gradient_select_button_new ("Gradient Test", NULL);
gimp_grid_attach_aligned (GTK_GRID (grid), 0, 1,
"Gradient Select:", 0.0, 0.5,
button, 1);
button = gimp_palette_select_button_new ("Palette Test", NULL);
gimp_grid_attach_aligned (GTK_GRID (grid), 0, 2,
"Palette Select:", 0.0, 0.5,
button, 1);
button = gimp_font_select_button_new ("Font Test", NULL);
gimp_grid_attach_aligned (GTK_GRID (grid), 0, 3,
"Font Select:", 0.0, 0.5,
button, 1);
button = gimp_pattern_select_button_new ("Pattern Test", NULL);
gimp_grid_attach_aligned (GTK_GRID (grid), 0, 4,
"Pattern Select:", 0.0, 0.5,
button, 1);
frame = gimp_frame_new (_("Curl Location"));
gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
gtk_widget_show (frame);
@ -1079,15 +1043,16 @@ static GimpRGB *
get_gradient_samples (GimpDrawable *drawable,
gboolean reverse)
{
gchar *gradient_name;
GimpGradient *gradient;
gint n_d_samples;
gdouble *d_samples = NULL;
GimpRGB *rgba;
gint i;
gradient_name = gimp_context_get_gradient ();
gradient = gimp_context_get_gradient ();
gimp_gradient_get_uniform_samples (gradient_name, NGRADSAMPLES, reverse,
gimp_gradient_get_uniform_samples (gradient, NGRADSAMPLES, reverse,
&n_d_samples, &d_samples);
rgba = g_new0 (GimpRGB, NGRADSAMPLES);
@ -1100,7 +1065,5 @@ get_gradient_samples (GimpDrawable *drawable,
d_samples[i*4 + 3]);
}
g_free (gradient_name);
return rgba;
}

View file

@ -98,13 +98,13 @@ def gradient_css_save(procedure, args, data):
stops = []
wk_stops = []
n_segments = Gimp.gradient_get_number_of_segments(gradient)
n_segments = gradient.get_number_of_segments()
last_stop = None
for index in range(n_segments):
success, lcolor, lopacity = Gimp.gradient_segment_get_left_color(gradient, index)
success, rcolor, ropacity = Gimp.gradient_segment_get_right_color(gradient, index)
success, lpos = Gimp.gradient_segment_get_left_pos(gradient, index)
success, rpos = Gimp.gradient_segment_get_right_pos(gradient, index)
success, lcolor, lopacity = gradient.segment_get_left_color(index)
success, rcolor, ropacity = gradient.segment_get_right_color(index)
success, lpos = gradient.segment_get_left_pos(index)
success, rpos = gradient.segment_get_right_pos(index)
lstop = color_to_html(lcolor) + " %d%%" % int(100 * lpos)
wk_lstop = "color-stop(%.03f, %s)" %(lpos, color_to_html(lcolor))
@ -142,8 +142,8 @@ class GradientsSaveAsCSS (Gimp.PlugIn):
_("The run mode"),
Gimp.RunMode.NONINTERACTIVE,
GObject.ParamFlags.READWRITE),
"gradient": (str,
_("Gradient to use"), "", "",
"gradient": (Gimp.Gradient,
_("Gradient to use"), "",
GObject.ParamFlags.READWRITE),
"file": (Gio.File,
_("File"), None,

View file

@ -26,6 +26,11 @@ import sys
def N_(message): return message
def _(message): return GLib.dgettext(None, message)
help_doc = r"""
Offset the colors in the palette.
Offsets and returns the given palette when it is editable,
otherwise copies the given palette and returns it.
"""
class PaletteOffset (Gimp.PlugIn):
## Parameter: run-mode ##
@ -41,8 +46,7 @@ class PaletteOffset (Gimp.PlugIn):
self._run_mode = run_mode
## Parameter: palette ##
@GObject.Property(type=str,
default="",
@GObject.Property(type=Gimp.Palette,
nick= _("Palette"),
blurb= _("Palette"))
def palette(self):
@ -65,10 +69,9 @@ class PaletteOffset (Gimp.PlugIn):
self._amount = amount
## Return: new-palette ##
@GObject.Property(type=str,
default=None,
nick=_("Name of the edited palette"),
blurb=_("Name of the newly created palette if read-only or the input palette otherwise"))
@GObject.Property(type=Gimp.Palette,
nick=_("The edited palette"),
blurb=_("The newly created palette when read-only, otherwise the input palette"))
def new_palette(self):
return self.new_palette
@ -90,7 +93,7 @@ class PaletteOffset (Gimp.PlugIn):
if name == 'python-fu-palette-offset':
procedure.set_menu_label(_("_Offset Palette..."))
procedure.set_documentation(_("Offset the colors in a palette"),
"palette_offset (palette, amount) -> modified_palette",
help_doc,
"")
procedure.set_attribution("Joao S. O. Bueno Calligaris, Carol Spears",
"(c) Joao S. O. Bueno Calligaris",
@ -118,11 +121,11 @@ class PaletteOffset (Gimp.PlugIn):
if args.length() > 1:
palette = args.index(1)
if palette == '' or palette is None:
if palette is None:
palette = Gimp.context_get_palette()
(exists, num_colors) = Gimp.palette_get_info(palette)
if not exists:
error = 'Unknown palette: {}'.format(palette)
if not palette.is_valid():
error = f'Invalid palette ID: {palette.get_id()}'
return procedure.new_return_values(Gimp.PDBStatusType.CALLING_ERROR,
GLib.Error(error))
@ -159,30 +162,32 @@ class PaletteOffset (Gimp.PlugIn):
dialog.show()
if dialog.run() != Gtk.ResponseType.OK:
print ("Canceled")
return procedure.new_return_values(Gimp.PDBStatusType.CANCEL,
GLib.Error())
GLib.Error("Canceled"))
amount = self.get_property("amount")
#If palette is read only, work on a copy:
editable = Gimp.palette_is_editable(palette)
editable = palette.is_editable()
if not editable:
palette = Gimp.palette_duplicate (palette)
palette = palette.duplicate()
num_colors = palette.get_color_count()
tmp_entry_array = []
for i in range (num_colors):
tmp_entry_array.append ((Gimp.palette_entry_get_name (palette, i)[1],
Gimp.palette_entry_get_color (palette, i)[1]))
tmp_entry_array.append ((palette.entry_get_name(i)[1],
palette.entry_get_color(i)[1]))
for i in range (num_colors):
target_index = i + amount
if target_index >= num_colors:
target_index -= num_colors
elif target_index < 0:
target_index += num_colors
Gimp.palette_entry_set_name (palette, target_index, tmp_entry_array[i][0])
Gimp.palette_entry_set_color (palette, target_index, tmp_entry_array[i][1])
palette.entry_set_name(target_index, tmp_entry_array[i][0])
palette.entry_set_color(target_index, tmp_entry_array[i][1])
retval = procedure.new_return_values(Gimp.PDBStatusType.SUCCESS, GLib.Error())
value = GObject.Value(GObject.TYPE_STRING, palette)
value = GObject.Value(Gimp.Palette, palette)
retval.remove(1)
retval.insert(1, value)
return retval

View file

@ -223,17 +223,17 @@ def palette_sort(palette, selection, slice_expr, channel1, ascending1,
pgrain = quantization_grain(pchannel, pquantize)
# If palette is read only, work on a copy:
editable = Gimp.palette_is_editable(palette)
editable = palette.is_editable()
if not editable:
palette = Gimp.palette_duplicate(palette)
palette = palette.duplicate()
(exists, num_colors) = Gimp.palette_get_info(palette)
num_colors = palette.get_color_count()
start, nrows, length = None, None, None
if selection == SELECT_AUTOSLICE:
def find_index(color, startindex=0):
for i in range(startindex, num_colors):
c = Gimp.palette_entry_get_color(palette, i)
c = palette.entry_get_color(i)
if c[1].r == color[1].r and c[1].g == color[1].g and c[1].b == color[1].b:
return i
return None
@ -279,8 +279,8 @@ def palette_sort(palette, selection, slice_expr, channel1, ascending1,
def get_colors(start, end):
result = []
for i in range(start, end):
entry = (Gimp.palette_entry_get_name (palette, i)[1],
Gimp.palette_entry_get_color (palette, i)[1])
entry = (palette.entry_get_name(i)[1],
palette.entry_get_color(i)[1])
index1 = channels_getter_1(entry[1], i)
index2 = channels_getter_2(entry[1], i)
index = ((index1 - (index1 % grain1)) * (1 if ascending1 else -1),
@ -293,8 +293,8 @@ def palette_sort(palette, selection, slice_expr, channel1, ascending1,
entry_list = get_colors(0, num_colors)
entry_list.sort(key=lambda v: v[0])
for i in range(num_colors):
Gimp.palette_entry_set_name (palette, i, entry_list[i][1][0])
Gimp.palette_entry_set_color (palette, i, entry_list[i][1][1])
palette.entry_set_name(i, entry_list[i][1][0])
palette.entry_set_color(i, entry_list[i][1][1])
elif selection == SELECT_PARTITIONED:
if num_colors < (start + length * nrows) - 1:
@ -305,12 +305,11 @@ def palette_sort(palette, selection, slice_expr, channel1, ascending1,
for row in range(nrows):
partition_spans = [1]
rowstart = start + (row * length)
old_color = Gimp.palette_entry_get_color (palette,
rowstart)[1]
old_color = palette.entry_get_color(rowstart)[1]
old_partition = pchannels_getter(old_color, rowstart)
old_partition = old_partition - (old_partition % pgrain)
for i in range(rowstart + 1, rowstart + length):
this_color = Gimp.palette_entry_get_color (palette, i)[1]
this_color = palette.entry_get_color(i)[1]
this_partition = pchannels_getter(this_color, i)
this_partition = this_partition - (this_partition % pgrain)
if this_partition == old_partition:
@ -320,7 +319,7 @@ def palette_sort(palette, selection, slice_expr, channel1, ascending1,
old_partition = this_partition
base = rowstart
for size in partition_spans:
palette_sort(palette, SELECT_SLICE, '%d:1,%d' % (base, size),
palette_sort(SELECT_SLICE, '%d:1,%d' % (base, size),
channel1, ascending1,
channel2, ascending2,
quantize, 0, 1.0)
@ -337,11 +336,24 @@ def palette_sort(palette, selection, slice_expr, channel1, ascending1,
sublist = get_colors(row_start, row_start + stride)
sublist.sort(key=lambda v: v[0])
for i, entry in zip(range(row_start, row_start + stride), sublist):
Gimp.palette_entry_set_name (palette, i, entry[1][0])
Gimp.palette_entry_set_color (palette, i, entry[1][1])
palette.entry_set_name(i, entry[1][0])
palette.entry_set_color(i, entry[1][1])
return palette
# FIXME: Write humanly readable help -
# See for reference: https://gitlab.gnome.org/GNOME/gimp/-/issues/4368#note_763460
# Important to describe the general effect on palettes rather than details of the sort.
help_doc = r"""
Sorts a palette, or part of a palette.
Sorts the given palette when it is editable, otherwise creates a new sorted palette.
The default is a 1D sort, but you can also sort over two color channels
or create a 2D sorted palette with sorted rows.
You can optionally install colormath (https://pypi.python.org/pypi/colormath/1.0.8)
to GIMP's Python to get even more channels to choose from.
"""
selections_option = [ _("All"), _("Slice / Array"), _("Autoslice (fg->bg)"), _("Partitioned") ]
class PaletteSort (Gimp.PlugIn):
## Parameters ##
@ -351,12 +363,10 @@ class PaletteSort (Gimp.PlugIn):
"The run mode",
Gimp.RunMode.INTERACTIVE,
GObject.ParamFlags.READWRITE),
# TODO. originally was: (PF_PALETTE, "palette", _("Palette"), ""),
# Should probably be of type Gimp.Palette .
"palette": (str,
# Originally: (PF_PALETTE, "palette", _("Palette"), ""),
"palette": (Gimp.Palette,
_("_Palette"),
_("Palette"),
"",
GObject.ParamFlags.READWRITE),
"selections": (int,
_("Select_ions"),
@ -407,10 +417,9 @@ class PaletteSort (Gimp.PlugIn):
GObject.ParamFlags.READWRITE),
# Returned value
"new_palette": (str,
"new_palette": (Gimp.Palette,
_("Palette"),
_("Palette"),
"",
GObject.ParamFlags.READWRITE),
}
@ -428,22 +437,9 @@ class PaletteSort (Gimp.PlugIn):
Gimp.PDBProcType.PLUGIN,
self.run, None)
procedure.set_menu_label(_("_Sort Palette..."))
# FIXME: Write humanly readable help -
# See for reference: https://gitlab.gnome.org/GNOME/gimp/-/issues/4368#note_763460
procedure.set_documentation(
N_("Sort the colors in a palette"),
dedent("""\
palette_sort (palette, selection, slice_expr, channel,
channel2, quantize, ascending, pchannel, pquantize) -> new_palette
Sorts a palette, or part of a palette, using several options.
One can select two color channels over which to sort,
and several auxiliary parameters create a 2D sorted
palette with sorted rows, among other things.
One can optionally install colormath
(https://pypi.python.org/pypi/colormath/1.0.8)
to GIMP's Python to get even more channels to choose from.
"""),
_("Sort the colors in a palette"),
help_doc,
""
)
procedure.set_attribution("João S. O. Bueno, Carol Spears, David Gowers",
@ -482,6 +478,15 @@ class PaletteSort (Gimp.PlugIn):
pchannel = args.index(9)
pquantize = args.index(10)
if palette is None:
palette = Gimp.context_get_palette()
if not palette.is_valid():
palette_name = palette.get_id()
error = f'Invalid palette id: {palette_name}'
return procedure.new_return_values(Gimp.PDBStatusType.CALLING_ERROR,
GLib.Error(error))
if run_mode == Gimp.RunMode.INTERACTIVE:
GimpUi.init('python-fu-palette-sort')
dialog = GimpUi.ProcedureDialog(procedure=procedure, config=config)
@ -531,14 +536,6 @@ class PaletteSort (Gimp.PlugIn):
dialog.destroy()
if palette == '' or palette is None:
palette = Gimp.context_get_palette()
(exists, num_colors) = Gimp.palette_get_info(palette)
if not exists:
error = 'Unknown palette: {}'.format(palette)
return procedure.new_return_values(Gimp.PDBStatusType.CALLING_ERROR,
GLib.Error(error))
try:
new_palette = palette_sort(palette, selection, slice_expr, channel1, ascending1,
channel2, ascending2, quantize, pchannel, pquantize)
@ -549,7 +546,7 @@ class PaletteSort (Gimp.PlugIn):
config.end_run(Gimp.PDBStatusType.SUCCESS)
return_val = procedure.new_return_values(Gimp.PDBStatusType.SUCCESS, GLib.Error())
value = GObject.Value(GObject.TYPE_STRING, new_palette)
value = GObject.Value(Gimp.Palette, new_palette)
return_val.remove(1)
return_val.insert(1, value)
return return_val

View file

@ -26,25 +26,29 @@ def _(message): return GLib.dgettext(None, message)
def make_gradient(palette, num_segments, num_colors):
gradient = Gimp.gradient_new(palette)
if (num_segments > 1):
Gimp.gradient_segment_range_split_uniform(gradient, 0, -1,
num_segments)
# name the gradient same as the source palette
# For now, the name of a resource is the same as the ID
palette_name = palette.get_id()
gradient = Gimp.Gradient.new(palette_name)
# assert gradient is valid but is has only one segment
assert gradient.get_number_of_segments() == 1
# split one segment into desired count
# index is zero-based
gradient.segment_range_split_uniform( 0, 0, num_segments)
for color_number in range(0,num_segments):
if color_number == num_colors - 1:
color_number_next = 0
else:
color_number_next = color_number + 1
_, color_left = Gimp.palette_entry_get_color(palette, color_number)
_, color_right = Gimp.palette_entry_get_color(palette, color_number_next)
Gimp.gradient_segment_set_left_color(gradient,
color_number, color_left,
100.0)
Gimp.gradient_segment_set_right_color(gradient,
color_number, color_right,
100.0)
_, color_left = palette.entry_get_color(color_number)
_, color_right = palette.entry_get_color(color_number_next)
gradient.segment_set_left_color( color_number, color_left, 100.0)
gradient.segment_set_right_color(color_number, color_right, 100.0)
# Side effects on the context. Probably not what most would expect.
Gimp.context_set_gradient(gradient)
return gradient
@ -53,13 +57,11 @@ def run(procedure, args, data):
palette = None
if args.length() > 1:
palette = args.index(1)
if palette == '' or palette is None:
if palette is None:
palette = Gimp.context_get_palette()
(exists, num_colors) = Gimp.palette_get_info(palette)
if not exists:
error = 'Unknown palette: {}'.format(palette)
return procedure.new_return_values(Gimp.PDBStatusType.CALLING_ERROR,
GLib.Error(error))
assert palette.is_valid()
num_colors = palette.get_color_count()
if procedure.get_name() == 'python-fu-palette-to-gradient':
num_segments = num_colors - 1
@ -78,7 +80,10 @@ def run(procedure, args, data):
# XXX: I don't try to get the GValue with retval.index(1) because it
# actually return a string (cf. pygobject#353). Just create a new
# GValue and replace the default one with this one.
value = GObject.Value(GObject.TYPE_STRING, gradient)
# This comment dates from when resources are strings:
# value = GObject.Value(GObject.TYPE_STRING, gradient)
value = GObject.Value(Gimp.Gradient, gradient)
retval.remove(1)
retval.insert(1, value)
@ -98,11 +103,11 @@ class PaletteToGradient (Gimp.PlugIn):
self.runmode = runmode
## Parameter: palette ##
@GObject.Property(type=str,
@GObject.Property(type=Gimp.Palette,
default=None,
nick= _("Palette"))
def palette(self):
'''Palette name or empty string for the currently selected palette'''
'''Palette or None for the currently selected palette'''
return self.palette
@palette.setter
@ -110,10 +115,10 @@ class PaletteToGradient (Gimp.PlugIn):
self.palette = palette
## Properties: return values ##
@GObject.Property(type=str,
@GObject.Property(type=Gimp.Gradient,
default="",
nick=_("Name of the newly created gradient"),
blurb=_("Name of the newly created gradient"))
nick=_("The newly created gradient"),
blurb=_("The newly created gradient"))
def new_gradient(self):
"""Read-write integer property."""
return self.new_gradient

View file

@ -492,31 +492,29 @@ shapes = [
def get_gradient_samples(num_samples):
gradient_name = Gimp.context_get_gradient()
gradient = Gimp.context_get_gradient()
reverse_mode = Gimp.context_get_gradient_reverse()
repeat_mode = Gimp.context_get_gradient_repeat_mode()
if repeat_mode == Gimp.RepeatMode.TRIANGULAR:
# Get two uniform samples, which are reversed from each other, and connect them.
samples = num_samples/2 + 1
success, color_samples = Gimp.gradient_get_uniform_samples(gradient_name,
samples, reverse_mode)
sample_count = num_samples/2 + 1
success, color_samples = gradient.get_uniform_samples(sample_count, reverse_mode)
del color_samples[-4:] # Delete last color because it will appear in the next sample
# If num_samples is odd, lets get an extra sample this time.
if num_samples % 2 == 1:
samples += 1
sample_count += 1
success, color_samples2 = Gimp.gradient_get_uniform_samples(gradient_name,
samples, 1 - reverse_mode)
success, color_samples2 = gradient.get_uniform_samples(sample_count, 1 - reverse_mode)
del color_samples2[-4:] # Delete last color because it will appear in the very first sample
color_samples = tuple(color_samples)
else:
success, color_samples = Gimp.gradient_get_uniform_samples(gradient_name, num_samples, reverse_mode)
success, color_samples = gradient.get_uniform_samples(num_samples, reverse_mode)
return color_samples
@ -592,7 +590,15 @@ class PreviewTool:
Gimp.context_set_defaults()
Gimp.context_set_foreground(foreground)
Gimp.context_enable_dynamics(False)
Gimp.context_set_brush('1. Pixel')
# Create a brush proxy. Set the 'id' property, not a Python attribute.
# The id must match an installed real brush.
# FUTURE: add method of brush, say get_named()
brush = Gimp.Brush()
brush.set_property('id', '1. Pixel')
assert brush.is_valid()
Gimp.context_set_brush(brush)
Gimp.context_set_brush_size(1.0)
Gimp.context_set_brush_spacing(3.0)
Gimp.pencil(layer, strokes)

View file

@ -146,8 +146,8 @@ script_fu_arg_free (SFArg *arg)
break;
case SF_BRUSH:
g_free (arg->default_value.sfa_brush.name);
g_free (arg->value.sfa_brush.name);
g_free (arg->default_value.sfa_brush);
g_free (arg->value.sfa_brush);
break;
case SF_OPTION:
@ -237,11 +237,8 @@ script_fu_arg_reset (SFArg *arg, gboolean should_reset_ids)
break;
case SF_BRUSH:
g_free (value->sfa_brush.name);
value->sfa_brush.name = g_strdup (default_value->sfa_brush.name);
value->sfa_brush.opacity = default_value->sfa_brush.opacity;
value->sfa_brush.spacing = default_value->sfa_brush.spacing;
value->sfa_brush.paint_mode = default_value->sfa_brush.paint_mode;
g_free (value->sfa_brush);
value->sfa_brush = g_strdup (default_value->sfa_brush);
break;
case SF_OPTION:
@ -355,17 +352,6 @@ script_fu_arg_get_param_spec (SFArg *arg,
case SF_VALUE:
case SF_STRING:
case SF_TEXT:
/* FUTURE special widgets.
* script-fu-interface does, but GimpProcedureDialog does not?
*/
case SF_FONT:
case SF_PALETTE:
case SF_PATTERN:
case SF_GRADIENT:
/* These cases the same type: gchar *.
* Use arbitrary SFArg field of that type.
*/
pspec = g_param_spec_string (name,
nick,
arg->label,
@ -373,9 +359,39 @@ script_fu_arg_get_param_spec (SFArg *arg,
G_PARAM_READWRITE);
break;
/* Subclasses of GimpResource. Special widgets. */
case SF_FONT:
pspec = gimp_param_spec_font (name,
nick,
arg->label,
FALSE, /* none OK */
G_PARAM_READWRITE | GIMP_PARAM_NO_VALIDATE);
break;
case SF_PALETTE:
pspec = gimp_param_spec_palette (name,
nick,
arg->label,
FALSE, /* none OK */
G_PARAM_READWRITE | GIMP_PARAM_NO_VALIDATE);
break;
case SF_PATTERN:
pspec = gimp_param_spec_pattern (name,
nick,
arg->label,
FALSE, /* none OK */
G_PARAM_READWRITE | GIMP_PARAM_NO_VALIDATE);
break;
case SF_GRADIENT:
pspec = gimp_param_spec_gradient (name,
nick,
arg->label,
FALSE, /* none OK */
G_PARAM_READWRITE | GIMP_PARAM_NO_VALIDATE);
break;
case SF_BRUSH:
/* FIXME: SF-BRUSH will not have opacity, etc. instead gimp_brush_select will choose only brush. */
/* FIXME: font, etc. are resource types. Brush is just the test for WIP. */
pspec = gimp_param_spec_brush (name,
nick,
arg->label,
@ -568,22 +584,29 @@ script_fu_arg_append_repr_from_gvalue (SFArg *arg,
case SF_PALETTE:
case SF_PATTERN:
case SF_GRADIENT:
g_string_append_printf (result_string, "\"%s\"", g_value_get_string (gvalue));
break;
case SF_BRUSH:
{
/* The GValue is a GObject of type GimpBrush having property "id" */
GimpBrush *brush;
gchar *brush_name;
/* The GValue is a GObject of type inheriting GimpResource having property "id" */
GimpResource *resource;
gchar *resource_name;
brush = g_value_get_object (gvalue);
g_object_get (brush, "id", &brush_name, NULL);
g_string_append_printf (result_string, "\"%s\"", brush_name);
/* !!! These only check whether gvalue CAN hold object type, not that it does. */
g_assert (G_VALUE_HOLDS_OBJECT (gvalue));
g_assert (GIMP_VALUE_HOLDS_RESOURCE (gvalue));
g_debug ("gvalue type is: %s", G_VALUE_TYPE_NAME(gvalue));
/* Check the value's type is suitable for a gvalue. */
g_assert (G_TYPE_IS_VALUE (G_VALUE_TYPE (gvalue)));
/* Check that gvalue actually holds type, AND IS NOT NULL. */
g_assert (G_VALUE_HOLDS (gvalue, GIMP_TYPE_RESOURCE ));
resource = g_value_get_object (gvalue);
g_object_get (resource, "id", &resource_name, NULL);
g_string_append_printf (result_string, "\"%s\"", resource_name);
}
break;
case SF_OPTION:
append_int_repr_from_gvalue (result_string, gvalue);
break;
@ -699,17 +722,7 @@ script_fu_arg_append_repr_from_self (SFArg *arg,
break;
case SF_BRUSH:
{
gchar buffer[G_ASCII_DTOSTR_BUF_SIZE];
g_ascii_dtostr (buffer, sizeof (buffer),
arg_value->sfa_brush.opacity);
g_string_append_printf (result_string, "'(\"%s\" %s %d %d)",
arg_value->sfa_brush.name,
buffer,
arg_value->sfa_brush.spacing,
arg_value->sfa_brush.paint_mode);
}
g_string_append_printf (result_string, "\"%s\"", arg_value->sfa_brush);
break;
case SF_OPTION:

View file

@ -44,7 +44,7 @@
*/
/* FUTURE: delete this after v3 is stable. */
#define DEBUG_CONFIG_PROPERTIES FALSE
#define DEBUG_CONFIG_PROPERTIES TRUE
#if DEBUG_CONFIG_PROPERTIES
static void
@ -59,6 +59,72 @@ dump_properties (GimpProcedureConfig *config)
g_printerr ("%s %s\n", pspecs[i]->name, G_PARAM_SPEC_TYPE_NAME (pspecs[i]));
g_free (pspecs);
}
static gint
get_length (GimpProcedureConfig *config)
{
GParamSpec **pspecs;
guint n_pspecs;
pspecs = g_object_class_list_properties (G_OBJECT_GET_CLASS (config),
&n_pspecs);
g_debug ("length config: %d", n_pspecs);
return n_pspecs;
}
/* Fill a new (length zero) gva with new gvalues (empty but holding the correct type)
from the config.
*/
static void
fill_gva_from (GimpProcedureConfig *config, GimpValueArray * gva)
{
GParamSpec **pspecs;
guint n_pspecs;
pspecs = g_object_class_list_properties (G_OBJECT_GET_CLASS (config),
&n_pspecs);
/* !!! Start at property 1 */
for (guint i = 1; i < n_pspecs; i++)
{
g_debug ("%s %s\n", pspecs[i]->name, G_PARAM_SPEC_TYPE_NAME (pspecs[i]));
/* append empty gvalue */
gimp_value_array_append (gva, NULL);
}
g_free (pspecs);
}
static void
dump_objects (GimpProcedureConfig *config)
{
/* Check it will return non-null objects. */
GimpValueArray *args;
gint length;
/* Need one less gvalue !!! */
args = gimp_value_array_new (get_length (config) - 1);
/* The array still has length zero. */
g_debug ("GVA length: %d", gimp_value_array_length (args));
fill_gva_from (config, args);
gimp_procedure_config_get_values (config, args);
if (args == NULL)
{
g_debug ("config holds no values");
return;
}
length = gimp_value_array_length (args);
for (guint i = 1; i < length; i++)
{
GValue *gvalue = gimp_value_array_index (args, i);
if (G_VALUE_HOLDS_OBJECT (gvalue))
if (g_value_get_object (gvalue) == NULL)
g_debug ("gvalue %d holds NULL object", i);
}
}
#endif
/* Run a dialog for a procedure, then interpret the script.
@ -117,6 +183,10 @@ script_fu_dialog_run (GimpProcedure *procedure,
* Instead, last used values or default values populate the config.
*/
gimp_procedure_config_begin_run (config, NULL, GIMP_RUN_INTERACTIVE, initial_args);
#if DEBUG_CONFIG_PROPERTIES
dump_objects (config);
#endif
/* Create a dialog having properties (describing arguments of the procedure)
* taken from the config.
@ -142,6 +212,11 @@ script_fu_dialog_run (GimpProcedure *procedure,
not_canceled = gimp_procedure_dialog_run (dialog);
/* Assert config holds validated arg values from a user interaction. */
#if DEBUG_CONFIG_PROPERTIES
dump_objects (config);
#endif
if (not_canceled)
{
/* initial_args is declared const.

View file

@ -81,33 +81,15 @@ static void script_fu_file_callback (GtkWidget *widget,
SFFilename *file);
static void script_fu_combo_callback (GtkWidget *widget,
SFOption *option);
static void script_fu_pattern_callback (gpointer data,
const gchar *name,
gint width,
gint height,
gint bytes,
const guchar *mask_data,
gboolean closing);
static void script_fu_gradient_callback (gpointer data,
const gchar *name,
gint width,
const gdouble *mask_data,
gboolean closing);
static void script_fu_font_callback (gpointer data,
const gchar *name,
gboolean closing);
static void script_fu_palette_callback (gpointer data,
const gchar *name,
gboolean closing);
static void script_fu_brush_callback (gpointer data,
const gchar *name,
gdouble opacity,
gint spacing,
GimpLayerMode paint_mode,
gint width,
gint height,
const guchar *mask_data,
static void script_fu_resource_set_handler (gpointer data,
gpointer resource,
gboolean closing);
static GtkWidget * script_fu_resource_widget (const gchar *title,
gchar **id,
GType resource_type);
static void script_fu_flush_events (void);
static void script_fu_activate_main_dialog (void);
@ -481,45 +463,36 @@ script_fu_interface (SFScript *script,
break;
case SF_FONT:
widget = gimp_font_select_button_new (_("Script-Fu Font Selection"),
arg->value.sfa_font);
g_signal_connect_swapped (widget, "font-set",
G_CALLBACK (script_fu_font_callback),
&arg->value.sfa_font);
widget = script_fu_resource_widget (_("Script-Fu Font Selection"),
&arg->value.sfa_font,
GIMP_TYPE_FONT);
break;
case SF_PALETTE:
widget = gimp_palette_select_button_new (_("Script-Fu Palette Selection"),
arg->value.sfa_palette);
g_signal_connect_swapped (widget, "palette-set",
G_CALLBACK (script_fu_palette_callback),
&arg->value.sfa_palette);
widget = script_fu_resource_widget (_("Script-Fu Palette Selection"),
&arg->value.sfa_palette,
GIMP_TYPE_PALETTE);
break;
case SF_PATTERN:
left_align = TRUE;
widget = gimp_pattern_select_button_new (_("Script-Fu Pattern Selection"),
arg->value.sfa_pattern);
g_signal_connect_swapped (widget, "pattern-set",
G_CALLBACK (script_fu_pattern_callback),
&arg->value.sfa_pattern);
widget = script_fu_resource_widget (_("Script-Fu Pattern Selection"),
&arg->value.sfa_pattern,
GIMP_TYPE_PATTERN);
break;
case SF_GRADIENT:
left_align = TRUE;
widget = gimp_gradient_select_button_new (_("Script-Fu Gradient Selection"),
arg->value.sfa_gradient);
g_signal_connect_swapped (widget, "gradient-set",
G_CALLBACK (script_fu_gradient_callback),
&arg->value.sfa_gradient);
widget = script_fu_resource_widget (_("Script-Fu Gradient Selection"),
&arg->value.sfa_gradient,
GIMP_TYPE_GRADIENT);
break;
case SF_BRUSH:
left_align = TRUE;
widget = gimp_brush_select_button_new (_("Script-Fu Brush Selection"), NULL);
g_signal_connect_swapped (widget, "brush-set",
G_CALLBACK (script_fu_brush_callback),
&arg->value.sfa_brush);
widget = script_fu_resource_widget (_("Script-Fu Brush Selection"),
&arg->value.sfa_brush,
GIMP_TYPE_BRUSH);
break;
case SF_OPTION:
@ -618,6 +591,75 @@ script_fu_interface (SFScript *script,
return sf_status;
}
/* Return a widget for choosing a resource.
* Generic on type.
*/
GtkWidget *
script_fu_resource_widget (const gchar *title,
gchar **id_handle,
GType resource_type)
{
GtkWidget *result_widget = NULL;
GimpResource *resource;
/* New resource instance, from string *id_handle. */
resource = g_object_new (resource_type, "id", *id_handle, NULL);
/* If not valid, substitute NULL
* String provided by script author might not name an installed font.
*/
/*
if ( ! gimp_resource_is_valid (resource) )
{
g_object_unref (resource);
resource = NULL;
}
*/
if (resource_type == GIMP_TYPE_FONT)
{
if ( ! gimp_font_is_valid (GIMP_FONT (resource)))
{
g_object_unref (resource);
resource = NULL;
}
result_widget = gimp_font_select_button_new (title, resource);
}
else if (resource_type == GIMP_TYPE_BRUSH)
{
result_widget = gimp_brush_select_button_new (title, resource);
}
else if (resource_type == GIMP_TYPE_GRADIENT)
{
result_widget = gimp_gradient_select_button_new (title, resource);
}
else if (resource_type == GIMP_TYPE_PALETTE)
{
result_widget = gimp_palette_select_button_new (title, resource);
}
else if (resource_type == GIMP_TYPE_PATTERN)
{
result_widget = gimp_pattern_select_button_new (title, resource);
}
else
{
g_warning ("%s: Unhandled resource type", G_STRFUNC);
}
if (result_widget != NULL)
{
/* All resource widgets emit signal resource-set
* Connect to our handler which will be passed the id_handle,
* the place to store the ID of the new choice of resource.
*/
g_signal_connect_swapped (result_widget, "resource-set",
G_CALLBACK (script_fu_resource_set_handler),
id_handle);
}
return result_widget;
}
static void
script_fu_interface_quit (SFScript *script)
{
@ -676,77 +718,26 @@ script_fu_combo_callback (GtkWidget *widget,
option->history = gtk_combo_box_get_active (GTK_COMBO_BOX (widget));
}
/* Handle resource-set signal.
* Store id of newly chosen resource in SF local cache of args.
*
* Note the callback is the same for all resource types.
* The callback passes only the resource, and no attributes of the resource,
* except it's ID.
*/
static void
script_fu_string_update (gchar **dest,
const gchar *src)
{
if (*dest)
g_free (*dest);
*dest = g_strdup (src);
}
static void
script_fu_pattern_callback (gpointer data,
const gchar *name,
gint width,
gint height,
gint bytes,
const guchar *mask_data,
script_fu_resource_set_handler (gpointer data, /* callback "data" */
gpointer resource,
gboolean closing)
{
script_fu_string_update (data, name);
if (closing) script_fu_activate_main_dialog ();
}
gchar **id_handle = data;
static void
script_fu_gradient_callback (gpointer data,
const gchar *name,
gint width,
const gdouble *mask_data,
gboolean closing)
{
script_fu_string_update (data, name);
if (closing) script_fu_activate_main_dialog ();
}
/* Free any existing copy of the id string. */
if (*id_handle)
g_free (*id_handle);
static void
script_fu_font_callback (gpointer data,
const gchar *name,
gboolean closing)
{
script_fu_string_update (data, name);
if (closing) script_fu_activate_main_dialog ();
}
static void
script_fu_palette_callback (gpointer data,
const gchar *name,
gboolean closing)
{
script_fu_string_update (data, name);
if (closing) script_fu_activate_main_dialog ();
}
static void
script_fu_brush_callback (gpointer data,
const gchar *name,
gdouble opacity,
gint spacing,
GimpLayerMode paint_mode,
gint width,
gint height,
const guchar *mask_data,
gboolean closing)
{
SFBrush *brush = data;
g_free (brush->name);
brush->name = g_strdup (name);
brush->opacity = opacity;
brush->spacing = spacing;
brush->paint_mode = paint_mode;
/* We don't own the resource, nor its string. Copy the string. */
*id_handle = g_strdup (gimp_resource_get_id (resource));
if (closing) script_fu_activate_main_dialog ();
}
@ -991,24 +982,34 @@ script_fu_reset (SFScript *script)
value->sfa_file.filename);
break;
/* Reset should get the initial/default value that the plugin author
* declared by name in the SF- declaration.
* Said name is a string stored in the default_value.sfa_font
*
* But this code goes away when ScriptFu uses GimpProcedureDialog.
* Rather than make this temporary code do the correct thing,
* instead simply pass NULL to reset to the value from context.
* It is extremely unlikely that any user depends on or will notice
* this temporaryily slightly changed behavior.
*/
case SF_FONT:
gimp_font_select_button_set_font (GIMP_FONT_SELECT_BUTTON (widget),
value->sfa_font);
NULL);
break;
case SF_PALETTE:
gimp_palette_select_button_set_palette (GIMP_PALETTE_SELECT_BUTTON (widget),
value->sfa_palette);
NULL);
break;
case SF_PATTERN:
gimp_pattern_select_button_set_pattern (GIMP_PATTERN_SELECT_BUTTON (widget),
value->sfa_pattern);
NULL);
break;
case SF_GRADIENT:
gimp_gradient_select_button_set_gradient (GIMP_GRADIENT_SELECT_BUTTON (widget),
value->sfa_gradient);
NULL);
break;
case SF_BRUSH:

View file

@ -332,6 +332,10 @@ script_fu_script_create_formal_args (scheme *sc,
if (!sc->vptr->is_list (sc, a))
return foreign_error (sc, "script-fu-register: brush defaults must be a list", 0);
#ifdef OLD
temporarily, still a list, but use only the name
future: not a list, only a name
brush_list = sc->vptr->pair_car (a);
arg->default_value.sfa_brush.name =
g_strdup (sc->vptr->string_value (sc->vptr->pair_car (brush_list)));
@ -347,6 +351,11 @@ script_fu_script_create_formal_args (scheme *sc,
brush_list = sc->vptr->pair_cdr (brush_list);
arg->default_value.sfa_brush.paint_mode =
sc->vptr->ivalue (sc->vptr->pair_car (brush_list));
#else
brush_list = sc->vptr->pair_car (a);
arg->default_value.sfa_brush =
g_strdup (sc->vptr->string_value (sc->vptr->pair_car (brush_list)));
#endif
}
break;

View file

@ -38,14 +38,6 @@ typedef struct
gchar *filename;
} SFFilename;
typedef struct
{
gchar *name;
gdouble opacity;
gint spacing;
GimpLayerMode paint_mode;
} SFBrush;
typedef struct
{
GSList *list;
@ -75,7 +67,7 @@ typedef union
gchar *sfa_gradient;
gchar *sfa_palette;
gchar *sfa_pattern;
SFBrush sfa_brush;
gchar *sfa_brush;
SFOption sfa_option;
SFEnum sfa_enum;
} SFArgValue;
@ -106,7 +98,7 @@ typedef struct
typedef struct
{
SFScript *script; // script which defined this menu path and label
SFScript *script; /* script which defined this menu path and label */
gchar *menu_path;
} SFMenu;

View file

@ -24,7 +24,7 @@
(define (script-fu-make-cmap-array palette)
(let* (
(num-colors (car (gimp-palette-get-info palette)))
(num-colors (car (gimp-palette-get-color-count palette)))
(cmap (cons-array (* num-colors 3) 'byte))
(color 0)
(i 0)
@ -44,7 +44,7 @@
(define (script-fu-set-cmap img drawable palette)
(gimp-image-set-colormap img
(* (car (gimp-palette-get-info palette)) 3)
(* (car (gimp-palette-get-color-count palette)) 3)
(script-fu-make-cmap-array palette))
(gimp-displays-flush)
)