[gimp] Bug 648776 - fixes symmetry painting after Massimo and Mitch's reviews.
- From: Jehan Pagès <jehanp src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp] Bug 648776 - fixes symmetry painting after Massimo and Mitch's reviews.
- Date: Tue, 2 Feb 2016 20:17:37 +0000 (UTC)
commit 1f4839288e8463138ec98f19478e2999f221dbdd
Author: Jehan <jehan girinstud io>
Date: Thu Jan 21 21:43:15 2016 +0100
Bug 648776 - fixes symmetry painting after Massimo and Mitch's reviews.
Use a GType for the PROP_SYMMETRY property of GimpImage, and create
a default "identity" symmetry for an image.
I still use a GimpIntComboBox but store the property value in the
user-data column because gpointer isn't a subset of gint.
Adds in libgimpwidgets:
- gimp_int_combo_box_set_active_by_user_data()
- gimp_int_combo_box_get_active_user_data()
- gimp_int_store_lookup_by_user_data()
- gimp_prop_pointer_combo_box_new() to create a GimpIntComboBox and
attach it to a gpointer property.
Thanks Massimo and Mitch for reviewing my code.
app/core/gimpimage-symmetry.c | 18 ++----
app/core/gimpimage.c | 56 ++++++++---------
app/widgets/gimpsymmetryeditor.c | 10 ++--
libgimpwidgets/gimpintcombobox.c | 66 ++++++++++++++++++++
libgimpwidgets/gimpintcombobox.h | 7 ++
libgimpwidgets/gimpintstore.c | 39 ++++++++++++
libgimpwidgets/gimpintstore.h | 3 +
libgimpwidgets/gimppropwidgets.c | 124 ++++++++++++++++++++++++++++++++++++--
libgimpwidgets/gimppropwidgets.h | 5 ++
9 files changed, 277 insertions(+), 51 deletions(-)
---
diff --git a/app/core/gimpimage-symmetry.c b/app/core/gimpimage-symmetry.c
index 1fc300f..b6c6dff 100644
--- a/app/core/gimpimage-symmetry.c
+++ b/app/core/gimpimage-symmetry.c
@@ -55,6 +55,9 @@ gimp_image_symmetry_list (void)
* @type: the #GType of the symmetry
*
* Creates a new #GimpSymmetry of @type attached to @image.
+ * @type must be a subtype of `GIMP_TYPE_SYMMETRY`.
+ * Note that using the base @type `GIMP_TYPE_SYMMETRY` creates an
+ * identity transformation.
*
* Returns: the new #GimpSymmetry.
**/
@@ -63,6 +66,7 @@ gimp_image_symmetry_new (GimpImage *image,
GType type)
{
GimpSymmetry *sym = NULL;
+ g_return_val_if_fail (g_type_is_a (type, GIMP_TYPE_SYMMETRY), NULL);
if (type != G_TYPE_NONE)
{
@@ -176,21 +180,11 @@ gimp_image_symmetry_select (GimpImage *image,
GimpSymmetry *
gimp_image_symmetry_selected (GimpImage *image)
{
- static GimpImage *last_image = NULL;
- static GimpSymmetry *identity = NULL;
- GimpImagePrivate *private;
+ GimpImagePrivate *private;
g_return_val_if_fail (GIMP_IS_IMAGE (image), FALSE);
- if (last_image != image)
- {
- if (identity)
- g_object_unref (identity);
- identity = gimp_image_symmetry_new (image,
- GIMP_TYPE_SYMMETRY);
- }
-
private = GIMP_IMAGE_GET_PRIVATE (image);
- return private->selected_symmetry ? private->selected_symmetry : identity;
+ return private->selected_symmetry;
}
diff --git a/app/core/gimpimage.c b/app/core/gimpimage.c
index 5900715..6e762ec 100644
--- a/app/core/gimpimage.c
+++ b/app/core/gimpimage.c
@@ -628,10 +628,11 @@ gimp_image_class_init (GimpImageClass *klass)
g_object_class_override_property (object_class, PROP_BUFFER, "buffer");
g_object_class_install_property (object_class, PROP_SYMMETRY,
- g_param_spec_int ("symmetry",
- NULL, _("Symmetry"),
- G_TYPE_NONE, G_MAXINT, G_TYPE_NONE,
- GIMP_PARAM_READWRITE));
+ g_param_spec_gtype ("symmetry",
+ NULL, _("Symmetry"),
+ GIMP_TYPE_SYMMETRY,
+ GIMP_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT));
g_type_class_add_private (klass, sizeof (GimpImagePrivate));
}
@@ -873,7 +874,8 @@ gimp_image_set_property (GObject *object,
break;
case PROP_SYMMETRY:
{
- GType type = g_value_get_int (value);
+ GList *iter;
+ GType type = g_value_get_gtype (value);
if (private->selected_symmetry)
g_object_set (private->selected_symmetry,
@@ -881,29 +883,25 @@ gimp_image_set_property (GObject *object,
NULL);
private->selected_symmetry = NULL;
- if (type != G_TYPE_NONE)
+
+ for (iter = private->symmetries; iter; iter = g_list_next (iter))
{
- GList *iter;
-
- for (iter = private->symmetries; iter; iter = g_list_next (iter))
- {
- GimpSymmetry *sym = iter->data;
- if (g_type_is_a (sym->type, type))
- private->selected_symmetry = iter->data;
- }
-
- if (private->selected_symmetry == NULL)
- {
- GimpSymmetry *sym;
-
- sym = gimp_image_symmetry_new (image, type);
- gimp_image_symmetry_add (image, sym);
- private->selected_symmetry = sym;
- }
- g_object_set (private->selected_symmetry,
- "active", TRUE,
- NULL);
+ GimpSymmetry *sym = iter->data;
+ if (type == sym->type)
+ private->selected_symmetry = iter->data;
+ }
+
+ if (private->selected_symmetry == NULL)
+ {
+ GimpSymmetry *sym;
+
+ sym = gimp_image_symmetry_new (image, type);
+ gimp_image_symmetry_add (image, sym);
+ private->selected_symmetry = sym;
}
+ g_object_set (private->selected_symmetry,
+ "active", TRUE,
+ NULL);
}
break;
default:
@@ -948,9 +946,9 @@ gimp_image_get_property (GObject *object,
g_value_set_object (value, gimp_image_get_buffer (GIMP_PICKABLE (image)));
break;
case PROP_SYMMETRY:
- g_value_set_int (value,
- private->selected_symmetry ?
- private->selected_symmetry->type : G_TYPE_NONE);
+ g_value_set_gtype (value,
+ private->selected_symmetry ?
+ private->selected_symmetry->type : GIMP_TYPE_SYMMETRY);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
diff --git a/app/widgets/gimpsymmetryeditor.c b/app/widgets/gimpsymmetryeditor.c
index eb5169d..9674aef 100644
--- a/app/widgets/gimpsymmetryeditor.c
+++ b/app/widgets/gimpsymmetryeditor.c
@@ -274,7 +274,7 @@ gimp_symmetry_editor_image_changed (GimpContext *context,
gtk_list_store_set (store, &iter,
GIMP_INT_STORE_LABEL,
klass->label,
- GIMP_INT_STORE_VALUE,
+ GIMP_INT_STORE_USER_DATA,
sym_iter->data,
-1);
g_type_class_unref (klass);
@@ -284,11 +284,11 @@ gimp_symmetry_editor_image_changed (GimpContext *context,
gtk_list_store_prepend (store, &iter);
gtk_list_store_set (store, &iter,
GIMP_INT_STORE_LABEL, _("None"),
- GIMP_INT_STORE_VALUE, G_TYPE_NONE,
+ GIMP_INT_STORE_USER_DATA, GIMP_TYPE_SYMMETRY,
-1);
- editor->p->menu = gimp_prop_int_combo_box_new (G_OBJECT (image),
- "symmetry",
- GIMP_INT_STORE (store));
+ editor->p->menu = gimp_prop_pointer_combo_box_new (G_OBJECT (image),
+ "symmetry",
+ GIMP_INT_STORE (store));
g_object_unref (store);
gimp_int_combo_box_set_label (GIMP_INT_COMBO_BOX (editor->p->menu),
diff --git a/libgimpwidgets/gimpintcombobox.c b/libgimpwidgets/gimpintcombobox.c
index c32062f..a270dcd 100644
--- a/libgimpwidgets/gimpintcombobox.c
+++ b/libgimpwidgets/gimpintcombobox.c
@@ -471,6 +471,72 @@ gimp_int_combo_box_get_active (GimpIntComboBox *combo_box,
}
/**
+ * gimp_int_combo_box_set_active_by_user_data:
+ * @combo_box: a #GimpIntComboBox
+ * @user_data: an integer value
+ *
+ * Looks up the item that has the given @user_data and makes it the
+ * selected item in the @combo_box.
+ *
+ * Return value: %TRUE on success or %FALSE if there was no item for
+ * this user-data.
+ *
+ * Since: 2.10
+ **/
+gboolean
+gimp_int_combo_box_set_active_by_user_data (GimpIntComboBox *combo_box,
+ gpointer user_data)
+{
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+
+ g_return_val_if_fail (GIMP_IS_INT_COMBO_BOX (combo_box), FALSE);
+
+ model = gtk_combo_box_get_model (GTK_COMBO_BOX (combo_box));
+
+ if (gimp_int_store_lookup_by_user_data (model, user_data, &iter))
+ {
+ gtk_combo_box_set_active_iter (GTK_COMBO_BOX (combo_box), &iter);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+ * gimp_int_combo_box_get_active_user_data:
+ * @combo_box: a #GimpIntComboBox
+ * @user_data: return location for the gpointer value
+ *
+ * Retrieves the user-data of the selected (active) item in the @combo_box.
+ *
+ * Return value: %TRUE if @user_data has been set or %FALSE if no item was
+ * active.
+ *
+ * Since: 2.10
+ **/
+gboolean
+gimp_int_combo_box_get_active_user_data (GimpIntComboBox *combo_box,
+ gpointer *user_data)
+{
+ GtkTreeIter iter;
+
+ g_return_val_if_fail (GIMP_IS_INT_COMBO_BOX (combo_box), FALSE);
+ g_return_val_if_fail (user_data != NULL, FALSE);
+
+ if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (combo_box), &iter))
+ {
+ gtk_tree_model_get (gtk_combo_box_get_model (GTK_COMBO_BOX (combo_box)),
+ &iter,
+ GIMP_INT_STORE_USER_DATA, user_data,
+ -1);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
* gimp_int_combo_box_connect:
* @combo_box: a #GimpIntComboBox
* @value: the value to set
diff --git a/libgimpwidgets/gimpintcombobox.h b/libgimpwidgets/gimpintcombobox.h
index 4652742..809f57d 100644
--- a/libgimpwidgets/gimpintcombobox.h
+++ b/libgimpwidgets/gimpintcombobox.h
@@ -85,6 +85,13 @@ gboolean gimp_int_combo_box_set_active (GimpIntComboBox *combo_box,
gboolean gimp_int_combo_box_get_active (GimpIntComboBox *combo_box,
gint *value);
+gboolean
+ gimp_int_combo_box_set_active_by_user_data (GimpIntComboBox *combo_box,
+ gpointer user_data);
+gboolean
+ gimp_int_combo_box_get_active_user_data (GimpIntComboBox *combo_box,
+ gpointer *user_data);
+
gulong gimp_int_combo_box_connect (GimpIntComboBox *combo_box,
gint value,
GCallback callback,
diff --git a/libgimpwidgets/gimpintstore.c b/libgimpwidgets/gimpintstore.c
index dbd6ac2..dc74ac2 100644
--- a/libgimpwidgets/gimpintstore.c
+++ b/libgimpwidgets/gimpintstore.c
@@ -309,3 +309,42 @@ gimp_int_store_lookup_by_value (GtkTreeModel *model,
return iter_valid;
}
+
+/**
+ * gimp_int_store_lookup_by_user_data:
+ * @model: a #GimpIntStore
+ * @user_data: a gpointer "user-data" to lookup in the @model
+ * @iter: return location for the iter of the given @user_data
+ *
+ * Iterate over the @model looking for @user_data.
+ *
+ * Return value: %TRUE if the user-data has been located and @iter is
+ * valid, %FALSE otherwise.
+ *
+ * Since: 2.10
+ **/
+gboolean
+gimp_int_store_lookup_by_user_data (GtkTreeModel *model,
+ gpointer user_data,
+ GtkTreeIter *iter)
+{
+ gboolean iter_valid = FALSE;
+
+ g_return_val_if_fail (GTK_IS_TREE_MODEL (model), FALSE);
+ g_return_val_if_fail (iter != NULL, FALSE);
+
+ for (iter_valid = gtk_tree_model_get_iter_first (model, iter);
+ iter_valid;
+ iter_valid = gtk_tree_model_iter_next (model, iter))
+ {
+ gpointer this;
+
+ gtk_tree_model_get (model, iter,
+ GIMP_INT_STORE_USER_DATA, &this,
+ -1);
+ if (this == user_data)
+ break;
+ }
+
+ return (gboolean) iter_valid;
+}
diff --git a/libgimpwidgets/gimpintstore.h b/libgimpwidgets/gimpintstore.h
index d819893..f77d0de 100644
--- a/libgimpwidgets/gimpintstore.h
+++ b/libgimpwidgets/gimpintstore.h
@@ -92,6 +92,9 @@ GtkListStore * gimp_int_store_new (void);
gboolean gimp_int_store_lookup_by_value (GtkTreeModel *model,
gint value,
GtkTreeIter *iter);
+gboolean gimp_int_store_lookup_by_user_data (GtkTreeModel *model,
+ gpointer user_data,
+ GtkTreeIter *iter);
G_END_DECLS
diff --git a/libgimpwidgets/gimppropwidgets.c b/libgimpwidgets/gimppropwidgets.c
index 37e91ce..96f9a11 100644
--- a/libgimpwidgets/gimppropwidgets.c
+++ b/libgimpwidgets/gimppropwidgets.c
@@ -337,11 +337,17 @@ gimp_prop_enum_check_button_notify (GObject *config,
/* int/enum combo box */
/*************************/
-static void gimp_prop_int_combo_box_callback (GtkWidget *widget,
- GObject *config);
-static void gimp_prop_int_combo_box_notify (GObject *config,
- GParamSpec *param_spec,
- GtkWidget *widget);
+static void gimp_prop_int_combo_box_callback (GtkWidget *widget,
+ GObject *config);
+static void gimp_prop_int_combo_box_notify (GObject *config,
+ GParamSpec *param_spec,
+ GtkWidget *widget);
+
+static void gimp_prop_pointer_combo_box_callback (GtkWidget *widget,
+ GObject *config);
+static void gimp_prop_pointer_combo_box_notify (GObject *config,
+ GParamSpec *param_spec,
+ GtkWidget *combo_box);
/**
* gimp_prop_int_combo_box_new:
@@ -398,6 +404,72 @@ gimp_prop_int_combo_box_new (GObject *config,
}
/**
+ * gimp_prop_pointer_combo_box_new:
+ * @config: Object to which property is attached.
+ * @property_name: Name of GType/gpointer property controlled by combo box.
+ * @store: #GimpIntStore holding list of labels, values, etc.
+ *
+ * Creates a #GimpIntComboBox widget to display and set the specified
+ * property. The contents of the widget are determined by @store,
+ * which should be created using gimp_int_store_new().
+ * Values are GType/gpointer data, and therefore must be stored in the
+ * "user-data" column, instead of the usual "value" column.
+ *
+ * Return value: The newly created #GimpIntComboBox widget.
+ *
+ * Since GIMP 2.10
+ */
+GtkWidget *
+gimp_prop_pointer_combo_box_new (GObject *config,
+ const gchar *property_name,
+ GimpIntStore *store)
+{
+ GParamSpec *param_spec;
+ GtkWidget *combo_box;
+ gpointer property_value;
+
+ 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,
+ G_TYPE_PARAM_GTYPE, G_STRFUNC);
+ if (! param_spec)
+ {
+ param_spec = check_param_spec_w (config, property_name,
+ G_TYPE_PARAM_POINTER, G_STRFUNC);
+ if (! param_spec)
+ return NULL;
+ }
+
+ g_object_get (config,
+ property_name, &property_value,
+ NULL);
+
+ /* We use a GimpIntComboBox but we cannot store gpointer in the
+ * "value" column, because gpointer is not a subset of gint. Instead
+ * we store the value in the "user-data" column which is a gpointer.
+ */
+ combo_box = g_object_new (GIMP_TYPE_INT_COMBO_BOX,
+ "model", store,
+ NULL);
+
+ gimp_int_combo_box_set_active_by_user_data (GIMP_INT_COMBO_BOX (combo_box),
+ property_value);
+
+ g_signal_connect (combo_box, "changed",
+ G_CALLBACK (gimp_prop_pointer_combo_box_callback),
+ config);
+
+ set_param_spec (G_OBJECT (combo_box), combo_box, param_spec);
+
+ connect_notify (config, property_name,
+ G_CALLBACK (gimp_prop_pointer_combo_box_notify),
+ combo_box);
+
+ return combo_box;
+}
+
+/**
* gimp_prop_enum_combo_box_new:
* @config: Object to which property is attached.
* @property_name: Name of enum property controlled by combo box.
@@ -510,6 +582,48 @@ gimp_prop_int_combo_box_notify (GObject *config,
config);
}
+static void
+gimp_prop_pointer_combo_box_callback (GtkWidget *widget,
+ GObject *config)
+{
+ GParamSpec *param_spec;
+ gpointer value;
+
+ param_spec = get_param_spec (G_OBJECT (widget));
+ if (! param_spec)
+ return;
+
+ if (gimp_int_combo_box_get_active_user_data (GIMP_INT_COMBO_BOX (widget),
+ &value))
+ {
+ g_object_set (config,
+ param_spec->name, value,
+ NULL);
+ }
+}
+
+static void
+gimp_prop_pointer_combo_box_notify (GObject *config,
+ GParamSpec *param_spec,
+ GtkWidget *combo_box)
+{
+ gpointer value;
+
+ g_object_get (config,
+ param_spec->name, &value,
+ NULL);
+
+ g_signal_handlers_block_by_func (combo_box,
+ gimp_prop_pointer_combo_box_callback,
+ config);
+
+ gimp_int_combo_box_set_active_by_user_data (GIMP_INT_COMBO_BOX (combo_box),
+ value);
+
+ g_signal_handlers_unblock_by_func (combo_box,
+ gimp_prop_pointer_combo_box_callback,
+ config);
+}
/************************/
/* boolean combo box */
diff --git a/libgimpwidgets/gimppropwidgets.h b/libgimpwidgets/gimppropwidgets.h
index 469e667..19dca84 100644
--- a/libgimpwidgets/gimppropwidgets.h
+++ b/libgimpwidgets/gimppropwidgets.h
@@ -55,6 +55,11 @@ GtkWidget * gimp_prop_int_combo_box_new (GObject *config,
const gchar *property_name,
GimpIntStore *store);
+/* GParamGType */
+
+GtkWidget * gimp_prop_pointer_combo_box_new (GObject *config,
+ const gchar *property_name,
+ GimpIntStore *store);
/* GParamEnum */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]