2012-01-29 15:42:34 +00:00
|
|
|
/* GTK - The GIMP Toolkit
|
|
|
|
* Copyright (C) 2012 Red Hat, Inc.
|
|
|
|
*
|
|
|
|
* 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 2 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, write to the
|
|
|
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
|
|
* Boston, MA 02111-1307, USA.
|
|
|
|
*/
|
|
|
|
|
2012-02-03 07:12:52 +00:00
|
|
|
/* TODO
|
|
|
|
* - touch
|
|
|
|
* - accessible color names
|
|
|
|
* - accessible relations for popups
|
|
|
|
* - api to replace palette
|
|
|
|
* - saving per-application (?)
|
|
|
|
* - better checkmark
|
|
|
|
* - use css for swatches
|
|
|
|
* - better popup theming
|
|
|
|
*/
|
|
|
|
|
2012-01-29 15:42:34 +00:00
|
|
|
#include "config.h"
|
|
|
|
|
|
|
|
#include "gtkcolorchooserprivate.h"
|
|
|
|
#include "gtkcoloreditor.h"
|
2012-01-30 23:37:00 +00:00
|
|
|
#include "gtkcolorplane.h"
|
2012-02-02 05:58:26 +00:00
|
|
|
#include "gtkcolorscale.h"
|
2012-02-01 05:58:07 +00:00
|
|
|
#include "gtkcolorswatch.h"
|
2012-01-30 14:56:20 +00:00
|
|
|
#include "gtkgrid.h"
|
2012-02-02 05:58:26 +00:00
|
|
|
#include "gtkorientable.h"
|
2012-01-30 14:56:20 +00:00
|
|
|
#include "gtkaspectframe.h"
|
|
|
|
#include "gtkdrawingarea.h"
|
|
|
|
#include "gtkentry.h"
|
2012-02-03 06:41:45 +00:00
|
|
|
#include "gtkoverlay.h"
|
2012-01-29 15:42:34 +00:00
|
|
|
#include "gtkhsv.h"
|
2012-01-30 14:56:20 +00:00
|
|
|
#include "gtkadjustment.h"
|
2012-02-03 06:41:45 +00:00
|
|
|
#include "gtklabel.h"
|
|
|
|
#include "gtkspinbutton.h"
|
|
|
|
#include "gtkalignment.h"
|
2012-01-30 14:56:20 +00:00
|
|
|
#include "gtkintl.h"
|
2012-01-29 15:42:34 +00:00
|
|
|
|
2012-01-30 14:56:20 +00:00
|
|
|
#include <math.h>
|
2012-01-29 15:42:34 +00:00
|
|
|
|
|
|
|
struct _GtkColorEditorPrivate
|
|
|
|
{
|
2012-02-03 06:41:45 +00:00
|
|
|
GtkWidget *overlay;
|
2012-01-30 14:56:20 +00:00
|
|
|
GtkWidget *grid;
|
|
|
|
GtkWidget *swatch;
|
|
|
|
GtkWidget *entry;
|
|
|
|
GtkWidget *h_slider;
|
2012-02-03 06:41:45 +00:00
|
|
|
GtkWidget *h_popup;
|
|
|
|
GtkWidget *h_entry;
|
2012-01-30 14:56:20 +00:00
|
|
|
GtkWidget *a_slider;
|
2012-02-03 06:41:45 +00:00
|
|
|
GtkWidget *a_popup;
|
|
|
|
GtkWidget *a_entry;
|
|
|
|
GtkWidget *sv_plane;
|
|
|
|
GtkWidget *sv_popup;
|
|
|
|
GtkWidget *s_entry;
|
|
|
|
GtkWidget *v_entry;
|
|
|
|
GtkWidget *current_popup;
|
|
|
|
GtkWidget *popdown_focus;
|
2012-01-30 14:56:20 +00:00
|
|
|
|
|
|
|
GtkAdjustment *h_adj;
|
2012-02-03 06:41:45 +00:00
|
|
|
GtkAdjustment *s_adj;
|
|
|
|
GtkAdjustment *v_adj;
|
2012-01-30 14:56:20 +00:00
|
|
|
GtkAdjustment *a_adj;
|
2012-02-01 05:37:36 +00:00
|
|
|
|
2012-01-31 07:05:37 +00:00
|
|
|
guint text_changed : 1;
|
|
|
|
guint show_alpha : 1;
|
2012-01-29 15:42:34 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
enum
|
|
|
|
{
|
|
|
|
PROP_ZERO,
|
2012-01-31 07:05:37 +00:00
|
|
|
PROP_COLOR,
|
|
|
|
PROP_SHOW_ALPHA
|
2012-01-29 15:42:34 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static void gtk_color_editor_iface_init (GtkColorChooserInterface *iface);
|
|
|
|
|
|
|
|
G_DEFINE_TYPE_WITH_CODE (GtkColorEditor, gtk_color_editor, GTK_TYPE_BOX,
|
|
|
|
G_IMPLEMENT_INTERFACE (GTK_TYPE_COLOR_CHOOSER,
|
|
|
|
gtk_color_editor_iface_init))
|
|
|
|
|
2012-01-30 14:56:20 +00:00
|
|
|
static guint
|
|
|
|
scale_round (gdouble value, gdouble scale)
|
|
|
|
{
|
|
|
|
value = floor (value * scale + 0.5);
|
|
|
|
value = MAX (value, 0);
|
|
|
|
value = MIN (value, scale);
|
|
|
|
return (guint)value;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
update_entry (GtkColorEditor *editor)
|
|
|
|
{
|
|
|
|
gchar *text;
|
2012-02-03 06:41:45 +00:00
|
|
|
gdouble h, s, v;
|
|
|
|
gdouble r, g, b;
|
|
|
|
|
|
|
|
h = gtk_adjustment_get_value (editor->priv->h_adj);
|
|
|
|
s = gtk_adjustment_get_value (editor->priv->s_adj);
|
|
|
|
v = gtk_adjustment_get_value (editor->priv->v_adj);
|
|
|
|
gtk_hsv_to_rgb (h, s, v, &r, &g, &b);
|
2012-01-30 14:56:20 +00:00
|
|
|
|
|
|
|
text = g_strdup_printf ("#%02X%02X%02X",
|
2012-02-03 06:41:45 +00:00
|
|
|
scale_round (r, 255),
|
|
|
|
scale_round (g, 255),
|
|
|
|
scale_round (b, 255));
|
2012-01-30 14:56:20 +00:00
|
|
|
gtk_entry_set_text (GTK_ENTRY (editor->priv->entry), text);
|
|
|
|
editor->priv->text_changed = FALSE;
|
|
|
|
g_free (text);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
entry_apply (GtkWidget *entry,
|
|
|
|
GtkColorEditor *editor)
|
|
|
|
{
|
|
|
|
GdkRGBA color;
|
|
|
|
gchar *text;
|
|
|
|
|
|
|
|
if (!editor->priv->text_changed)
|
|
|
|
return;
|
|
|
|
|
|
|
|
text = gtk_editable_get_chars (GTK_EDITABLE (editor->priv->entry), 0, -1);
|
|
|
|
if (gdk_rgba_parse (&color, text))
|
|
|
|
{
|
2012-02-03 06:41:45 +00:00
|
|
|
color.alpha = gtk_adjustment_get_value (editor->priv->a_adj);
|
2012-01-30 23:37:00 +00:00
|
|
|
gtk_color_chooser_set_color (GTK_COLOR_CHOOSER (editor), &color);
|
2012-01-30 14:56:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
editor->priv->text_changed = FALSE;
|
|
|
|
|
|
|
|
g_free (text);
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
entry_focus_out (GtkWidget *entry,
|
|
|
|
GdkEventFocus *event,
|
|
|
|
GtkColorEditor *editor)
|
|
|
|
{
|
|
|
|
entry_apply (entry, editor);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
entry_text_changed (GtkWidget *entry,
|
|
|
|
GParamSpec *pspec,
|
|
|
|
GtkColorEditor *editor)
|
|
|
|
{
|
|
|
|
editor->priv->text_changed = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2012-02-03 06:41:45 +00:00
|
|
|
hsv_changed (GtkColorEditor *editor)
|
2012-01-30 14:56:20 +00:00
|
|
|
{
|
2012-02-03 06:41:45 +00:00
|
|
|
GdkRGBA color;
|
|
|
|
gdouble h, s, v;
|
|
|
|
|
|
|
|
h = gtk_adjustment_get_value (editor->priv->h_adj);
|
|
|
|
s = gtk_adjustment_get_value (editor->priv->s_adj);
|
|
|
|
v = gtk_adjustment_get_value (editor->priv->v_adj);
|
|
|
|
gtk_hsv_to_rgb (h, s, v, &color.red, &color.green, &color.blue);
|
|
|
|
color.alpha = gtk_adjustment_get_value (editor->priv->a_adj);
|
2012-01-30 14:56:20 +00:00
|
|
|
update_entry (editor);
|
2012-02-03 06:41:45 +00:00
|
|
|
gtk_color_swatch_set_color (GTK_COLOR_SWATCH (editor->priv->swatch), &color);
|
|
|
|
gtk_color_scale_set_color (GTK_COLOR_SCALE (editor->priv->a_slider), &color);
|
2012-01-30 14:56:20 +00:00
|
|
|
g_object_notify (G_OBJECT (editor), "color");
|
|
|
|
}
|
|
|
|
|
2012-01-30 23:37:00 +00:00
|
|
|
static void
|
2012-02-03 06:41:45 +00:00
|
|
|
dismiss_current_popup (GtkColorEditor *editor)
|
|
|
|
{
|
|
|
|
if (editor->priv->current_popup)
|
|
|
|
{
|
|
|
|
gtk_widget_hide (editor->priv->current_popup);
|
|
|
|
editor->priv->current_popup = NULL;
|
|
|
|
if (editor->priv->popdown_focus)
|
|
|
|
{
|
|
|
|
gtk_widget_grab_focus (editor->priv->popdown_focus);
|
|
|
|
editor->priv->popdown_focus = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
popup_edit (GtkWidget *widget,
|
2012-01-30 23:37:00 +00:00
|
|
|
GtkColorEditor *editor)
|
|
|
|
{
|
2012-02-03 06:41:45 +00:00
|
|
|
GtkWidget *popup = NULL;
|
|
|
|
GtkWidget *toplevel;
|
|
|
|
GtkWidget *focus;
|
|
|
|
|
|
|
|
if (widget == editor->priv->sv_plane)
|
|
|
|
{
|
|
|
|
popup = editor->priv->sv_popup;
|
|
|
|
focus = editor->priv->s_entry;
|
|
|
|
}
|
|
|
|
else if (widget == editor->priv->h_slider)
|
|
|
|
{
|
|
|
|
popup = editor->priv->h_popup;
|
|
|
|
focus = editor->priv->h_entry;
|
|
|
|
}
|
|
|
|
else if (widget == editor->priv->a_slider)
|
|
|
|
{
|
|
|
|
popup = editor->priv->a_popup;
|
|
|
|
focus = editor->priv->a_entry;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (popup)
|
|
|
|
{
|
|
|
|
dismiss_current_popup (editor);
|
|
|
|
toplevel = gtk_widget_get_toplevel (GTK_WIDGET (editor));
|
|
|
|
editor->priv->popdown_focus = gtk_window_get_focus (GTK_WINDOW (toplevel));
|
|
|
|
editor->priv->current_popup = popup;
|
|
|
|
gtk_widget_show (popup);
|
|
|
|
gtk_widget_grab_focus (focus);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
popup_key_press (GtkWidget *popup,
|
|
|
|
GdkEventKey *event,
|
|
|
|
GtkColorEditor *editor)
|
|
|
|
{
|
|
|
|
if (event->keyval == GDK_KEY_Escape)
|
|
|
|
{
|
|
|
|
dismiss_current_popup (editor);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
get_child_position (GtkOverlay *overlay,
|
|
|
|
GtkWidget *widget,
|
|
|
|
GtkAllocation *allocation,
|
|
|
|
GtkColorEditor *editor)
|
|
|
|
{
|
|
|
|
GtkRequisition req;
|
|
|
|
GtkAllocation alloc;
|
|
|
|
gint s, e;
|
|
|
|
|
|
|
|
gtk_widget_get_preferred_size (widget, &req, NULL);
|
|
|
|
|
|
|
|
allocation->width = req.width;
|
|
|
|
allocation->height = req.height;
|
|
|
|
|
|
|
|
if (widget == editor->priv->sv_popup)
|
|
|
|
{
|
2012-02-03 06:48:29 +00:00
|
|
|
if (gtk_widget_get_direction (GTK_WIDGET (overlay)) == GTK_TEXT_DIR_RTL)
|
2012-02-03 06:41:45 +00:00
|
|
|
allocation->x = 0;
|
|
|
|
else
|
|
|
|
allocation->x = gtk_widget_get_allocated_width (GTK_WIDGET (overlay)) - req.width;
|
|
|
|
allocation->y = req.height / 3;
|
|
|
|
}
|
|
|
|
else if (widget == editor->priv->h_popup)
|
|
|
|
{
|
|
|
|
gtk_widget_get_allocation (editor->priv->h_slider, &alloc);
|
|
|
|
gtk_range_get_slider_range (GTK_RANGE (editor->priv->h_slider), &s, &e);
|
|
|
|
|
2012-02-03 06:48:29 +00:00
|
|
|
if (gtk_widget_get_direction (GTK_WIDGET (overlay)) == GTK_TEXT_DIR_RTL)
|
2012-02-03 06:41:45 +00:00
|
|
|
gtk_widget_translate_coordinates (editor->priv->h_slider,
|
|
|
|
gtk_widget_get_parent (editor->priv->grid),
|
|
|
|
- req.width, (s + e - req.height) / 2,
|
|
|
|
&allocation->x, &allocation->y);
|
|
|
|
else
|
|
|
|
gtk_widget_translate_coordinates (editor->priv->h_slider,
|
|
|
|
gtk_widget_get_parent (editor->priv->grid),
|
|
|
|
alloc.width, (s + e - req.height) / 2,
|
|
|
|
&allocation->x, &allocation->y);
|
|
|
|
}
|
|
|
|
else if (widget == editor->priv->a_popup)
|
|
|
|
{
|
|
|
|
gtk_widget_get_allocation (editor->priv->a_slider, &alloc);
|
|
|
|
gtk_range_get_slider_range (GTK_RANGE (editor->priv->a_slider), &s, &e);
|
|
|
|
|
|
|
|
gtk_widget_translate_coordinates (editor->priv->a_slider,
|
|
|
|
gtk_widget_get_parent (editor->priv->grid),
|
|
|
|
(s + e - req.width) / 2, - req.height,
|
|
|
|
&allocation->x, &allocation->y);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
allocation->x = CLAMP (allocation->x, 0, gtk_widget_get_allocated_width (GTK_WIDGET (overlay)) - req.width);
|
|
|
|
allocation->y = CLAMP (allocation->y, 0, gtk_widget_get_allocated_height (GTK_WIDGET (overlay)) - req.height);
|
|
|
|
|
|
|
|
return TRUE;
|
2012-01-30 23:37:00 +00:00
|
|
|
}
|
|
|
|
|
2012-01-30 14:56:20 +00:00
|
|
|
static void
|
2012-02-03 06:41:45 +00:00
|
|
|
value_changed (GtkAdjustment *a, GtkAdjustment *as)
|
2012-01-30 14:56:20 +00:00
|
|
|
{
|
2012-02-03 06:41:45 +00:00
|
|
|
gdouble scale;
|
|
|
|
|
|
|
|
scale = gtk_adjustment_get_upper (as) / gtk_adjustment_get_upper (a);
|
|
|
|
g_signal_handlers_block_by_func (as, value_changed, a);
|
|
|
|
gtk_adjustment_set_value (as, gtk_adjustment_get_value (a) * scale);
|
|
|
|
g_signal_handlers_unblock_by_func (as, value_changed, a);
|
|
|
|
}
|
|
|
|
|
|
|
|
static GtkAdjustment *
|
|
|
|
scaled_adjustment (GtkAdjustment *a, gdouble scale)
|
|
|
|
{
|
|
|
|
GtkAdjustment *as;
|
|
|
|
|
|
|
|
as = gtk_adjustment_new (gtk_adjustment_get_value (a) * scale,
|
|
|
|
gtk_adjustment_get_lower (a) * scale,
|
|
|
|
gtk_adjustment_get_upper (a) * scale,
|
|
|
|
gtk_adjustment_get_step_increment (a) * scale,
|
|
|
|
gtk_adjustment_get_page_increment (a) * scale,
|
|
|
|
gtk_adjustment_get_page_size (a) * scale);
|
|
|
|
|
|
|
|
g_signal_connect (a, "value-changed", G_CALLBACK (value_changed), as);
|
|
|
|
g_signal_connect (as, "value-changed", G_CALLBACK (value_changed), a);
|
|
|
|
|
|
|
|
return as;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
popup_draw (GtkWidget *popup, cairo_t *cr, GtkColorEditor *editor)
|
|
|
|
{
|
|
|
|
GtkStyleContext *context;
|
|
|
|
gint width, height;
|
|
|
|
|
|
|
|
context = gtk_widget_get_style_context (popup);
|
|
|
|
width = gtk_widget_get_allocated_width (popup);
|
|
|
|
height = gtk_widget_get_allocated_height (popup);
|
|
|
|
|
|
|
|
gtk_render_background (context, cr, 0, 0, width, height);
|
|
|
|
gtk_render_frame (context, cr, 0, 0, width, height);
|
|
|
|
|
|
|
|
return FALSE;
|
2012-01-30 14:56:20 +00:00
|
|
|
}
|
|
|
|
|
2012-01-29 15:42:34 +00:00
|
|
|
static void
|
|
|
|
gtk_color_editor_init (GtkColorEditor *editor)
|
|
|
|
{
|
2012-01-30 14:56:20 +00:00
|
|
|
GtkWidget *grid;
|
2012-02-03 06:41:45 +00:00
|
|
|
GtkWidget *box;
|
2012-02-02 05:58:26 +00:00
|
|
|
GtkWidget *slider;
|
2012-02-03 06:41:45 +00:00
|
|
|
GtkWidget *alignment;
|
|
|
|
GtkAdjustment *adj;
|
|
|
|
GdkRGBA transparent = { 0, 0, 0, 0 };
|
2012-01-29 15:42:34 +00:00
|
|
|
|
|
|
|
editor->priv = G_TYPE_INSTANCE_GET_PRIVATE (editor,
|
|
|
|
GTK_TYPE_COLOR_EDITOR,
|
|
|
|
GtkColorEditorPrivate);
|
2012-01-31 07:05:37 +00:00
|
|
|
editor->priv->show_alpha = TRUE;
|
|
|
|
|
2012-02-03 06:41:45 +00:00
|
|
|
editor->priv->h_adj = gtk_adjustment_new (0, 0, 1, 0.01, 0.1, 0);
|
|
|
|
editor->priv->s_adj = gtk_adjustment_new (0, 0, 1, 0.01, 0.1, 0);
|
|
|
|
editor->priv->v_adj = gtk_adjustment_new (0, 0, 1, 0.01, 0.1, 0);
|
|
|
|
editor->priv->a_adj = gtk_adjustment_new (0, 0, 1, 0.01, 0.1, 0);
|
|
|
|
g_object_ref_sink (editor->priv->h_adj);
|
|
|
|
g_object_ref_sink (editor->priv->s_adj);
|
|
|
|
g_object_ref_sink (editor->priv->v_adj);
|
|
|
|
g_object_ref_sink (editor->priv->a_adj);
|
|
|
|
g_signal_connect_swapped (editor->priv->h_adj, "value-changed",
|
|
|
|
G_CALLBACK (hsv_changed), editor);
|
|
|
|
g_signal_connect_swapped (editor->priv->s_adj, "value-changed",
|
|
|
|
G_CALLBACK (hsv_changed), editor);
|
|
|
|
g_signal_connect_swapped (editor->priv->a_adj, "value-changed",
|
|
|
|
G_CALLBACK (hsv_changed), editor);
|
|
|
|
g_signal_connect_swapped (editor->priv->v_adj, "value-changed",
|
|
|
|
G_CALLBACK (hsv_changed), editor);
|
|
|
|
|
2012-01-29 15:42:34 +00:00
|
|
|
gtk_widget_push_composite_child ();
|
|
|
|
|
2012-02-03 06:41:45 +00:00
|
|
|
editor->priv->overlay = gtk_overlay_new ();
|
|
|
|
gtk_widget_override_background_color (editor->priv->overlay, 0, &transparent);
|
2012-01-30 14:56:20 +00:00
|
|
|
editor->priv->grid = grid = gtk_grid_new ();
|
|
|
|
gtk_grid_set_row_spacing (GTK_GRID (grid), 12);
|
|
|
|
gtk_grid_set_column_spacing (GTK_GRID (grid), 12);
|
|
|
|
|
2012-02-01 05:58:07 +00:00
|
|
|
editor->priv->swatch = gtk_color_swatch_new ();
|
|
|
|
gtk_widget_set_sensitive (editor->priv->swatch, FALSE);
|
|
|
|
gtk_color_swatch_set_corner_radii (GTK_COLOR_SWATCH (editor->priv->swatch), 2, 2, 2, 2);
|
|
|
|
|
2012-01-30 14:56:20 +00:00
|
|
|
editor->priv->entry = gtk_entry_new ();
|
|
|
|
g_signal_connect (editor->priv->entry, "activate",
|
|
|
|
G_CALLBACK (entry_apply), editor);
|
|
|
|
g_signal_connect (editor->priv->entry, "notify::text",
|
|
|
|
G_CALLBACK (entry_text_changed), editor);
|
|
|
|
g_signal_connect (editor->priv->entry, "focus-out-event",
|
|
|
|
G_CALLBACK (entry_focus_out), editor);
|
|
|
|
|
2012-02-03 17:13:06 +00:00
|
|
|
editor->priv->h_slider = slider = gtk_color_scale_new (editor->priv->h_adj,
|
|
|
|
GTK_COLOR_SCALE_HUE);
|
|
|
|
gtk_orientable_set_orientation (GTK_ORIENTABLE (slider), GTK_ORIENTATION_VERTICAL);
|
2012-02-03 06:41:45 +00:00
|
|
|
if (gtk_widget_get_direction (slider) == GTK_TEXT_DIR_RTL)
|
|
|
|
gtk_style_context_add_class (gtk_widget_get_style_context (slider), GTK_STYLE_CLASS_SCALE_HAS_MARKS_ABOVE);
|
|
|
|
else
|
|
|
|
gtk_style_context_add_class (gtk_widget_get_style_context (slider), GTK_STYLE_CLASS_SCALE_HAS_MARKS_BELOW);
|
|
|
|
|
2012-02-03 17:13:06 +00:00
|
|
|
editor->priv->a_slider = slider = gtk_color_scale_new (editor->priv->a_adj,
|
|
|
|
GTK_COLOR_SCALE_ALPHA);
|
|
|
|
gtk_orientable_set_orientation (GTK_ORIENTABLE (slider), GTK_ORIENTATION_HORIZONTAL);
|
2012-02-02 05:58:26 +00:00
|
|
|
gtk_style_context_add_class (gtk_widget_get_style_context (slider), GTK_STYLE_CLASS_SCALE_HAS_MARKS_ABOVE);
|
2012-02-03 06:41:45 +00:00
|
|
|
|
|
|
|
editor->priv->sv_plane = gtk_color_plane_new (editor->priv->h_adj,
|
|
|
|
editor->priv->s_adj,
|
|
|
|
editor->priv->v_adj);
|
|
|
|
gtk_widget_set_size_request (editor->priv->sv_plane, 300, 300);
|
2012-01-30 14:56:20 +00:00
|
|
|
|
|
|
|
gtk_grid_attach (GTK_GRID (grid), editor->priv->swatch, 1, 0, 1, 1);
|
|
|
|
gtk_grid_attach (GTK_GRID (grid), editor->priv->entry, 2, 0, 1, 1);
|
|
|
|
gtk_grid_attach (GTK_GRID (grid), editor->priv->h_slider, 0, 1, 1, 1);
|
|
|
|
gtk_grid_attach (GTK_GRID (grid), editor->priv->sv_plane, 1, 1, 2, 1);
|
|
|
|
gtk_grid_attach (GTK_GRID (grid), editor->priv->a_slider, 1, 2, 2, 1);
|
2012-02-03 12:27:10 +00:00
|
|
|
|
|
|
|
/* This extra alignment is necessary so we have room to the sides
|
|
|
|
* to place the popups as desired
|
|
|
|
*/
|
2012-02-03 06:41:45 +00:00
|
|
|
alignment = gtk_alignment_new (0.5, 0.5, 0, 0);
|
|
|
|
gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 0, 0, 30, 30);
|
|
|
|
gtk_container_add (GTK_CONTAINER (editor->priv->overlay), alignment);
|
|
|
|
gtk_container_add (GTK_CONTAINER (alignment), grid);
|
|
|
|
|
|
|
|
editor->priv->sv_popup = gtk_alignment_new (0.5, 0.5, 0, 0);
|
|
|
|
gtk_style_context_add_class (gtk_widget_get_style_context (editor->priv->sv_popup),
|
|
|
|
GTK_STYLE_CLASS_TOOLTIP);
|
|
|
|
gtk_alignment_set_padding (GTK_ALIGNMENT (editor->priv->sv_popup), 12, 12, 12, 12);
|
|
|
|
grid = gtk_grid_new ();
|
|
|
|
gtk_grid_set_column_spacing (GTK_GRID (grid), 6);
|
|
|
|
adj = scaled_adjustment (editor->priv->s_adj, 100);
|
|
|
|
editor->priv->s_entry = gtk_spin_button_new (adj, 1, 0);
|
|
|
|
g_signal_connect (editor->priv->s_entry, "key-press-event",
|
|
|
|
G_CALLBACK (popup_key_press), editor);
|
|
|
|
|
|
|
|
adj = scaled_adjustment (editor->priv->v_adj, 100);
|
|
|
|
editor->priv->v_entry = gtk_spin_button_new (adj, 1, 0);
|
|
|
|
g_signal_connect (editor->priv->v_entry, "key-press-event",
|
|
|
|
G_CALLBACK (popup_key_press), editor);
|
|
|
|
|
|
|
|
gtk_container_add (GTK_CONTAINER (editor->priv->sv_popup), grid);
|
2012-02-03 06:48:29 +00:00
|
|
|
gtk_grid_attach (GTK_GRID (grid), gtk_label_new (C_("Color channel", "S")), 0, 0, 1, 1);
|
2012-02-03 06:41:45 +00:00
|
|
|
gtk_grid_attach (GTK_GRID (grid), editor->priv->s_entry, 1, 0, 1, 1);
|
2012-02-03 06:48:29 +00:00
|
|
|
gtk_grid_attach (GTK_GRID (grid), gtk_label_new (C_("Color channel", "V")), 0, 1, 1, 1);
|
2012-02-03 06:41:45 +00:00
|
|
|
gtk_grid_attach (GTK_GRID (grid), editor->priv->v_entry, 1, 1, 1, 1);
|
|
|
|
gtk_widget_show_all (editor->priv->sv_popup);
|
|
|
|
gtk_widget_hide (editor->priv->sv_popup);
|
|
|
|
gtk_widget_set_no_show_all (editor->priv->sv_popup, TRUE);
|
|
|
|
|
|
|
|
gtk_overlay_add_overlay (GTK_OVERLAY (editor->priv->overlay), editor->priv->sv_popup);
|
|
|
|
|
|
|
|
g_signal_connect (editor->priv->sv_popup, "draw",
|
|
|
|
G_CALLBACK (popup_draw), editor);
|
|
|
|
g_signal_connect (editor->priv->sv_plane, "popup-menu",
|
|
|
|
G_CALLBACK (popup_edit), editor);
|
|
|
|
|
|
|
|
editor->priv->h_popup = gtk_alignment_new (0.5, 0.5, 0, 0);
|
|
|
|
gtk_style_context_add_class (gtk_widget_get_style_context (editor->priv->h_popup),
|
|
|
|
GTK_STYLE_CLASS_TOOLTIP);
|
|
|
|
gtk_alignment_set_padding (GTK_ALIGNMENT (editor->priv->h_popup), 12, 12, 12, 12);
|
|
|
|
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
|
|
|
|
adj = scaled_adjustment (editor->priv->h_adj, 100);
|
|
|
|
editor->priv->h_entry = gtk_spin_button_new (adj, 1, 0);
|
|
|
|
g_signal_connect (editor->priv->h_entry, "key-press-event",
|
|
|
|
G_CALLBACK (popup_key_press), editor);
|
|
|
|
gtk_container_add (GTK_CONTAINER (editor->priv->h_popup), box);
|
2012-02-03 06:48:29 +00:00
|
|
|
gtk_container_add (GTK_CONTAINER (box), gtk_label_new (C_("Color channel", "H")));
|
2012-02-03 06:41:45 +00:00
|
|
|
gtk_container_add (GTK_CONTAINER (box), editor->priv->h_entry);
|
|
|
|
gtk_widget_show_all (editor->priv->h_popup);
|
|
|
|
gtk_widget_hide (editor->priv->h_popup);
|
|
|
|
gtk_widget_set_no_show_all (editor->priv->h_popup, TRUE);
|
|
|
|
|
|
|
|
gtk_overlay_add_overlay (GTK_OVERLAY (editor->priv->overlay), editor->priv->h_popup);
|
|
|
|
|
|
|
|
g_signal_connect (editor->priv->h_popup, "draw",
|
|
|
|
G_CALLBACK (popup_draw), editor);
|
|
|
|
g_signal_connect (editor->priv->h_slider, "popup-menu",
|
|
|
|
G_CALLBACK (popup_edit), editor);
|
|
|
|
|
|
|
|
editor->priv->a_popup = gtk_alignment_new (0.5, 0.5, 0, 0);
|
|
|
|
gtk_style_context_add_class (gtk_widget_get_style_context (editor->priv->a_popup),
|
|
|
|
GTK_STYLE_CLASS_TOOLTIP);
|
|
|
|
gtk_alignment_set_padding (GTK_ALIGNMENT (editor->priv->a_popup), 12, 12, 12, 12);
|
|
|
|
grid = gtk_grid_new ();
|
|
|
|
gtk_grid_set_column_spacing (GTK_GRID (grid), 6);
|
|
|
|
adj = scaled_adjustment (editor->priv->a_adj, 100);
|
|
|
|
editor->priv->a_entry = gtk_spin_button_new (adj, 1, 0);
|
|
|
|
g_signal_connect (editor->priv->a_entry, "key-press-event",
|
|
|
|
G_CALLBACK (popup_key_press), editor);
|
|
|
|
gtk_container_add (GTK_CONTAINER (editor->priv->a_popup), grid);
|
2012-02-03 06:48:29 +00:00
|
|
|
gtk_grid_attach (GTK_GRID (grid), gtk_label_new (C_("Color channel", "A")), 0, 0, 1, 1);
|
2012-02-03 06:41:45 +00:00
|
|
|
gtk_grid_attach (GTK_GRID (grid), editor->priv->a_entry, 1, 0, 1, 1);
|
|
|
|
gtk_widget_show_all (editor->priv->a_popup);
|
|
|
|
gtk_widget_hide (editor->priv->a_popup);
|
|
|
|
gtk_widget_set_no_show_all (editor->priv->a_popup, TRUE);
|
|
|
|
|
|
|
|
gtk_overlay_add_overlay (GTK_OVERLAY (editor->priv->overlay), editor->priv->a_popup);
|
|
|
|
|
|
|
|
g_signal_connect (editor->priv->a_popup, "draw",
|
|
|
|
G_CALLBACK (popup_draw), editor);
|
|
|
|
g_signal_connect (editor->priv->a_slider, "popup-menu",
|
|
|
|
G_CALLBACK (popup_edit), editor);
|
|
|
|
|
|
|
|
g_signal_connect (editor->priv->overlay, "get-child-position",
|
|
|
|
G_CALLBACK (get_child_position), editor);
|
2012-02-03 11:49:08 +00:00
|
|
|
g_signal_connect (editor, "notify::visible",
|
|
|
|
G_CALLBACK (dismiss_current_popup), NULL);
|
2012-02-03 06:41:45 +00:00
|
|
|
|
|
|
|
gtk_widget_show_all (editor->priv->overlay);
|
|
|
|
|
|
|
|
gtk_container_add (GTK_CONTAINER (editor), editor->priv->overlay);
|
2012-01-29 15:42:34 +00:00
|
|
|
gtk_widget_pop_composite_child ();
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gtk_color_editor_get_property (GObject *object,
|
|
|
|
guint prop_id,
|
|
|
|
GValue *value,
|
|
|
|
GParamSpec *pspec)
|
|
|
|
{
|
2012-01-31 07:05:37 +00:00
|
|
|
GtkColorEditor *ce = GTK_COLOR_EDITOR (object);
|
2012-01-29 15:42:34 +00:00
|
|
|
GtkColorChooser *cc = GTK_COLOR_CHOOSER (object);
|
|
|
|
|
|
|
|
switch (prop_id)
|
|
|
|
{
|
|
|
|
case PROP_COLOR:
|
|
|
|
{
|
|
|
|
GdkRGBA color;
|
|
|
|
gtk_color_chooser_get_color (cc, &color);
|
|
|
|
g_value_set_boxed (value, &color);
|
|
|
|
}
|
2012-01-31 07:05:37 +00:00
|
|
|
break;
|
|
|
|
case PROP_SHOW_ALPHA:
|
|
|
|
g_value_set_boolean (value, gtk_widget_get_visible (ce->priv->a_slider));
|
|
|
|
break;
|
2012-01-29 15:42:34 +00:00
|
|
|
default:
|
|
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-01-31 07:05:37 +00:00
|
|
|
static void
|
|
|
|
gtk_color_editor_set_show_alpha (GtkColorEditor *editor,
|
|
|
|
gboolean show_alpha)
|
|
|
|
{
|
|
|
|
if (editor->priv->show_alpha != show_alpha)
|
|
|
|
{
|
|
|
|
editor->priv->show_alpha = show_alpha;
|
|
|
|
|
2012-02-01 05:58:07 +00:00
|
|
|
gtk_widget_set_visible (editor->priv->a_slider, show_alpha);
|
|
|
|
|
|
|
|
gtk_color_swatch_set_show_alpha (GTK_COLOR_SWATCH (editor->priv->swatch), show_alpha);
|
2012-01-31 07:05:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-01-29 15:42:34 +00:00
|
|
|
static void
|
|
|
|
gtk_color_editor_set_property (GObject *object,
|
|
|
|
guint prop_id,
|
|
|
|
const GValue *value,
|
|
|
|
GParamSpec *pspec)
|
|
|
|
{
|
2012-01-31 07:05:37 +00:00
|
|
|
GtkColorEditor *ce = GTK_COLOR_EDITOR (object);
|
2012-01-29 15:42:34 +00:00
|
|
|
GtkColorChooser *cc = GTK_COLOR_CHOOSER (object);
|
|
|
|
|
|
|
|
switch (prop_id)
|
|
|
|
{
|
|
|
|
case PROP_COLOR:
|
|
|
|
gtk_color_chooser_set_color (cc, g_value_get_boxed (value));
|
2012-01-31 07:05:37 +00:00
|
|
|
break;
|
|
|
|
case PROP_SHOW_ALPHA:
|
|
|
|
gtk_color_editor_set_show_alpha (ce, g_value_get_boolean (value));
|
|
|
|
break;
|
2012-01-29 15:42:34 +00:00
|
|
|
default:
|
|
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-02-01 05:37:36 +00:00
|
|
|
static void
|
|
|
|
gtk_color_editor_finalize (GObject *object)
|
|
|
|
{
|
2012-02-03 06:41:45 +00:00
|
|
|
GtkColorEditor *editor = GTK_COLOR_EDITOR (object);
|
|
|
|
|
|
|
|
g_clear_object (&editor->priv->h_adj);
|
|
|
|
g_clear_object (&editor->priv->s_adj);
|
|
|
|
g_clear_object (&editor->priv->v_adj);
|
|
|
|
g_clear_object (&editor->priv->a_adj);
|
|
|
|
|
2012-02-01 05:37:36 +00:00
|
|
|
G_OBJECT_CLASS (gtk_color_editor_parent_class)->finalize (object);
|
|
|
|
}
|
|
|
|
|
2012-01-29 15:42:34 +00:00
|
|
|
static void
|
|
|
|
gtk_color_editor_class_init (GtkColorEditorClass *class)
|
|
|
|
{
|
|
|
|
GObjectClass *object_class = G_OBJECT_CLASS (class);
|
|
|
|
|
2012-02-01 05:37:36 +00:00
|
|
|
object_class->finalize = gtk_color_editor_finalize;
|
2012-01-29 15:42:34 +00:00
|
|
|
object_class->get_property = gtk_color_editor_get_property;
|
|
|
|
object_class->set_property = gtk_color_editor_set_property;
|
|
|
|
|
|
|
|
g_object_class_override_property (object_class, PROP_COLOR, "color");
|
2012-01-31 07:05:37 +00:00
|
|
|
g_object_class_override_property (object_class, PROP_SHOW_ALPHA, "show-alpha");
|
2012-01-29 15:42:34 +00:00
|
|
|
|
|
|
|
g_type_class_add_private (class, sizeof (GtkColorEditorPrivate));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gtk_color_editor_get_color (GtkColorChooser *chooser,
|
|
|
|
GdkRGBA *color)
|
|
|
|
{
|
|
|
|
GtkColorEditor *editor = GTK_COLOR_EDITOR (chooser);
|
2012-02-03 06:41:45 +00:00
|
|
|
gdouble h, s, v;
|
2012-01-29 15:42:34 +00:00
|
|
|
|
2012-02-03 06:41:45 +00:00
|
|
|
h = gtk_adjustment_get_value (editor->priv->h_adj);
|
|
|
|
s = gtk_adjustment_get_value (editor->priv->s_adj);
|
|
|
|
v = gtk_adjustment_get_value (editor->priv->v_adj);
|
|
|
|
gtk_hsv_to_rgb (h, s, v, &color->red, &color->green, &color->blue);
|
|
|
|
color->alpha = gtk_adjustment_get_value (editor->priv->a_adj);
|
2012-01-29 15:42:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gtk_color_editor_set_color (GtkColorChooser *chooser,
|
|
|
|
const GdkRGBA *color)
|
|
|
|
{
|
|
|
|
GtkColorEditor *editor = GTK_COLOR_EDITOR (chooser);
|
2012-02-01 05:58:07 +00:00
|
|
|
gdouble h, s, v;
|
2012-01-29 15:42:34 +00:00
|
|
|
|
2012-02-01 05:58:07 +00:00
|
|
|
gtk_rgb_to_hsv (color->red, color->green, color->blue, &h, &s, &v);
|
|
|
|
|
|
|
|
gtk_adjustment_set_value (editor->priv->h_adj, h);
|
2012-02-03 06:41:45 +00:00
|
|
|
gtk_adjustment_set_value (editor->priv->s_adj, s);
|
|
|
|
gtk_adjustment_set_value (editor->priv->v_adj, v);
|
2012-02-01 05:58:07 +00:00
|
|
|
gtk_adjustment_set_value (editor->priv->a_adj, color->alpha);
|
2012-02-03 06:41:45 +00:00
|
|
|
gtk_color_swatch_set_color (GTK_COLOR_SWATCH (editor->priv->swatch), color);
|
|
|
|
gtk_color_scale_set_color (GTK_COLOR_SCALE (editor->priv->a_slider), color);
|
|
|
|
|
2012-02-01 05:58:07 +00:00
|
|
|
update_entry (editor);
|
2012-01-30 14:56:20 +00:00
|
|
|
|
2012-02-01 05:58:07 +00:00
|
|
|
gtk_widget_queue_draw (GTK_WIDGET (editor));
|
2012-01-30 14:56:20 +00:00
|
|
|
|
2012-01-29 15:42:34 +00:00
|
|
|
g_object_notify (G_OBJECT (editor), "color");
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gtk_color_editor_iface_init (GtkColorChooserInterface *iface)
|
|
|
|
{
|
|
|
|
iface->get_color = gtk_color_editor_get_color;
|
|
|
|
iface->set_color = gtk_color_editor_set_color;
|
|
|
|
}
|
|
|
|
|
|
|
|
GtkWidget *
|
|
|
|
gtk_color_editor_new (void)
|
|
|
|
{
|
|
|
|
return (GtkWidget *) g_object_new (GTK_TYPE_COLOR_EDITOR, NULL);
|
|
|
|
}
|