mirror of https://github.com/GNOME/gimp.git
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.
This commit is contained in:
parent
3449652fe8
commit
4ea2b430be
|
@ -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 \
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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__ */
|
|
@ -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;
|
||||
}
|
|
@ -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__ */
|
|
@ -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.
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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',
|
||||
|
|
Loading…
Reference in New Issue