From 0b2d8fedc32b07da9842d2ffabec090307db3ace Mon Sep 17 00:00:00 2001 From: Jehan Date: Thu, 6 Jun 2024 20:16:58 +0200 Subject: [PATCH] libgimp, libgimpwidgets: ability to generate a GimpIntRadioFrame for GimpChoice arguments. This includes a new function gimp_prop_choice_radio_frame_new() which creates GimpIntRadioFrame from GimpChoice properties. GimpChoice GimpProcedure arguments are still creating a combo box by default, but it is now possible to override this default behavior to get a radio frame by calling first: ```C gimp_procedure_dialog_get_widget (dialog, "arg-name", GIMP_TYPE_INT_RADIO_FRAME); ``` --- libgimp/gimpproceduredialog.c | 21 ++++- libgimpwidgets/gimppropwidgets.c | 155 ++++++++++++++++++++++++++++++- libgimpwidgets/gimppropwidgets.h | 2 + libgimpwidgets/gimpwidgets.def | 1 + 4 files changed, 173 insertions(+), 6 deletions(-) diff --git a/libgimp/gimpproceduredialog.c b/libgimp/gimpproceduredialog.c index d227795e15..76f6a11fce 100644 --- a/libgimp/gimpproceduredialog.c +++ b/libgimp/gimpproceduredialog.c @@ -627,6 +627,10 @@ gimp_procedure_dialog_set_ok_label (GimpProcedureDialog *dialog, * * %GIMP_TYPE_LABEL_ENTRY (default): an entry with a label. * * %GTK_TYPE_ENTRY: an entry with no label. * * %GTK_TYPE_TEXT_VIEW: a text view with no label. + * - %GIMP_TYPE_CHOICE: + * * %GTK_TYPE_COMBO_BOX (default): a combo box displaying every + * choice. + * * %GIMP_TYPE_INT_RADIO_FRAME: a frame with radio buttons. * - %GEGL_TYPE_COLOR: * * %GIMP_TYPE_LABEL_COLOR (default): a color button with a label. * Please use gimp_procedure_dialog_get_color_widget() for a @@ -799,10 +803,19 @@ gimp_procedure_dialog_get_widget (GimpProcedureDialog *dialog, } else if (G_PARAM_SPEC_TYPE (pspec) == GIMP_TYPE_PARAM_CHOICE) { - widget = gimp_prop_choice_combo_box_new (G_OBJECT (dialog->priv->config), property); - gtk_widget_set_vexpand (widget, FALSE); - gtk_widget_set_hexpand (widget, TRUE); - widget = gimp_label_string_widget_new (g_param_spec_get_nick (pspec), widget); + if (widget_type == G_TYPE_NONE || widget_type == GTK_TYPE_COMBO_BOX) + { + widget = gimp_prop_choice_combo_box_new (G_OBJECT (dialog->priv->config), property); + gtk_widget_set_vexpand (widget, FALSE); + gtk_widget_set_hexpand (widget, TRUE); + widget = gimp_label_string_widget_new (g_param_spec_get_nick (pspec), widget); + } + else if (widget_type == GIMP_TYPE_INT_RADIO_FRAME) + { + widget = gimp_prop_choice_radio_frame_new (G_OBJECT (dialog->priv->config), property); + gtk_widget_set_vexpand (widget, FALSE); + gtk_widget_set_hexpand (widget, TRUE); + } } /* GimpResource subclasses */ /* FUTURE: title the chooser more specifically, with a prefix that is the nick of the property. */ diff --git a/libgimpwidgets/gimppropwidgets.c b/libgimpwidgets/gimppropwidgets.c index 6e9d27a3b0..614b0e9e8b 100644 --- a/libgimpwidgets/gimppropwidgets.c +++ b/libgimpwidgets/gimppropwidgets.c @@ -2617,8 +2617,6 @@ gimp_prop_string_combo_box_new (GObject *config, * specified property. * * Returns: (transfer full): The newly created #GimpStringComboBox widget. - * - * Since: 2.4 */ GtkWidget * gimp_prop_choice_combo_box_new (GObject *config, @@ -2731,6 +2729,159 @@ gimp_prop_choice_combo_box_is_sensitive (const gchar *nick, } +/*************************/ +/* choice radio frame */ +/*************************/ + +static gboolean +gimp_prop_widget_choice_is_sensitive (gint value, + gpointer user_data, + gint *new_value, + gpointer data); +static gboolean +gimp_prop_widget_choice_string_to_int (GBinding *binding, + const GValue *from_value, + GValue *to_value, + gpointer user_data); +static gboolean +gimp_prop_widget_choice_int_to_string (GBinding *binding, + const GValue *from_value, + GValue *to_value, + gpointer user_data); + + +/** + * gimp_prop_choice_radio_frame_new: + * @config: Object to which property is attached. + * @property_name: Name of %GimpChoice property controlled by radio buttons. + * + * Creates a [class@GimpUi.IntRadioFrame] widget to display and set the + * specified [class@Gimp.Choice] property. + * + * Returns: (transfer full): The newly created #GimpIntRadioFrame widget. + */ +GtkWidget * +gimp_prop_choice_radio_frame_new (GObject *config, + const gchar *property_name) +{ + GParamSpec *param_spec; + GimpParamSpecChoice *cspec; + GtkWidget *frame; + GtkWidget *title; + GimpIntStore *store; + GList *values; + GList *iter; + + g_return_val_if_fail (G_IS_OBJECT (config), NULL); + g_return_val_if_fail (property_name != NULL, NULL); + + param_spec = check_param_spec_w (config, property_name, + GIMP_TYPE_PARAM_CHOICE, G_STRFUNC); + if (! param_spec) + return NULL; + + cspec = GIMP_PARAM_SPEC_CHOICE (param_spec); + values = gimp_choice_list_nicks (cspec->choice); + store = g_object_new (GIMP_TYPE_INT_STORE, NULL); + + for (iter = values; iter; iter = iter->next) + { + const gchar *nick = iter->data; + const gchar *label = gimp_choice_get_label (cspec->choice, nick); + gint id = gimp_choice_get_id (cspec->choice, nick); + + gtk_list_store_insert_with_values (GTK_LIST_STORE (store), NULL, -1, + GIMP_INT_STORE_VALUE, id, + GIMP_INT_STORE_LABEL, label, + -1); + + } + + frame = gimp_int_radio_frame_new_from_store (NULL, store); + title = gtk_label_new_with_mnemonic (g_param_spec_get_nick (param_spec)); + gtk_frame_set_label_widget (GTK_FRAME (frame), title); + gimp_help_set_help_data (frame, g_param_spec_get_blurb (param_spec), NULL); + g_object_unref (store); + + gimp_int_radio_frame_set_sensitivity (GIMP_INT_RADIO_FRAME (frame), + (GimpIntRadioFrameSensitivityFunc) gimp_prop_widget_choice_is_sensitive, + cspec->choice, NULL); + + g_object_bind_property_full (config, property_name, + frame, "value", + G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE, + gimp_prop_widget_choice_string_to_int, + gimp_prop_widget_choice_int_to_string, + cspec->choice, NULL); + + gimp_widget_set_bound_property (frame, config, property_name); + + gtk_widget_show (frame); + gtk_widget_show (title); + + return frame; +} + +static gboolean +gimp_prop_widget_choice_is_sensitive (gint value, + gpointer user_data, + gint *new_value, + gpointer data) +{ + GimpChoice *choice = GIMP_CHOICE (data); + GList *values; + GList *iter; + + values = gimp_choice_list_nicks (choice); + + for (iter = values; iter; iter = iter->next) + { + if (gimp_choice_get_id (choice, iter->data) == value) + return gimp_choice_is_valid (choice, iter->data); + } + + return FALSE; +} + +static gboolean +gimp_prop_widget_choice_string_to_int (GBinding *binding, + const GValue *from_value, + GValue *to_value, + gpointer user_data) +{ + GimpChoice *choice = GIMP_CHOICE (user_data); + const gchar *val = g_value_get_string (from_value); + + g_value_set_int (to_value, gimp_choice_get_id (choice, val)); + + return TRUE; +} + +static gboolean +gimp_prop_widget_choice_int_to_string (GBinding *binding, + const GValue *from_value, + GValue *to_value, + gpointer user_data) +{ + GimpChoice *choice = GIMP_CHOICE (user_data); + gint val = g_value_get_int (from_value); + GList *values; + GList *iter; + + values = gimp_choice_list_nicks (choice); + + for (iter = values; iter; iter = iter->next) + { + if (gimp_choice_get_id (choice, iter->data) == val) + { + g_value_set_string (to_value, iter->data); + break; + } + } + + return (iter != NULL); +} + /*************************/ /* file chooser button */ /*************************/ diff --git a/libgimpwidgets/gimppropwidgets.h b/libgimpwidgets/gimppropwidgets.h index 6010db35d0..4c6e52f993 100644 --- a/libgimpwidgets/gimppropwidgets.h +++ b/libgimpwidgets/gimppropwidgets.h @@ -168,6 +168,8 @@ GtkWidget * gimp_prop_string_combo_box_new (GObject *config, gint label_column); GtkWidget * gimp_prop_choice_combo_box_new (GObject *config, const gchar *property_name); +GtkWidget * gimp_prop_choice_radio_frame_new (GObject *config, + const gchar *property_name); /* GimpParamPath */ diff --git a/libgimpwidgets/gimpwidgets.def b/libgimpwidgets/gimpwidgets.def index 641443f69a..c966a6c847 100644 --- a/libgimpwidgets/gimpwidgets.def +++ b/libgimpwidgets/gimpwidgets.def @@ -371,6 +371,7 @@ EXPORTS gimp_prop_boolean_radio_frame_new gimp_prop_check_button_new gimp_prop_choice_combo_box_new + gimp_prop_choice_radio_frame_new gimp_prop_color_area_new gimp_prop_color_select_new gimp_prop_coordinates_connect