[gimp] libgimpwidgets: new GimpLabeled class and GimpLabelSpin subclass.
- From: Jehan <jehanp src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp] libgimpwidgets: new GimpLabeled class and GimpLabelSpin subclass.
- Date: Thu, 5 Nov 2020 17:19:15 +0000 (UTC)
commit 4ea2b430beaff6282115eec07639f194a11232fe
Author: Jehan <jehan girinstud io>
Date: Thu Nov 5 01:13:49 2020 +0100
libgimpwidgets: new GimpLabeled class and GimpLabelSpin subclass.
There is currently no property widget which just creates a
GimpSpinButton with a label. Just as the GimpScaleEntry was needed, this
one is as well.
I am creating a GimpLabeled abstract class which will represent various
widgets with a label. While this may seem a bit over-engineered for such
a basic feature, this will actually bring some consistency and a common
parent. In particular this can be used to get the GtkLabel with a common
interface to add them all in a common GtkSizeGroup when generating
dialogs automatically, hence make dialogs with properly aligned labels
and edition widgets.
libgimpwidgets/Makefile.gi | 4 +
libgimpwidgets/gimplabeled.c | 243 ++++++++++++++++++
libgimpwidgets/gimplabeled.h | 79 ++++++
libgimpwidgets/gimplabelspin.c | 527 ++++++++++++++++++++++++++++++++++++++
libgimpwidgets/gimplabelspin.h | 72 ++++++
libgimpwidgets/gimppropwidgets.c | 45 ++++
libgimpwidgets/gimppropwidgets.h | 5 +
libgimpwidgets/gimpwidgets.h | 2 +
libgimpwidgets/gimpwidgetstypes.h | 2 +
libgimpwidgets/meson.build | 4 +
10 files changed, 983 insertions(+)
---
diff --git a/libgimpwidgets/Makefile.gi b/libgimpwidgets/Makefile.gi
index d00854d1fc..a20897e01f 100644
--- a/libgimpwidgets/Makefile.gi
+++ b/libgimpwidgets/Makefile.gi
@@ -34,6 +34,8 @@ libgimpwidgets_introspectable_headers = \
../libgimpwidgets/gimpicons.h \
../libgimpwidgets/gimpintcombobox.h \
../libgimpwidgets/gimpintstore.h \
+ ../libgimpwidgets/gimplabeled.h \
+ ../libgimpwidgets/gimplabelspin.h \
../libgimpwidgets/gimpmemsizeentry.h \
../libgimpwidgets/gimpnumberpairentry.h \
../libgimpwidgets/gimpoffsetarea.h \
@@ -95,6 +97,8 @@ libgimpwidgets_introspectable = \
../libgimpwidgets/gimpicons.c \
../libgimpwidgets/gimpintcombobox.c \
../libgimpwidgets/gimpintstore.c \
+ ../libgimpwidgets/gimplabeled.c \
+ ../libgimpwidgets/gimplabelspin.c \
../libgimpwidgets/gimpmemsizeentry.c \
../libgimpwidgets/gimpnumberpairentry.c \
../libgimpwidgets/gimpoffsetarea.c \
diff --git a/libgimpwidgets/gimplabeled.c b/libgimpwidgets/gimplabeled.c
new file mode 100644
index 0000000000..f39a8b8739
--- /dev/null
+++ b/libgimpwidgets/gimplabeled.c
@@ -0,0 +1,243 @@
+/* LIBGIMP - The GIMP Library
+ * Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
+ *
+ * gimplabeled.c
+ * Copyright (C) 2020 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
+ * Library 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 <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpmath/gimpmath.h"
+#include "libgimpbase/gimpbase.h"
+
+#include "gimpwidgets.h"
+
+
+/**
+ * SECTION: gimplabeled
+ * @title: GimpLabeled
+ * @short_description: Widget containing a label as mnemonic for another
+ * widget.
+ *
+ * This widget is a #GtkGrid showing a #GtkLabel used as mnemonic on
+ * another widget.
+ **/
+
+enum
+{
+ PROP_0,
+ PROP_LABEL,
+};
+
+typedef struct _GimpLabeledPrivate
+{
+ GtkWidget *label;
+ GtkWidget *mnemonic_widget;
+} GimpLabeledPrivate;
+
+
+static void gimp_labeled_constructed (GObject *object);
+static void gimp_labeled_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec);
+static void gimp_labeled_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec);
+
+G_DEFINE_TYPE_WITH_PRIVATE (GimpLabeled, gimp_labeled, GTK_TYPE_GRID)
+
+#define parent_class gimp_labeled_parent_class
+
+
+static void
+gimp_labeled_class_init (GimpLabeledClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->constructed = gimp_labeled_constructed;
+ object_class->set_property = gimp_labeled_set_property;
+ object_class->get_property = gimp_labeled_get_property;
+
+ /**
+ * GimpLabeled:label:
+ *
+ * Label text with pango markup and mnemonic.
+ *
+ * Since: 3.0
+ **/
+ g_object_class_install_property (object_class, PROP_LABEL,
+ g_param_spec_string ("label",
+ "Label text",
+ "The text of the label part of this widget",
+ NULL,
+ GIMP_PARAM_READWRITE));
+}
+
+static void
+gimp_labeled_init (GimpLabeled *labeled)
+{
+}
+
+static void
+gimp_labeled_constructed (GObject *object)
+{
+ GimpLabeledClass *klass;
+ GimpLabeled *labeled = GIMP_LABELED (object);
+ GimpLabeledPrivate *priv = gimp_labeled_get_instance_private (labeled);
+ gint x = 0;
+ gint y = 0;
+ gint width = 1;
+ gint height = 1;
+
+ G_OBJECT_CLASS (parent_class)->constructed (object);
+
+ priv->label = gtk_label_new_with_mnemonic (NULL);
+ gtk_label_set_xalign (GTK_LABEL (priv->label), 0.0);
+
+ klass = GIMP_LABELED_GET_CLASS (labeled);
+ g_return_if_fail (klass->populate);
+ priv->mnemonic_widget = klass->populate (labeled, &x, &y, &width, &height);
+
+ if (priv->mnemonic_widget)
+ gtk_label_set_mnemonic_widget (GTK_LABEL (priv->label), priv->mnemonic_widget);
+
+ gtk_grid_attach (GTK_GRID (labeled), priv->label, x, y, width, height);
+ gtk_widget_show (priv->label);
+}
+
+static void
+gimp_labeled_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GimpLabeled *entry = GIMP_LABELED (object);
+ GimpLabeledPrivate *priv = gimp_labeled_get_instance_private (entry);
+
+ switch (property_id)
+ {
+ case PROP_LABEL:
+ {
+ /* This should not happen since the property is **not** set with
+ * G_PARAM_CONSTRUCT, hence the label should exist when the
+ * property is first set.
+ */
+ g_return_if_fail (priv->label);
+
+ gtk_label_set_markup_with_mnemonic (GTK_LABEL (priv->label),
+ g_value_get_string (value));
+ }
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void
+gimp_labeled_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GimpLabeled *entry = GIMP_LABELED (object);
+ GimpLabeledPrivate *priv = gimp_labeled_get_instance_private (entry);
+
+ switch (property_id)
+ {
+ case PROP_LABEL:
+ g_value_set_string (value, gtk_label_get_label (GTK_LABEL (priv->label)));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+/* Public functions */
+
+/**
+ * gimp_labeled_get_label:
+ * @labeled: The #GimpLabeled.
+ *
+ * This function returns the #GtkLabel packed in @labeled. This can be
+ * useful if you need to customize some aspects of the widget.
+ *
+ * Returns: (transfer none): The #GtkLabel contained in @labeled.
+ **/
+GtkWidget *
+gimp_labeled_get_label (GimpLabeled *labeled)
+{
+ GimpLabeledPrivate *priv = gimp_labeled_get_instance_private (labeled);
+
+ g_return_val_if_fail (GIMP_IS_LABELED (labeled), NULL);
+
+ return priv->label;
+}
+
+/**
+ * gimp_labeled_get_text:
+ * @labeled: the #GimpLabeled.
+ *
+ * This function will return exactly what you entered with
+ * gimp_labeled_set_text() or through the "label" property because this
+ * class expects labels to have mnemonics (and allows Pango formatting).
+ * To obtain instead the text as displayed with mnemonics and markup
+ * removed, call:
+ * |[<!-- language="C" -->
+ * gtk_label_get_text (GTK_LABEL (gimp_labeled_get_label (@labeled)));
+ * ]|
+ *
+ * Returns: the label text as entered, which includes pango markup and
+ * mnemonics similarly to gtk_label_get_label().
+ */
+const gchar *
+gimp_labeled_get_text (GimpLabeled *labeled)
+{
+ GimpLabeledPrivate *priv = gimp_labeled_get_instance_private (labeled);
+
+ g_return_val_if_fail (GIMP_IS_LABELED (labeled), NULL);
+
+ return gtk_label_get_label (GTK_LABEL (priv->label));
+}
+
+/**
+ * gimp_labeled_set_text:
+ * @labeled: the #GimpLabeled.
+ * @text: label text with Pango markup and mnemonic.
+ *
+ * This is the equivalent of running
+ * gtk_label_set_markup_with_mnemonic() on the #GtkLabel as a
+ * #GimpLabeled expects a mnemonic. Pango markup are also allowed.
+ */
+void
+gimp_labeled_set_text (GimpLabeled *labeled,
+ const gchar *text)
+{
+ GimpLabeledPrivate *priv = gimp_labeled_get_instance_private (labeled);
+
+ g_return_if_fail (GIMP_IS_LABELED (labeled));
+
+ gtk_label_set_markup_with_mnemonic (GTK_LABEL (priv->label), text);
+}
diff --git a/libgimpwidgets/gimplabeled.h b/libgimpwidgets/gimplabeled.h
new file mode 100644
index 0000000000..e0a5aa019b
--- /dev/null
+++ b/libgimpwidgets/gimplabeled.h
@@ -0,0 +1,79 @@
+/* LIBGIMP - The GIMP Library
+ * Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
+ *
+ * gimplabeled.h
+ * Copyright (C) 2020 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_WIDGETS_H_INSIDE__) && !defined (GIMP_WIDGETS_COMPILATION)
+#error "Only <libgimpwidgets/gimpwidgets.h> can be included directly."
+#endif
+
+#ifndef __GIMP_LABELED_H__
+#define __GIMP_LABELED_H__
+
+G_BEGIN_DECLS
+
+#define GIMP_TYPE_LABELED (gimp_labeled_get_type ())
+G_DECLARE_DERIVABLE_TYPE (GimpLabeled, gimp_labeled, GIMP, LABELED, GtkGrid)
+
+struct _GimpLabeledClass
+{
+ GtkGridClass parent_class;
+
+ /* Class methods */
+
+ /**
+ * GimpLabelledClass::populate:
+ *
+ * Fill the #GtkGrid with any necessary widget and sets the
+ * coordinates and dimensions the #GtkLabel should be attached to.
+ * By default, @x, @y, @width and @height will be pre-filled with 0,
+ * 0, 1 and 1 respectively, i.e. the top-left of the grid. There is no
+ * need to edit these output variables unless your subclass wants the
+ * label to be placed elsewhere.
+ *
+ * Returns: (transfer none): the #GtkWidget which the label must be
+ * set as mnemonic to.
+ **/
+ GtkWidget * (* populate) (GimpLabeled *labeled,
+ gint *x,
+ gint *y,
+ gint *width,
+ gint *height);
+
+ /* Padding for future expansion */
+ void (* _gimp_reserved1) (void);
+ void (* _gimp_reserved2) (void);
+ void (* _gimp_reserved3) (void);
+ void (* _gimp_reserved4) (void);
+ void (* _gimp_reserved5) (void);
+ void (* _gimp_reserved6) (void);
+ void (* _gimp_reserved7) (void);
+ void (* _gimp_reserved8) (void);
+};
+
+GtkWidget * gimp_labeled_get_label (GimpLabeled *labeled);
+
+const gchar * gimp_labeled_get_text (GimpLabeled *labeled);
+void gimp_labeled_set_text (GimpLabeled *labeled,
+ const gchar *text);
+
+
+G_END_DECLS
+
+#endif /* __GIMP_LABELED_H__ */
diff --git a/libgimpwidgets/gimplabelspin.c b/libgimpwidgets/gimplabelspin.c
new file mode 100644
index 0000000000..55f37a24db
--- /dev/null
+++ b/libgimpwidgets/gimplabelspin.c
@@ -0,0 +1,527 @@
+/* LIBGIMP - The GIMP Library
+ * Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
+ *
+ * gimplabelspin.c
+ * Copyright (C) 2020 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
+ * Library 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 <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpcolor/gimpcolor.h"
+#include "libgimpmath/gimpmath.h"
+#include "libgimpbase/gimpbase.h"
+
+#include "gimpwidgets.h"
+
+
+/**
+ * SECTION: gimplabelspin
+ * @title: GimpLabelSpin
+ * @short_description: Widget containing a spin button and a label.
+ *
+ * This widget is a subclass of #GimpLabeled with a #GimpSpinButton.
+ **/
+
+enum
+{
+ VALUE_CHANGED,
+ LAST_SIGNAL
+};
+
+enum
+{
+ PROP_0,
+ PROP_VALUE,
+ PROP_LOWER,
+ PROP_UPPER,
+ PROP_DIGITS,
+};
+
+typedef struct _GimpLabelSpinPrivate
+{
+ GimpLabeled parent_instance;
+
+ GtkWidget *spinbutton;
+ GtkAdjustment *spin_adjustment;
+} GimpLabelSpinPrivate;
+
+static void gimp_label_spin_constructed (GObject *object);
+static void gimp_label_spin_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec);
+static void gimp_label_spin_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec);
+
+static GtkWidget * gimp_label_spin_populate (GimpLabeled *spin,
+ gint *x,
+ gint *y,
+ gint *width,
+ gint *height);
+
+static void gimp_label_spin_update_spin_width (GimpLabelSpin *spin);
+static void gimp_label_spin_update_increments (GimpLabelSpin *spin);
+
+G_DEFINE_TYPE_WITH_PRIVATE (GimpLabelSpin, gimp_label_spin, GIMP_TYPE_LABELED)
+
+#define parent_class gimp_label_spin_parent_class
+
+static guint gimp_label_spin_signals[LAST_SIGNAL] = { 0 };
+
+static void
+gimp_label_spin_class_init (GimpLabelSpinClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GimpLabeledClass *labeled_class = GIMP_LABELED_CLASS (klass);
+
+ gimp_label_spin_signals[VALUE_CHANGED] =
+ g_signal_new ("value-changed",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (GimpLabelSpinClass, value_changed),
+ NULL, NULL, NULL,
+ G_TYPE_NONE, 0);
+
+ object_class->constructed = gimp_label_spin_constructed;
+ object_class->set_property = gimp_label_spin_set_property;
+ object_class->get_property = gimp_label_spin_get_property;
+
+ labeled_class->populate = gimp_label_spin_populate;
+
+ /**
+ * GimpLabelSpin:value:
+ *
+ * The currently set value.
+ *
+ * Since: 3.0
+ **/
+ g_object_class_install_property (object_class, PROP_VALUE,
+ g_param_spec_double ("value", NULL,
+ "Current value",
+ -G_MAXDOUBLE, G_MAXDOUBLE, 1.0,
+ GIMP_PARAM_READWRITE));
+
+ /**
+ * GimpLabelSpin:lower:
+ *
+ * The lower bound of the spin button.
+ *
+ * Since: 3.0
+ **/
+ g_object_class_install_property (object_class, PROP_LOWER,
+ g_param_spec_double ("lower", NULL,
+ "Minimum value",
+ -G_MAXDOUBLE, G_MAXDOUBLE, 1.0,
+ GIMP_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT));
+
+ /**
+ * GimpLabelSpin:upper:
+ *
+ * The upper bound of the spin button.
+ *
+ * Since: 3.0
+ **/
+ g_object_class_install_property (object_class, PROP_UPPER,
+ g_param_spec_double ("upper", NULL,
+ "Max value",
+ -G_MAXDOUBLE, G_MAXDOUBLE, 0.0,
+ GIMP_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT));
+
+ /**
+ * GimpLabelSpin:digits:
+ *
+ * The number of decimal places to display.
+ *
+ * Since: 3.0
+ **/
+ g_object_class_install_property (object_class, PROP_DIGITS,
+ g_param_spec_uint ("digits", NULL,
+ "The number of decimal places to display",
+ 0, G_MAXUINT, 2,
+ GIMP_PARAM_READWRITE));
+}
+
+static void
+gimp_label_spin_init (GimpLabelSpin *spin)
+{
+ GimpLabelSpinPrivate *priv = gimp_label_spin_get_instance_private (spin);
+
+ /* We want the adjustment to exist at init so that construction
+ * properties can apply (default values are bogus but should be
+ * properly overrided with expected values if the object was created
+ * with gimp_label_spin_new().
+ */
+ priv->spin_adjustment = gtk_adjustment_new (0.0, 0.0, 100.0, 1.0, 10.0, 0.0);
+
+ gtk_grid_set_row_spacing (GTK_GRID (spin), 6);
+ gtk_grid_set_column_spacing (GTK_GRID (spin), 6);
+}
+
+static void
+gimp_label_spin_constructed (GObject *object)
+{
+ GimpLabelSpin *spin = GIMP_LABEL_SPIN (object);
+ GimpLabelSpinPrivate *priv = gimp_label_spin_get_instance_private (spin);
+
+ G_OBJECT_CLASS (parent_class)->constructed (object);
+
+ /* This is important to make this object into a property widget. It
+ * will allow config object to bind the "value" property of this
+ * widget, and therefore be updated automatically.
+ */
+ g_object_bind_property (G_OBJECT (priv->spin_adjustment), "value",
+ G_OBJECT (spin), "value",
+ G_BINDING_BIDIRECTIONAL |
+ G_BINDING_SYNC_CREATE);
+
+ gimp_label_spin_update_spin_width (spin);
+ gimp_label_spin_update_increments (spin);
+}
+
+static void
+gimp_label_spin_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GimpLabelSpin *spin = GIMP_LABEL_SPIN (object);
+ GimpLabelSpinPrivate *priv = gimp_label_spin_get_instance_private (spin);
+
+ switch (property_id)
+ {
+ case PROP_VALUE:
+ /* Avoid looping forever since we have bound this widget's
+ * "value" property with the spin button "value" property.
+ */
+ if (gtk_adjustment_get_value (priv->spin_adjustment) != g_value_get_double (value))
+ gtk_adjustment_set_value (priv->spin_adjustment, g_value_get_double (value));
+
+ g_signal_emit (object, gimp_label_spin_signals[VALUE_CHANGED], 0);
+ break;
+ case PROP_LOWER:
+ gtk_adjustment_set_lower (priv->spin_adjustment,
+ g_value_get_double (value));
+ if (priv->spinbutton)
+ {
+ gimp_label_spin_update_spin_width (spin);
+ gimp_label_spin_update_increments (spin);
+ }
+ break;
+ case PROP_UPPER:
+ gtk_adjustment_set_upper (priv->spin_adjustment,
+ g_value_get_double (value));
+ if (priv->spinbutton)
+ {
+ gimp_label_spin_update_spin_width (spin);
+ gimp_label_spin_update_increments (spin);
+ }
+ break;
+ case PROP_DIGITS:
+ if (priv->spinbutton)
+ {
+ gtk_spin_button_set_digits (GTK_SPIN_BUTTON (priv->spinbutton),
+ g_value_get_uint (value));
+
+ gimp_label_spin_update_spin_width (spin);
+ gimp_label_spin_update_increments (spin);
+ }
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void
+gimp_label_spin_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GimpLabelSpin *spin = GIMP_LABEL_SPIN (object);
+ GimpLabelSpinPrivate *priv = gimp_label_spin_get_instance_private (spin);
+ GtkSpinButton *spinbutton = GTK_SPIN_BUTTON (priv->spinbutton);
+
+ switch (property_id)
+ {
+ case PROP_VALUE:
+ g_value_set_double (value, gtk_adjustment_get_value (priv->spin_adjustment));
+ break;
+ case PROP_LOWER:
+ g_value_set_double (value, gtk_adjustment_get_lower (priv->spin_adjustment));
+ break;
+ case PROP_UPPER:
+ g_value_set_double (value, gtk_adjustment_get_upper (priv->spin_adjustment));
+ break;
+ case PROP_DIGITS:
+ g_value_set_uint (value, gtk_spin_button_get_digits (spinbutton));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static GtkWidget *
+gimp_label_spin_populate (GimpLabeled *labeled,
+ gint *x,
+ gint *y,
+ gint *width,
+ gint *height)
+{
+ GimpLabelSpin *spin = GIMP_LABEL_SPIN (labeled);
+ GimpLabelSpinPrivate *priv = gimp_label_spin_get_instance_private (spin);
+
+ priv->spinbutton = gimp_spin_button_new (priv->spin_adjustment, 2.0, 2.0);
+ gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (priv->spinbutton), TRUE);
+
+ gtk_grid_attach (GTK_GRID (spin), priv->spinbutton, 1, 0, 1, 1);
+ gtk_widget_show (priv->spinbutton);
+
+ return priv->spinbutton;
+}
+
+static void
+gimp_label_spin_update_spin_width (GimpLabelSpin *spin)
+{
+ GimpLabelSpinPrivate *priv = gimp_label_spin_get_instance_private (spin);
+ gint width = 0;
+ gdouble lower;
+ gdouble upper;
+ gint digits;
+
+ g_return_if_fail (GIMP_IS_LABEL_SPIN (spin));
+
+ g_object_get (spin,
+ "lower", &lower,
+ "upper", &upper,
+ "digits", &digits,
+ NULL);
+
+ /* Necessary size to display the max/min integer values, with optional
+ * negative sign.
+ */
+ width = (gint) floor (log10 (upper) + 1) + (upper < 0.0 ? 1 : 0);
+ width = MAX (width, (gint) floor (log10 (lower) + 1) + (lower < 0.0 ? 1 : 0));
+
+ /* Adding decimal digits and separator. */
+ width += (digits > 0 ? 1 + digits : 0);
+
+ /* Overlong spin button are useless. */
+ width = MIN (10, width);
+
+ gtk_entry_set_width_chars (GTK_ENTRY (priv->spinbutton), width);
+}
+
+static void
+gimp_label_spin_update_increments (GimpLabelSpin *spin)
+{
+ gdouble lower;
+ gdouble upper;
+ gdouble range;
+
+ g_return_if_fail (GIMP_IS_LABEL_SPIN (spin));
+
+ g_object_get (spin,
+ "lower", &lower,
+ "upper", &upper,
+ NULL);
+
+ g_return_if_fail (upper >= lower);
+
+ range = upper - lower;
+
+ if (range > 0 && range <= 1.0)
+ {
+ gdouble places = 10.0;
+ gdouble step;
+ gdouble page;
+
+ /* Compute some acceptable step and page increments always in the
+ * format `10**-X` where X is the rounded precision.
+ * So for instance:
+ * 0.8 will have increments 0.01 and 0.1.
+ * 0.3 will have increments 0.001 and 0.01.
+ * 0.06 will also have increments 0.001 and 0.01.
+ */
+ while (range * places < 5.0)
+ places *= 10.0;
+
+
+ step = 0.1 / places;
+ page = 1.0 / places;
+
+ gimp_label_spin_set_increments (spin, step, page);
+ }
+ else if (range <= 2.0)
+ {
+ gimp_label_spin_set_increments (spin, 0.01, 0.1);
+ }
+ else if (range <= 5.0)
+ {
+ gimp_label_spin_set_increments (spin, 0.1, 1.0);
+ }
+ else if (range <= 40.0)
+ {
+ gimp_label_spin_set_increments (spin, 1.0, 2.0);
+ }
+ else
+ {
+ gimp_label_spin_set_increments (spin, 1.0, 10.0);
+ }
+}
+
+
+/* Public Functions */
+
+
+/**
+ * gimp_label_spin_new:
+ * @text: The text for the #GtkLabel.
+ * @value: The initial value.
+ * @lower: The lower boundary.
+ * @upper: The upper boundary.
+ * @digits: The number of decimal digits.
+ *
+ * Returns: (transfer full): The new #GimpLabelSpin widget.
+ **/
+GtkWidget *
+gimp_label_spin_new (const gchar *text,
+ gdouble value,
+ gdouble lower,
+ gdouble upper,
+ guint digits)
+{
+ GtkWidget *labeled;
+
+ labeled = g_object_new (GIMP_TYPE_LABEL_SPIN,
+ "label", text,
+ "value", value,
+ "lower", lower,
+ "upper", upper,
+ "digits", digits,
+ NULL);
+
+ return labeled;
+}
+
+/**
+ * gimp_label_spin_set_value:
+ * @spin: The #GtkLabelSpin.
+ * @value: A new value.
+ *
+ * This function sets the value shown by @spin.
+ **/
+void
+gimp_label_spin_set_value (GimpLabelSpin *spin,
+ gdouble value)
+{
+ g_return_if_fail (GIMP_IS_LABEL_SPIN (spin));
+
+ g_object_set (spin,
+ "value", value,
+ NULL);
+}
+
+/**
+ * gimp_label_spin_get_value:
+ * @spin: The #GtkLabelSpin.
+ *
+ * This function returns the value shown by @spin.
+ *
+ * Returns: The value currently set.
+ **/
+gdouble
+gimp_label_spin_get_value (GimpLabelSpin *spin)
+{
+ gdouble value;
+
+ g_return_val_if_fail (GIMP_IS_LABEL_SPIN (spin), 0.0);
+
+ g_object_get (spin,
+ "value", &value,
+ NULL);
+ return value;
+}
+
+/**
+ * gimp_label_spin_set_increments:
+ * @spin: the #GimpLabelSpin.
+ * @step: the step increment.
+ * @page: the page increment.
+ *
+ * Set the step and page increments of the spin button.
+ * By default, these increment values are automatically computed
+ * depending on the range based on common usage. So you will likely not
+ * need to run this for most case. Yet if you want specific increments
+ * (which the widget cannot guess), you can call this function.
+ */
+void
+gimp_label_spin_set_increments (GimpLabelSpin *spin,
+ gdouble step,
+ gdouble page)
+{
+ GimpLabelSpinPrivate *priv = gimp_label_spin_get_instance_private (spin);
+ GtkSpinButton *spinbutton;
+ gdouble lower;
+ gdouble upper;
+
+ g_return_if_fail (GIMP_IS_LABEL_SPIN (spin));
+ g_return_if_fail (step < page);
+
+ spinbutton = GTK_SPIN_BUTTON (priv->spinbutton);
+
+ gtk_spin_button_get_range (spinbutton, &lower, &upper);
+ g_return_if_fail (upper >= lower);
+ g_return_if_fail (step < upper - lower && page < upper - lower);
+
+ g_object_freeze_notify (G_OBJECT (spinbutton));
+ gtk_adjustment_set_step_increment (gtk_spin_button_get_adjustment (spinbutton), step);
+ gtk_adjustment_set_page_increment (gtk_spin_button_get_adjustment (spinbutton), page);
+ g_object_thaw_notify (G_OBJECT (spinbutton));
+
+ g_object_set (priv->spinbutton,
+ "climb-rate", step,
+ NULL);
+}
+
+/**
+ * gimp_label_spin_get_spin_button:
+ * @spin: The #GimpLabelSpin
+ *
+ * This function returns the #GimpSpinButton packed in @spin.
+ *
+ * Returns: (transfer none): The #GimpSpinButton contained in @spin.
+ **/
+GtkWidget *
+gimp_label_spin_get_spin_button (GimpLabelSpin *spin)
+{
+ GimpLabelSpinPrivate *priv = gimp_label_spin_get_instance_private (spin);
+
+ g_return_val_if_fail (GIMP_IS_LABEL_SPIN (spin), NULL);
+
+ return priv->spinbutton;
+}
diff --git a/libgimpwidgets/gimplabelspin.h b/libgimpwidgets/gimplabelspin.h
new file mode 100644
index 0000000000..63316aa69c
--- /dev/null
+++ b/libgimpwidgets/gimplabelspin.h
@@ -0,0 +1,72 @@
+/* LIBGIMP - The GIMP Library
+ * Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
+ *
+ * gimpcolorscaleentry.h
+ * Copyright (C) 2020 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_WIDGETS_H_INSIDE__) && !defined (GIMP_WIDGETS_COMPILATION)
+#error "Only <libgimpwidgets/gimpwidgets.h> can be included directly."
+#endif
+
+#ifndef __GIMP_LABEL_SPIN_H__
+#define __GIMP_LABEL_SPIN_H__
+
+#include <libgimpwidgets/gimplabeled.h>
+
+G_BEGIN_DECLS
+
+#define GIMP_TYPE_LABEL_SPIN (gimp_label_spin_get_type ())
+G_DECLARE_DERIVABLE_TYPE (GimpLabelSpin, gimp_label_spin, GIMP, LABEL_SPIN, GimpLabeled)
+
+struct _GimpLabelSpinClass
+{
+ GimpLabeledClass parent_class;
+
+ /* Signals */
+ void (* value_changed) (GimpLabelSpin *spin);
+
+ /* Padding for future expansion */
+ void (* _gimp_reserved1) (void);
+ void (* _gimp_reserved2) (void);
+ void (* _gimp_reserved3) (void);
+ void (* _gimp_reserved4) (void);
+ void (* _gimp_reserved5) (void);
+ void (* _gimp_reserved6) (void);
+ void (* _gimp_reserved7) (void);
+ void (* _gimp_reserved8) (void);
+};
+
+GtkWidget * gimp_label_spin_new (const gchar *text,
+ gdouble value,
+ gdouble lower,
+ gdouble upper,
+ guint digits);
+
+void gimp_label_spin_set_value (GimpLabelSpin *spin,
+ gdouble value);
+gdouble gimp_label_spin_get_value (GimpLabelSpin *spin);
+
+void gimp_label_spin_set_increments (GimpLabelSpin *spin,
+ gdouble step,
+ gdouble page);
+
+GtkWidget * gimp_label_spin_get_spin_button (GimpLabelSpin *spin);
+
+G_END_DECLS
+
+#endif /* __GIMP_LABEL_SPIN_H__ */
diff --git a/libgimpwidgets/gimppropwidgets.c b/libgimpwidgets/gimppropwidgets.c
index 2290d44677..a9d9104cac 100644
--- a/libgimpwidgets/gimppropwidgets.c
+++ b/libgimpwidgets/gimppropwidgets.c
@@ -1395,6 +1395,51 @@ gimp_prop_spin_button_new (GObject *config,
return spinbutton;
}
+/**
+ * gimp_prop_label_spin_new:
+ * @config: Object to which property is attached.
+ * @digits: Number of digits after decimal point to display.
+ *
+ * Creates a #GimpLabelSpin to set and display the value of the
+ * specified double property.
+ *
+ * Returns: (transfer full): A new #libgimpwidgets-gimpspinbutton.
+ *
+ * Since: 2.4
+ */
+GtkWidget *
+gimp_prop_label_spin_new (GObject *config,
+ const gchar *property_name,
+ gint digits)
+{
+ const gchar *label;
+ GParamSpec *param_spec;
+ GtkWidget *widget;
+ gdouble value;
+ gdouble lower;
+ gdouble upper;
+
+ param_spec = find_param_spec (config, property_name, G_STRFUNC);
+ if (! param_spec)
+ return NULL;
+
+ if (! get_numeric_values (config,
+ param_spec, &value, &lower, &upper, G_STRFUNC))
+ return NULL;
+
+ if (! G_IS_PARAM_SPEC_DOUBLE (param_spec))
+ digits = 0;
+
+ label = g_param_spec_get_nick (param_spec);
+ widget = gimp_label_spin_new (label, value, lower, upper, digits);
+
+ g_object_bind_property (config, property_name,
+ widget, "value",
+ G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
+
+ return widget;
+}
+
/**
* gimp_prop_hscale_new:
* @config: Object to which property is attached.
diff --git a/libgimpwidgets/gimppropwidgets.h b/libgimpwidgets/gimppropwidgets.h
index 03922c5823..78adefde97 100644
--- a/libgimpwidgets/gimppropwidgets.h
+++ b/libgimpwidgets/gimppropwidgets.h
@@ -114,6 +114,11 @@ GtkWidget * gimp_prop_spin_button_new (GObject *config,
gdouble page_increment,
gint digits);
+GtkWidget * gimp_prop_label_spin_new (GObject *config,
+ const gchar *property_name,
+ gint digits);
+
+
GtkWidget * gimp_prop_hscale_new (GObject *config,
const gchar *property_name,
gdouble step_increment,
diff --git a/libgimpwidgets/gimpwidgets.h b/libgimpwidgets/gimpwidgets.h
index 7c3c866098..6b13e0ae45 100644
--- a/libgimpwidgets/gimpwidgets.h
+++ b/libgimpwidgets/gimpwidgets.h
@@ -61,6 +61,8 @@
#include <libgimpwidgets/gimpicons.h>
#include <libgimpwidgets/gimpintcombobox.h>
#include <libgimpwidgets/gimpintstore.h>
+#include <libgimpwidgets/gimplabeled.h>
+#include <libgimpwidgets/gimplabelspin.h>
#include <libgimpwidgets/gimpmemsizeentry.h>
#include <libgimpwidgets/gimpnumberpairentry.h>
#include <libgimpwidgets/gimpoffsetarea.h>
diff --git a/libgimpwidgets/gimpwidgetstypes.h b/libgimpwidgets/gimpwidgetstypes.h
index 6f868bcc1d..3177bf39e9 100644
--- a/libgimpwidgets/gimpwidgetstypes.h
+++ b/libgimpwidgets/gimpwidgetstypes.h
@@ -62,6 +62,8 @@ typedef struct _GimpFrame GimpFrame;
typedef struct _GimpHintBox GimpHintBox;
typedef struct _GimpIntComboBox GimpIntComboBox;
typedef struct _GimpIntStore GimpIntStore;
+typedef struct _GimpLabeled GimpLabeled;
+typedef struct _GimpLabelSpin GimpLabelSpin;
typedef struct _GimpMemsizeEntry GimpMemsizeEntry;
typedef struct _GimpNumberPairEntry GimpNumberPairEntry;
typedef struct _GimpOffsetArea GimpOffsetArea;
diff --git a/libgimpwidgets/meson.build b/libgimpwidgets/meson.build
index 44c781610e..beec696930 100644
--- a/libgimpwidgets/meson.build
+++ b/libgimpwidgets/meson.build
@@ -54,6 +54,8 @@ libgimpwidgets_sources_introspectable = files(
'gimpicons.c',
'gimpintcombobox.c',
'gimpintstore.c',
+ 'gimplabeled.c',
+ 'gimplabelspin.c',
'gimpmemsizeentry.c',
'gimpnumberpairentry.c',
'gimpoffsetarea.c',
@@ -126,6 +128,8 @@ libgimpwidgets_headers_introspectable = files(
'gimphintbox.h',
'gimpicons.h',
'gimpintcombobox.h',
+ 'gimplabeled.h',
+ 'gimplabelspin.h',
'gimpintstore.h',
'gimpmemsizeentry.h',
'gimpnumberpairentry.h',
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]