/* LIBPIKA - The PIKA Library * Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball * * pikacolorselector.c * Copyright (C) 2002 Michael Natterer * * based on: * Colour selector module * Copyright (C) 1999 Austin Donnelly * * 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 * . */ #include "config.h" #include #include #include "libpikacolor/pikacolor.h" #include "libpikaconfig/pikaconfig.h" #include "pikawidgetstypes.h" #include "pikacolorselector.h" #include "pikaicons.h" #include "pikawidgetsmarshal.h" /** * SECTION: pikacolorselector * @title: PikaColorSelector * @short_description: Pluggable PIKA color selector modules. * @see_also: #GModule, #GTypeModule, #PikaModule * * Functions and definitions for creating pluggable PIKA color * selector modules. **/ enum { COLOR_CHANGED, CHANNEL_CHANGED, MODEL_VISIBLE_CHANGED, LAST_SIGNAL }; struct _PikaColorSelectorPrivate { gboolean model_visible[3]; }; #define GET_PRIVATE(obj) (((PikaColorSelector *) (obj))->priv) static void pika_color_selector_dispose (GObject *object); G_DEFINE_TYPE_WITH_PRIVATE (PikaColorSelector, pika_color_selector, GTK_TYPE_BOX) #define parent_class pika_color_selector_parent_class static guint selector_signals[LAST_SIGNAL] = { 0 }; static void pika_color_selector_class_init (PikaColorSelectorClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->dispose = pika_color_selector_dispose; selector_signals[COLOR_CHANGED] = g_signal_new ("color-changed", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (PikaColorSelectorClass, color_changed), NULL, NULL, _pika_widgets_marshal_VOID__BOXED_BOXED, G_TYPE_NONE, 2, PIKA_TYPE_RGB, PIKA_TYPE_RGB); selector_signals[CHANNEL_CHANGED] = g_signal_new ("channel-changed", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (PikaColorSelectorClass, channel_changed), NULL, NULL, NULL, G_TYPE_NONE, 1, PIKA_TYPE_COLOR_SELECTOR_CHANNEL); selector_signals[MODEL_VISIBLE_CHANGED] = g_signal_new ("model-visible-changed", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (PikaColorSelectorClass, model_visible_changed), NULL, NULL, _pika_widgets_marshal_VOID__ENUM_BOOLEAN, G_TYPE_NONE, 2, PIKA_TYPE_COLOR_SELECTOR_MODEL, G_TYPE_BOOLEAN); klass->name = "Unnamed"; klass->help_id = NULL; klass->icon_name = PIKA_ICON_PALETTE; klass->set_toggles_visible = NULL; klass->set_toggles_sensitive = NULL; klass->set_show_alpha = NULL; klass->set_color = NULL; klass->set_channel = NULL; klass->set_model_visible = NULL; klass->color_changed = NULL; klass->channel_changed = NULL; klass->model_visible_changed = NULL; klass->set_config = NULL; } static void pika_color_selector_init (PikaColorSelector *selector) { PikaColorSelectorPrivate *priv; selector->priv = pika_color_selector_get_instance_private (selector); priv = GET_PRIVATE (selector); selector->toggles_visible = TRUE; selector->toggles_sensitive = TRUE; selector->show_alpha = TRUE; gtk_orientable_set_orientation (GTK_ORIENTABLE (selector), GTK_ORIENTATION_VERTICAL); pika_rgba_set (&selector->rgb, 0.0, 0.0, 0.0, 1.0); pika_rgb_to_hsv (&selector->rgb, &selector->hsv); selector->channel = PIKA_COLOR_SELECTOR_RED; priv->model_visible[PIKA_COLOR_SELECTOR_MODEL_RGB] = TRUE; priv->model_visible[PIKA_COLOR_SELECTOR_MODEL_LCH] = TRUE; priv->model_visible[PIKA_COLOR_SELECTOR_MODEL_HSV] = FALSE; } static void pika_color_selector_dispose (GObject *object) { pika_color_selector_set_config (PIKA_COLOR_SELECTOR (object), NULL); G_OBJECT_CLASS (parent_class)->dispose (object); } /* public functions */ /** * pika_color_selector_new: * @selector_type: The #GType of the selector to create. * @rgb: The initial color to be edited. * @hsv: The same color in HSV. * @channel: The selector's initial channel. * * Creates a new #PikaColorSelector widget of type @selector_type. * * Note that this is mostly internal API to be used by other widgets. * * Please use pika_color_selection_new() for the "PIKA-typical" color * selection widget. Also see pika_color_button_new(). * * Retunn value: the new #PikaColorSelector widget. **/ GtkWidget * pika_color_selector_new (GType selector_type, const PikaRGB *rgb, const PikaHSV *hsv, PikaColorSelectorChannel channel) { PikaColorSelector *selector; g_return_val_if_fail (g_type_is_a (selector_type, PIKA_TYPE_COLOR_SELECTOR), NULL); g_return_val_if_fail (rgb != NULL, NULL); g_return_val_if_fail (hsv != NULL, NULL); selector = g_object_new (selector_type, NULL); pika_color_selector_set_color (selector, rgb, hsv); pika_color_selector_set_channel (selector, channel); return GTK_WIDGET (selector); } /** * pika_color_selector_set_toggles_visible: * @selector: A #PikaColorSelector widget. * @visible: The new @visible setting. * * Sets the @visible property of the @selector's toggles. * * This function has no effect if this @selector instance has no * toggles to switch channels. **/ void pika_color_selector_set_toggles_visible (PikaColorSelector *selector, gboolean visible) { g_return_if_fail (PIKA_IS_COLOR_SELECTOR (selector)); if (selector->toggles_visible != visible) { PikaColorSelectorClass *selector_class; selector->toggles_visible = visible ? TRUE : FALSE; selector_class = PIKA_COLOR_SELECTOR_GET_CLASS (selector); if (selector_class->set_toggles_visible) selector_class->set_toggles_visible (selector, visible); } } /** * pika_color_selector_get_toggles_visible: * @selector: A #PikaColorSelector widget. * * Returns the @visible property of the @selector's toggles. * * Returns: %TRUE if the #PikaColorSelector's toggles are visible. * * Since: 2.10 **/ gboolean pika_color_selector_get_toggles_visible (PikaColorSelector *selector) { g_return_val_if_fail (PIKA_IS_COLOR_SELECTOR (selector), FALSE); return selector->toggles_visible; } /** * pika_color_selector_set_toggles_sensitive: * @selector: A #PikaColorSelector widget. * @sensitive: The new @sensitive setting. * * Sets the @sensitive property of the @selector's toggles. * * This function has no effect if this @selector instance has no * toggles to switch channels. **/ void pika_color_selector_set_toggles_sensitive (PikaColorSelector *selector, gboolean sensitive) { g_return_if_fail (PIKA_IS_COLOR_SELECTOR (selector)); if (selector->toggles_sensitive != sensitive) { PikaColorSelectorClass *selector_class; selector->toggles_sensitive = sensitive ? TRUE : FALSE; selector_class = PIKA_COLOR_SELECTOR_GET_CLASS (selector); if (selector_class->set_toggles_sensitive) selector_class->set_toggles_sensitive (selector, sensitive); } } /** * pika_color_selector_get_toggles_sensitive: * @selector: A #PikaColorSelector widget. * * Returns the @sensitive property of the @selector's toggles. * * Returns: %TRUE if the #PikaColorSelector's toggles are sensitive. * * Since: 2.10 **/ gboolean pika_color_selector_get_toggles_sensitive (PikaColorSelector *selector) { g_return_val_if_fail (PIKA_IS_COLOR_SELECTOR (selector), FALSE); return selector->toggles_sensitive; } /** * pika_color_selector_set_show_alpha: * @selector: A #PikaColorSelector widget. * @show_alpha: The new @show_alpha setting. * * Sets the @show_alpha property of the @selector widget. **/ void pika_color_selector_set_show_alpha (PikaColorSelector *selector, gboolean show_alpha) { g_return_if_fail (PIKA_IS_COLOR_SELECTOR (selector)); if (show_alpha != selector->show_alpha) { PikaColorSelectorClass *selector_class; selector->show_alpha = show_alpha ? TRUE : FALSE; selector_class = PIKA_COLOR_SELECTOR_GET_CLASS (selector); if (selector_class->set_show_alpha) selector_class->set_show_alpha (selector, show_alpha); } } /** * pika_color_selector_get_show_alpha: * @selector: A #PikaColorSelector widget. * * Returns the @selector's @show_alpha property. * * Returns: %TRUE if the #PikaColorSelector has alpha controls. * * Since: 2.10 **/ gboolean pika_color_selector_get_show_alpha (PikaColorSelector *selector) { g_return_val_if_fail (PIKA_IS_COLOR_SELECTOR (selector), FALSE); return selector->show_alpha; } /** * pika_color_selector_set_color: * @selector: A #PikaColorSelector widget. * @rgb: The new color. * @hsv: The same color in HSV. * * Sets the color shown in the @selector widget. **/ void pika_color_selector_set_color (PikaColorSelector *selector, const PikaRGB *rgb, const PikaHSV *hsv) { PikaColorSelectorClass *selector_class; g_return_if_fail (PIKA_IS_COLOR_SELECTOR (selector)); g_return_if_fail (rgb != NULL); g_return_if_fail (hsv != NULL); selector->rgb = *rgb; selector->hsv = *hsv; selector_class = PIKA_COLOR_SELECTOR_GET_CLASS (selector); if (selector_class->set_color) selector_class->set_color (selector, rgb, hsv); pika_color_selector_emit_color_changed (selector); } /** * pika_color_selector_get_color: * @selector: A #PikaColorSelector widget. * @rgb: (out caller-allocates): Return location for the color. * @hsv: (out caller-allocates): Return location for the same same * color in HSV. * * Retrieves the color shown in the @selector widget. * * Since: 2.10 **/ void pika_color_selector_get_color (PikaColorSelector *selector, PikaRGB *rgb, PikaHSV *hsv) { g_return_if_fail (PIKA_IS_COLOR_SELECTOR (selector)); g_return_if_fail (rgb != NULL); g_return_if_fail (hsv != NULL); *rgb = selector->rgb; *hsv = selector->hsv; } /** * pika_color_selector_set_channel: * @selector: A #PikaColorSelector widget. * @channel: The new @channel setting. * * Sets the @channel property of the @selector widget. * * Changes between displayed channels if this @selector instance has * the ability to show different channels. * This will also update the color model if needed. **/ void pika_color_selector_set_channel (PikaColorSelector *selector, PikaColorSelectorChannel channel) { g_return_if_fail (PIKA_IS_COLOR_SELECTOR (selector)); if (channel != selector->channel) { PikaColorSelectorClass *selector_class; PikaColorSelectorModel model = -1; selector->channel = channel; switch (channel) { case PIKA_COLOR_SELECTOR_RED: case PIKA_COLOR_SELECTOR_GREEN: case PIKA_COLOR_SELECTOR_BLUE: model = PIKA_COLOR_SELECTOR_MODEL_RGB; break; case PIKA_COLOR_SELECTOR_HUE: case PIKA_COLOR_SELECTOR_SATURATION: case PIKA_COLOR_SELECTOR_VALUE: model = PIKA_COLOR_SELECTOR_MODEL_HSV; break; case PIKA_COLOR_SELECTOR_LCH_LIGHTNESS: case PIKA_COLOR_SELECTOR_LCH_CHROMA: case PIKA_COLOR_SELECTOR_LCH_HUE: model = PIKA_COLOR_SELECTOR_MODEL_LCH; break; case PIKA_COLOR_SELECTOR_ALPHA: /* Alpha channel does not change the color model. */ break; default: /* Should not happen. */ g_return_if_reached (); break; } selector_class = PIKA_COLOR_SELECTOR_GET_CLASS (selector); if (selector_class->set_channel) selector_class->set_channel (selector, channel); pika_color_selector_emit_channel_changed (selector); if (model != -1) { /* make visibility of LCH and HSV mutuallky exclusive */ if (model == PIKA_COLOR_SELECTOR_MODEL_HSV) { pika_color_selector_set_model_visible (selector, PIKA_COLOR_SELECTOR_MODEL_LCH, FALSE); } else if (model == PIKA_COLOR_SELECTOR_MODEL_LCH) { pika_color_selector_set_model_visible (selector, PIKA_COLOR_SELECTOR_MODEL_HSV, FALSE); } pika_color_selector_set_model_visible (selector, model, TRUE); } } } /** * pika_color_selector_get_channel: * @selector: A #PikaColorSelector widget. * * Returns the @selector's current channel. * * Returns: The #PikaColorSelectorChannel currently shown by the * @selector. * * Since: 2.10 **/ PikaColorSelectorChannel pika_color_selector_get_channel (PikaColorSelector *selector) { g_return_val_if_fail (PIKA_IS_COLOR_SELECTOR (selector), PIKA_COLOR_SELECTOR_RED); return selector->channel; } /** * pika_color_selector_set_model_visible: * @selector: A #PikaColorSelector widget. * @model: The affected #PikaColorSelectorModel. * @visible: The new visible setting. * * Sets the @model visible/invisible on the @selector widget. * * Toggles visibility of displayed models if this @selector instance * has the ability to show different color models. * * Since: 2.10 **/ void pika_color_selector_set_model_visible (PikaColorSelector *selector, PikaColorSelectorModel model, gboolean visible) { PikaColorSelectorPrivate *priv; g_return_if_fail (PIKA_IS_COLOR_SELECTOR (selector)); priv = GET_PRIVATE (selector); visible = visible ? TRUE : FALSE; if (visible != priv->model_visible[model]) { PikaColorSelectorClass *selector_class; priv->model_visible[model] = visible; selector_class = PIKA_COLOR_SELECTOR_GET_CLASS (selector); if (selector_class->set_model_visible) selector_class->set_model_visible (selector, model, visible); pika_color_selector_emit_model_visible_changed (selector, model); } } /** * pika_color_selector_get_model_visible: * @selector: A #PikaColorSelector widget. * @model: The #PikaColorSelectorModel. * * Returns: whether @model is visible in @selector. * * Since: 2.10 **/ gboolean pika_color_selector_get_model_visible (PikaColorSelector *selector, PikaColorSelectorModel model) { PikaColorSelectorPrivate *priv; g_return_val_if_fail (PIKA_IS_COLOR_SELECTOR (selector), FALSE); priv = GET_PRIVATE (selector); return priv->model_visible[model]; } /** * pika_color_selector_emit_color_changed: * @selector: A #PikaColorSelector widget. * * Emits the "color-changed" signal. */ void pika_color_selector_emit_color_changed (PikaColorSelector *selector) { g_return_if_fail (PIKA_IS_COLOR_SELECTOR (selector)); g_signal_emit (selector, selector_signals[COLOR_CHANGED], 0, &selector->rgb, &selector->hsv); } /** * pika_color_selector_emit_channel_changed: * @selector: A #PikaColorSelector widget. * * Emits the "channel-changed" signal. */ void pika_color_selector_emit_channel_changed (PikaColorSelector *selector) { g_return_if_fail (PIKA_IS_COLOR_SELECTOR (selector)); g_signal_emit (selector, selector_signals[CHANNEL_CHANGED], 0, selector->channel); } /** * pika_color_selector_emit_model_visible_changed: * @selector: A #PikaColorSelector widget. * @model: The #PikaColorSelectorModel where visibility changed. * * Emits the "model-visible-changed" signal. * * Since: 2.10 */ void pika_color_selector_emit_model_visible_changed (PikaColorSelector *selector, PikaColorSelectorModel model) { PikaColorSelectorPrivate *priv; g_return_if_fail (PIKA_IS_COLOR_SELECTOR (selector)); priv = GET_PRIVATE (selector); g_signal_emit (selector, selector_signals[MODEL_VISIBLE_CHANGED], 0, model, priv->model_visible[model]); } /** * pika_color_selector_set_config: * @selector: a #PikaColorSelector widget. * @config: a #PikaColorConfig object. * * Sets the color management configuration to use with this color selector. * * Since: 2.4 */ void pika_color_selector_set_config (PikaColorSelector *selector, PikaColorConfig *config) { PikaColorSelectorClass *selector_class; g_return_if_fail (PIKA_IS_COLOR_SELECTOR (selector)); g_return_if_fail (config == NULL || PIKA_IS_COLOR_CONFIG (config)); selector_class = PIKA_COLOR_SELECTOR_GET_CLASS (selector); if (selector_class->set_config) selector_class->set_config (selector, config); } /** * pika_color_selector_set_simulation * @selector: a #PikaColorSelector widget. * @profile: a #PikaColorProfile object. * @intent: a #PikaColorRenderingIntent enum. * @bpc: a gboolean. * * Sets the simulation options to use with this color selector. * * Since: 3.0 */ void pika_color_selector_set_simulation (PikaColorSelector *selector, PikaColorProfile *profile, PikaColorRenderingIntent intent, gboolean bpc) { PikaColorSelectorClass *selector_class; g_return_if_fail (PIKA_IS_COLOR_SELECTOR (selector)); g_return_if_fail (profile == NULL || PIKA_IS_COLOR_PROFILE (profile)); selector_class = PIKA_COLOR_SELECTOR_GET_CLASS (selector); if (selector_class->set_simulation) selector_class->set_simulation (selector, profile, intent, bpc); }