mirror of https://github.com/GNOME/gimp.git
libgimp: have gimp_procedure_dialog_new() behave like g_object_new().
It is now discouraged to create constructor-type _new() functions with custom code, which would make them behave differently that simply calling g_object_new() with the GType and relevant properties. The main reason is that some bindings would create objects with g_object_new() so it should create expected code too. See: https://gi.readthedocs.io/en/latest/writingbindableapis.html#custom-code-in-constructors Here it was complicated for a few reasons: - We hack "title" property to use the procedure's menu label by default (without the mnemonic). For this, I overrode the GtkWindow property. - We want "use-header-bar" to follow the application general settings by default. Since it is a CONSTRUCT_ONLY property, g_object_set() is not possible in _init() and _constructed(). Instead I had to override the constructor() method to set this at construction time (yet still allow API users to override this with the property at creation). - Similarly, "help-func" is a CONSTRUCT_ONLY property, so I used the same trick. - As for "help-id", I now just set it in _constructed(). This was the easy one.
This commit is contained in:
parent
24dc6bfeac
commit
8176bd0828
|
@ -39,6 +39,10 @@ enum
|
|||
PROP_0,
|
||||
PROP_PROCEDURE,
|
||||
PROP_CONFIG,
|
||||
|
||||
/* From here the overridden properties. */
|
||||
PROP_TITLE,
|
||||
|
||||
N_PROPS
|
||||
};
|
||||
|
||||
|
@ -72,42 +76,45 @@ typedef struct GimpProcedureDialogSensitiveData
|
|||
} GimpProcedureDialogSensitiveData;
|
||||
|
||||
|
||||
static void gimp_procedure_dialog_constructed (GObject *object);
|
||||
static void gimp_procedure_dialog_dispose (GObject *object);
|
||||
static void gimp_procedure_dialog_set_property (GObject *object,
|
||||
guint property_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec);
|
||||
static void gimp_procedure_dialog_get_property (GObject *object,
|
||||
guint property_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec);
|
||||
static GObject * gimp_procedure_dialog_constructor (GType type,
|
||||
guint n_construct_properties,
|
||||
GObjectConstructParam *construct_properties);
|
||||
static void gimp_procedure_dialog_constructed (GObject *object);
|
||||
static void gimp_procedure_dialog_dispose (GObject *object);
|
||||
static void gimp_procedure_dialog_set_property (GObject *object,
|
||||
guint property_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec);
|
||||
static void gimp_procedure_dialog_get_property (GObject *object,
|
||||
guint property_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec);
|
||||
|
||||
static void gimp_procedure_dialog_real_fill_list (GimpProcedureDialog *dialog,
|
||||
GimpProcedure *procedure,
|
||||
GimpProcedureConfig *config,
|
||||
GList *properties);
|
||||
static void gimp_procedure_dialog_real_fill_list (GimpProcedureDialog *dialog,
|
||||
GimpProcedure *procedure,
|
||||
GimpProcedureConfig *config,
|
||||
GList *properties);
|
||||
|
||||
static void gimp_procedure_dialog_reset_initial (GtkWidget *button,
|
||||
GimpProcedureDialog *dialog);
|
||||
static void gimp_procedure_dialog_reset_factory (GtkWidget *button,
|
||||
GimpProcedureDialog *dialog);
|
||||
static void gimp_procedure_dialog_load_defaults (GtkWidget *button,
|
||||
GimpProcedureDialog *dialog);
|
||||
static void gimp_procedure_dialog_save_defaults (GtkWidget *button,
|
||||
GimpProcedureDialog *dialog);
|
||||
static void gimp_procedure_dialog_reset_initial (GtkWidget *button,
|
||||
GimpProcedureDialog *dialog);
|
||||
static void gimp_procedure_dialog_reset_factory (GtkWidget *button,
|
||||
GimpProcedureDialog *dialog);
|
||||
static void gimp_procedure_dialog_load_defaults (GtkWidget *button,
|
||||
GimpProcedureDialog *dialog);
|
||||
static void gimp_procedure_dialog_save_defaults (GtkWidget *button,
|
||||
GimpProcedureDialog *dialog);
|
||||
|
||||
static gboolean gimp_procedure_dialog_check_mnemonic (GimpProcedureDialog *dialog,
|
||||
GtkWidget *widget,
|
||||
const gchar *id,
|
||||
const gchar *core_id);
|
||||
static gboolean gimp_procedure_dialog_check_mnemonic (GimpProcedureDialog *dialog,
|
||||
GtkWidget *widget,
|
||||
const gchar *id,
|
||||
const gchar *core_id);
|
||||
static GtkWidget *
|
||||
gimp_procedure_dialog_fill_container_list (GimpProcedureDialog *dialog,
|
||||
const gchar *container_id,
|
||||
GtkContainer *container,
|
||||
GList *properties);
|
||||
gimp_procedure_dialog_fill_container_list (GimpProcedureDialog *dialog,
|
||||
const gchar *container_id,
|
||||
GtkContainer *container,
|
||||
GList *properties);
|
||||
|
||||
static void gimp_procedure_dialog_sensitive_data_free (GimpProcedureDialogSensitiveData *data);
|
||||
static void gimp_procedure_dialog_sensitive_data_free (GimpProcedureDialogSensitiveData *data);
|
||||
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (GimpProcedureDialog, gimp_procedure_dialog,
|
||||
|
@ -123,6 +130,7 @@ gimp_procedure_dialog_class_init (GimpProcedureDialogClass *klass)
|
|||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->constructor = gimp_procedure_dialog_constructor;
|
||||
object_class->constructed = gimp_procedure_dialog_constructed;
|
||||
object_class->dispose = gimp_procedure_dialog_dispose;
|
||||
object_class->get_property = gimp_procedure_dialog_get_property;
|
||||
|
@ -136,7 +144,7 @@ gimp_procedure_dialog_class_init (GimpProcedureDialogClass *klass)
|
|||
"The GimpProcedure this dialog is used with",
|
||||
GIMP_TYPE_PROCEDURE,
|
||||
GIMP_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT);
|
||||
G_PARAM_CONSTRUCT_ONLY);
|
||||
|
||||
props[PROP_CONFIG] =
|
||||
g_param_spec_object ("config",
|
||||
|
@ -146,7 +154,17 @@ gimp_procedure_dialog_class_init (GimpProcedureDialogClass *klass)
|
|||
GIMP_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT);
|
||||
|
||||
g_object_class_install_properties (object_class, N_PROPS, props);
|
||||
g_object_class_install_properties (object_class, N_PROPS - 1, props);
|
||||
|
||||
/**
|
||||
* GimpProcedureDialog:title:
|
||||
*
|
||||
* Overrides the "title" property of #GtkWindow.
|
||||
* When %NULL, the title is taken from the #GimpProcedure menu label.
|
||||
*
|
||||
* Since: 3.0
|
||||
*/
|
||||
g_object_class_override_property (object_class, PROP_TITLE, "title");
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -162,11 +180,68 @@ gimp_procedure_dialog_init (GimpProcedureDialog *dialog)
|
|||
(GDestroyNotify) gimp_procedure_dialog_sensitive_data_free);
|
||||
}
|
||||
|
||||
static GObject *
|
||||
gimp_procedure_dialog_constructor (GType type,
|
||||
guint n_construct_properties,
|
||||
GObjectConstructParam *construct_properties)
|
||||
{
|
||||
gboolean use_header_bar = FALSE;
|
||||
gboolean use_header_bar_edited = FALSE;
|
||||
gboolean help_func_edited = FALSE;
|
||||
|
||||
g_object_get (gtk_settings_get_default (),
|
||||
"gtk-dialogs-use-header", &use_header_bar,
|
||||
NULL);
|
||||
|
||||
for (guint i = 0; i < n_construct_properties; i++)
|
||||
{
|
||||
/* We need to override the default values of some properties and
|
||||
* can't do it in _init() or _constructed() because it's too late
|
||||
* for G_PARAM_CONSTRUCT_ONLY properties.
|
||||
* Moreover we don't do it in _new() because we need this to work
|
||||
* also in bindings sometimes using only constructors to
|
||||
* initialize their object, hence we can't rely on our _new()
|
||||
* function (relying on _new() functions doing more than the
|
||||
* constructor is now discouraged by GTK/GLib developers).
|
||||
*/
|
||||
GObjectConstructParam property;
|
||||
|
||||
property = construct_properties[i];
|
||||
if (! use_header_bar_edited &&
|
||||
g_strcmp0 (g_param_spec_get_name (property.pspec),
|
||||
"use-header-bar") == 0)
|
||||
{
|
||||
if (g_value_get_int (property.value) == -1)
|
||||
g_value_set_int (property.value, (gint) use_header_bar);
|
||||
|
||||
use_header_bar_edited = TRUE;
|
||||
}
|
||||
else if (! help_func_edited &&
|
||||
g_strcmp0 (g_param_spec_get_name (property.pspec),
|
||||
"help-func") == 0)
|
||||
{
|
||||
if (g_value_get_pointer (property.value) == NULL)
|
||||
g_value_set_pointer (property.value,
|
||||
gimp_standard_help_func);
|
||||
|
||||
help_func_edited = TRUE;
|
||||
}
|
||||
|
||||
if (use_header_bar_edited && help_func_edited)
|
||||
break;
|
||||
}
|
||||
|
||||
return G_OBJECT_CLASS (parent_class)->constructor (type,
|
||||
n_construct_properties,
|
||||
construct_properties);
|
||||
}
|
||||
|
||||
static void
|
||||
gimp_procedure_dialog_constructed (GObject *object)
|
||||
{
|
||||
GimpProcedureDialog *dialog;
|
||||
GimpProcedure *procedure;
|
||||
const gchar *help_id;
|
||||
const gchar *ok_label;
|
||||
GtkWidget *hbox;
|
||||
GtkWidget *button;
|
||||
|
@ -180,9 +255,17 @@ gimp_procedure_dialog_constructed (GObject *object)
|
|||
dialog = GIMP_PROCEDURE_DIALOG (object);
|
||||
procedure = dialog->priv->procedure;
|
||||
|
||||
role = g_strdup_printf ("gimp-%s", gimp_procedure_get_name (procedure));
|
||||
role = g_strdup_printf ("gimp-%s", gimp_procedure_get_name (procedure));
|
||||
help_id = gimp_procedure_get_help_id (procedure);
|
||||
g_object_set (object,
|
||||
"role", role,
|
||||
"role", role,
|
||||
"help-id", help_id,
|
||||
/* This may seem weird, but this is actually because we
|
||||
* are overriding this property and if the title is NULL
|
||||
* in particular, we create one out of the procedure's
|
||||
* menu label. So we force the reset this way.
|
||||
*/
|
||||
"title", gtk_window_get_title (GTK_WINDOW (dialog)),
|
||||
NULL);
|
||||
g_free (role);
|
||||
|
||||
|
@ -319,6 +402,32 @@ gimp_procedure_dialog_set_property (GObject *object,
|
|||
gimp_config_duplicate (GIMP_CONFIG (dialog->priv->config));
|
||||
break;
|
||||
|
||||
case PROP_TITLE:
|
||||
{
|
||||
GtkWidget *bogus = NULL;
|
||||
const gchar *title;
|
||||
|
||||
title = g_value_get_string (value);
|
||||
|
||||
if (title == NULL)
|
||||
{
|
||||
/* Use the procedure menu label, but remove mnemonic
|
||||
* underscore. Ugly yet must reliable way as GTK does not
|
||||
* expose a function to do this from a string (and better
|
||||
* not to copy-paste the internal function from GTK code).
|
||||
*/
|
||||
bogus = gtk_label_new (NULL);
|
||||
gtk_label_set_markup_with_mnemonic (GTK_LABEL (g_object_ref_sink (bogus)),
|
||||
gimp_procedure_get_menu_label (dialog->priv->procedure));
|
||||
title = gtk_label_get_text (GTK_LABEL (bogus));
|
||||
}
|
||||
if (title != NULL)
|
||||
gtk_window_set_title (GTK_WINDOW (dialog), title);
|
||||
|
||||
g_clear_object (&bogus);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
|
@ -343,6 +452,11 @@ gimp_procedure_dialog_get_property (GObject *object,
|
|||
g_value_set_object (value, dialog->priv->config);
|
||||
break;
|
||||
|
||||
case PROP_TITLE:
|
||||
g_value_set_string (value,
|
||||
gtk_window_get_title (GTK_WINDOW (dialog)));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
|
@ -404,46 +518,17 @@ gimp_procedure_dialog_new (GimpProcedure *procedure,
|
|||
GimpProcedureConfig *config,
|
||||
const gchar *title)
|
||||
{
|
||||
GtkWidget *dialog;
|
||||
GtkWidget *bogus = NULL;
|
||||
const gchar *help_id;
|
||||
gboolean use_header_bar;
|
||||
|
||||
g_return_val_if_fail (GIMP_IS_PROCEDURE (procedure), NULL);
|
||||
g_return_val_if_fail (GIMP_IS_PROCEDURE_CONFIG (config), NULL);
|
||||
g_return_val_if_fail (gimp_procedure_config_get_procedure (config) ==
|
||||
procedure, NULL);
|
||||
g_return_val_if_fail (title != NULL || gimp_procedure_get_menu_label (procedure), NULL);
|
||||
|
||||
help_id = gimp_procedure_get_help_id (procedure);
|
||||
if (title == NULL)
|
||||
{
|
||||
/* Remove mnemonic underscore. Ugly but must reliable way as GTK
|
||||
* does not expose a function to do this from a string (and better
|
||||
* not to copy-paste the internal function from GTK code).
|
||||
*/
|
||||
bogus = gtk_label_new (NULL);
|
||||
gtk_label_set_markup_with_mnemonic (GTK_LABEL (g_object_ref_sink (bogus)),
|
||||
gimp_procedure_get_menu_label (procedure));
|
||||
title = gtk_label_get_text (GTK_LABEL (bogus));
|
||||
}
|
||||
|
||||
g_object_get (gtk_settings_get_default (),
|
||||
"gtk-dialogs-use-header", &use_header_bar,
|
||||
NULL);
|
||||
|
||||
dialog = g_object_new (GIMP_TYPE_PROCEDURE_DIALOG,
|
||||
"procedure", procedure,
|
||||
"config", config,
|
||||
"title", title,
|
||||
"help-func", gimp_standard_help_func,
|
||||
"help-id", help_id,
|
||||
"use-header-bar", use_header_bar,
|
||||
NULL);
|
||||
|
||||
g_clear_object (&bogus);
|
||||
|
||||
return GTK_WIDGET (dialog);
|
||||
return g_object_new (GIMP_TYPE_PROCEDURE_DIALOG,
|
||||
"procedure", procedure,
|
||||
"config", config,
|
||||
"title", title,
|
||||
NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue