927 lines
33 KiB
C
927 lines
33 KiB
C
/* LIBPIKA - The PIKA Library
|
|
* Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
|
|
*
|
|
* pikacolorscales.c
|
|
* Copyright (C) 2002 Michael Natterer <mitch@gimp.org>
|
|
*
|
|
* based on color_notebook module
|
|
* Copyright (C) 1998 Austin Donnelly <austin@greenend.org.uk>
|
|
*
|
|
* 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 <string.h>
|
|
|
|
#include <gegl.h>
|
|
#include <gtk/gtk.h>
|
|
|
|
#include "libpikabase/pikabase.h"
|
|
#include "libpikacolor/pikacolor.h"
|
|
#include "libpikamath/pikamath.h"
|
|
|
|
#include "pikawidgetstypes.h"
|
|
|
|
#include "pikacolorscale.h"
|
|
#include "pikacolorscales.h"
|
|
#include "pikawidgets.h"
|
|
|
|
#include "libpika/libpika-intl.h"
|
|
|
|
|
|
/**
|
|
* SECTION: pikacolorscales
|
|
* @title: PikaColorScales
|
|
* @short_description: A #PikaColorSelector implementation.
|
|
*
|
|
* The #PikaColorScales widget is an implementation of a
|
|
* #PikaColorSelector. It shows a group of #PikaColorScale widgets
|
|
* that allow to adjust the HSV, LCH, and RGB color channels.
|
|
**/
|
|
|
|
|
|
enum
|
|
{
|
|
PROP_0,
|
|
PROP_SHOW_RGB_U8,
|
|
PROP_SHOW_HSV
|
|
};
|
|
|
|
enum
|
|
{
|
|
PIKA_COLOR_SELECTOR_RED_U8 = PIKA_COLOR_SELECTOR_LCH_HUE + 1,
|
|
PIKA_COLOR_SELECTOR_GREEN_U8,
|
|
PIKA_COLOR_SELECTOR_BLUE_U8,
|
|
PIKA_COLOR_SELECTOR_ALPHA_U8
|
|
};
|
|
|
|
|
|
typedef struct _PikaLCH PikaLCH;
|
|
|
|
struct _PikaLCH
|
|
{
|
|
gdouble l, c, h, a;
|
|
};
|
|
|
|
|
|
typedef struct _ColorScale ColorScale;
|
|
|
|
struct _ColorScale
|
|
{
|
|
PikaColorSelectorChannel channel;
|
|
|
|
gdouble default_value;
|
|
gdouble scale_min_value;
|
|
gdouble scale_max_value;
|
|
gdouble scale_inc;
|
|
gdouble spin_min_value;
|
|
gdouble spin_max_value;
|
|
};
|
|
|
|
|
|
#define PIKA_COLOR_SCALES_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PIKA_TYPE_COLOR_SCALES, PikaColorScalesClass))
|
|
#define PIKA_IS_COLOR_SCALES_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PIKA_TYPE_COLOR_SCALES))
|
|
#define PIKA_COLOR_SCALES_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PIKA_TYPE_COLOR_SCALES, PikaColorScalesClass))
|
|
|
|
|
|
typedef struct _PikaColorScalesClass PikaColorScalesClass;
|
|
|
|
struct _PikaColorScales
|
|
{
|
|
PikaColorSelector parent_instance;
|
|
|
|
gboolean show_rgb_u8;
|
|
GBinding *show_rgb_u8_binding;
|
|
GBinding *show_hsv_binding;
|
|
|
|
GtkWidget *lch_group;
|
|
GtkWidget *hsv_group;
|
|
GtkWidget *rgb_percent_group;
|
|
GtkWidget *rgb_u8_group;
|
|
GtkWidget *alpha_percent_group;
|
|
GtkWidget *alpha_u8_group;
|
|
|
|
GtkWidget *dummy_u8_toggle;
|
|
GtkWidget *toggles[14];
|
|
GtkWidget *scales[14];
|
|
};
|
|
|
|
struct _PikaColorScalesClass
|
|
{
|
|
PikaColorSelectorClass parent_class;
|
|
};
|
|
|
|
|
|
static void pika_color_scales_dispose (GObject *object);
|
|
static void pika_color_scales_get_property (GObject *object,
|
|
guint property_id,
|
|
GValue *value,
|
|
GParamSpec *pspec);
|
|
static void pika_color_scales_set_property (GObject *object,
|
|
guint property_id,
|
|
const GValue *value,
|
|
GParamSpec *pspec);
|
|
|
|
static void pika_color_scales_togg_sensitive (PikaColorSelector *selector,
|
|
gboolean sensitive);
|
|
static void pika_color_scales_togg_visible (PikaColorSelector *selector,
|
|
gboolean visible);
|
|
|
|
static void pika_color_scales_set_show_alpha (PikaColorSelector *selector,
|
|
gboolean show_alpha);
|
|
static void pika_color_scales_set_color (PikaColorSelector *selector,
|
|
const PikaRGB *rgb,
|
|
const PikaHSV *hsv);
|
|
static void pika_color_scales_set_channel (PikaColorSelector *selector,
|
|
PikaColorSelectorChannel channel);
|
|
static void pika_color_scales_set_model_visible
|
|
(PikaColorSelector *selector,
|
|
PikaColorSelectorModel model,
|
|
gboolean visible);
|
|
static void pika_color_scales_set_config (PikaColorSelector *selector,
|
|
PikaColorConfig *config);
|
|
|
|
static void pika_color_scales_update_visible (PikaColorScales *scales);
|
|
static void pika_color_scales_update_scales (PikaColorScales *scales,
|
|
gint skip);
|
|
static void pika_color_scales_toggle_changed (GtkWidget *widget,
|
|
PikaColorScales *scales);
|
|
static void pika_color_scales_scale_changed (GtkWidget *scale,
|
|
PikaColorScales *scales);
|
|
static void pika_color_scales_toggle_lch_hsv (GtkToggleButton *toggle,
|
|
PikaColorScales *scales);
|
|
|
|
|
|
G_DEFINE_TYPE (PikaColorScales, pika_color_scales, PIKA_TYPE_COLOR_SELECTOR)
|
|
|
|
#define parent_class pika_color_scales_parent_class
|
|
|
|
static const Babl *fish_rgb_to_lch = NULL;
|
|
static const Babl *fish_lch_to_rgb = NULL;
|
|
|
|
static const ColorScale scale_defs[] =
|
|
{
|
|
{ PIKA_COLOR_SELECTOR_HUE, 0, 0, 360, 30, 0, 360 },
|
|
{ PIKA_COLOR_SELECTOR_SATURATION, 0, 0, 100, 10, 0, 500 },
|
|
{ PIKA_COLOR_SELECTOR_VALUE, 0, 0, 100, 10, 0, 500 },
|
|
|
|
{ PIKA_COLOR_SELECTOR_RED, 0, 0, 100, 10, -500, 500 },
|
|
{ PIKA_COLOR_SELECTOR_GREEN, 0, 0, 100, 10, -500, 500 },
|
|
{ PIKA_COLOR_SELECTOR_BLUE, 0, 0, 100, 10, -500, 500 },
|
|
{ PIKA_COLOR_SELECTOR_ALPHA, 0, 0, 100, 10, 0, 100 },
|
|
|
|
{ PIKA_COLOR_SELECTOR_LCH_LIGHTNESS, 0, 0, 100, 10, 0, 300 },
|
|
{ PIKA_COLOR_SELECTOR_LCH_CHROMA, 0, 0, 200, 10, 0, 300 },
|
|
{ PIKA_COLOR_SELECTOR_LCH_HUE, 0, 0, 360, 30, 0, 360 },
|
|
|
|
{ (PikaColorSelectorChannel) PIKA_COLOR_SELECTOR_RED_U8,
|
|
0, 0, 255, 16, -1275, 1275 },
|
|
{ (PikaColorSelectorChannel) PIKA_COLOR_SELECTOR_GREEN_U8,
|
|
0, 0, 255, 16, -1275, 1275 },
|
|
{ (PikaColorSelectorChannel) PIKA_COLOR_SELECTOR_BLUE_U8,
|
|
0, 0, 255, 16, -1275, 1275 },
|
|
{ (PikaColorSelectorChannel) PIKA_COLOR_SELECTOR_ALPHA_U8,
|
|
0, 0, 255, 16, 0, 255 }
|
|
};
|
|
|
|
|
|
static void
|
|
pika_color_scales_class_init (PikaColorScalesClass *klass)
|
|
{
|
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
|
|
PikaColorSelectorClass *selector_class = PIKA_COLOR_SELECTOR_CLASS (klass);
|
|
|
|
object_class->dispose = pika_color_scales_dispose;
|
|
object_class->get_property = pika_color_scales_get_property;
|
|
object_class->set_property = pika_color_scales_set_property;
|
|
|
|
selector_class->name = _("Scales");
|
|
selector_class->help_id = "pika-colorselector-scales";
|
|
selector_class->icon_name = PIKA_ICON_DIALOG_TOOL_OPTIONS;
|
|
selector_class->set_toggles_visible = pika_color_scales_togg_visible;
|
|
selector_class->set_toggles_sensitive = pika_color_scales_togg_sensitive;
|
|
selector_class->set_show_alpha = pika_color_scales_set_show_alpha;
|
|
selector_class->set_color = pika_color_scales_set_color;
|
|
selector_class->set_channel = pika_color_scales_set_channel;
|
|
selector_class->set_model_visible = pika_color_scales_set_model_visible;
|
|
selector_class->set_config = pika_color_scales_set_config;
|
|
|
|
g_object_class_install_property (object_class, PROP_SHOW_RGB_U8,
|
|
g_param_spec_boolean ("show-rgb-u8",
|
|
"Show RGB 0..255",
|
|
"Show RGB 0..255 scales",
|
|
FALSE,
|
|
PIKA_PARAM_READWRITE |
|
|
G_PARAM_CONSTRUCT));
|
|
g_object_class_install_property (object_class, PROP_SHOW_HSV,
|
|
g_param_spec_boolean ("show-hsv",
|
|
"Show HSV",
|
|
"Show HSV instead of LCH",
|
|
FALSE,
|
|
PIKA_PARAM_READWRITE |
|
|
G_PARAM_CONSTRUCT));
|
|
|
|
gtk_widget_class_set_css_name (widget_class, "PikaColorScales");
|
|
|
|
fish_rgb_to_lch = babl_fish (babl_format ("R'G'B'A double"),
|
|
babl_format ("CIE LCH(ab) alpha double"));
|
|
fish_lch_to_rgb = babl_fish (babl_format ("CIE LCH(ab) alpha double"),
|
|
babl_format ("R'G'B'A double"));
|
|
}
|
|
|
|
static GtkWidget *
|
|
create_group (PikaColorScales *scales,
|
|
GSList **radio_group,
|
|
GtkSizeGroup *size_group0,
|
|
GtkSizeGroup *size_group1,
|
|
GtkSizeGroup *size_group2,
|
|
PikaColorSelectorChannel first_channel,
|
|
PikaColorSelectorChannel last_channel)
|
|
{
|
|
PikaColorSelector *selector = PIKA_COLOR_SELECTOR (scales);
|
|
GtkWidget *grid;
|
|
GEnumClass *enum_class;
|
|
gint row;
|
|
gint i;
|
|
|
|
grid = gtk_grid_new ();
|
|
gtk_grid_set_row_spacing (GTK_GRID (grid), 1);
|
|
gtk_grid_set_column_spacing (GTK_GRID (grid), 1);
|
|
|
|
enum_class = g_type_class_ref (PIKA_TYPE_COLOR_SELECTOR_CHANNEL);
|
|
|
|
for (i = first_channel, row = 0; i <= last_channel; i++, row++)
|
|
{
|
|
const PikaEnumDesc *enum_desc;
|
|
gint enum_value = i;
|
|
gboolean is_u8 = FALSE;
|
|
|
|
if (enum_value >= PIKA_COLOR_SELECTOR_RED_U8 &&
|
|
enum_value <= PIKA_COLOR_SELECTOR_ALPHA_U8)
|
|
{
|
|
enum_value -= 7;
|
|
is_u8 = TRUE;
|
|
}
|
|
|
|
enum_desc = pika_enum_get_desc (enum_class, enum_value);
|
|
|
|
if (i == PIKA_COLOR_SELECTOR_ALPHA ||
|
|
i == PIKA_COLOR_SELECTOR_ALPHA_U8)
|
|
{
|
|
/* just to allocate the space via the size group */
|
|
scales->toggles[i] = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
|
|
}
|
|
else
|
|
{
|
|
scales->toggles[i] = gtk_radio_button_new (*radio_group);
|
|
*radio_group =
|
|
gtk_radio_button_get_group (GTK_RADIO_BUTTON (scales->toggles[i]));
|
|
|
|
if (enum_value == pika_color_selector_get_channel (selector))
|
|
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (scales->toggles[i]),
|
|
TRUE);
|
|
|
|
if (is_u8)
|
|
{
|
|
/* bind the RGB U8 toggles to the RGB percent toggles */
|
|
g_object_bind_property (scales->toggles[i - 7], "active",
|
|
scales->toggles[i], "active",
|
|
G_BINDING_SYNC_CREATE |
|
|
G_BINDING_BIDIRECTIONAL);
|
|
}
|
|
else
|
|
{
|
|
g_signal_connect (scales->toggles[i], "toggled",
|
|
G_CALLBACK (pika_color_scales_toggle_changed),
|
|
scales);
|
|
}
|
|
}
|
|
|
|
gtk_grid_attach (GTK_GRID (grid), scales->toggles[i], 0, row, 1, 1);
|
|
|
|
if (pika_color_selector_get_toggles_visible (selector))
|
|
gtk_widget_show (scales->toggles[i]);
|
|
|
|
pika_help_set_help_data (scales->toggles[i],
|
|
gettext (enum_desc->value_help), NULL);
|
|
|
|
gtk_size_group_add_widget (size_group0, scales->toggles[i]);
|
|
|
|
scales->scales[i] =
|
|
pika_color_scale_entry_new (gettext (enum_desc->value_desc),
|
|
scale_defs[i].default_value,
|
|
scale_defs[i].spin_min_value,
|
|
scale_defs[i].spin_max_value,
|
|
1);
|
|
gtk_grid_attach (GTK_GRID (grid), scales->scales[i], 1, row, 3, 1);
|
|
pika_label_spin_set_increments (PIKA_LABEL_SPIN (scales->scales[i]),
|
|
1.0, scale_defs[i].scale_inc);
|
|
pika_help_set_help_data (scales->scales[i],
|
|
gettext (enum_desc->value_help),
|
|
NULL);
|
|
gtk_widget_show (scales->scales[i]);
|
|
|
|
pika_scale_entry_set_bounds (PIKA_SCALE_ENTRY (scales->scales[i]),
|
|
scale_defs[i].scale_min_value,
|
|
scale_defs[i].scale_max_value,
|
|
TRUE);
|
|
|
|
g_object_add_weak_pointer (G_OBJECT (scales->scales[i]),
|
|
(gpointer) &scales->scales[i]);
|
|
|
|
pika_color_scale_set_channel (PIKA_COLOR_SCALE (pika_scale_entry_get_range (PIKA_SCALE_ENTRY (scales->scales[i]))),
|
|
enum_value);
|
|
gtk_size_group_add_widget (size_group1, scales->scales[i]);
|
|
|
|
gtk_size_group_add_widget (size_group2,
|
|
pika_label_spin_get_spin_button (PIKA_LABEL_SPIN (scales->scales[i])));
|
|
|
|
g_signal_connect (scales->scales[i], "value-changed",
|
|
G_CALLBACK (pika_color_scales_scale_changed),
|
|
scales);
|
|
}
|
|
|
|
g_type_class_unref (enum_class);
|
|
|
|
return grid;
|
|
}
|
|
|
|
static void
|
|
pika_color_scales_init (PikaColorScales *scales)
|
|
{
|
|
PikaColorSelector *selector = PIKA_COLOR_SELECTOR (scales);
|
|
GtkSizeGroup *size_group0;
|
|
GtkSizeGroup *size_group1;
|
|
GtkSizeGroup *size_group2;
|
|
GtkWidget *hbox;
|
|
GtkWidget *radio1;
|
|
GtkWidget *radio2;
|
|
GtkWidget *grid;
|
|
GSList *main_group;
|
|
GSList *u8_group;
|
|
|
|
gtk_box_set_spacing (GTK_BOX (scales), 5);
|
|
|
|
scales->show_rgb_u8_binding = NULL;
|
|
scales->show_hsv_binding = NULL;
|
|
|
|
/* don't need the toggles for our own operation */
|
|
selector->toggles_visible = FALSE;
|
|
|
|
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2);
|
|
gtk_box_pack_start (GTK_BOX (scales), hbox, 0, 0, FALSE);
|
|
gtk_widget_show (hbox);
|
|
|
|
main_group = NULL;
|
|
u8_group = NULL;
|
|
|
|
scales->dummy_u8_toggle = gtk_radio_button_new (NULL);
|
|
g_object_ref_sink (scales->dummy_u8_toggle);
|
|
u8_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (scales->dummy_u8_toggle));
|
|
|
|
size_group0 = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
|
|
size_group1 = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
|
|
size_group2 = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
|
|
|
|
scales->rgb_percent_group =
|
|
grid = create_group (scales, &main_group,
|
|
size_group0, size_group1, size_group2,
|
|
PIKA_COLOR_SELECTOR_RED,
|
|
PIKA_COLOR_SELECTOR_BLUE);
|
|
gtk_box_pack_start (GTK_BOX (scales), grid, FALSE, FALSE, 0);
|
|
|
|
scales->rgb_u8_group =
|
|
grid = create_group (scales, &u8_group,
|
|
size_group0, size_group1, size_group2,
|
|
(PikaColorSelectorChannel) PIKA_COLOR_SELECTOR_RED_U8,
|
|
(PikaColorSelectorChannel) PIKA_COLOR_SELECTOR_BLUE_U8);
|
|
gtk_box_pack_start (GTK_BOX (scales), grid, FALSE, FALSE, 0);
|
|
|
|
scales->lch_group =
|
|
grid = create_group (scales, &main_group,
|
|
size_group0, size_group1, size_group2,
|
|
PIKA_COLOR_SELECTOR_LCH_LIGHTNESS,
|
|
PIKA_COLOR_SELECTOR_LCH_HUE);
|
|
gtk_box_pack_start (GTK_BOX (scales), grid, FALSE, FALSE, 0);
|
|
|
|
scales->hsv_group =
|
|
grid = create_group (scales, &main_group,
|
|
size_group0, size_group1, size_group2,
|
|
PIKA_COLOR_SELECTOR_HUE,
|
|
PIKA_COLOR_SELECTOR_VALUE);
|
|
gtk_box_pack_start (GTK_BOX (scales), grid, FALSE, FALSE, 0);
|
|
|
|
scales->alpha_percent_group =
|
|
grid = create_group (scales, &main_group,
|
|
size_group0, size_group1, size_group2,
|
|
PIKA_COLOR_SELECTOR_ALPHA,
|
|
PIKA_COLOR_SELECTOR_ALPHA);
|
|
gtk_box_pack_start (GTK_BOX (scales), grid, FALSE, FALSE, 0);
|
|
|
|
scales->alpha_u8_group =
|
|
grid = create_group (scales, &u8_group,
|
|
size_group0, size_group1, size_group2,
|
|
(PikaColorSelectorChannel) PIKA_COLOR_SELECTOR_ALPHA_U8,
|
|
(PikaColorSelectorChannel) PIKA_COLOR_SELECTOR_ALPHA_U8);
|
|
gtk_box_pack_start (GTK_BOX (scales), grid, FALSE, FALSE, 0);
|
|
|
|
g_object_unref (size_group0);
|
|
g_object_unref (size_group1);
|
|
g_object_unref (size_group2);
|
|
|
|
radio1 = gtk_radio_button_new_with_label (NULL, _("0..100"));
|
|
radio2 = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON (radio1),
|
|
_("0..255"));
|
|
|
|
gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (radio1), FALSE);
|
|
gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (radio2), FALSE);
|
|
|
|
gtk_box_pack_start (GTK_BOX (hbox), radio1, FALSE, FALSE, 0);
|
|
gtk_box_pack_start (GTK_BOX (hbox), radio2, FALSE, FALSE, 0);
|
|
|
|
gtk_widget_show (radio1);
|
|
gtk_widget_show (radio2);
|
|
|
|
if (scales->show_rgb_u8)
|
|
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (radio2), TRUE);
|
|
else
|
|
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (radio1), TRUE);
|
|
|
|
g_object_bind_property (G_OBJECT (radio2), "active",
|
|
G_OBJECT (scales), "show-rgb-u8",
|
|
G_BINDING_SYNC_CREATE |
|
|
G_BINDING_BIDIRECTIONAL);
|
|
|
|
radio1 = gtk_radio_button_new_with_label (NULL, _("LCh"));
|
|
radio2 = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON (radio1),
|
|
_("HSV"));
|
|
|
|
gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (radio1), FALSE);
|
|
gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (radio2), FALSE);
|
|
|
|
gtk_box_pack_end (GTK_BOX (hbox), radio2, FALSE, FALSE, 0);
|
|
gtk_box_pack_end (GTK_BOX (hbox), radio1, FALSE, FALSE, 0);
|
|
|
|
gtk_widget_show (radio1);
|
|
gtk_widget_show (radio2);
|
|
|
|
if (pika_color_selector_get_model_visible (selector,
|
|
PIKA_COLOR_SELECTOR_MODEL_HSV))
|
|
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (radio2), TRUE);
|
|
else
|
|
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (radio1), TRUE);
|
|
|
|
g_object_bind_property (G_OBJECT (radio2), "active",
|
|
G_OBJECT (scales), "show-hsv",
|
|
G_BINDING_SYNC_CREATE |
|
|
G_BINDING_BIDIRECTIONAL);
|
|
|
|
g_signal_connect (radio1, "toggled",
|
|
G_CALLBACK (pika_color_scales_toggle_lch_hsv),
|
|
scales);
|
|
|
|
pika_color_scales_update_visible (scales);
|
|
}
|
|
|
|
static void
|
|
pika_color_scales_dispose (GObject *object)
|
|
{
|
|
PikaColorScales *scales = PIKA_COLOR_SCALES (object);
|
|
|
|
g_clear_object (&scales->dummy_u8_toggle);
|
|
|
|
g_clear_pointer (&scales->show_rgb_u8_binding, g_binding_unbind);
|
|
g_clear_pointer (&scales->show_hsv_binding, g_binding_unbind);
|
|
|
|
G_OBJECT_CLASS (parent_class)->dispose (object);
|
|
}
|
|
|
|
static void
|
|
pika_color_scales_get_property (GObject *object,
|
|
guint property_id,
|
|
GValue *value,
|
|
GParamSpec *pspec)
|
|
{
|
|
PikaColorScales *scales = PIKA_COLOR_SCALES (object);
|
|
gboolean hsv;
|
|
|
|
switch (property_id)
|
|
{
|
|
case PROP_SHOW_RGB_U8:
|
|
g_value_set_boolean (value, scales->show_rgb_u8);
|
|
break;
|
|
case PROP_SHOW_HSV:
|
|
hsv = pika_color_selector_get_model_visible (PIKA_COLOR_SELECTOR (object),
|
|
PIKA_COLOR_SELECTOR_MODEL_HSV);
|
|
g_value_set_boolean (value, hsv);
|
|
break;
|
|
|
|
default:
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
pika_color_scales_set_property (GObject *object,
|
|
guint property_id,
|
|
const GValue *value,
|
|
GParamSpec *pspec)
|
|
{
|
|
PikaColorScales *scales = PIKA_COLOR_SCALES (object);
|
|
gboolean show_hsv;
|
|
|
|
switch (property_id)
|
|
{
|
|
case PROP_SHOW_RGB_U8:
|
|
pika_color_scales_set_show_rgb_u8 (scales, g_value_get_boolean (value));
|
|
break;
|
|
case PROP_SHOW_HSV:
|
|
show_hsv = g_value_get_boolean (value);
|
|
|
|
pika_color_selector_set_model_visible (PIKA_COLOR_SELECTOR (object),
|
|
PIKA_COLOR_SELECTOR_MODEL_LCH,
|
|
! show_hsv);
|
|
pika_color_selector_set_model_visible (PIKA_COLOR_SELECTOR (object),
|
|
PIKA_COLOR_SELECTOR_MODEL_HSV,
|
|
show_hsv);
|
|
break;
|
|
|
|
default:
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
pika_color_scales_togg_sensitive (PikaColorSelector *selector,
|
|
gboolean sensitive)
|
|
{
|
|
PikaColorScales *scales = PIKA_COLOR_SCALES (selector);
|
|
gint i;
|
|
|
|
for (i = 0; i < G_N_ELEMENTS (scale_defs); i++)
|
|
if (scales->toggles[i])
|
|
gtk_widget_set_sensitive (scales->toggles[i], sensitive);
|
|
}
|
|
|
|
static void
|
|
pika_color_scales_togg_visible (PikaColorSelector *selector,
|
|
gboolean visible)
|
|
{
|
|
PikaColorScales *scales = PIKA_COLOR_SCALES (selector);
|
|
gint i;
|
|
|
|
for (i = 0; i < G_N_ELEMENTS (scale_defs); i++)
|
|
if (scales->toggles[i])
|
|
gtk_widget_set_visible (scales->toggles[i], visible);
|
|
}
|
|
|
|
static void
|
|
pika_color_scales_set_show_alpha (PikaColorSelector *selector,
|
|
gboolean show_alpha)
|
|
{
|
|
pika_color_scales_update_visible (PIKA_COLOR_SCALES (selector));
|
|
}
|
|
|
|
static void
|
|
pika_color_scales_set_color (PikaColorSelector *selector,
|
|
const PikaRGB *rgb,
|
|
const PikaHSV *hsv)
|
|
{
|
|
PikaColorScales *scales = PIKA_COLOR_SCALES (selector);
|
|
|
|
pika_color_scales_update_scales (scales, -1);
|
|
}
|
|
|
|
static void
|
|
pika_color_scales_set_channel (PikaColorSelector *selector,
|
|
PikaColorSelectorChannel channel)
|
|
{
|
|
PikaColorScales *scales = PIKA_COLOR_SCALES (selector);
|
|
|
|
if (GTK_IS_RADIO_BUTTON (scales->toggles[channel]))
|
|
{
|
|
g_signal_handlers_block_by_func (scales->toggles[channel],
|
|
pika_color_scales_toggle_changed,
|
|
scales);
|
|
|
|
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (scales->toggles[channel]),
|
|
TRUE);
|
|
|
|
g_signal_handlers_unblock_by_func (scales->toggles[channel],
|
|
pika_color_scales_toggle_changed,
|
|
scales);
|
|
}
|
|
}
|
|
|
|
static void
|
|
pika_color_scales_set_model_visible (PikaColorSelector *selector,
|
|
PikaColorSelectorModel model,
|
|
gboolean visible)
|
|
{
|
|
pika_color_scales_update_visible (PIKA_COLOR_SCALES (selector));
|
|
}
|
|
|
|
static void
|
|
pika_color_scales_set_config (PikaColorSelector *selector,
|
|
PikaColorConfig *config)
|
|
{
|
|
PikaColorScales *scales = PIKA_COLOR_SCALES (selector);
|
|
gint i;
|
|
|
|
g_clear_pointer (&scales->show_rgb_u8_binding, g_binding_unbind);
|
|
g_clear_pointer (&scales->show_hsv_binding, g_binding_unbind);
|
|
|
|
if (config)
|
|
{
|
|
scales->show_rgb_u8_binding = g_object_bind_property (config, "show-rgb-u8",
|
|
scales, "show-rgb-u8",
|
|
G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
|
|
scales->show_hsv_binding = g_object_bind_property (config, "show-hsv",
|
|
scales, "show-hsv",
|
|
G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
|
|
}
|
|
|
|
|
|
for (i = 0; i < G_N_ELEMENTS (scale_defs); i++)
|
|
{
|
|
if (scales->scales[i])
|
|
pika_color_scale_set_color_config (PIKA_COLOR_SCALE (pika_scale_entry_get_range (PIKA_SCALE_ENTRY (scales->scales[i]))),
|
|
config);
|
|
}
|
|
}
|
|
|
|
|
|
/* public functions */
|
|
|
|
void
|
|
pika_color_scales_set_show_rgb_u8 (PikaColorScales *scales,
|
|
gboolean show_rgb_u8)
|
|
{
|
|
g_return_if_fail (PIKA_IS_COLOR_SCALES (scales));
|
|
|
|
show_rgb_u8 = show_rgb_u8 ? TRUE : FALSE;
|
|
|
|
if (show_rgb_u8 != scales->show_rgb_u8)
|
|
{
|
|
scales->show_rgb_u8 = show_rgb_u8;
|
|
|
|
g_object_notify (G_OBJECT (scales), "show-rgb-u8");
|
|
|
|
pika_color_scales_update_visible (scales);
|
|
}
|
|
}
|
|
|
|
gboolean
|
|
pika_color_scales_get_show_rgb_u8 (PikaColorScales *scales)
|
|
{
|
|
g_return_val_if_fail (PIKA_IS_COLOR_SCALES (scales), FALSE);
|
|
|
|
return scales->show_rgb_u8;
|
|
}
|
|
|
|
|
|
/* private functions */
|
|
|
|
static void
|
|
pika_color_scales_update_visible (PikaColorScales *scales)
|
|
{
|
|
PikaColorSelector *selector = PIKA_COLOR_SELECTOR (scales);
|
|
gboolean show_alpha;
|
|
gboolean rgb_visible;
|
|
gboolean lch_visible;
|
|
gboolean hsv_visible;
|
|
|
|
show_alpha = pika_color_selector_get_show_alpha (selector);
|
|
rgb_visible = pika_color_selector_get_model_visible (selector,
|
|
PIKA_COLOR_SELECTOR_MODEL_RGB);
|
|
lch_visible = pika_color_selector_get_model_visible (selector,
|
|
PIKA_COLOR_SELECTOR_MODEL_LCH);
|
|
hsv_visible = pika_color_selector_get_model_visible (selector,
|
|
PIKA_COLOR_SELECTOR_MODEL_HSV);
|
|
|
|
gtk_widget_set_visible (scales->rgb_u8_group,
|
|
rgb_visible && scales->show_rgb_u8);
|
|
gtk_widget_set_visible (scales->rgb_percent_group,
|
|
rgb_visible && ! scales->show_rgb_u8);
|
|
|
|
gtk_widget_set_visible (scales->lch_group, lch_visible);
|
|
gtk_widget_set_visible (scales->hsv_group, hsv_visible);
|
|
|
|
gtk_widget_set_visible (scales->alpha_percent_group,
|
|
show_alpha && ! scales->show_rgb_u8);
|
|
gtk_widget_set_visible (scales->alpha_u8_group,
|
|
show_alpha && scales->show_rgb_u8);
|
|
}
|
|
|
|
static void
|
|
pika_color_scales_update_scales (PikaColorScales *scales,
|
|
gint skip)
|
|
{
|
|
PikaColorSelector *selector = PIKA_COLOR_SELECTOR (scales);
|
|
PikaLCH lch;
|
|
gdouble values[G_N_ELEMENTS (scale_defs)];
|
|
gint i;
|
|
|
|
babl_process (fish_rgb_to_lch, &selector->rgb, &lch, 1);
|
|
|
|
values[PIKA_COLOR_SELECTOR_HUE] = selector->hsv.h * 360.0;
|
|
values[PIKA_COLOR_SELECTOR_SATURATION] = selector->hsv.s * 100.0;
|
|
values[PIKA_COLOR_SELECTOR_VALUE] = selector->hsv.v * 100.0;
|
|
|
|
values[PIKA_COLOR_SELECTOR_RED] = selector->rgb.r * 100.0;
|
|
values[PIKA_COLOR_SELECTOR_GREEN] = selector->rgb.g * 100.0;
|
|
values[PIKA_COLOR_SELECTOR_BLUE] = selector->rgb.b * 100.0;
|
|
values[PIKA_COLOR_SELECTOR_ALPHA] = selector->rgb.a * 100.0;
|
|
|
|
values[PIKA_COLOR_SELECTOR_LCH_LIGHTNESS] = lch.l;
|
|
values[PIKA_COLOR_SELECTOR_LCH_CHROMA] = lch.c;
|
|
values[PIKA_COLOR_SELECTOR_LCH_HUE] = lch.h;
|
|
|
|
values[PIKA_COLOR_SELECTOR_RED_U8] = selector->rgb.r * 255.0;
|
|
values[PIKA_COLOR_SELECTOR_GREEN_U8] = selector->rgb.g * 255.0;
|
|
values[PIKA_COLOR_SELECTOR_BLUE_U8] = selector->rgb.b * 255.0;
|
|
values[PIKA_COLOR_SELECTOR_ALPHA_U8] = selector->rgb.a * 255.0;
|
|
|
|
for (i = 0; i < G_N_ELEMENTS (scale_defs); i++)
|
|
{
|
|
if (i != skip)
|
|
{
|
|
g_signal_handlers_block_by_func (scales->scales[i],
|
|
pika_color_scales_scale_changed,
|
|
scales);
|
|
|
|
pika_label_spin_set_value (PIKA_LABEL_SPIN (scales->scales[i]), values[i]);
|
|
|
|
g_signal_handlers_unblock_by_func (scales->scales[i],
|
|
pika_color_scales_scale_changed,
|
|
scales);
|
|
}
|
|
|
|
pika_color_scale_set_color (PIKA_COLOR_SCALE (pika_scale_entry_get_range (PIKA_SCALE_ENTRY (scales->scales[i]))),
|
|
&selector->rgb, &selector->hsv);
|
|
}
|
|
}
|
|
|
|
static void
|
|
pika_color_scales_toggle_changed (GtkWidget *widget,
|
|
PikaColorScales *scales)
|
|
{
|
|
PikaColorSelector *selector = PIKA_COLOR_SELECTOR (scales);
|
|
|
|
if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)))
|
|
{
|
|
gint i;
|
|
|
|
for (i = 0; i < G_N_ELEMENTS (scale_defs); i++)
|
|
{
|
|
if (widget == scales->toggles[i])
|
|
{
|
|
pika_color_selector_set_channel (selector, i);
|
|
|
|
if (i < PIKA_COLOR_SELECTOR_RED ||
|
|
i > PIKA_COLOR_SELECTOR_BLUE)
|
|
{
|
|
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (scales->dummy_u8_toggle),
|
|
TRUE);
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
pika_color_scales_scale_changed (GtkWidget *scale,
|
|
PikaColorScales *scales)
|
|
{
|
|
PikaColorSelector *selector = PIKA_COLOR_SELECTOR (scales);
|
|
gdouble value = pika_label_spin_get_value (PIKA_LABEL_SPIN (scale));
|
|
PikaLCH lch;
|
|
gint i;
|
|
|
|
for (i = 0; i < G_N_ELEMENTS (scale_defs); i++)
|
|
if (scales->scales[i] == scale)
|
|
break;
|
|
|
|
switch (i)
|
|
{
|
|
case PIKA_COLOR_SELECTOR_HUE:
|
|
selector->hsv.h = value / 360.0;
|
|
break;
|
|
|
|
case PIKA_COLOR_SELECTOR_SATURATION:
|
|
selector->hsv.s = value / 100.0;
|
|
break;
|
|
|
|
case PIKA_COLOR_SELECTOR_VALUE:
|
|
selector->hsv.v = value / 100.0;
|
|
break;
|
|
|
|
case PIKA_COLOR_SELECTOR_RED:
|
|
selector->rgb.r = value / 100.0;
|
|
break;
|
|
|
|
case PIKA_COLOR_SELECTOR_GREEN:
|
|
selector->rgb.g = value / 100.0;
|
|
break;
|
|
|
|
case PIKA_COLOR_SELECTOR_BLUE:
|
|
selector->rgb.b = value / 100.0;
|
|
break;
|
|
|
|
case PIKA_COLOR_SELECTOR_ALPHA:
|
|
selector->hsv.a = selector->rgb.a = value / 100.0;
|
|
break;
|
|
|
|
case PIKA_COLOR_SELECTOR_LCH_LIGHTNESS:
|
|
babl_process (fish_rgb_to_lch, &selector->rgb, &lch, 1);
|
|
lch.l = value;
|
|
break;
|
|
|
|
case PIKA_COLOR_SELECTOR_LCH_CHROMA:
|
|
babl_process (fish_rgb_to_lch, &selector->rgb, &lch, 1);
|
|
lch.c = value;
|
|
break;
|
|
|
|
case PIKA_COLOR_SELECTOR_LCH_HUE:
|
|
babl_process (fish_rgb_to_lch, &selector->rgb, &lch, 1);
|
|
lch.h = value;
|
|
break;
|
|
|
|
case PIKA_COLOR_SELECTOR_RED_U8:
|
|
selector->rgb.r = value / 255.0;
|
|
break;
|
|
|
|
case PIKA_COLOR_SELECTOR_GREEN_U8:
|
|
selector->rgb.g = value / 255.0;
|
|
break;
|
|
|
|
case PIKA_COLOR_SELECTOR_BLUE_U8:
|
|
selector->rgb.b = value / 255.0;
|
|
break;
|
|
|
|
case PIKA_COLOR_SELECTOR_ALPHA_U8:
|
|
selector->hsv.a = selector->rgb.a = value / 255.0;
|
|
break;
|
|
}
|
|
|
|
if ((i >= PIKA_COLOR_SELECTOR_HUE) &&
|
|
(i <= PIKA_COLOR_SELECTOR_VALUE))
|
|
{
|
|
pika_hsv_to_rgb (&selector->hsv, &selector->rgb);
|
|
}
|
|
else if ((i >= PIKA_COLOR_SELECTOR_LCH_LIGHTNESS) &&
|
|
(i <= PIKA_COLOR_SELECTOR_LCH_HUE))
|
|
{
|
|
babl_process (fish_lch_to_rgb, &lch, &selector->rgb, 1);
|
|
pika_rgb_to_hsv (&selector->rgb, &selector->hsv);
|
|
}
|
|
else if ((i >= PIKA_COLOR_SELECTOR_RED) &&
|
|
(i <= PIKA_COLOR_SELECTOR_BLUE))
|
|
{
|
|
pika_rgb_to_hsv (&selector->rgb, &selector->hsv);
|
|
}
|
|
else if ((i >= PIKA_COLOR_SELECTOR_RED_U8) &&
|
|
(i <= PIKA_COLOR_SELECTOR_BLUE_U8))
|
|
{
|
|
pika_rgb_to_hsv (&selector->rgb, &selector->hsv);
|
|
}
|
|
|
|
pika_color_scales_update_scales (scales, i);
|
|
|
|
pika_color_selector_emit_color_changed (selector);
|
|
}
|
|
|
|
static void
|
|
pika_color_scales_toggle_lch_hsv (GtkToggleButton *toggle,
|
|
PikaColorScales *scales)
|
|
{
|
|
PikaColorSelector *selector = PIKA_COLOR_SELECTOR (scales);
|
|
gboolean show_hsv = ! gtk_toggle_button_get_active (toggle);
|
|
|
|
pika_color_selector_set_model_visible (selector,
|
|
PIKA_COLOR_SELECTOR_MODEL_LCH,
|
|
! show_hsv);
|
|
pika_color_selector_set_model_visible (selector,
|
|
PIKA_COLOR_SELECTOR_MODEL_HSV,
|
|
show_hsv);
|
|
g_object_set (scales, "show-hsv", show_hsv, NULL);
|
|
}
|