PIKApp/libpikawidgets/pikacolorscales.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);
}