PIKApp/libpikawidgets/pikacolornotebook.c

629 lines
22 KiB
C
Raw Normal View History

2023-09-26 00:35:21 +02:00
/* LIBPIKA - The PIKA Library
* Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
*
* pikacolornotebook.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 <gegl.h>
#include <gtk/gtk.h>
#include "libpikacolor/pikacolor.h"
#include "pikawidgetstypes.h"
#include "pikacolornotebook.h"
#include "pikacolorscales.h"
#include "pikahelpui.h"
#include "libpika/libpika-intl.h"
/**
* SECTION: pikacolornotebook
* @title: PikaColorNotebook
* @short_description: A #PikaColorSelector implementation.
*
* The #PikaColorNotebook widget is an implementation of a
* #PikaColorSelector. It serves as a container for
* #PikaColorSelectors.
**/
#define DEFAULT_TAB_ICON_SIZE GTK_ICON_SIZE_BUTTON
struct _PikaColorNotebookPrivate
{
GtkWidget *notebook;
GList *selectors;
PikaColorSelector *cur_page;
};
#define GET_PRIVATE(obj) (((PikaColorNotebook *) obj)->priv)
static void pika_color_notebook_style_updated (GtkWidget *widget);
static void pika_color_notebook_togg_visible (PikaColorSelector *selector,
gboolean visible);
static void pika_color_notebook_togg_sensitive (PikaColorSelector *selector,
gboolean sensitive);
static void pika_color_notebook_set_show_alpha (PikaColorSelector *selector,
gboolean show_alpha);
static void pika_color_notebook_set_color (PikaColorSelector *selector,
const PikaRGB *rgb,
const PikaHSV *hsv);
static void pika_color_notebook_set_channel (PikaColorSelector *selector,
PikaColorSelectorChannel channel);
static void pika_color_notebook_set_model_visible
(PikaColorSelector *selector,
PikaColorSelectorModel model,
gboolean gboolean);
static void pika_color_notebook_set_config (PikaColorSelector *selector,
PikaColorConfig *config);
static void pika_color_notebook_switch_page (GtkNotebook *gtk_notebook,
gpointer page,
guint page_num,
PikaColorNotebook *notebook);
static void pika_color_notebook_color_changed (PikaColorSelector *page,
const PikaRGB *rgb,
const PikaHSV *hsv,
PikaColorNotebook *notebook);
static void pika_color_notebook_channel_changed (PikaColorSelector *page,
PikaColorSelectorChannel channel,
PikaColorNotebook *notebook);
static void pika_color_notebook_model_visible_changed
(PikaColorSelector *page,
PikaColorSelectorModel model,
gboolean visible,
PikaColorNotebook *notebook);
static GtkWidget * pika_color_notebook_add_page (PikaColorNotebook *notebook,
GType page_type);
static void pika_color_notebook_remove_selector (GtkContainer *container,
GtkWidget *widget,
PikaColorNotebook *notebook);
G_DEFINE_TYPE_WITH_PRIVATE (PikaColorNotebook, pika_color_notebook,
PIKA_TYPE_COLOR_SELECTOR)
#define parent_class pika_color_notebook_parent_class
static void
pika_color_notebook_class_init (PikaColorNotebookClass *klass)
{
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
PikaColorSelectorClass *selector_class = PIKA_COLOR_SELECTOR_CLASS (klass);
widget_class->style_updated = pika_color_notebook_style_updated;
selector_class->name = "Notebook";
selector_class->help_id = "pika-colorselector-notebook";
selector_class->set_toggles_visible = pika_color_notebook_togg_visible;
selector_class->set_toggles_sensitive = pika_color_notebook_togg_sensitive;
selector_class->set_show_alpha = pika_color_notebook_set_show_alpha;
selector_class->set_color = pika_color_notebook_set_color;
selector_class->set_channel = pika_color_notebook_set_channel;
selector_class->set_model_visible = pika_color_notebook_set_model_visible;
selector_class->set_config = pika_color_notebook_set_config;
gtk_widget_class_install_style_property (widget_class,
g_param_spec_enum ("tab-icon-size",
NULL,
"Size for icons displayed in the tab",
GTK_TYPE_ICON_SIZE,
DEFAULT_TAB_ICON_SIZE,
G_PARAM_READABLE));
gtk_widget_class_set_css_name (widget_class, "PikaColorNotebook");
}
static void
pika_color_notebook_init (PikaColorNotebook *notebook)
{
PikaColorNotebookPrivate *private = GET_PRIVATE (notebook);
GType *selector_types;
guint n_selector_types;
guint i;
notebook->priv = pika_color_notebook_get_instance_private (notebook);
private = notebook->priv;
private->notebook = gtk_notebook_new ();
gtk_notebook_popup_enable (GTK_NOTEBOOK (private->notebook));
gtk_box_pack_start (GTK_BOX (notebook), private->notebook, TRUE, TRUE, 0);
gtk_widget_show (private->notebook);
g_signal_connect (private->notebook, "switch-page",
G_CALLBACK (pika_color_notebook_switch_page),
notebook);
g_signal_connect (private->notebook, "remove",
G_CALLBACK (pika_color_notebook_remove_selector),
notebook);
selector_types = g_type_children (PIKA_TYPE_COLOR_SELECTOR,
&n_selector_types);
if (n_selector_types == 2)
{
gtk_notebook_set_show_tabs (GTK_NOTEBOOK (private->notebook), FALSE);
gtk_notebook_set_show_border (GTK_NOTEBOOK (private->notebook), FALSE);
}
for (i = 0; i < n_selector_types; i++)
{
/* skip ourselves */
if (g_type_is_a (selector_types[i], PIKA_TYPE_COLOR_NOTEBOOK))
continue;
/* skip the "Scales" color selector */
if (g_type_is_a (selector_types[i], PIKA_TYPE_COLOR_SCALES))
continue;
pika_color_notebook_add_page (notebook, selector_types[i]);
}
g_free (selector_types);
}
static void
pika_color_notebook_style_updated (GtkWidget *widget)
{
PikaColorNotebookPrivate *private = GET_PRIVATE (widget);
GList *list;
GtkIconSize icon_size;
GTK_WIDGET_CLASS (parent_class)->style_updated (widget);
gtk_widget_style_get (widget,
"tab-icon-size", &icon_size,
NULL);
for (list = private->selectors; list; list = g_list_next (list))
{
PikaColorSelectorClass *selector_class;
GtkWidget *image;
selector_class = PIKA_COLOR_SELECTOR_GET_CLASS (list->data);
image = gtk_image_new_from_icon_name (selector_class->icon_name,
icon_size);
pika_help_set_help_data (image, gettext (selector_class->name), NULL);
gtk_notebook_set_tab_label (GTK_NOTEBOOK (private->notebook),
GTK_WIDGET (list->data),
image);
}
}
static void
pika_color_notebook_togg_visible (PikaColorSelector *selector,
gboolean visible)
{
PikaColorNotebookPrivate *private = GET_PRIVATE (selector);
GList *list;
for (list = private->selectors; list; list = g_list_next (list))
{
PikaColorSelector *child = list->data;
pika_color_selector_set_toggles_visible (child, visible);
}
}
static void
pika_color_notebook_togg_sensitive (PikaColorSelector *selector,
gboolean sensitive)
{
PikaColorNotebookPrivate *private = GET_PRIVATE (selector);
GList *list;
for (list = private->selectors; list; list = g_list_next (list))
{
PikaColorSelector *child = list->data;
pika_color_selector_set_toggles_sensitive (child, sensitive);
}
}
static void
pika_color_notebook_set_show_alpha (PikaColorSelector *selector,
gboolean show_alpha)
{
PikaColorNotebookPrivate *private = GET_PRIVATE (selector);
GList *list;
for (list = private->selectors; list; list = g_list_next (list))
{
PikaColorSelector *child = list->data;
pika_color_selector_set_show_alpha (child, show_alpha);
}
}
static void
pika_color_notebook_set_color (PikaColorSelector *selector,
const PikaRGB *rgb,
const PikaHSV *hsv)
{
PikaColorNotebookPrivate *private = GET_PRIVATE (selector);
g_signal_handlers_block_by_func (private->cur_page,
pika_color_notebook_color_changed,
selector);
pika_color_selector_set_color (private->cur_page, rgb, hsv);
g_signal_handlers_unblock_by_func (private->cur_page,
pika_color_notebook_color_changed,
selector);
}
static void
pika_color_notebook_set_channel (PikaColorSelector *selector,
PikaColorSelectorChannel channel)
{
PikaColorNotebookPrivate *private = GET_PRIVATE (selector);
g_signal_handlers_block_by_func (private->cur_page,
pika_color_notebook_channel_changed,
selector);
pika_color_selector_set_channel (private->cur_page, channel);
g_signal_handlers_unblock_by_func (private->cur_page,
pika_color_notebook_channel_changed,
selector);
}
static void
pika_color_notebook_set_model_visible (PikaColorSelector *selector,
PikaColorSelectorModel model,
gboolean visible)
{
PikaColorNotebookPrivate *private = GET_PRIVATE (selector);
g_signal_handlers_block_by_func (private->cur_page,
pika_color_notebook_model_visible_changed,
selector);
pika_color_selector_set_model_visible (private->cur_page, model, visible);
g_signal_handlers_unblock_by_func (private->cur_page,
pika_color_notebook_model_visible_changed,
selector);
}
static void
pika_color_notebook_set_config (PikaColorSelector *selector,
PikaColorConfig *config)
{
PikaColorNotebookPrivate *private = GET_PRIVATE (selector);
GList *list;
for (list = private->selectors; list; list = g_list_next (list))
{
PikaColorSelector *child = list->data;
pika_color_selector_set_config (child, config);
}
}
static void
pika_color_notebook_switch_page (GtkNotebook *gtk_notebook,
gpointer page,
guint page_num,
PikaColorNotebook *notebook)
{
PikaColorNotebookPrivate *private = GET_PRIVATE (notebook);
PikaColorSelector *selector = PIKA_COLOR_SELECTOR (notebook);
GtkWidget *page_widget;
PikaColorSelectorModel model;
page_widget = gtk_notebook_get_nth_page (gtk_notebook, page_num);
private->cur_page = PIKA_COLOR_SELECTOR (page_widget);
g_signal_handlers_block_by_func (private->cur_page,
pika_color_notebook_color_changed,
notebook);
g_signal_handlers_block_by_func (private->cur_page,
pika_color_notebook_channel_changed,
notebook);
g_signal_handlers_block_by_func (private->cur_page,
pika_color_notebook_model_visible_changed,
notebook);
pika_color_selector_set_color (private->cur_page,
&selector->rgb,
&selector->hsv);
pika_color_selector_set_channel (private->cur_page,
pika_color_selector_get_channel (selector));
for (model = PIKA_COLOR_SELECTOR_MODEL_RGB;
model <= PIKA_COLOR_SELECTOR_MODEL_HSV;
model++)
{
gboolean visible = pika_color_selector_get_model_visible (selector, model);
pika_color_selector_set_model_visible (private->cur_page, model,
visible);
}
g_signal_handlers_unblock_by_func (private->cur_page,
pika_color_notebook_color_changed,
notebook);
g_signal_handlers_unblock_by_func (private->cur_page,
pika_color_notebook_channel_changed,
notebook);
g_signal_handlers_unblock_by_func (private->cur_page,
pika_color_notebook_model_visible_changed,
notebook);
}
static void
pika_color_notebook_color_changed (PikaColorSelector *page,
const PikaRGB *rgb,
const PikaHSV *hsv,
PikaColorNotebook *notebook)
{
PikaColorSelector *selector = PIKA_COLOR_SELECTOR (notebook);
selector->rgb = *rgb;
selector->hsv = *hsv;
pika_color_selector_emit_color_changed (selector);
}
static void
pika_color_notebook_channel_changed (PikaColorSelector *page,
PikaColorSelectorChannel channel,
PikaColorNotebook *notebook)
{
PikaColorSelector *selector = PIKA_COLOR_SELECTOR (notebook);
pika_color_selector_set_channel (selector, channel);
}
static void
pika_color_notebook_model_visible_changed (PikaColorSelector *page,
PikaColorSelectorModel model,
gboolean visible,
PikaColorNotebook *notebook)
{
PikaColorSelector *selector = PIKA_COLOR_SELECTOR (notebook);
pika_color_selector_set_model_visible (selector, model, visible);
}
static GtkWidget *
pika_color_notebook_add_page (PikaColorNotebook *notebook,
GType page_type)
{
PikaColorNotebookPrivate *private = GET_PRIVATE (notebook);
PikaColorSelector *selector = PIKA_COLOR_SELECTOR (notebook);
PikaColorSelectorClass *selector_class;
GtkWidget *page;
GtkWidget *menu_widget;
GtkWidget *image;
GtkWidget *label;
gboolean show_alpha;
page = pika_color_selector_new (page_type,
&selector->rgb,
&selector->hsv,
pika_color_selector_get_channel (selector));
if (! page)
return NULL;
selector_class = PIKA_COLOR_SELECTOR_GET_CLASS (page);
show_alpha = pika_color_selector_get_show_alpha (PIKA_COLOR_SELECTOR (notebook));
pika_color_selector_set_show_alpha (PIKA_COLOR_SELECTOR (page), show_alpha);
menu_widget = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 4);
image = gtk_image_new_from_icon_name (selector_class->icon_name,
GTK_ICON_SIZE_MENU);
gtk_box_pack_start (GTK_BOX (menu_widget), image, FALSE, FALSE, 0);
gtk_widget_show (image);
label = gtk_label_new (gettext (selector_class->name));
gtk_box_pack_start (GTK_BOX (menu_widget), label, FALSE, FALSE, 0);
gtk_widget_show (label);
image = gtk_image_new_from_icon_name (selector_class->icon_name,
DEFAULT_TAB_ICON_SIZE);
pika_help_set_help_data (image, gettext (selector_class->name), NULL);
gtk_notebook_append_page_menu (GTK_NOTEBOOK (private->notebook),
page, image, menu_widget);
if (! private->cur_page)
private->cur_page = PIKA_COLOR_SELECTOR (page);
private->selectors = g_list_append (private->selectors, page);
gtk_widget_show (page);
g_signal_connect (page, "color-changed",
G_CALLBACK (pika_color_notebook_color_changed),
notebook);
g_signal_connect (page, "channel-changed",
G_CALLBACK (pika_color_notebook_channel_changed),
notebook);
g_signal_connect (page, "model-visible-changed",
G_CALLBACK (pika_color_notebook_model_visible_changed),
notebook);
return page;
}
static void
pika_color_notebook_remove_selector (GtkContainer *container,
GtkWidget *widget,
PikaColorNotebook *notebook)
{
notebook->priv->selectors = g_list_remove (notebook->priv->selectors,
widget);
if (! notebook->priv->selectors)
notebook->priv->cur_page = NULL;
}
/**
* pika_color_notebook_set_has_page:
* @notebook: A #PikaColorNotebook widget.
* @page_type: The #GType of the notebook page to add or remove.
* @has_page: Whether the page should be added or removed.
*
* This function adds and removed pages to / from a #PikaColorNotebook.
* The @page_type passed must be a #PikaColorSelector subtype.
*
* Returns: (transfer none): The new page widget, if @has_page was
* %TRUE, or %NULL if @has_page was %FALSE.
**/
GtkWidget *
pika_color_notebook_set_has_page (PikaColorNotebook *notebook,
GType page_type,
gboolean has_page)
{
GList *list;
g_return_val_if_fail (PIKA_IS_COLOR_NOTEBOOK (notebook), NULL);
g_return_val_if_fail (g_type_is_a (page_type, PIKA_TYPE_COLOR_SELECTOR),
NULL);
g_return_val_if_fail (! g_type_is_a (page_type, PIKA_TYPE_COLOR_NOTEBOOK),
NULL);
for (list = notebook->priv->selectors; list; list = g_list_next (list))
{
PikaColorSelector *page = list->data;
if (G_TYPE_FROM_INSTANCE (page) == page_type)
{
if (has_page)
return GTK_WIDGET (page);
gtk_container_remove (GTK_CONTAINER (notebook->priv->notebook),
GTK_WIDGET (page));
return NULL;
}
}
if (! has_page)
return NULL;
return pika_color_notebook_add_page (notebook, page_type);
}
/**
* pika_color_notebook_get_notebook:
* @notebook: A #PikaColorNotebook widget.
*
* Returns: (transfer none) (type GtkNotebook): The #GtkNotebook inside.
*
* Since: 3.0
**/
GtkWidget *
pika_color_notebook_get_notebook (PikaColorNotebook *notebook)
{
g_return_val_if_fail (PIKA_IS_COLOR_NOTEBOOK (notebook), NULL);
return notebook->priv->notebook;
}
/**
* pika_color_notebook_get_selectors:
* @notebook: A #PikaColorNotebook widget.
*
* Returns: (element-type PikaColorSelector) (transfer none): The
* notebook's list of #PikaColorSelector's.
*
* Since: 3.0
**/
GList *
pika_color_notebook_get_selectors (PikaColorNotebook *notebook)
{
g_return_val_if_fail (PIKA_IS_COLOR_NOTEBOOK (notebook), NULL);
return notebook->priv->selectors;
}
/**
* pika_color_notebook_get_current_selector:
* @notebook: A #PikaColorNotebook widget.
*
* Returns: (transfer none): The active page's #PikaColorSelector.
*
* Since: 3.0
**/
PikaColorSelector *
pika_color_notebook_get_current_selector (PikaColorNotebook *notebook)
{
g_return_val_if_fail (PIKA_IS_COLOR_NOTEBOOK (notebook), NULL);
return notebook->priv->cur_page;
}
/**
* pika_color_notebook_set_simulation:
* @notebook: A #PikaColorNotebook widget.
* @profile: A #PikaColorProfile object.
* @intent: A #PikaColorRenderingIntent enum.
* @bpc: A gboolean.
*
* Updates all selectors with the current simulation settings.
*
* Since: 3.0
**/
void
pika_color_notebook_set_simulation (PikaColorNotebook *notebook,
PikaColorProfile *profile,
PikaColorRenderingIntent intent,
gboolean bpc)
{
GList *list;
g_return_if_fail (PIKA_IS_COLOR_NOTEBOOK (notebook));
g_return_if_fail (profile == NULL || PIKA_IS_COLOR_PROFILE (profile));
for (list = notebook->priv->selectors; list; list = g_list_next (list))
{
PikaColorSelector *selector = list->data;
if (selector)
pika_color_selector_set_simulation (selector, profile, intent, bpc);
}
}