ScriptFu: add Scheme language function script-fu-register-regular
Building on prior commits, with a few small fixes to them. First demonstrable changes towards #12605. Font map plugin is ported as a test case. Old-style plugins using script-fu-register still work.
This commit is contained in:

committed by
Lloyd Konneker

parent
d361256977
commit
d0a6c4c758
@ -77,6 +77,8 @@ static pointer script_fu_register_call (scheme *sc,
|
||||
pointer a);
|
||||
static pointer script_fu_register_call_filter (scheme *sc,
|
||||
pointer a);
|
||||
static pointer script_fu_register_call_regular (scheme *sc,
|
||||
pointer a);
|
||||
static pointer script_fu_menu_register_call (scheme *sc,
|
||||
pointer a);
|
||||
static pointer script_fu_use_v3_call (scheme *sc,
|
||||
@ -571,12 +573,14 @@ ts_define_procedure (sc, "load-extension", scm_load_ext);
|
||||
{
|
||||
ts_define_procedure (sc, "script-fu-register", script_fu_register_call);
|
||||
ts_define_procedure (sc, "script-fu-register-filter", script_fu_register_call_filter);
|
||||
ts_define_procedure (sc, "script-fu-register-regular", script_fu_register_call_regular);
|
||||
ts_define_procedure (sc, "script-fu-menu-register", script_fu_menu_register_call);
|
||||
}
|
||||
else
|
||||
{
|
||||
ts_define_procedure (sc, "script-fu-register", script_fu_nil_call);
|
||||
ts_define_procedure (sc, "script-fu-register-filter", script_fu_nil_call);
|
||||
ts_define_procedure (sc, "script-fu-register-regular", script_fu_nil_call);
|
||||
ts_define_procedure (sc, "script-fu-menu-register", script_fu_nil_call);
|
||||
}
|
||||
|
||||
@ -1484,6 +1488,13 @@ script_fu_register_call_filter (scheme *sc,
|
||||
return script_fu_add_script_filter (sc, a);
|
||||
}
|
||||
|
||||
static pointer
|
||||
script_fu_register_call_regular (scheme *sc,
|
||||
pointer a)
|
||||
{
|
||||
return script_fu_add_script_regular (sc, a);
|
||||
}
|
||||
|
||||
static pointer
|
||||
script_fu_menu_register_call (scheme *sc,
|
||||
pointer a)
|
||||
|
@ -142,10 +142,30 @@ sf_dialog_can_be_run (GimpProcedure *procedure,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Omit leading "procedure" and "run-mode" properties.
|
||||
* Caller must free the list.
|
||||
*/
|
||||
static GList*
|
||||
sf_get_suffix_of_config_prop_names (GimpProcedureConfig *config)
|
||||
{
|
||||
guint n_specs;
|
||||
GParamSpec ** pspecs = g_object_class_list_properties (G_OBJECT_GET_CLASS (config), &n_specs);
|
||||
GList *property_names = NULL;
|
||||
|
||||
for (guint i=2; i<n_specs; i++)
|
||||
property_names = g_list_append (property_names, (void*) g_param_spec_get_name (pspecs[i]));
|
||||
|
||||
g_free (pspecs);
|
||||
return property_names;
|
||||
}
|
||||
|
||||
/* Create and run a dialog for a procedure.
|
||||
* Returns true when not canceled.
|
||||
* Side effects on config.
|
||||
*
|
||||
* When should_skip_runmode, the config has a run-mode property
|
||||
* the dialog does not show.
|
||||
*
|
||||
* Procedure may be GimpImageProcedure or ordinary GimpProcedure.
|
||||
*
|
||||
* Requires gimp_ui_init already called.
|
||||
@ -153,7 +173,8 @@ sf_dialog_can_be_run (GimpProcedure *procedure,
|
||||
static gboolean
|
||||
sf_dialog_run (GimpProcedure *procedure,
|
||||
SFScript *script,
|
||||
GimpProcedureConfig *config)
|
||||
GimpProcedureConfig *config,
|
||||
gboolean should_skip_runmode)
|
||||
{
|
||||
GimpProcedureDialog *dialog = NULL;
|
||||
gboolean not_canceled;
|
||||
@ -178,10 +199,19 @@ sf_dialog_run (GimpProcedure *procedure,
|
||||
/* Create custom widget where the stock widget is not adequate. */
|
||||
script_fu_widgets_custom_add (dialog, script);
|
||||
|
||||
/* NULL means create widgets for all properties of the procedure
|
||||
* that we have not already created custom widgets for.
|
||||
*/
|
||||
gimp_procedure_dialog_fill_list (dialog, NULL);
|
||||
/* Create widgets for all properties of the procedure not already created. */
|
||||
if (should_skip_runmode)
|
||||
{
|
||||
GList *property_names = sf_get_suffix_of_config_prop_names (config);
|
||||
|
||||
gimp_procedure_dialog_fill_list (dialog, property_names);
|
||||
g_list_free (property_names);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* NULL means: all properties. */
|
||||
gimp_procedure_dialog_fill_list (dialog, NULL);
|
||||
}
|
||||
|
||||
not_canceled = gimp_procedure_dialog_run (dialog);
|
||||
|
||||
@ -214,7 +244,7 @@ script_fu_dialog_run_image_proc (
|
||||
if (! sf_dialog_can_be_run (procedure, script, config))
|
||||
return gimp_procedure_new_return_values (procedure, GIMP_PDB_EXECUTION_ERROR, NULL);
|
||||
|
||||
not_canceled = sf_dialog_run (procedure, script, config);
|
||||
not_canceled = sf_dialog_run (procedure, script, config, FALSE);
|
||||
/* Assert config holds validated arg values from a user interaction. */
|
||||
|
||||
if (not_canceled)
|
||||
@ -227,7 +257,7 @@ script_fu_dialog_run_image_proc (
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Run a dialog for an Procedure, then interpret the script. */
|
||||
/* Run a dialog for a generic GimpProcedure, then interpret the script. */
|
||||
GimpValueArray*
|
||||
script_fu_dialog_run_regular_proc (GimpProcedure *procedure,
|
||||
SFScript *script,
|
||||
@ -240,7 +270,8 @@ script_fu_dialog_run_regular_proc (GimpProcedure *procedure,
|
||||
if (! sf_dialog_can_be_run (procedure, script, config))
|
||||
return gimp_procedure_new_return_values (procedure, GIMP_PDB_EXECUTION_ERROR, NULL);
|
||||
|
||||
not_canceled = sf_dialog_run (procedure, script, config);
|
||||
not_canceled = sf_dialog_run (procedure, script, config,
|
||||
TRUE); /* skip run-mode prop of config. */
|
||||
/* Assert config holds validated arg values from a user interaction. */
|
||||
|
||||
if (not_canceled)
|
||||
|
@ -119,6 +119,78 @@ script_fu_script_new_from_metadata_args (scheme *sc,
|
||||
return script;
|
||||
}
|
||||
|
||||
/* Traverse Scheme argument list
|
||||
* creating a new SFScript with metadata, but empty SFArgs (formal arg specs)
|
||||
*
|
||||
* Takes a handle to a pointer into the argument list.
|
||||
* Advances the pointer past the metadata args.
|
||||
*
|
||||
* Returns new SFScript.
|
||||
*
|
||||
* For a script declaring using script-fu-register-regular,
|
||||
* declared without image_type or drawable_arity.
|
||||
*/
|
||||
SFScript*
|
||||
script_fu_script_new_from_metadata_regular (scheme *sc,
|
||||
pointer *handle)
|
||||
{
|
||||
SFScript *script;
|
||||
const gchar *name;
|
||||
const gchar *menu_label;
|
||||
const gchar *blurb;
|
||||
const gchar *author;
|
||||
const gchar *copyright;
|
||||
const gchar *date;
|
||||
const gchar *image_types;
|
||||
guint n_args;
|
||||
|
||||
/* dereference handle into local pointer. */
|
||||
pointer a = *handle;
|
||||
|
||||
g_debug ("script_fu_script_new_from_metadata_args");
|
||||
|
||||
/* Require list_length starting at a is >= 5
|
||||
* else strange parsing errors at plugin query time.
|
||||
*/
|
||||
|
||||
name = sc->vptr->string_value (sc->vptr->pair_car (a));
|
||||
a = sc->vptr->pair_cdr (a);
|
||||
menu_label = sc->vptr->string_value (sc->vptr->pair_car (a));
|
||||
a = sc->vptr->pair_cdr (a);
|
||||
blurb = sc->vptr->string_value (sc->vptr->pair_car (a));
|
||||
a = sc->vptr->pair_cdr (a);
|
||||
author = sc->vptr->string_value (sc->vptr->pair_car (a));
|
||||
a = sc->vptr->pair_cdr (a);
|
||||
/* Copyright is same as author.
|
||||
* script-fu-register-regular does not require declaring copyright owner
|
||||
* separately from the author.
|
||||
*/
|
||||
copyright = author;
|
||||
date = sc->vptr->string_value (sc->vptr->pair_car (a));
|
||||
a = sc->vptr->pair_cdr (a);
|
||||
|
||||
/* Image types not used for regular procedures. */
|
||||
image_types = NULL;
|
||||
|
||||
/* Store local, advanced pointer at handle from caller. */
|
||||
*handle = a;
|
||||
|
||||
/* Calculate supplied number of formal arguments of the PDB procedure,
|
||||
* each takes three actual args from Scheme call.
|
||||
*/
|
||||
n_args = sc->vptr->list_length (sc, a) / 3;
|
||||
|
||||
/* This allocates empty array of SFArg. Hereafter, script knows its n_args. */
|
||||
script = script_fu_script_new (name,
|
||||
menu_label,
|
||||
blurb,
|
||||
author,
|
||||
copyright,
|
||||
date,
|
||||
image_types,
|
||||
n_args);
|
||||
return script;
|
||||
}
|
||||
|
||||
/* GimpResource
|
||||
*
|
||||
|
@ -23,6 +23,9 @@ pointer script_fu_script_create_formal_args (scheme *sc,
|
||||
SFScript *script);
|
||||
SFScript *script_fu_script_new_from_metadata_args (scheme *sc,
|
||||
pointer *handle);
|
||||
SFScript *script_fu_script_new_from_metadata_regular
|
||||
(scheme *sc,
|
||||
pointer *handle);
|
||||
pointer script_fu_script_parse_drawable_arity_arg (scheme *sc,
|
||||
pointer *handle,
|
||||
SFScript *script);
|
||||
|
@ -144,20 +144,23 @@ script_fu_run_image_procedure (GimpProcedure *procedure, /* GimpImageProc
|
||||
*/
|
||||
GimpValueArray *
|
||||
script_fu_run_regular_procedure (GimpProcedure *procedure,
|
||||
GimpRunMode run_mode,
|
||||
GimpProcedureConfig *config,
|
||||
gpointer data)
|
||||
{
|
||||
|
||||
GimpValueArray *result = NULL;
|
||||
SFScript *script;
|
||||
GimpRunMode run_mode;
|
||||
|
||||
g_debug ("%s", G_STRFUNC);
|
||||
|
||||
g_debug ("script_fu_run_regular_procedure");
|
||||
script = script_fu_find_script (gimp_procedure_get_name (procedure));
|
||||
|
||||
if (! script)
|
||||
return gimp_procedure_new_return_values (procedure, GIMP_PDB_CALLING_ERROR, NULL);
|
||||
|
||||
/* Unlike ImageProcedure, run-mode is a prop in the config. */
|
||||
g_object_get (config, "run-mode", &run_mode, NULL);
|
||||
ts_set_run_mode (run_mode);
|
||||
|
||||
/* Need Gegl. Also inits ui, needed when mode is interactive. */
|
||||
|
@ -31,7 +31,6 @@ GimpValueArray *script_fu_run_image_procedure (GimpProcedure *procedure,
|
||||
gpointer data);
|
||||
GimpValueArray *script_fu_run_regular_procedure (
|
||||
GimpProcedure *procedure,
|
||||
GimpRunMode run_mode,
|
||||
GimpProcedureConfig *config,
|
||||
gpointer data);
|
||||
|
||||
|
@ -157,8 +157,7 @@ script_fu_script_create_PDB_procedure (GimpPlugIn *plug_in,
|
||||
|
||||
if (script->proc_class == GIMP_TYPE_IMAGE_PROCEDURE)
|
||||
{
|
||||
g_debug ("script_fu_script_create_PDB_procedure: %s, plugin type %i, image_proc",
|
||||
script->name, plug_in_type);
|
||||
g_debug ("%s: %s, plugin type %i, image_proc", G_STRFUNC, script->name, plug_in_type);
|
||||
|
||||
procedure = gimp_image_procedure_new (plug_in, script->name,
|
||||
plug_in_type,
|
||||
@ -176,34 +175,67 @@ script_fu_script_create_PDB_procedure (GimpPlugIn *plug_in,
|
||||
*/
|
||||
script_fu_script_set_proc_args (procedure, script, 0);
|
||||
|
||||
/* The script declared arity, convey to GIMP. */
|
||||
script_fu_script_set_drawable_sensitivity (procedure, script);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Script declares a GimpProcedure.
|
||||
* Dispatch on which scheme function the script registered with.
|
||||
*
|
||||
* v2 had only script-fu-register.
|
||||
* For compatibility, we still support it,
|
||||
*/
|
||||
g_assert (script->proc_class == GIMP_TYPE_PROCEDURE);
|
||||
g_debug ("script_fu_script_create_PDB_procedure: %s, plugin type %i, ordinary proc",
|
||||
script->name, plug_in_type);
|
||||
|
||||
procedure = gimp_procedure_new (plug_in, script->name,
|
||||
plug_in_type,
|
||||
script_fu_run_procedure,
|
||||
script, NULL);
|
||||
if (script_fu_script_get_is_old_style (script))
|
||||
{
|
||||
g_debug ("%s: %s, plugin type %i, old-style", G_STRFUNC, script->name, plug_in_type);
|
||||
|
||||
script_fu_script_set_proc_metadata (procedure, script);
|
||||
procedure = gimp_procedure_new (plug_in, script->name,
|
||||
plug_in_type,
|
||||
script_fu_run_procedure, /* old-style */
|
||||
script, NULL);
|
||||
|
||||
gimp_procedure_add_enum_argument (procedure, "run-mode",
|
||||
"Run mode", "The run mode",
|
||||
GIMP_TYPE_RUN_MODE,
|
||||
GIMP_RUN_INTERACTIVE,
|
||||
G_PARAM_READWRITE);
|
||||
script_fu_script_set_proc_metadata (procedure, script);
|
||||
|
||||
script_fu_script_set_proc_args (procedure, script, 0);
|
||||
gimp_procedure_add_enum_argument (procedure, "run-mode",
|
||||
"Run mode", "The run mode",
|
||||
GIMP_TYPE_RUN_MODE,
|
||||
GIMP_RUN_INTERACTIVE,
|
||||
G_PARAM_READWRITE);
|
||||
|
||||
/* !!! Author did not declare drawable arity, it was inferred. */
|
||||
script_fu_script_set_drawable_sensitivity (procedure, script);
|
||||
script_fu_script_set_proc_args (procedure, script, 0);
|
||||
|
||||
/* !!! Author did not declare drawable arity, it was inferred. */
|
||||
script_fu_script_set_drawable_sensitivity (procedure, script);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_debug ("%s: %s, plugin type %i, old-style", G_STRFUNC, script->name, plug_in_type);
|
||||
|
||||
procedure = gimp_procedure_new (plug_in, script->name,
|
||||
plug_in_type,
|
||||
script_fu_run_regular_procedure, /* new-style */
|
||||
script, NULL);
|
||||
|
||||
script_fu_script_set_proc_metadata (procedure, script);
|
||||
|
||||
gimp_procedure_add_enum_argument (procedure, "run-mode",
|
||||
"Run mode", "The run mode",
|
||||
GIMP_TYPE_RUN_MODE,
|
||||
GIMP_RUN_INTERACTIVE,
|
||||
G_PARAM_READWRITE);
|
||||
|
||||
script_fu_script_set_proc_args (procedure, script, 0);
|
||||
|
||||
/* The script did not declare arity.
|
||||
* new-style regular procedure always arity SF_NO_DRAWABLE.
|
||||
* This conveys to GIMP.
|
||||
*/
|
||||
script_fu_script_set_drawable_sensitivity (procedure, script);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return procedure;
|
||||
}
|
||||
|
||||
@ -458,6 +490,11 @@ script_fu_script_get_command_for_image_proc (SFScript *script,
|
||||
return g_string_free (s, FALSE);
|
||||
}
|
||||
|
||||
/* The difference between count of config properties and count of script args.
|
||||
* config will have 2 extra, leading property: "procedure" and "run_mode".
|
||||
*/
|
||||
#define SF_ARGS_TO_CONFIG_OFFSET 2
|
||||
|
||||
gchar *
|
||||
script_fu_script_get_command_for_regular_proc (SFScript *script,
|
||||
GimpProcedureConfig *config)
|
||||
@ -476,13 +513,12 @@ script_fu_script_get_command_for_regular_proc (SFScript *script,
|
||||
/* The command has no run mode. */
|
||||
|
||||
/* config contains the "other" args
|
||||
* Iterate over the GimpValueArray.
|
||||
* Iterate over the GimpValueArray, starting at an offset.
|
||||
* But script->args should be the same length, and types should match.
|
||||
*/
|
||||
pspecs = g_object_class_list_properties (G_OBJECT_GET_CLASS (config), &n_pspecs);
|
||||
|
||||
/* config will have 1 additional property: "procedure". */
|
||||
for (i = 1; i < n_pspecs; i++)
|
||||
for (i = SF_ARGS_TO_CONFIG_OFFSET; i < n_pspecs; i++)
|
||||
{
|
||||
GParamSpec *pspec = pspecs[i];
|
||||
GValue value = G_VALUE_INIT;
|
||||
@ -491,7 +527,8 @@ script_fu_script_get_command_for_regular_proc (SFScript *script,
|
||||
|
||||
g_value_init (&value, pspec->value_type);
|
||||
g_object_get_property (G_OBJECT (config), pspec->name, &value);
|
||||
script_fu_arg_append_repr_from_gvalue (&script->args[i - 1], s, &value);
|
||||
script_fu_arg_append_repr_from_gvalue (&script->args[i - SF_ARGS_TO_CONFIG_OFFSET],
|
||||
s, &value);
|
||||
g_value_unset (&value);
|
||||
}
|
||||
|
||||
@ -686,3 +723,25 @@ script_fu_script_set_drawable_sensitivity (GimpProcedure *procedure, SFScript *s
|
||||
g_warning ("Unhandled case for SFDrawableArity");
|
||||
}
|
||||
}
|
||||
|
||||
/* Set drawable arity of script to NONE, meaning a regular procedure,
|
||||
* always enabled (sensitive)
|
||||
*/
|
||||
void
|
||||
script_fu_script_set_drawable_arity_none (SFScript *script)
|
||||
{
|
||||
script->drawable_arity = SF_NO_DRAWABLE;
|
||||
}
|
||||
|
||||
/* Only settable, never cleared, defaults to false. */
|
||||
void
|
||||
script_fu_script_set_is_old_style (SFScript *script)
|
||||
{
|
||||
script->is_old_style = TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
script_fu_script_get_is_old_style (SFScript *script)
|
||||
{
|
||||
return script->is_old_style;
|
||||
}
|
@ -61,6 +61,9 @@ GimpProcedure * script_fu_script_create_PDB_procedure (GimpPlugIn *plug_
|
||||
SFScript *script,
|
||||
GimpPDBProcType plug_in_type);
|
||||
|
||||
void script_fu_script_infer_drawable_arity (SFScript *script);
|
||||
void script_fu_script_infer_drawable_arity (SFScript *script);
|
||||
void script_fu_script_set_drawable_arity_none (SFScript *script);
|
||||
void script_fu_script_set_is_old_style (SFScript *script);
|
||||
gboolean script_fu_script_get_is_old_style (SFScript *script);
|
||||
|
||||
#endif /* __SCRIPT_FU_SCRIPT__ */
|
||||
|
@ -197,6 +197,8 @@ script_fu_add_script (scheme *sc,
|
||||
|
||||
script->proc_class = GIMP_TYPE_PROCEDURE;
|
||||
|
||||
script_fu_script_set_is_old_style (script);
|
||||
|
||||
script_fu_try_map_menu (script);
|
||||
script_fu_append_script_to_tree (script);
|
||||
return sc->NIL;
|
||||
@ -249,6 +251,45 @@ script_fu_add_script_filter (scheme *sc,
|
||||
return sc->NIL;
|
||||
}
|
||||
|
||||
/* For a script's call to script-fu-register-regular.
|
||||
* Traverse Scheme argument list creating a new SFScript
|
||||
* whose drawable_arity is SF_NO_DRAWABLE
|
||||
*
|
||||
* Return NIL or a foreign_error
|
||||
*/
|
||||
pointer
|
||||
script_fu_add_script_regular (scheme *sc,
|
||||
pointer a)
|
||||
{
|
||||
SFScript *script;
|
||||
pointer args_error; /* a foreign_error or NIL. */
|
||||
|
||||
/* Check metadata args args are present.
|
||||
* Has two less arg than script-fu-register.
|
||||
* Last metadata arg is "copyright date"
|
||||
*/
|
||||
if (sc->vptr->list_length (sc, a) < 5)
|
||||
return foreign_error (sc, "script-fu-register-filter: Not enough arguments", 0);
|
||||
|
||||
/* pass handle i.e. "&a" ("a" of type "pointer" is on the stack) */
|
||||
script = script_fu_script_new_from_metadata_regular (sc, &a);
|
||||
|
||||
script_fu_script_set_drawable_arity_none (script);
|
||||
|
||||
/* Parse the args to this function that are formal declarations of
|
||||
* the args to the PDB procedure being defined.
|
||||
*/
|
||||
args_error = script_fu_script_create_formal_args (sc, &a, script);
|
||||
if (args_error != sc->NIL)
|
||||
return args_error;
|
||||
|
||||
script->proc_class = GIMP_TYPE_PROCEDURE;
|
||||
|
||||
script_fu_try_map_menu (script);
|
||||
script_fu_append_script_to_tree (script);
|
||||
return sc->NIL;
|
||||
}
|
||||
|
||||
pointer
|
||||
script_fu_add_menu (scheme *sc,
|
||||
pointer a)
|
||||
|
@ -24,6 +24,8 @@ pointer script_fu_add_script (scheme *sc,
|
||||
pointer a);
|
||||
pointer script_fu_add_script_filter (scheme *sc,
|
||||
pointer a);
|
||||
pointer script_fu_add_script_regular (scheme *sc,
|
||||
pointer a);
|
||||
pointer script_fu_add_menu (scheme *sc,
|
||||
pointer a);
|
||||
|
||||
|
@ -93,6 +93,8 @@ typedef struct
|
||||
SFArg *args;
|
||||
SFDrawableArity drawable_arity;
|
||||
GType proc_class; /* GimpProcedure or GimpImageProcedure. */
|
||||
/* is declared using script-fu-register and dialog is old-style. */
|
||||
gboolean is_old_style;
|
||||
} SFScript;
|
||||
|
||||
/* ScriptFu keeps array of SFArg, it's private arg specs.
|
||||
|
@ -163,13 +163,11 @@
|
||||
)
|
||||
)
|
||||
|
||||
(script-fu-register "script-fu-font-map"
|
||||
(script-fu-register-regular "script-fu-font-map"
|
||||
_"Render _Font Map..."
|
||||
_"Create an image filled with previews of fonts matching a fontname filter"
|
||||
"Spencer Kimball"
|
||||
"Spencer Kimball"
|
||||
"1997"
|
||||
""
|
||||
SF-STRING _"_Text" "How quickly daft jumping zebras vex."
|
||||
SF-TOGGLE _"Use font _name as text" FALSE
|
||||
SF-TOGGLE _"_Labels" TRUE
|
||||
|
Reference in New Issue
Block a user