libgimpbase: new GimpChoice class meant to represent a list of allowed values.

This will be used for creating limited lists of strings as argument types for
procedures.
Ideally enums are the best type for this, but it can only be used for generic
libgimp* enum types, not custom enums created only for a given plug-in. For
this, we currently just demote the args to ints which lose any semantic. A
limited list of string will give back some semantic and some better validation,
even though it's a tiny bit more annoying to work with strings than int types
(at least in C).
This commit is contained in:
Jehan 2023-08-03 00:20:10 +02:00
parent 29ce8f234f
commit 7e6b01a4e5
4 changed files with 420 additions and 0 deletions

View file

@ -17,6 +17,16 @@ EXPORTS
gimp_check_size_get_type
gimp_check_type_get_type
gimp_checks_get_colors
gimp_choice_add
gimp_choice_get_documentation
gimp_choice_get_help
gimp_choice_get_id
gimp_choice_get_label
gimp_choice_get_type
gimp_choice_is_valid
gimp_choice_list_nicks
gimp_choice_new
gimp_choice_new_with_values
gimp_clone_type_get_type
gimp_color_tag_get_type
gimp_component_type_get_type

340
libgimpbase/gimpchoice.c Normal file
View file

@ -0,0 +1,340 @@
/* LIBGIMP - The GIMP Library
* Copyright (C) 1995-2000 Peter Mattis and Spencer Kimball
*
* gimpchoice.c
*
* This library is free software: you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see
* <https://www.gnu.org/licenses/>.
*/
#include "config.h"
#include <glib-object.h>
#include "gimpbasetypes.h"
#include "gimpchoice.h"
#include "gimpparamspecs.h"
typedef struct _GimpChoiceDesc
{
gchar *label;
gchar *help;
gint id;
} GimpChoiceDesc;
struct _GimpChoice
{
GObject parent_instance;
GHashTable *choices;
GList *keys;
};
static void gimp_choice_finalize (GObject *object);
static void gimp_choice_desc_free (GimpChoiceDesc *desc);
G_DEFINE_TYPE (GimpChoice, gimp_choice, G_TYPE_OBJECT)
#define parent_class gimp_choice_parent_class
static void
gimp_choice_class_init (GimpChoiceClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = gimp_choice_finalize;
}
static void
gimp_choice_init (GimpChoice *choice)
{
choice->choices = g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
(GDestroyNotify) gimp_choice_desc_free);
}
static void
gimp_choice_finalize (GObject *object)
{
GimpChoice *choice = GIMP_CHOICE (object);
g_hash_table_unref (choice->choices);
g_list_free_full (choice->keys, (GDestroyNotify) g_free);
}
/* Public API */
/**
* gimp_choice_new:
*
* Returns: (transfer full): a #GimpChoice.
*
* Since: 3.0
**/
GimpChoice *
gimp_choice_new (void)
{
GimpChoice *choice;
choice = g_object_new (GIMP_TYPE_CHOICE, NULL);
return choice;
}
/**
* gimp_choice_new_with_values:
* @nick: the first value.
* @id: integer ID for @nick.
* @label: the label of @nick.
* @help: longer help text for @nick.
* ...: more triplets of string to pre-fill the created %GimpChoice.
*
* Returns: (transfer full): a #GimpChoice.
*
* Since: 3.0
**/
GimpChoice *
gimp_choice_new_with_values (const gchar *nick,
gint id,
const gchar *label,
const gchar *help,
...)
{
GimpChoice *choice;
va_list va_args;
g_return_val_if_fail (nick != NULL, NULL);
g_return_val_if_fail (label != NULL, NULL);
choice = gimp_choice_new ();
va_start (va_args, help);
do
{
gimp_choice_add (choice, nick, id, label, help);
nick = va_arg (va_args, const gchar *);
if (nick == NULL)
break;
id = va_arg (va_args, gint);
label = va_arg (va_args, const gchar *);
if (label == NULL)
{
g_critical ("%s: nick '%s' cannot have a NULL label.", G_STRFUNC, nick);
break;
}
help = va_arg (va_args, const gchar *);
}
while (TRUE);
va_end (va_args);
return choice;
}
/**
* gimp_choice_add:
* @choice: the %GimpChoice.
* @nick: the nick of @choice.
* @id: optional integer ID for @nick.
* @label: the label of @choice.
* @help: optional longer help text for @nick.
*
* This procedure adds a new possible value to @choice list of values.
* The @id is an optional integer identifier. This can be useful for instance
* when you want to work with different enum values mapped to each @nick.
*
* Since: 3.0
**/
void
gimp_choice_add (GimpChoice *choice,
const gchar *nick,
gint id,
const gchar *label,
const gchar *help)
{
GimpChoiceDesc *desc;
GList *duplicate;
g_return_if_fail (label != NULL);
desc = g_new0 (GimpChoiceDesc, 1);
desc->id = id;
desc->label = g_strdup (label);
desc->help = help != NULL ? g_strdup (help) : NULL;
g_hash_table_insert (choice->choices, g_strdup (nick), desc);
duplicate = g_list_find_custom (choice->keys, nick, (GCompareFunc) g_strcmp0);
if (duplicate != NULL)
{
choice->keys = g_list_remove_link (choice->keys, duplicate);
gimp_choice_desc_free (duplicate->data);
g_list_free (duplicate);
}
choice->keys = g_list_append (choice->keys, g_strdup (nick));
}
/**
* gimp_choice_is_valid:
* @choice: a %GimpChoice.
* @nick: the nick to check.
*
* This procedure checks if the given @nick is valid and refers to
* an existing choice.
*
* Returns: Whether the choice is valid.
*
* Since: 3.0
**/
gboolean
gimp_choice_is_valid (GimpChoice *choice,
const gchar *nick)
{
return (g_hash_table_lookup (choice->choices, nick) != NULL);
}
/**
* gimp_choice_list_nicks:
* @choice: a %GimpChoice.
* @nick: the nick to check.
*
* This procedure returns the list of nicks allowed for @choice.
*
* Returns: (element-type gchar*) (transfer none): The list of @choice's nicks.
*
* Since: 3.0
**/
GList *
gimp_choice_list_nicks (GimpChoice *choice)
{
/* I don't use g_hash_table_get_keys() on purpose, because I want to retain
* the adding-time order.
*/
return choice->keys;
}
/**
* gimp_choice_get_id:
* @choice: a %GimpChoice.
* @nick: the nick to lookup.
*
* Returns: the ID of @nick.
*
* Since: 3.0
**/
gint
gimp_choice_get_id (GimpChoice *choice,
const gchar *nick)
{
GimpChoiceDesc *desc;
desc = g_hash_table_lookup (choice->choices, nick);
if (desc)
return desc->id;
else
return 0;
}
/**
* gimp_choice_get_label:
* @choice: a %GimpChoice.
* @nick: the nick to lookup.
*
* Returns: (transfer none): the label of @nick.
*
* Since: 3.0
**/
const gchar *
gimp_choice_get_label (GimpChoice *choice,
const gchar *nick)
{
GimpChoiceDesc *desc;
desc = g_hash_table_lookup (choice->choices, nick);
if (desc)
return desc->label;
else
return NULL;
}
/**
* gimp_choice_get_help:
* @choice: a %GimpChoice.
* @nick: the nick to lookup.
*
* Returns the longer documentation for @nick.
*
* Returns: (transfer none): the help text of @nick.
*
* Since: 3.0
**/
const gchar *
gimp_choice_get_help (GimpChoice *choice,
const gchar *nick)
{
GimpChoiceDesc *desc;
desc = g_hash_table_lookup (choice->choices, nick);
if (desc)
return desc->help;
else
return NULL;
}
/**
* gimp_choice_get_documentation:
* @choice: the %GimpChoice.
* @nick: the possible value's nick you need documentation for.
* @label: (transfer none): the label of @nick.
* @help: (transfer none): the help text of @nick.
*
* Returns the documentation strings for @nick.
*
* Returns: %TRUE if @nick is found, %FALSE otherwise.
*
* Since: 3.0
**/
gboolean
gimp_choice_get_documentation (GimpChoice *choice,
const gchar *nick,
const gchar **label,
const gchar **help)
{
GimpChoiceDesc *desc;
desc = g_hash_table_lookup (choice->choices, nick);
if (desc)
{
*label = desc->label;
*help = desc->help;
return TRUE;
}
return FALSE;
}
/* Private functions */
static void
gimp_choice_desc_free (GimpChoiceDesc *desc)
{
g_free (desc->label);
g_free (desc->help);
g_free (desc);
}

69
libgimpbase/gimpchoice.h Normal file
View file

@ -0,0 +1,69 @@
/* LIBGIMP - The GIMP Library
* Copyright (C) 1995-2000 Peter Mattis and Spencer Kimball
*
* gimpchoice.h
* Copyright (C) 2023 Jehan
*
* This library is free software: you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see
* <https://www.gnu.org/licenses/>.
*/
#if !defined (__GIMP_BASE_H_INSIDE__) && !defined (GIMP_BASE_COMPILATION)
#error "Only <libgimpbase/gimpbase.h> can be included directly."
#endif
#ifndef __GIMP_CHOICE_H__
#define __GIMP_CHOICE_H__
G_BEGIN_DECLS
/* For information look into the C source or the html documentation */
#define GIMP_TYPE_CHOICE (gimp_choice_get_type ())
G_DECLARE_FINAL_TYPE (GimpChoice, gimp_choice, GIMP, CHOICE, GObject)
GimpChoice * gimp_choice_new (void);
GimpChoice * gimp_choice_new_with_values (const gchar *nick,
gint id,
const gchar *label,
const gchar *help,
...) G_GNUC_NULL_TERMINATED;
void gimp_choice_add (GimpChoice *choice,
const gchar *nick,
gint id,
const gchar *label,
const gchar *help);
gboolean gimp_choice_is_valid (GimpChoice *choice,
const gchar *nick);
GList * gimp_choice_list_nicks (GimpChoice *choice);
gint gimp_choice_get_id (GimpChoice *choice,
const gchar *nick);
const gchar * gimp_choice_get_label (GimpChoice *choice,
const gchar *nick);
const gchar * gimp_choice_get_help (GimpChoice *choice,
const gchar *nick);
gboolean gimp_choice_get_documentation (GimpChoice *choice,
const gchar *nick,
const gchar **label,
const gchar **help);
G_END_DECLS
#endif /* __GIMP_CHOICE_H__ */

View file

@ -51,6 +51,7 @@ stamp_compat_enums = custom_target('stamp-gimpcompatenums.h',
libgimpbase_sources_introspectable = files(
'gimpbasetypes.c',
'gimpchecks.c',
'gimpchoice.c',
'gimpcpuaccel.c',
'gimpenv.c',
'gimpmemsize.c',