[gimp] libgimpwidgets: new GimpLabelColor widget (color area with a label).



commit d7fb0842a14223cb06a90b9a67d3113999bd7e38
Author: Jehan <jehan girinstud io>
Date:   Wed Feb 16 22:20:46 2022 +0100

    libgimpwidgets: new GimpLabelColor widget (color area with a label).
    
    I tried to have a not too overwhelming API, so we just ask for the label
    and initial color at construction. We keep sane defaults for the rest
    and let people tweak the result by getting the color area widgets
    themselves (if they need to force-showing flat colors or change the drag
    buttons in particular).
    
    Another thing I wondered about was the initial size of the color area.
    Without a size request or being in some container expanding its
    children (which may also be ugly), it ends up too small. I can imagine
    such widget being used especially when you want to display several
    color rectangles next to each other with a label each. So I just set it
    this way. Anyone is free to request a resize after constructing the
    object.
    
    Last but not least, the position of the label was especially of interest
    here. For my idea of a list of colors, I could definitely imagine color
    blocks aligned with vertically-oriented labels above or below. It might
    be worth adding an API for this later on.

 libgimpwidgets/Makefile.gi           |   2 +
 libgimpwidgets/gimpcolorarea.c       |   4 +-
 libgimpwidgets/gimplabelcolor.c      | 322 +++++++++++++++++++++++++++++++++++
 libgimpwidgets/gimplabelcolor.h      |  71 ++++++++
 libgimpwidgets/gimpwidgets-private.h |   3 +
 libgimpwidgets/gimpwidgets.h         |   1 +
 libgimpwidgets/gimpwidgetstypes.h    |   1 +
 libgimpwidgets/meson.build           |   2 +
 8 files changed, 404 insertions(+), 2 deletions(-)
---
diff --git a/libgimpwidgets/Makefile.gi b/libgimpwidgets/Makefile.gi
index 685f015482..d65c790c06 100644
--- a/libgimpwidgets/Makefile.gi
+++ b/libgimpwidgets/Makefile.gi
@@ -34,6 +34,7 @@ libgimpwidgets_introspectable_headers =       \
        ../libgimpwidgets/gimpicons.h                   \
        ../libgimpwidgets/gimpintcombobox.h                     \
        ../libgimpwidgets/gimpintstore.h                        \
+       ../libgimpwidgets/gimplabelcolor.h                      \
        ../libgimpwidgets/gimplabeled.h                         \
        ../libgimpwidgets/gimplabelentry.h                      \
        ../libgimpwidgets/gimplabelintwidget.h                  \
@@ -100,6 +101,7 @@ libgimpwidgets_introspectable =     \
        ../libgimpwidgets/gimpicons.c                   \
        ../libgimpwidgets/gimpintcombobox.c                     \
        ../libgimpwidgets/gimpintstore.c                        \
+       ../libgimpwidgets/gimplabelcolor.c                      \
        ../libgimpwidgets/gimplabeled.c                         \
        ../libgimpwidgets/gimplabelentry.c                      \
        ../libgimpwidgets/gimplabelintwidget.c                  \
diff --git a/libgimpwidgets/gimpcolorarea.c b/libgimpwidgets/gimpcolorarea.c
index d29bcd9b7a..0ea20d82ba 100644
--- a/libgimpwidgets/gimpcolorarea.c
+++ b/libgimpwidgets/gimpcolorarea.c
@@ -33,6 +33,7 @@
 #include "gimpcairo-utils.h"
 #include "gimpcolorarea.h"
 #include "gimpwidgetsutils.h"
+#include "gimpwidgets-private.h"
 
 
 /**
@@ -45,7 +46,6 @@
  **/
 
 
-#define RGBA_EPSILON        1e-6
 #define DRAG_PREVIEW_SIZE   32
 #define DRAG_ICON_OFFSET    -8
 
@@ -539,7 +539,7 @@ gimp_color_area_set_color (GimpColorArea *area,
 
   priv = GET_PRIVATE (area);
 
-  if (gimp_rgba_distance (&priv->color, color) < RGBA_EPSILON)
+  if (gimp_rgba_distance (&priv->color, color) < GIMP_RGBA_EPSILON)
     return;
 
   priv->color = *color;
diff --git a/libgimpwidgets/gimplabelcolor.c b/libgimpwidgets/gimplabelcolor.c
new file mode 100644
index 0000000000..a77cfb0a7e
--- /dev/null
+++ b/libgimpwidgets/gimplabelcolor.c
@@ -0,0 +1,322 @@
+/* LIBGIMP - The GIMP Library
+ * Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
+ *
+ * gimplabelcolor.c
+ * Copyright (C) 2022 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"
+#include "gimpwidgets-private.h"
+
+
+/**
+ * SECTION: gimplabelcolor
+ * @title: GimpLabelColor
+ * @short_description: Widget containing a color area and a label.
+ *
+ * This widget is a subclass of #GimpLabeled with a #GtkColor.
+ **/
+
+enum
+{
+  VALUE_CHANGED,
+  LAST_SIGNAL
+};
+
+enum
+{
+  PROP_0,
+  PROP_VALUE,
+};
+
+typedef struct _GimpLabelColorPrivate
+{
+  GtkWidget *area;
+} GimpLabelColorPrivate;
+
+static void        gimp_label_color_constructed       (GObject       *object);
+static void        gimp_label_color_set_property      (GObject       *object,
+                                                       guint          property_id,
+                                                       const GValue  *value,
+                                                       GParamSpec    *pspec);
+static void        gimp_label_color_get_property      (GObject       *object,
+                                                       guint          property_id,
+                                                       GValue        *value,
+                                                       GParamSpec    *pspec);
+
+static GtkWidget * gimp_label_color_populate          (GimpLabeled   *color,
+                                                       gint          *x,
+                                                       gint          *y,
+                                                       gint          *width,
+                                                       gint          *height);
+
+G_DEFINE_TYPE_WITH_PRIVATE (GimpLabelColor, gimp_label_color, GIMP_TYPE_LABELED)
+
+#define parent_class gimp_label_color_parent_class
+
+static guint gimp_label_color_signals[LAST_SIGNAL] = { 0 };
+
+static void
+gimp_label_color_class_init (GimpLabelColorClass *klass)
+{
+  GObjectClass     *object_class  = G_OBJECT_CLASS (klass);
+  GimpLabeledClass *labeled_class = GIMP_LABELED_CLASS (klass);
+  GimpRGB           black;
+
+  gimp_label_color_signals[VALUE_CHANGED] =
+    g_signal_new ("value-changed",
+                  G_TYPE_FROM_CLASS (klass),
+                  G_SIGNAL_RUN_FIRST,
+                  G_STRUCT_OFFSET (GimpLabelColorClass, value_changed),
+                  NULL, NULL, NULL,
+                  G_TYPE_NONE, 0);
+
+  object_class->constructed  = gimp_label_color_constructed;
+  object_class->set_property = gimp_label_color_set_property;
+  object_class->get_property = gimp_label_color_get_property;
+
+  labeled_class->populate    = gimp_label_color_populate;
+
+  /**
+   * GimpLabelColor:value:
+   *
+   * The currently set value.
+   *
+   * Since: 3.0
+   **/
+  gimp_rgba_set (&black, 0.0, 0.0, 0.0, 1.0);
+  g_object_class_install_property (object_class, PROP_VALUE,
+                                   gimp_param_spec_rgb ("value",
+                                                        "Color",
+                                                        "The displayed color",
+                                                        TRUE, &black,
+                                                        GIMP_PARAM_READWRITE |
+                                                        G_PARAM_CONSTRUCT));
+}
+
+static void
+gimp_label_color_init (GimpLabelColor *color)
+{
+  GimpLabelColorPrivate *priv = gimp_label_color_get_instance_private (color);
+  GimpRGB                black;
+
+  gimp_rgba_set (&black, 0.0, 0.0, 0.0, 1.0);
+  priv->area = gimp_color_area_new (&black, GIMP_COLOR_AREA_SMALL_CHECKS,
+                                    GDK_BUTTON1_MASK | GDK_BUTTON2_MASK);
+
+  /* Typically for a labelled color area, a small square next to your
+   * label is probably what you want to display.
+   */
+  gtk_widget_set_size_request (priv->area, 20, 20);
+}
+
+static void
+gimp_label_color_constructed (GObject *object)
+{
+  GimpLabelColor        *color = GIMP_LABEL_COLOR (object);
+  GimpLabelColorPrivate *priv  = gimp_label_color_get_instance_private (color);
+
+  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->area), "color",
+                          G_OBJECT (color),      "value",
+                          G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
+}
+
+static void
+gimp_label_color_set_property (GObject      *object,
+                               guint         property_id,
+                               const GValue *value,
+                               GParamSpec   *pspec)
+{
+  GimpLabelColor        *lcolor = GIMP_LABEL_COLOR (object);
+  GimpLabelColorPrivate *priv  = gimp_label_color_get_instance_private (lcolor);
+
+  switch (property_id)
+    {
+    case PROP_VALUE:
+        {
+          GimpRGB *new_color;
+          GimpRGB  color;
+
+          new_color = g_value_get_boxed (value);
+
+          gimp_color_area_get_color (GIMP_COLOR_AREA (priv->area), &color);
+
+          /* Avoid looping forever since we have bound this widget's
+           * "value" property with the color button "value" property.
+           */
+          if (gimp_rgba_distance (&color, new_color) >= GIMP_RGBA_EPSILON)
+            {
+              gimp_color_area_set_color (GIMP_COLOR_AREA (priv->area), new_color);
+              g_signal_emit (object, gimp_label_color_signals[VALUE_CHANGED], 0);
+            }
+        }
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+      break;
+    }
+}
+
+static void
+gimp_label_color_get_property (GObject    *object,
+                               guint       property_id,
+                               GValue     *value,
+                               GParamSpec *pspec)
+{
+  GimpLabelColor        *color = GIMP_LABEL_COLOR (object);
+  GimpLabelColorPrivate *priv  = gimp_label_color_get_instance_private (color);
+
+  switch (property_id)
+    {
+    case PROP_VALUE:
+        {
+          GimpRGB c;
+
+          gimp_color_area_get_color (GIMP_COLOR_AREA( priv->area), &c);
+
+          g_value_set_boxed (value, &c);
+        }
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+      break;
+    }
+}
+
+static GtkWidget *
+gimp_label_color_populate (GimpLabeled *labeled,
+                           gint        *x,
+                           gint        *y,
+                           gint        *width,
+                           gint        *height)
+{
+  GimpLabelColor        *color = GIMP_LABEL_COLOR (labeled);
+  GimpLabelColorPrivate *priv = gimp_label_color_get_instance_private (color);
+
+  gtk_grid_attach (GTK_GRID (color), priv->area, 1, 0, 1, 1);
+  /* Make sure the label and color won't be glued next to each other's. */
+  gtk_grid_set_column_spacing (GTK_GRID (color),
+                               4 * gtk_widget_get_scale_factor (GTK_WIDGET (color)));
+  gtk_widget_show (priv->area);
+
+  return priv->area;
+}
+
+
+/* Public Functions */
+
+
+/**
+ * gimp_label_color_new:
+ * @label:  The text for the #GtkLabel.
+ * @color:  The color displayed.
+ *
+ * Creates a #GimpLabelColor which contains a widget and displays a
+ * color area. By default, the color area is of type
+ * %GIMP_COLOR_AREA_SMALL_CHECKS, which means transparency of @color
+ * will be shown. Moreover the color is draggable to other widgets
+ * accepting color drops with buttons 1 and 2.
+ *
+ * If you wish to customize any of these default behaviours, get the
+ * #GimpColorArea with gimp_label_color_get_color_area().
+ *
+ * Returns: (transfer full): The new #GimpLabelColor widget.
+ **/
+GtkWidget *
+gimp_label_color_new (const gchar   *label,
+                      const GimpRGB *color)
+{
+  GtkWidget *labeled;
+
+  labeled = g_object_new (GIMP_TYPE_LABEL_COLOR,
+                          "label",  label,
+                          "value",  color,
+                          NULL);
+
+  return labeled;
+}
+
+/**
+ * gimp_label_color_set_value:
+ * @color: The #GtkLabelColor.
+ * @value: A new value.
+ *
+ * This function sets the value in the #GtkColor inside @color.
+ **/
+void
+gimp_label_color_set_value (GimpLabelColor *color,
+                            const GimpRGB  *value)
+{
+  g_return_if_fail (GIMP_IS_LABEL_COLOR (color));
+
+  g_object_set (color,
+                "value", value,
+                NULL);
+}
+
+/**
+ * gimp_label_color_get_value:
+ * @color: The #GtkLabelColor.
+ * @value: (out): The color to assign to the color area.
+ *
+ * This function returns the value shown by @color.
+ **/
+void
+gimp_label_color_get_value (GimpLabelColor *color,
+                            GimpRGB        *value)
+{
+  GimpLabelColorPrivate *priv = gimp_label_color_get_instance_private (color);
+
+  g_return_if_fail (GIMP_IS_LABEL_COLOR (color));
+
+  gimp_color_area_get_color (GIMP_COLOR_AREA (priv->area), value);
+}
+
+/**
+ * gimp_label_color_get_color_area:
+ * @color: The #GimpLabelColor
+ *
+ * This function returns the #GimpColorArea packed in @color.
+ *
+ * Returns: (transfer none): The #GimpColorArea packed in @color.
+ **/
+GtkWidget *
+gimp_label_color_get_color_area (GimpLabelColor *color)
+{
+  GimpLabelColorPrivate *priv = gimp_label_color_get_instance_private (color);
+
+  g_return_val_if_fail (GIMP_IS_LABEL_COLOR (color), NULL);
+
+  return priv->area;
+}
diff --git a/libgimpwidgets/gimplabelcolor.h b/libgimpwidgets/gimplabelcolor.h
new file mode 100644
index 0000000000..a104e23418
--- /dev/null
+++ b/libgimpwidgets/gimplabelcolor.h
@@ -0,0 +1,71 @@
+/* LIBGIMP - The GIMP Library
+ * Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
+ *
+ * gimplabelcolor.h
+ * Copyright (C) 2022 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_COLOR_H__
+#define __GIMP_LABEL_COLOR_H__
+
+#include <libgimpwidgets/gimplabeled.h>
+
+G_BEGIN_DECLS
+
+#define GIMP_TYPE_LABEL_COLOR (gimp_label_color_get_type ())
+G_DECLARE_DERIVABLE_TYPE (GimpLabelColor, gimp_label_color, GIMP, LABEL_COLOR, GimpLabeled)
+
+struct _GimpLabelColorClass
+{
+  GimpLabeledClass   parent_class;
+
+  /*  Signals */
+  void (* value_changed)   (GimpLabelColor *color);
+
+  /* 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_color_new            (const gchar       *label,
+                                             const GimpRGB     *color);
+
+/* TODO: it would be interesting for such a widget to have an API to
+ * customize the label being also above or below, left or right. I could
+ * imagine wanting to pretty-list several colors with specific layouts.
+ */
+
+void        gimp_label_color_set_value      (GimpLabelColor     *color,
+                                             const GimpRGB      *value);
+void        gimp_label_color_get_value      (GimpLabelColor     *color,
+                                             GimpRGB            *value);
+
+GtkWidget * gimp_label_color_get_color_area (GimpLabelColor     *color);
+
+G_END_DECLS
+
+#endif /* __GIMP_LABEL_COLOR_H__ */
diff --git a/libgimpwidgets/gimpwidgets-private.h b/libgimpwidgets/gimpwidgets-private.h
index cd6feedf47..ad095c20e7 100644
--- a/libgimpwidgets/gimpwidgets-private.h
+++ b/libgimpwidgets/gimpwidgets-private.h
@@ -22,6 +22,9 @@
 #ifndef __GIMP_WIDGETS_PRIVATE_H__
 #define __GIMP_WIDGETS_PRIVATE_H__
 
+/* Used to compare similar colors across several widgets. */
+#define GIMP_RGBA_EPSILON 1e-6
+
 
 typedef gboolean (* GimpGetColorFunc)      (GimpRGB *color);
 typedef void     (* GimpEnsureModulesFunc) (void);
diff --git a/libgimpwidgets/gimpwidgets.h b/libgimpwidgets/gimpwidgets.h
index b7dc789081..9756fd656d 100644
--- a/libgimpwidgets/gimpwidgets.h
+++ b/libgimpwidgets/gimpwidgets.h
@@ -61,6 +61,7 @@
 #include <libgimpwidgets/gimpicons.h>
 #include <libgimpwidgets/gimpintcombobox.h>
 #include <libgimpwidgets/gimpintstore.h>
+#include <libgimpwidgets/gimplabelcolor.h>
 #include <libgimpwidgets/gimplabeled.h>
 #include <libgimpwidgets/gimplabelentry.h>
 #include <libgimpwidgets/gimplabelintwidget.h>
diff --git a/libgimpwidgets/gimpwidgetstypes.h b/libgimpwidgets/gimpwidgetstypes.h
index 940698e757..2e41789a64 100644
--- a/libgimpwidgets/gimpwidgetstypes.h
+++ b/libgimpwidgets/gimpwidgetstypes.h
@@ -63,6 +63,7 @@ typedef struct _GimpHintBox                   GimpHintBox;
 typedef struct _GimpIntComboBox               GimpIntComboBox;
 typedef struct _GimpIntStore                  GimpIntStore;
 typedef struct _GimpLabeled                   GimpLabeled;
+typedef struct _GimpLabelColor                GimpLabelColor;
 typedef struct _GimpLabelEntry                GimpLabelEntry;
 typedef struct _GimpLabelSpin                 GimpLabelSpin;
 typedef struct _GimpMemsizeEntry              GimpMemsizeEntry;
diff --git a/libgimpwidgets/meson.build b/libgimpwidgets/meson.build
index 9521a69cf9..e4fa9f01ca 100644
--- a/libgimpwidgets/meson.build
+++ b/libgimpwidgets/meson.build
@@ -54,6 +54,7 @@ libgimpwidgets_sources_introspectable = files(
   'gimpicons.c',
   'gimpintcombobox.c',
   'gimpintstore.c',
+  'gimplabelcolor.c',
   'gimplabeled.c',
   'gimplabelintwidget.c',
   'gimplabelspin.c',
@@ -131,6 +132,7 @@ libgimpwidgets_headers_introspectable = files(
   'gimphintbox.h',
   'gimpicons.h',
   'gimpintcombobox.h',
+  'gimplabelcolor.h',
   'gimplabeled.h',
   'gimplabelintwidget.h',
   'gimplabelspin.h',


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]