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
|
2012-02-27 13:01:10 +00:00
|
|
|
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
2012-01-29 15:42:34 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
|
2012-02-09 00:36:10 +00:00
|
|
|
#include "gtkcoloreditorprivate.h"
|
2012-02-04 05:02:49 +00:00
|
|
|
|
|
|
|
#include "gtkcolorchooserprivate.h"
|
2012-02-09 00:36:10 +00:00
|
|
|
#include "gtkcolorplaneprivate.h"
|
|
|
|
#include "gtkcolorscaleprivate.h"
|
|
|
|
#include "gtkcolorswatchprivate.h"
|
2012-02-04 01:38:21 +00:00
|
|
|
#include "gtkcolorutils.h"
|
2018-07-26 22:46:37 +00:00
|
|
|
#include "gtkcolorpickerprivate.h"
|
2012-01-30 14:56:20 +00:00
|
|
|
#include "gtkgrid.h"
|
2018-07-26 22:46:37 +00:00
|
|
|
#include "gtkbutton.h"
|
2014-06-15 15:57:59 +00:00
|
|
|
#include "gtkintl.h"
|
2012-02-02 05:58:26 +00:00
|
|
|
#include "gtkorientable.h"
|
2012-01-30 14:56:20 +00:00
|
|
|
#include "gtkentry.h"
|
2012-02-03 06:41:45 +00:00
|
|
|
#include "gtkoverlay.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"
|
2018-02-08 00:27:16 +00:00
|
|
|
#include "gtkeventcontrollerkey.h"
|
2019-03-02 13:49:00 +00:00
|
|
|
#include "gtkroot.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
|
|
|
|
2020-03-28 21:16:42 +00:00
|
|
|
typedef struct _GtkColorEditorClass GtkColorEditorClass;
|
|
|
|
|
|
|
|
struct _GtkColorEditor
|
2012-01-29 15:42:34 +00:00
|
|
|
{
|
2020-03-28 21:16:42 +00:00
|
|
|
GtkBox parent_instance;
|
|
|
|
|
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
|
|
|
|
2018-07-26 22:46:37 +00:00
|
|
|
GtkWidget *picker_button;
|
|
|
|
GtkColorPicker *picker;
|
|
|
|
|
2020-07-24 13:54:49 +00:00
|
|
|
int popup_position;
|
2016-03-12 03:44:17 +00:00
|
|
|
|
2012-01-31 07:05:37 +00:00
|
|
|
guint text_changed : 1;
|
2012-02-04 05:02:49 +00:00
|
|
|
guint use_alpha : 1;
|
2012-01-29 15:42:34 +00:00
|
|
|
};
|
|
|
|
|
2020-03-28 21:16:42 +00:00
|
|
|
struct _GtkColorEditorClass
|
|
|
|
{
|
|
|
|
GtkBoxClass parent_class;
|
|
|
|
};
|
|
|
|
|
2012-01-29 15:42:34 +00:00
|
|
|
enum
|
|
|
|
{
|
|
|
|
PROP_ZERO,
|
2012-02-03 23:34:33 +00:00
|
|
|
PROP_RGBA,
|
|
|
|
PROP_USE_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
|
2020-07-24 20:32:16 +00:00
|
|
|
scale_round (double value, double scale)
|
2012-01-30 14:56:20 +00:00
|
|
|
{
|
|
|
|
value = floor (value * scale + 0.5);
|
|
|
|
value = MAX (value, 0);
|
|
|
|
value = MIN (value, scale);
|
|
|
|
return (guint)value;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2012-02-04 05:02:49 +00:00
|
|
|
entry_set_rgba (GtkColorEditor *editor,
|
|
|
|
const GdkRGBA *color)
|
2012-01-30 14:56:20 +00:00
|
|
|
{
|
2020-07-24 18:40:36 +00:00
|
|
|
char *text;
|
2012-01-30 14:56:20 +00:00
|
|
|
|
|
|
|
text = g_strdup_printf ("#%02X%02X%02X",
|
2012-02-04 05:02:49 +00:00
|
|
|
scale_round (color->red, 255),
|
|
|
|
scale_round (color->green, 255),
|
|
|
|
scale_round (color->blue, 255));
|
2020-03-28 21:16:42 +00:00
|
|
|
gtk_editable_set_text (GTK_EDITABLE (editor->entry), text);
|
|
|
|
editor->text_changed = FALSE;
|
2012-01-30 14:56:20 +00:00
|
|
|
g_free (text);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
entry_apply (GtkWidget *entry,
|
|
|
|
GtkColorEditor *editor)
|
|
|
|
{
|
|
|
|
GdkRGBA color;
|
2020-07-24 18:40:36 +00:00
|
|
|
char *text;
|
2012-01-30 14:56:20 +00:00
|
|
|
|
2020-03-28 21:16:42 +00:00
|
|
|
if (!editor->text_changed)
|
2012-01-30 14:56:20 +00:00
|
|
|
return;
|
|
|
|
|
2020-03-28 21:16:42 +00:00
|
|
|
text = gtk_editable_get_chars (GTK_EDITABLE (editor->entry), 0, -1);
|
2012-01-30 14:56:20 +00:00
|
|
|
if (gdk_rgba_parse (&color, text))
|
|
|
|
{
|
2020-03-28 21:16:42 +00:00
|
|
|
color.alpha = gtk_adjustment_get_value (editor->a_adj);
|
2012-02-03 23:34:33 +00:00
|
|
|
gtk_color_chooser_set_rgba (GTK_COLOR_CHOOSER (editor), &color);
|
2012-01-30 14:56:20 +00:00
|
|
|
}
|
|
|
|
|
2020-03-28 21:16:42 +00:00
|
|
|
editor->text_changed = FALSE;
|
2012-01-30 14:56:20 +00:00
|
|
|
|
|
|
|
g_free (text);
|
|
|
|
}
|
|
|
|
|
2018-01-06 20:35:54 +00:00
|
|
|
static void
|
|
|
|
entry_focus_changed (GtkWidget *entry,
|
|
|
|
GParamSpec *pspec,
|
|
|
|
GtkColorEditor *editor)
|
2012-01-30 14:56:20 +00:00
|
|
|
{
|
2018-01-06 20:35:54 +00:00
|
|
|
if (!gtk_widget_has_focus (entry))
|
|
|
|
entry_apply (entry, editor);
|
2012-01-30 14:56:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
entry_text_changed (GtkWidget *entry,
|
|
|
|
GParamSpec *pspec,
|
|
|
|
GtkColorEditor *editor)
|
|
|
|
{
|
2020-03-28 21:16:42 +00:00
|
|
|
editor->text_changed = TRUE;
|
2012-01-30 14:56:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
2020-07-24 20:32:16 +00:00
|
|
|
double h, s, v, a;
|
2012-02-03 06:41:45 +00:00
|
|
|
|
2020-03-28 21:16:42 +00:00
|
|
|
h = gtk_adjustment_get_value (editor->h_adj);
|
|
|
|
s = gtk_adjustment_get_value (editor->s_adj);
|
|
|
|
v = gtk_adjustment_get_value (editor->v_adj);
|
|
|
|
a = gtk_adjustment_get_value (editor->a_adj);
|
2012-02-04 05:02:49 +00:00
|
|
|
|
2012-02-03 06:41:45 +00:00
|
|
|
gtk_hsv_to_rgb (h, s, v, &color.red, &color.green, &color.blue);
|
2012-02-04 05:02:49 +00:00
|
|
|
color.alpha = a;
|
|
|
|
|
2020-03-28 21:16:42 +00:00
|
|
|
gtk_color_swatch_set_rgba (GTK_COLOR_SWATCH (editor->swatch), &color);
|
|
|
|
gtk_color_scale_set_rgba (GTK_COLOR_SCALE (editor->a_slider), &color);
|
2012-02-04 05:02:49 +00:00
|
|
|
entry_set_rgba (editor, &color);
|
|
|
|
|
2012-02-03 23:34:33 +00:00
|
|
|
g_object_notify (G_OBJECT (editor), "rgba");
|
2012-01-30 14:56:20 +00:00
|
|
|
}
|
|
|
|
|
2012-01-30 23:37:00 +00:00
|
|
|
static void
|
2012-02-03 06:41:45 +00:00
|
|
|
dismiss_current_popup (GtkColorEditor *editor)
|
|
|
|
{
|
2020-03-28 21:16:42 +00:00
|
|
|
if (editor->current_popup)
|
2012-02-03 06:41:45 +00:00
|
|
|
{
|
2020-03-28 21:16:42 +00:00
|
|
|
gtk_widget_hide (editor->current_popup);
|
|
|
|
editor->current_popup = NULL;
|
|
|
|
editor->popup_position = 0;
|
|
|
|
if (editor->popdown_focus)
|
2012-02-03 06:41:45 +00:00
|
|
|
{
|
2020-03-28 21:16:42 +00:00
|
|
|
if (gtk_widget_is_visible (editor->popdown_focus))
|
|
|
|
gtk_widget_grab_focus (editor->popdown_focus);
|
|
|
|
g_clear_object (&editor->popdown_focus);
|
2012-02-03 06:41:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2020-03-19 02:36:31 +00:00
|
|
|
popup_edit (GtkWidget *widget,
|
|
|
|
const char *action_name,
|
|
|
|
GVariant *parameters)
|
2012-01-30 23:37:00 +00:00
|
|
|
{
|
2020-03-19 02:36:31 +00:00
|
|
|
GtkColorEditor *editor = GTK_COLOR_EDITOR (widget);
|
2012-02-03 06:41:45 +00:00
|
|
|
GtkWidget *popup = NULL;
|
2019-03-17 23:41:26 +00:00
|
|
|
GtkRoot *root;
|
2012-02-03 06:41:45 +00:00
|
|
|
GtkWidget *focus;
|
2020-07-24 13:54:49 +00:00
|
|
|
int position;
|
|
|
|
int s, e;
|
2020-03-19 02:36:31 +00:00
|
|
|
const char *param;
|
|
|
|
|
|
|
|
param = g_variant_get_string (parameters, NULL);
|
2012-02-03 06:41:45 +00:00
|
|
|
|
2020-03-19 02:36:31 +00:00
|
|
|
if (strcmp (param, "sv") == 0)
|
2012-02-03 06:41:45 +00:00
|
|
|
{
|
2020-03-28 21:16:42 +00:00
|
|
|
popup = editor->sv_popup;
|
|
|
|
focus = editor->s_entry;
|
2016-03-12 03:44:17 +00:00
|
|
|
position = 0;
|
2012-02-03 06:41:45 +00:00
|
|
|
}
|
2020-03-19 02:36:31 +00:00
|
|
|
else if (strcmp (param, "h") == 0)
|
2012-02-03 06:41:45 +00:00
|
|
|
{
|
2020-03-28 21:16:42 +00:00
|
|
|
popup = editor->h_popup;
|
|
|
|
focus = editor->h_entry;
|
|
|
|
gtk_range_get_slider_range (GTK_RANGE (editor->h_slider), &s, &e);
|
2016-03-12 03:44:17 +00:00
|
|
|
position = (s + e) / 2;
|
2012-02-03 06:41:45 +00:00
|
|
|
}
|
2020-03-19 02:36:31 +00:00
|
|
|
else if (strcmp (param, "a") == 0)
|
2012-02-03 06:41:45 +00:00
|
|
|
{
|
2020-03-28 21:16:42 +00:00
|
|
|
popup = editor->a_popup;
|
|
|
|
focus = editor->a_entry;
|
|
|
|
gtk_range_get_slider_range (GTK_RANGE (editor->a_slider), &s, &e);
|
2016-03-12 03:44:17 +00:00
|
|
|
position = (s + e) / 2;
|
2012-02-03 06:41:45 +00:00
|
|
|
}
|
2020-03-19 02:36:31 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
g_warning ("unsupported popup_edit parameter %s", param);
|
|
|
|
}
|
2012-02-03 06:41:45 +00:00
|
|
|
|
2020-03-28 21:16:42 +00:00
|
|
|
if (popup == editor->current_popup)
|
2015-06-14 02:32:05 +00:00
|
|
|
dismiss_current_popup (editor);
|
|
|
|
else if (popup)
|
2012-02-03 06:41:45 +00:00
|
|
|
{
|
|
|
|
dismiss_current_popup (editor);
|
2019-03-17 23:41:26 +00:00
|
|
|
root = gtk_widget_get_root (GTK_WIDGET (editor));
|
2020-03-28 21:16:42 +00:00
|
|
|
g_set_object (&editor->popdown_focus, gtk_root_get_focus (root));
|
|
|
|
editor->current_popup = popup;
|
|
|
|
editor->popup_position = position;
|
2012-02-03 06:41:45 +00:00
|
|
|
gtk_widget_show (popup);
|
|
|
|
gtk_widget_grab_focus (focus);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
2018-02-08 00:27:16 +00:00
|
|
|
popup_key_pressed (GtkEventController *controller,
|
|
|
|
guint keyval,
|
|
|
|
guint keycode,
|
|
|
|
GdkModifierType state,
|
|
|
|
GtkColorEditor *editor)
|
2012-02-03 06:41:45 +00:00
|
|
|
{
|
2018-02-08 00:27:16 +00:00
|
|
|
if (keyval == GDK_KEY_Escape)
|
2012-02-03 06:41:45 +00:00
|
|
|
{
|
|
|
|
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;
|
2020-07-24 13:54:49 +00:00
|
|
|
int s, e;
|
2020-05-17 21:08:01 +00:00
|
|
|
double x, y;
|
2012-02-03 06:41:45 +00:00
|
|
|
|
|
|
|
gtk_widget_get_preferred_size (widget, &req, NULL);
|
|
|
|
|
2014-06-29 02:38:13 +00:00
|
|
|
allocation->x = 0;
|
|
|
|
allocation->y = 0;
|
2012-02-03 06:41:45 +00:00
|
|
|
allocation->width = req.width;
|
|
|
|
allocation->height = req.height;
|
|
|
|
|
2020-03-28 21:16:42 +00:00
|
|
|
if (widget == editor->sv_popup)
|
2012-02-03 06:41:45 +00:00
|
|
|
{
|
2020-03-28 21:16:42 +00:00
|
|
|
gtk_widget_translate_coordinates (editor->sv_plane,
|
|
|
|
gtk_widget_get_parent (editor->grid),
|
2016-03-12 03:44:17 +00:00
|
|
|
0, -6,
|
2020-05-17 21:08:01 +00:00
|
|
|
&x, &y);
|
2012-02-03 06:48:29 +00:00
|
|
|
if (gtk_widget_get_direction (GTK_WIDGET (overlay)) == GTK_TEXT_DIR_RTL)
|
2020-05-17 21:08:01 +00:00
|
|
|
x = 0;
|
2012-02-03 06:41:45 +00:00
|
|
|
else
|
2020-05-17 21:08:01 +00:00
|
|
|
x = gtk_widget_get_width (GTK_WIDGET (overlay)) - req.width;
|
2012-02-03 06:41:45 +00:00
|
|
|
}
|
2020-03-28 21:16:42 +00:00
|
|
|
else if (widget == editor->h_popup)
|
2012-02-03 06:41:45 +00:00
|
|
|
{
|
2020-03-28 21:16:42 +00:00
|
|
|
gtk_widget_get_allocation (editor->h_slider, &alloc);
|
|
|
|
gtk_range_get_slider_range (GTK_RANGE (editor->h_slider), &s, &e);
|
2012-02-03 06:41:45 +00:00
|
|
|
|
2012-02-03 06:48:29 +00:00
|
|
|
if (gtk_widget_get_direction (GTK_WIDGET (overlay)) == GTK_TEXT_DIR_RTL)
|
2020-03-28 21:16:42 +00:00
|
|
|
gtk_widget_translate_coordinates (editor->h_slider,
|
|
|
|
gtk_widget_get_parent (editor->grid),
|
|
|
|
- req.width - 6, editor->popup_position - req.height / 2,
|
2020-05-17 21:08:01 +00:00
|
|
|
&x, &y);
|
2012-02-03 06:41:45 +00:00
|
|
|
else
|
2020-03-28 21:16:42 +00:00
|
|
|
gtk_widget_translate_coordinates (editor->h_slider,
|
|
|
|
gtk_widget_get_parent (editor->grid),
|
|
|
|
alloc.width + 6, editor->popup_position - req.height / 2,
|
2020-05-17 21:08:01 +00:00
|
|
|
&x, &y);
|
2012-02-03 06:41:45 +00:00
|
|
|
}
|
2020-03-28 21:16:42 +00:00
|
|
|
else if (widget == editor->a_popup)
|
2012-02-03 06:41:45 +00:00
|
|
|
{
|
2020-03-28 21:16:42 +00:00
|
|
|
gtk_widget_get_allocation (editor->a_slider, &alloc);
|
|
|
|
gtk_range_get_slider_range (GTK_RANGE (editor->a_slider), &s, &e);
|
2012-02-03 06:41:45 +00:00
|
|
|
|
2020-03-28 21:16:42 +00:00
|
|
|
gtk_widget_translate_coordinates (editor->a_slider,
|
|
|
|
gtk_widget_get_parent (editor->grid),
|
|
|
|
editor->popup_position - req.width / 2, - req.height - 6,
|
2020-05-17 21:08:01 +00:00
|
|
|
&x, &y);
|
2012-02-03 06:41:45 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
return FALSE;
|
|
|
|
|
2020-05-17 21:08:01 +00:00
|
|
|
allocation->x = CLAMP (x, 0, gtk_widget_get_width (GTK_WIDGET (overlay)) - req.width);
|
|
|
|
allocation->y = CLAMP (y, 0, gtk_widget_get_height (GTK_WIDGET (overlay)) - req.height);
|
2012-02-03 06:41:45 +00:00
|
|
|
|
|
|
|
return TRUE;
|
2012-01-30 23:37:00 +00:00
|
|
|
}
|
|
|
|
|
2012-01-30 14:56:20 +00:00
|
|
|
static void
|
2012-02-04 05:02:49 +00:00
|
|
|
value_changed (GtkAdjustment *a,
|
|
|
|
GtkAdjustment *as)
|
2012-01-30 14:56:20 +00:00
|
|
|
{
|
2020-07-24 20:32:16 +00:00
|
|
|
double scale;
|
2012-02-03 06:41:45 +00:00
|
|
|
|
|
|
|
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 *
|
2012-02-04 05:02:49 +00:00
|
|
|
scaled_adjustment (GtkAdjustment *a,
|
2020-07-24 20:32:16 +00:00
|
|
|
double scale)
|
2012-02-03 06:41:45 +00:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2018-07-26 22:46:37 +00:00
|
|
|
static void
|
|
|
|
color_picked (GObject *source,
|
|
|
|
GAsyncResult *res,
|
|
|
|
gpointer data)
|
|
|
|
{
|
|
|
|
GtkColorPicker *picker = GTK_COLOR_PICKER (source);
|
|
|
|
GtkColorEditor *editor = data;
|
|
|
|
GError *error = NULL;
|
|
|
|
GdkRGBA *color;
|
|
|
|
|
|
|
|
color = gtk_color_picker_pick_finish (picker, res, &error);
|
|
|
|
if (color == NULL)
|
|
|
|
{
|
|
|
|
g_error_free (error);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
gtk_color_chooser_set_rgba (GTK_COLOR_CHOOSER (editor), color);
|
|
|
|
gdk_rgba_free (color);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
pick_color (GtkButton *button,
|
|
|
|
GtkColorEditor *editor)
|
|
|
|
{
|
2020-03-28 21:16:42 +00:00
|
|
|
gtk_color_picker_pick (editor->picker, color_picked, editor);
|
2018-07-26 22:46:37 +00:00
|
|
|
}
|
|
|
|
|
2012-01-29 15:42:34 +00:00
|
|
|
static void
|
|
|
|
gtk_color_editor_init (GtkColorEditor *editor)
|
|
|
|
{
|
2018-04-20 17:58:06 +00:00
|
|
|
GtkEventController *controller;
|
|
|
|
|
2020-03-28 21:16:42 +00:00
|
|
|
editor->use_alpha = TRUE;
|
2012-01-31 07:05:37 +00:00
|
|
|
|
2013-03-29 12:47:38 +00:00
|
|
|
g_type_ensure (GTK_TYPE_COLOR_SCALE);
|
|
|
|
g_type_ensure (GTK_TYPE_COLOR_PLANE);
|
|
|
|
g_type_ensure (GTK_TYPE_COLOR_SWATCH);
|
|
|
|
gtk_widget_init_template (GTK_WIDGET (editor));
|
|
|
|
|
2020-03-28 21:16:42 +00:00
|
|
|
if (gtk_widget_get_direction (editor->h_slider) == GTK_TEXT_DIR_RTL)
|
|
|
|
gtk_widget_add_css_class (editor->h_slider, "marks-before");
|
2012-02-03 06:41:45 +00:00
|
|
|
else
|
2020-03-28 21:16:42 +00:00
|
|
|
gtk_widget_add_css_class (editor->h_slider, "marks-after");
|
2012-02-04 05:02:49 +00:00
|
|
|
|
2013-03-29 12:47:38 +00:00
|
|
|
/* Create the scaled popup adjustments manually here because connecting user data is not
|
|
|
|
* supported by template GtkBuilder xml (it would be possible to set this up in the xml
|
|
|
|
* but require 4 separate callbacks and would be rather ugly).
|
|
|
|
*/
|
2020-03-28 21:16:42 +00:00
|
|
|
gtk_spin_button_set_adjustment (GTK_SPIN_BUTTON (editor->h_entry), scaled_adjustment (editor->h_adj, 360));
|
|
|
|
gtk_spin_button_set_adjustment (GTK_SPIN_BUTTON (editor->s_entry), scaled_adjustment (editor->s_adj, 100));
|
|
|
|
gtk_spin_button_set_adjustment (GTK_SPIN_BUTTON (editor->v_entry), scaled_adjustment (editor->v_adj, 100));
|
|
|
|
gtk_spin_button_set_adjustment (GTK_SPIN_BUTTON (editor->a_entry), scaled_adjustment (editor->a_adj, 100));
|
2013-03-29 12:47:38 +00:00
|
|
|
|
|
|
|
/* This can be setup in the .ui file, but requires work in Glade otherwise it cannot be edited there */
|
2020-03-28 21:16:42 +00:00
|
|
|
gtk_overlay_add_overlay (GTK_OVERLAY (editor->overlay), editor->sv_popup);
|
|
|
|
gtk_overlay_add_overlay (GTK_OVERLAY (editor->overlay), editor->h_popup);
|
|
|
|
gtk_overlay_add_overlay (GTK_OVERLAY (editor->overlay), editor->a_popup);
|
2015-10-31 02:16:18 +00:00
|
|
|
|
2018-04-20 17:58:06 +00:00
|
|
|
controller = gtk_event_controller_key_new ();
|
|
|
|
g_signal_connect (controller, "key-pressed", G_CALLBACK (popup_key_pressed), editor);
|
2020-03-28 21:16:42 +00:00
|
|
|
gtk_widget_add_controller (editor->h_entry, controller);
|
2018-04-20 17:58:06 +00:00
|
|
|
controller = gtk_event_controller_key_new ();
|
|
|
|
g_signal_connect (controller, "key-pressed", G_CALLBACK (popup_key_pressed), editor);
|
2020-03-28 21:16:42 +00:00
|
|
|
gtk_widget_add_controller (editor->s_entry, controller);
|
2018-04-20 17:58:06 +00:00
|
|
|
controller = gtk_event_controller_key_new ();
|
|
|
|
g_signal_connect (controller, "key-pressed", G_CALLBACK (popup_key_pressed), editor);
|
2020-03-28 21:16:42 +00:00
|
|
|
gtk_widget_add_controller (editor->v_entry, controller);
|
2018-04-20 17:58:06 +00:00
|
|
|
controller = gtk_event_controller_key_new ();
|
|
|
|
g_signal_connect (controller, "key-pressed", G_CALLBACK (popup_key_pressed), editor);
|
2020-03-28 21:16:42 +00:00
|
|
|
gtk_widget_add_controller (editor->a_entry, controller);
|
2018-02-08 00:27:16 +00:00
|
|
|
|
2020-03-28 21:16:42 +00:00
|
|
|
gtk_widget_remove_css_class (editor->swatch, "activatable");
|
2018-07-26 22:46:37 +00:00
|
|
|
|
2020-03-28 21:16:42 +00:00
|
|
|
editor->picker = gtk_color_picker_new ();
|
|
|
|
if (editor->picker == NULL)
|
|
|
|
gtk_widget_hide (editor->picker_button);
|
2012-01-29 15:42:34 +00:00
|
|
|
}
|
|
|
|
|
2016-06-21 11:57:20 +00:00
|
|
|
static void
|
|
|
|
gtk_color_editor_dispose (GObject *object)
|
|
|
|
{
|
|
|
|
GtkColorEditor *editor = GTK_COLOR_EDITOR (object);
|
|
|
|
|
|
|
|
dismiss_current_popup (editor);
|
2020-03-28 21:16:42 +00:00
|
|
|
g_clear_object (&editor->picker);
|
2016-06-21 11:57:20 +00:00
|
|
|
|
|
|
|
G_OBJECT_CLASS (gtk_color_editor_parent_class)->dispose (object);
|
|
|
|
}
|
|
|
|
|
2012-01-29 15:42:34 +00:00
|
|
|
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)
|
|
|
|
{
|
2012-02-03 23:34:33 +00:00
|
|
|
case PROP_RGBA:
|
2012-01-29 15:42:34 +00:00
|
|
|
{
|
|
|
|
GdkRGBA color;
|
2012-02-03 23:34:33 +00:00
|
|
|
gtk_color_chooser_get_rgba (cc, &color);
|
2012-01-29 15:42:34 +00:00
|
|
|
g_value_set_boxed (value, &color);
|
|
|
|
}
|
2012-01-31 07:05:37 +00:00
|
|
|
break;
|
2012-02-03 23:34:33 +00:00
|
|
|
case PROP_USE_ALPHA:
|
2020-03-28 21:16:42 +00:00
|
|
|
g_value_set_boolean (value, gtk_widget_get_visible (ce->a_slider));
|
2012-01-31 07:05:37 +00:00
|
|
|
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
|
2012-02-03 23:34:33 +00:00
|
|
|
gtk_color_editor_set_use_alpha (GtkColorEditor *editor,
|
|
|
|
gboolean use_alpha)
|
2012-01-31 07:05:37 +00:00
|
|
|
{
|
2020-03-28 21:16:42 +00:00
|
|
|
if (editor->use_alpha != use_alpha)
|
2012-01-31 07:05:37 +00:00
|
|
|
{
|
2020-03-28 21:16:42 +00:00
|
|
|
editor->use_alpha = use_alpha;
|
|
|
|
gtk_widget_set_visible (editor->a_slider, use_alpha);
|
|
|
|
gtk_color_swatch_set_use_alpha (GTK_COLOR_SWATCH (editor->swatch), use_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)
|
|
|
|
{
|
2012-02-03 23:34:33 +00:00
|
|
|
case PROP_RGBA:
|
|
|
|
gtk_color_chooser_set_rgba (cc, g_value_get_boxed (value));
|
2012-01-31 07:05:37 +00:00
|
|
|
break;
|
2012-02-03 23:34:33 +00:00
|
|
|
case PROP_USE_ALPHA:
|
|
|
|
gtk_color_editor_set_use_alpha (ce, g_value_get_boolean (value));
|
2012-01-31 07:05:37 +00:00
|
|
|
break;
|
2012-01-29 15:42:34 +00:00
|
|
|
default:
|
|
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gtk_color_editor_class_init (GtkColorEditorClass *class)
|
|
|
|
{
|
|
|
|
GObjectClass *object_class = G_OBJECT_CLASS (class);
|
2013-03-29 12:47:38 +00:00
|
|
|
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
|
2012-01-29 15:42:34 +00:00
|
|
|
|
2016-06-21 11:57:20 +00:00
|
|
|
object_class->dispose = gtk_color_editor_dispose;
|
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;
|
|
|
|
|
2012-02-03 23:34:33 +00:00
|
|
|
g_object_class_override_property (object_class, PROP_RGBA, "rgba");
|
|
|
|
g_object_class_override_property (object_class, PROP_USE_ALPHA, "use-alpha");
|
2012-01-29 15:42:34 +00:00
|
|
|
|
2013-03-29 12:47:38 +00:00
|
|
|
/* Bind class to template
|
|
|
|
*/
|
|
|
|
gtk_widget_class_set_template_from_resource (widget_class,
|
2014-01-23 23:59:20 +00:00
|
|
|
"/org/gtk/libgtk/ui/gtkcoloreditor.ui");
|
2013-03-29 12:47:38 +00:00
|
|
|
|
2020-03-28 21:16:42 +00:00
|
|
|
gtk_widget_class_bind_template_child (widget_class, GtkColorEditor, overlay);
|
|
|
|
gtk_widget_class_bind_template_child (widget_class, GtkColorEditor, grid);
|
|
|
|
gtk_widget_class_bind_template_child (widget_class, GtkColorEditor, swatch);
|
|
|
|
gtk_widget_class_bind_template_child (widget_class, GtkColorEditor, entry);
|
|
|
|
gtk_widget_class_bind_template_child (widget_class, GtkColorEditor, h_slider);
|
|
|
|
gtk_widget_class_bind_template_child (widget_class, GtkColorEditor, h_popup);
|
|
|
|
gtk_widget_class_bind_template_child (widget_class, GtkColorEditor, h_entry);
|
|
|
|
gtk_widget_class_bind_template_child (widget_class, GtkColorEditor, a_slider);
|
|
|
|
gtk_widget_class_bind_template_child (widget_class, GtkColorEditor, a_popup);
|
|
|
|
gtk_widget_class_bind_template_child (widget_class, GtkColorEditor, a_entry);
|
|
|
|
gtk_widget_class_bind_template_child (widget_class, GtkColorEditor, sv_plane);
|
|
|
|
gtk_widget_class_bind_template_child (widget_class, GtkColorEditor, sv_popup);
|
|
|
|
gtk_widget_class_bind_template_child (widget_class, GtkColorEditor, s_entry);
|
|
|
|
gtk_widget_class_bind_template_child (widget_class, GtkColorEditor, v_entry);
|
|
|
|
gtk_widget_class_bind_template_child (widget_class, GtkColorEditor, h_adj);
|
|
|
|
gtk_widget_class_bind_template_child (widget_class, GtkColorEditor, s_adj);
|
|
|
|
gtk_widget_class_bind_template_child (widget_class, GtkColorEditor, v_adj);
|
|
|
|
gtk_widget_class_bind_template_child (widget_class, GtkColorEditor, a_adj);
|
|
|
|
gtk_widget_class_bind_template_child (widget_class, GtkColorEditor, picker_button);
|
2013-07-26 17:49:49 +00:00
|
|
|
|
|
|
|
gtk_widget_class_bind_template_callback (widget_class, hsv_changed);
|
|
|
|
gtk_widget_class_bind_template_callback (widget_class, dismiss_current_popup);
|
|
|
|
gtk_widget_class_bind_template_callback (widget_class, get_child_position);
|
|
|
|
gtk_widget_class_bind_template_callback (widget_class, entry_text_changed);
|
|
|
|
gtk_widget_class_bind_template_callback (widget_class, entry_apply);
|
2018-01-06 20:35:54 +00:00
|
|
|
gtk_widget_class_bind_template_callback (widget_class, entry_focus_changed);
|
2018-07-26 22:46:37 +00:00
|
|
|
gtk_widget_class_bind_template_callback (widget_class, pick_color);
|
2020-03-19 02:36:31 +00:00
|
|
|
|
2020-04-11 03:59:21 +00:00
|
|
|
/**
|
|
|
|
* GtkColorEditor|color.edit:
|
|
|
|
* @component: the component to edit, "h", "sv" or "a"
|
|
|
|
*
|
|
|
|
* Opens the edit popup for one of the color components.
|
|
|
|
*/
|
2020-03-19 02:36:31 +00:00
|
|
|
gtk_widget_class_install_action (widget_class, "color.edit", "s", popup_edit);
|
2012-01-29 15:42:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2012-02-03 23:34:33 +00:00
|
|
|
gtk_color_editor_get_rgba (GtkColorChooser *chooser,
|
|
|
|
GdkRGBA *color)
|
2012-01-29 15:42:34 +00:00
|
|
|
{
|
|
|
|
GtkColorEditor *editor = GTK_COLOR_EDITOR (chooser);
|
2019-12-10 13:22:52 +00:00
|
|
|
float h, s, v;
|
2012-01-29 15:42:34 +00:00
|
|
|
|
2020-03-28 21:16:42 +00:00
|
|
|
h = gtk_adjustment_get_value (editor->h_adj);
|
|
|
|
s = gtk_adjustment_get_value (editor->s_adj);
|
|
|
|
v = gtk_adjustment_get_value (editor->v_adj);
|
2012-02-03 06:41:45 +00:00
|
|
|
gtk_hsv_to_rgb (h, s, v, &color->red, &color->green, &color->blue);
|
2020-03-28 21:16:42 +00:00
|
|
|
color->alpha = gtk_adjustment_get_value (editor->a_adj);
|
2012-01-29 15:42:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2012-02-03 23:34:33 +00:00
|
|
|
gtk_color_editor_set_rgba (GtkColorChooser *chooser,
|
|
|
|
const GdkRGBA *color)
|
2012-01-29 15:42:34 +00:00
|
|
|
{
|
|
|
|
GtkColorEditor *editor = GTK_COLOR_EDITOR (chooser);
|
2019-12-10 13:22:52 +00:00
|
|
|
float 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);
|
|
|
|
|
2020-03-28 21:16:42 +00:00
|
|
|
gtk_adjustment_set_value (editor->h_adj, h);
|
|
|
|
gtk_adjustment_set_value (editor->s_adj, s);
|
|
|
|
gtk_adjustment_set_value (editor->v_adj, v);
|
|
|
|
gtk_adjustment_set_value (editor->a_adj, color->alpha);
|
2012-02-04 05:02:49 +00:00
|
|
|
|
2020-03-28 21:16:42 +00:00
|
|
|
gtk_color_swatch_set_rgba (GTK_COLOR_SWATCH (editor->swatch), color);
|
|
|
|
gtk_color_scale_set_rgba (GTK_COLOR_SCALE (editor->a_slider), color);
|
2012-02-04 05:02:49 +00:00
|
|
|
entry_set_rgba (editor, color);
|
2012-01-30 14:56:20 +00:00
|
|
|
|
2012-02-03 23:34:33 +00:00
|
|
|
g_object_notify (G_OBJECT (editor), "rgba");
|
2012-01-29 15:42:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gtk_color_editor_iface_init (GtkColorChooserInterface *iface)
|
|
|
|
{
|
2012-02-03 23:34:33 +00:00
|
|
|
iface->get_rgba = gtk_color_editor_get_rgba;
|
|
|
|
iface->set_rgba = gtk_color_editor_set_rgba;
|
2012-01-29 15:42:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
GtkWidget *
|
|
|
|
gtk_color_editor_new (void)
|
|
|
|
{
|
|
|
|
return (GtkWidget *) g_object_new (GTK_TYPE_COLOR_EDITOR, NULL);
|
|
|
|
}
|