mirror of https://github.com/GNOME/gimp.git
231 lines
7.6 KiB
C
231 lines
7.6 KiB
C
/* GIMP - The GNU Image Manipulation Program
|
|
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
|
*
|
|
* Copyright (C) 2024 Lloyd Konneker
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include <libgimp/gimpui.h>
|
|
|
|
#include "script-fu-types.h"
|
|
#include "script-fu-widgets-custom.h"
|
|
|
|
/* Widgets in GimpProcedureDialog *custom* to ScriptFu.
|
|
*
|
|
* GimpProcedureDialog provides stock widgets
|
|
* based on the type of a procedure argument.
|
|
* A custom widget is the same kind of widget as stock, but specialized.
|
|
*
|
|
* Both stock and custom widgets are keyed to a property name
|
|
* of the GimpProcedure for the script.
|
|
* You add custom widgets, then call gimp_procedure_dialog_fill_list()
|
|
* which adds a stock widget for any property name not having a custom widget.
|
|
*
|
|
* FUTURE: implement these in GimpProcedureDialog.
|
|
* That can't be done now because GParamSpecs are limited
|
|
* in the types they can describe.
|
|
* E.G. SF-OPTION describes an enumerated type
|
|
* that can't be described completely in a GParamSpec.
|
|
* E.G. property type GFile is a general type
|
|
* whose subtypes: existing-file, existing-dir, or file-to-save
|
|
* can't be described in a GParamSpec.
|
|
*
|
|
* Most SFArg types are supported by stock widgets.
|
|
*
|
|
* SF-FILENAME is stock.
|
|
* For property of type G_TYPE_FILE.
|
|
* A GtkFileChooser in the mode for user to open a existing file.
|
|
*
|
|
* SF-DIRNAME is custom.
|
|
* Also a GtkFileChooser but in mode for user to choose a directory.
|
|
*
|
|
* FUTURE:
|
|
* SF-SAVE-FILENAME is custom.
|
|
* Also a GtkFileChooser but in mode for user to save a file
|
|
* (choose a file to replace, or enter filename and choose a directory.)
|
|
*
|
|
* SF-OPTION is custom.
|
|
* Is an int combo box widget, for an enumeration defined by the script
|
|
* (versus SF-ENUM for enums defined by GIMP.)
|
|
* Note SF-OPTION does not create symbols in the interpreter.
|
|
* The script itself, and all other plugins, must use integer literals
|
|
* to denote values.
|
|
*
|
|
* SF-ADJUSTMENT:SF-SLIDER is custom.
|
|
* Default widget for propety of type DOUBLE is an entry w/ spinner.
|
|
* Override with a slider w/ spinner.
|
|
*/
|
|
|
|
/* Does SFArg type need custom widget? */
|
|
static gboolean
|
|
sf_arg_type_is_custom (SFScript *script,
|
|
guint arg_index)
|
|
{
|
|
gboolean result=FALSE;
|
|
|
|
switch (script->args[arg_index].type)
|
|
{
|
|
case SF_DIRNAME:
|
|
case SF_OPTION:
|
|
result = TRUE;
|
|
break;
|
|
case SF_ADJUSTMENT:
|
|
if (script->args[arg_index].default_value.sfa_adjustment.type == SF_SLIDER)
|
|
result = TRUE;
|
|
break;
|
|
default:
|
|
result = FALSE;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/* Returns new GtkListStore from SFArg declaration.
|
|
* Transfers ownership of the allocated, returned store.
|
|
* Ownership transfers to a dialog, which frees it on dialog destroy.
|
|
*
|
|
* Returned value is never NULL.
|
|
* Returned store can be empty if the declaration of the arg is non-sensical.
|
|
*/
|
|
static GtkListStore *
|
|
sf_widget_custom_new_int_store (SFArg *arg)
|
|
{
|
|
GtkListStore *result;
|
|
GSList *list;
|
|
guint counter = 0; /* SF enumerations start at 0. */
|
|
|
|
/* Create empty store. */
|
|
result = g_object_new (GIMP_TYPE_INT_STORE, NULL);
|
|
|
|
/* Iterate over list of names of enumerated values,
|
|
* appending each to store having value equal to the iteration index.
|
|
*
|
|
* ScriptFu does NOT define constant Scheme symbols in the interpreter;
|
|
* the names of enumerated values are not available to the script,
|
|
* which must use integer literals or (define other symbols for the values.)
|
|
*/
|
|
for (list = arg->default_value.sfa_option.list;
|
|
list;
|
|
list = g_slist_next (list))
|
|
{
|
|
GtkTreeIter iter;
|
|
|
|
gtk_list_store_append (result, &iter);
|
|
gtk_list_store_set (result, &iter,
|
|
GIMP_INT_STORE_VALUE, counter,
|
|
GIMP_INT_STORE_LABEL, list->data,
|
|
-1);
|
|
counter++;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/* Adds widget for arg of type SF-OPTION to the dialog.
|
|
* Widget is a combobox widget.
|
|
* Specializes the widget by a custom store i.e. model
|
|
* derived from the arg's declaration.
|
|
*/
|
|
static void
|
|
sf_widget_custom_option (GimpProcedureDialog *dialog,
|
|
SFArg *arg)
|
|
{
|
|
GtkListStore *store;
|
|
|
|
store = sf_widget_custom_new_int_store (arg);
|
|
gimp_procedure_dialog_get_int_combo (dialog,
|
|
arg->property_name,
|
|
GIMP_INT_STORE (store));
|
|
}
|
|
|
|
/* Adds widget for arg of type SF-DIRNAME to the dialog.
|
|
* Widget is a GtkFileChooserButton.
|
|
* Specializes the widget to be in mode for user to choose a directory.
|
|
*
|
|
* Note that this is implemented by gtk_file_chooser_button,
|
|
* which does not support ACTION_SAVE, and which becomes obsolete in Gtk4.
|
|
* Thus, we don't have SF-SAVE-FILENAME.
|
|
* To offer save, a script must use two widgets:
|
|
* SF-STRING for user to name a file to save,
|
|
* and SF-DIRNAME for user to choose directory to save to.
|
|
*/
|
|
static void
|
|
sf_widget_custom_dirname (GimpProcedureDialog *dialog,
|
|
SFArg *arg)
|
|
{
|
|
gimp_procedure_dialog_get_file_chooser (dialog,
|
|
arg->property_name,
|
|
GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER);
|
|
}
|
|
|
|
/* Adds widget for arg of type SF-ADJUSTMENT:SF_SLIDER to the dialog.
|
|
* Specializes the widget: slider instead of entry, and a spinner
|
|
*/
|
|
static void
|
|
sf_widget_custom_slider (GimpProcedureDialog *dialog,
|
|
SFArg *arg)
|
|
{
|
|
/* Widget belongs to dialog, discard the returned ref. */
|
|
(void) gimp_procedure_dialog_get_widget (dialog,
|
|
arg->property_name,
|
|
GIMP_TYPE_SCALE_ENTRY);
|
|
}
|
|
|
|
/* Add a custom widget for a script's arg to the script's dialog.
|
|
* Does nothing when the type of the arg does not need a custom widget.
|
|
*
|
|
* Widget is associated with the arg's property, by name of the property.
|
|
* The arg's property is a property of the Procedure.
|
|
* The widget will be positioned in the dialog by order of property.
|
|
*/
|
|
static void
|
|
sf_widget_custom_add_to_dialog (GimpProcedureDialog *dialog,
|
|
SFArg *arg)
|
|
{
|
|
/* Handles same cases as sf_arg_type_is_custom() */
|
|
switch (arg->type)
|
|
{
|
|
case SF_OPTION:
|
|
sf_widget_custom_option (dialog, arg);
|
|
break;
|
|
case SF_DIRNAME:
|
|
sf_widget_custom_dirname (dialog, arg);
|
|
break;
|
|
case SF_ADJUSTMENT:
|
|
/* We already know sfa_adjustment.type == SF_SLIDER. */
|
|
sf_widget_custom_slider (dialog, arg);
|
|
break;
|
|
default:
|
|
g_warning ("%s Unhandled custom widget type.", G_STRFUNC);
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
/* Add custom widgets to dialog, for certain type of args of script. */
|
|
void
|
|
script_fu_widgets_custom_add (GimpProcedureDialog *dialog,
|
|
SFScript *script)
|
|
{
|
|
for (int arg_index=0; arg_index < script->n_args; arg_index++)
|
|
{
|
|
if (sf_arg_type_is_custom (script, arg_index))
|
|
{
|
|
sf_widget_custom_add_to_dialog (dialog, &script->args[arg_index]);
|
|
}
|
|
}
|
|
}
|