1/* GTK - The GIMP Toolkit
2 * Copyright (C) 2012 Red Hat, Inc.
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include "config.h"
19
20#include "gtkcoloreditorprivate.h"
21
22#include "gtkcolorchooserprivate.h"
23#include "gtkcolorplaneprivate.h"
24#include "gtkcolorscaleprivate.h"
25#include "gtkcolorswatchprivate.h"
26#include "gtkcolorutils.h"
27#include "gtkcolorpickerprivate.h"
28#include "gtkgrid.h"
29#include "gtkbutton.h"
30#include "gtkintl.h"
31#include "gtkorientable.h"
32#include "gtkentry.h"
33#include "gtkoverlay.h"
34#include "gtkadjustment.h"
35#include "gtklabel.h"
36#include "gtkspinbutton.h"
37#include "gtkeventcontrollerkey.h"
38#include "gtkroot.h"
39
40#include <math.h>
41
42typedef struct _GtkColorEditorClass GtkColorEditorClass;
43
44struct _GtkColorEditor
45{
46 GtkBox parent_instance;
47
48 GtkWidget *overlay;
49 GtkWidget *grid;
50 GtkWidget *swatch;
51 GtkWidget *entry;
52 GtkWidget *h_slider;
53 GtkWidget *h_popup;
54 GtkWidget *h_entry;
55 GtkWidget *a_slider;
56 GtkWidget *a_popup;
57 GtkWidget *a_entry;
58 GtkWidget *sv_plane;
59 GtkWidget *sv_popup;
60 GtkWidget *s_entry;
61 GtkWidget *v_entry;
62 GtkWidget *current_popup;
63 GtkWidget *popdown_focus;
64
65 GtkAdjustment *h_adj;
66 GtkAdjustment *s_adj;
67 GtkAdjustment *v_adj;
68 GtkAdjustment *a_adj;
69
70 GtkWidget *picker_button;
71 GtkColorPicker *picker;
72
73 int popup_position;
74
75 guint text_changed : 1;
76 guint use_alpha : 1;
77};
78
79struct _GtkColorEditorClass
80{
81 GtkBoxClass parent_class;
82};
83
84enum
85{
86 PROP_ZERO,
87 PROP_RGBA,
88 PROP_USE_ALPHA
89};
90
91static void gtk_color_editor_iface_init (GtkColorChooserInterface *iface);
92
93G_DEFINE_TYPE_WITH_CODE (GtkColorEditor, gtk_color_editor, GTK_TYPE_BOX,
94 G_IMPLEMENT_INTERFACE (GTK_TYPE_COLOR_CHOOSER,
95 gtk_color_editor_iface_init))
96
97static guint
98scale_round (double value, double scale)
99{
100 value = floor (x: value * scale + 0.5);
101 value = MAX (value, 0);
102 value = MIN (value, scale);
103 return (guint)value;
104}
105
106static void
107entry_set_rgba (GtkColorEditor *editor,
108 const GdkRGBA *color)
109{
110 char *text;
111
112 text = g_strdup_printf (format: "#%02X%02X%02X",
113 scale_round (value: color->red, scale: 255),
114 scale_round (value: color->green, scale: 255),
115 scale_round (value: color->blue, scale: 255));
116 gtk_editable_set_text (GTK_EDITABLE (editor->entry), text);
117 editor->text_changed = FALSE;
118 g_free (mem: text);
119}
120
121static void
122entry_apply (GtkWidget *entry,
123 GtkColorEditor *editor)
124{
125 GdkRGBA color;
126 char *text;
127
128 if (!editor->text_changed)
129 return;
130
131 text = gtk_editable_get_chars (GTK_EDITABLE (editor->entry), start_pos: 0, end_pos: -1);
132 if (gdk_rgba_parse (rgba: &color, spec: text))
133 {
134 color.alpha = gtk_adjustment_get_value (adjustment: editor->a_adj);
135 gtk_color_chooser_set_rgba (GTK_COLOR_CHOOSER (editor), color: &color);
136 }
137
138 editor->text_changed = FALSE;
139
140 g_free (mem: text);
141}
142
143static void
144entry_focus_changed (GtkWidget *entry,
145 GParamSpec *pspec,
146 GtkColorEditor *editor)
147{
148 if (!gtk_widget_has_focus (widget: entry))
149 entry_apply (entry, editor);
150}
151
152static void
153entry_text_changed (GtkWidget *entry,
154 GParamSpec *pspec,
155 GtkColorEditor *editor)
156{
157 editor->text_changed = TRUE;
158}
159
160static void
161hsv_changed (GtkColorEditor *editor)
162{
163 GdkRGBA color;
164 double h, s, v, a;
165
166 h = gtk_adjustment_get_value (adjustment: editor->h_adj);
167 s = gtk_adjustment_get_value (adjustment: editor->s_adj);
168 v = gtk_adjustment_get_value (adjustment: editor->v_adj);
169 a = gtk_adjustment_get_value (adjustment: editor->a_adj);
170
171 gtk_hsv_to_rgb (h, s, v, r: &color.red, g: &color.green, b: &color.blue);
172 color.alpha = a;
173
174 gtk_color_swatch_set_rgba (GTK_COLOR_SWATCH (editor->swatch), color: &color);
175 gtk_color_scale_set_rgba (GTK_COLOR_SCALE (editor->a_slider), color: &color);
176 entry_set_rgba (editor, color: &color);
177
178 g_object_notify (G_OBJECT (editor), property_name: "rgba");
179}
180
181static void
182dismiss_current_popup (GtkColorEditor *editor)
183{
184 if (editor->current_popup)
185 {
186 gtk_widget_hide (widget: editor->current_popup);
187 editor->current_popup = NULL;
188 editor->popup_position = 0;
189 if (editor->popdown_focus)
190 {
191 if (gtk_widget_is_visible (widget: editor->popdown_focus))
192 gtk_widget_grab_focus (widget: editor->popdown_focus);
193 g_clear_object (&editor->popdown_focus);
194 }
195 }
196}
197
198static void
199popup_edit (GtkWidget *widget,
200 const char *action_name,
201 GVariant *parameters)
202{
203 GtkColorEditor *editor = GTK_COLOR_EDITOR (widget);
204 GtkWidget *popup = NULL;
205 GtkRoot *root;
206 GtkWidget *focus;
207 int position;
208 int s, e;
209 const char *param;
210
211 param = g_variant_get_string (value: parameters, NULL);
212
213 if (strcmp (s1: param, s2: "sv") == 0)
214 {
215 popup = editor->sv_popup;
216 focus = editor->s_entry;
217 position = 0;
218 }
219 else if (strcmp (s1: param, s2: "h") == 0)
220 {
221 popup = editor->h_popup;
222 focus = editor->h_entry;
223 gtk_range_get_slider_range (GTK_RANGE (editor->h_slider), slider_start: &s, slider_end: &e);
224 position = (s + e) / 2;
225 }
226 else if (strcmp (s1: param, s2: "a") == 0)
227 {
228 popup = editor->a_popup;
229 focus = editor->a_entry;
230 gtk_range_get_slider_range (GTK_RANGE (editor->a_slider), slider_start: &s, slider_end: &e);
231 position = (s + e) / 2;
232 }
233 else
234 {
235 g_warning ("unsupported popup_edit parameter %s", param);
236 }
237
238 if (popup == editor->current_popup)
239 dismiss_current_popup (editor);
240 else if (popup)
241 {
242 dismiss_current_popup (editor);
243 root = gtk_widget_get_root (GTK_WIDGET (editor));
244 g_set_object (&editor->popdown_focus, gtk_root_get_focus (root));
245 editor->current_popup = popup;
246 editor->popup_position = position;
247 gtk_widget_show (widget: popup);
248 gtk_widget_grab_focus (widget: focus);
249 }
250}
251
252static gboolean
253popup_key_pressed (GtkEventController *controller,
254 guint keyval,
255 guint keycode,
256 GdkModifierType state,
257 GtkColorEditor *editor)
258{
259 if (keyval == GDK_KEY_Escape)
260 {
261 dismiss_current_popup (editor);
262 return TRUE;
263 }
264
265 return FALSE;
266}
267
268static gboolean
269get_child_position (GtkOverlay *overlay,
270 GtkWidget *widget,
271 GtkAllocation *allocation,
272 GtkColorEditor *editor)
273{
274 GtkRequisition req;
275 GtkAllocation alloc;
276 int s, e;
277 double x, y;
278
279 gtk_widget_get_preferred_size (widget, minimum_size: &req, NULL);
280
281 allocation->x = 0;
282 allocation->y = 0;
283 allocation->width = req.width;
284 allocation->height = req.height;
285
286 if (widget == editor->sv_popup)
287 {
288 gtk_widget_translate_coordinates (src_widget: editor->sv_plane,
289 dest_widget: gtk_widget_get_parent (widget: editor->grid),
290 src_x: 0, src_y: -6,
291 dest_x: &x, dest_y: &y);
292 if (gtk_widget_get_direction (GTK_WIDGET (overlay)) == GTK_TEXT_DIR_RTL)
293 x = 0;
294 else
295 x = gtk_widget_get_width (GTK_WIDGET (overlay)) - req.width;
296 }
297 else if (widget == editor->h_popup)
298 {
299 gtk_widget_get_allocation (widget: editor->h_slider, allocation: &alloc);
300 gtk_range_get_slider_range (GTK_RANGE (editor->h_slider), slider_start: &s, slider_end: &e);
301
302 if (gtk_widget_get_direction (GTK_WIDGET (overlay)) == GTK_TEXT_DIR_RTL)
303 gtk_widget_translate_coordinates (src_widget: editor->h_slider,
304 dest_widget: gtk_widget_get_parent (widget: editor->grid),
305 src_x: - req.width - 6, src_y: editor->popup_position - req.height / 2,
306 dest_x: &x, dest_y: &y);
307 else
308 gtk_widget_translate_coordinates (src_widget: editor->h_slider,
309 dest_widget: gtk_widget_get_parent (widget: editor->grid),
310 src_x: alloc.width + 6, src_y: editor->popup_position - req.height / 2,
311 dest_x: &x, dest_y: &y);
312 }
313 else if (widget == editor->a_popup)
314 {
315 gtk_widget_get_allocation (widget: editor->a_slider, allocation: &alloc);
316 gtk_range_get_slider_range (GTK_RANGE (editor->a_slider), slider_start: &s, slider_end: &e);
317
318 gtk_widget_translate_coordinates (src_widget: editor->a_slider,
319 dest_widget: gtk_widget_get_parent (widget: editor->grid),
320 src_x: editor->popup_position - req.width / 2, src_y: - req.height - 6,
321 dest_x: &x, dest_y: &y);
322 }
323 else
324 return FALSE;
325
326 allocation->x = CLAMP (x, 0, gtk_widget_get_width (GTK_WIDGET (overlay)) - req.width);
327 allocation->y = CLAMP (y, 0, gtk_widget_get_height (GTK_WIDGET (overlay)) - req.height);
328
329 return TRUE;
330}
331
332static void
333value_changed (GtkAdjustment *a,
334 GtkAdjustment *as)
335{
336 double scale;
337
338 scale = gtk_adjustment_get_upper (adjustment: as) / gtk_adjustment_get_upper (adjustment: a);
339 g_signal_handlers_block_by_func (as, value_changed, a);
340 gtk_adjustment_set_value (adjustment: as, value: gtk_adjustment_get_value (adjustment: a) * scale);
341 g_signal_handlers_unblock_by_func (as, value_changed, a);
342}
343
344static GtkAdjustment *
345scaled_adjustment (GtkAdjustment *a,
346 double scale)
347{
348 GtkAdjustment *as;
349
350 as = gtk_adjustment_new (value: gtk_adjustment_get_value (adjustment: a) * scale,
351 lower: gtk_adjustment_get_lower (adjustment: a) * scale,
352 upper: gtk_adjustment_get_upper (adjustment: a) * scale,
353 step_increment: gtk_adjustment_get_step_increment (adjustment: a) * scale,
354 page_increment: gtk_adjustment_get_page_increment (adjustment: a) * scale,
355 page_size: gtk_adjustment_get_page_size (adjustment: a) * scale);
356
357 g_signal_connect (a, "value-changed", G_CALLBACK (value_changed), as);
358 g_signal_connect (as, "value-changed", G_CALLBACK (value_changed), a);
359
360 return as;
361}
362
363static void
364color_picked (GObject *source,
365 GAsyncResult *res,
366 gpointer data)
367{
368 GtkColorPicker *picker = GTK_COLOR_PICKER (source);
369 GtkColorEditor *editor = data;
370 GError *error = NULL;
371 GdkRGBA *color;
372
373 color = gtk_color_picker_pick_finish (picker, res, error: &error);
374 if (color == NULL)
375 {
376 g_error_free (error);
377 }
378 else
379 {
380 gtk_color_chooser_set_rgba (GTK_COLOR_CHOOSER (editor), color);
381 gdk_rgba_free (rgba: color);
382 }
383}
384
385static void
386pick_color (GtkButton *button,
387 GtkColorEditor *editor)
388{
389 gtk_color_picker_pick (picker: editor->picker, callback: color_picked, user_data: editor);
390}
391
392static void
393gtk_color_editor_init (GtkColorEditor *editor)
394{
395 GtkEventController *controller;
396
397 editor->use_alpha = TRUE;
398
399 g_type_ensure (GTK_TYPE_COLOR_SCALE);
400 g_type_ensure (GTK_TYPE_COLOR_PLANE);
401 g_type_ensure (GTK_TYPE_COLOR_SWATCH);
402 gtk_widget_init_template (GTK_WIDGET (editor));
403
404 if (gtk_widget_get_direction (widget: editor->h_slider) == GTK_TEXT_DIR_RTL)
405 gtk_widget_add_css_class (widget: editor->h_slider, css_class: "marks-before");
406 else
407 gtk_widget_add_css_class (widget: editor->h_slider, css_class: "marks-after");
408
409 /* Create the scaled popup adjustments manually here because connecting user data is not
410 * supported by template GtkBuilder xml (it would be possible to set this up in the xml
411 * but require 4 separate callbacks and would be rather ugly).
412 */
413 gtk_spin_button_set_adjustment (GTK_SPIN_BUTTON (editor->h_entry), adjustment: scaled_adjustment (a: editor->h_adj, scale: 360));
414 gtk_spin_button_set_adjustment (GTK_SPIN_BUTTON (editor->s_entry), adjustment: scaled_adjustment (a: editor->s_adj, scale: 100));
415 gtk_spin_button_set_adjustment (GTK_SPIN_BUTTON (editor->v_entry), adjustment: scaled_adjustment (a: editor->v_adj, scale: 100));
416 gtk_spin_button_set_adjustment (GTK_SPIN_BUTTON (editor->a_entry), adjustment: scaled_adjustment (a: editor->a_adj, scale: 100));
417
418 /* This can be setup in the .ui file, but requires work in Glade otherwise it cannot be edited there */
419 gtk_overlay_add_overlay (GTK_OVERLAY (editor->overlay), widget: editor->sv_popup);
420 gtk_overlay_add_overlay (GTK_OVERLAY (editor->overlay), widget: editor->h_popup);
421 gtk_overlay_add_overlay (GTK_OVERLAY (editor->overlay), widget: editor->a_popup);
422
423 controller = gtk_event_controller_key_new ();
424 g_signal_connect (controller, "key-pressed", G_CALLBACK (popup_key_pressed), editor);
425 gtk_widget_add_controller (widget: editor->h_entry, controller);
426 controller = gtk_event_controller_key_new ();
427 g_signal_connect (controller, "key-pressed", G_CALLBACK (popup_key_pressed), editor);
428 gtk_widget_add_controller (widget: editor->s_entry, controller);
429 controller = gtk_event_controller_key_new ();
430 g_signal_connect (controller, "key-pressed", G_CALLBACK (popup_key_pressed), editor);
431 gtk_widget_add_controller (widget: editor->v_entry, controller);
432 controller = gtk_event_controller_key_new ();
433 g_signal_connect (controller, "key-pressed", G_CALLBACK (popup_key_pressed), editor);
434 gtk_widget_add_controller (widget: editor->a_entry, controller);
435
436 gtk_widget_remove_css_class (widget: editor->swatch, css_class: "activatable");
437
438 editor->picker = gtk_color_picker_new ();
439 if (editor->picker == NULL)
440 gtk_widget_hide (widget: editor->picker_button);
441}
442
443static void
444gtk_color_editor_dispose (GObject *object)
445{
446 GtkColorEditor *editor = GTK_COLOR_EDITOR (object);
447
448 dismiss_current_popup (editor);
449 g_clear_object (&editor->picker);
450
451 G_OBJECT_CLASS (gtk_color_editor_parent_class)->dispose (object);
452}
453
454static void
455gtk_color_editor_get_property (GObject *object,
456 guint prop_id,
457 GValue *value,
458 GParamSpec *pspec)
459{
460 GtkColorEditor *ce = GTK_COLOR_EDITOR (object);
461 GtkColorChooser *cc = GTK_COLOR_CHOOSER (object);
462
463 switch (prop_id)
464 {
465 case PROP_RGBA:
466 {
467 GdkRGBA color;
468 gtk_color_chooser_get_rgba (chooser: cc, color: &color);
469 g_value_set_boxed (value, v_boxed: &color);
470 }
471 break;
472 case PROP_USE_ALPHA:
473 g_value_set_boolean (value, v_boolean: gtk_widget_get_visible (widget: ce->a_slider));
474 break;
475 default:
476 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
477 break;
478 }
479}
480
481static void
482gtk_color_editor_set_use_alpha (GtkColorEditor *editor,
483 gboolean use_alpha)
484{
485 if (editor->use_alpha != use_alpha)
486 {
487 editor->use_alpha = use_alpha;
488 gtk_widget_set_visible (widget: editor->a_slider, visible: use_alpha);
489 gtk_color_swatch_set_use_alpha (GTK_COLOR_SWATCH (editor->swatch), use_alpha);
490 }
491}
492
493static void
494gtk_color_editor_set_property (GObject *object,
495 guint prop_id,
496 const GValue *value,
497 GParamSpec *pspec)
498{
499 GtkColorEditor *ce = GTK_COLOR_EDITOR (object);
500 GtkColorChooser *cc = GTK_COLOR_CHOOSER (object);
501
502 switch (prop_id)
503 {
504 case PROP_RGBA:
505 gtk_color_chooser_set_rgba (chooser: cc, color: g_value_get_boxed (value));
506 break;
507 case PROP_USE_ALPHA:
508 gtk_color_editor_set_use_alpha (editor: ce, use_alpha: g_value_get_boolean (value));
509 break;
510 default:
511 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
512 break;
513 }
514}
515
516static void
517gtk_color_editor_class_init (GtkColorEditorClass *class)
518{
519 GObjectClass *object_class = G_OBJECT_CLASS (class);
520 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
521
522 object_class->dispose = gtk_color_editor_dispose;
523 object_class->get_property = gtk_color_editor_get_property;
524 object_class->set_property = gtk_color_editor_set_property;
525
526 g_object_class_override_property (oclass: object_class, property_id: PROP_RGBA, name: "rgba");
527 g_object_class_override_property (oclass: object_class, property_id: PROP_USE_ALPHA, name: "use-alpha");
528
529 /* Bind class to template
530 */
531 gtk_widget_class_set_template_from_resource (widget_class,
532 resource_name: "/org/gtk/libgtk/ui/gtkcoloreditor.ui");
533
534 gtk_widget_class_bind_template_child (widget_class, GtkColorEditor, overlay);
535 gtk_widget_class_bind_template_child (widget_class, GtkColorEditor, grid);
536 gtk_widget_class_bind_template_child (widget_class, GtkColorEditor, swatch);
537 gtk_widget_class_bind_template_child (widget_class, GtkColorEditor, entry);
538 gtk_widget_class_bind_template_child (widget_class, GtkColorEditor, h_slider);
539 gtk_widget_class_bind_template_child (widget_class, GtkColorEditor, h_popup);
540 gtk_widget_class_bind_template_child (widget_class, GtkColorEditor, h_entry);
541 gtk_widget_class_bind_template_child (widget_class, GtkColorEditor, a_slider);
542 gtk_widget_class_bind_template_child (widget_class, GtkColorEditor, a_popup);
543 gtk_widget_class_bind_template_child (widget_class, GtkColorEditor, a_entry);
544 gtk_widget_class_bind_template_child (widget_class, GtkColorEditor, sv_plane);
545 gtk_widget_class_bind_template_child (widget_class, GtkColorEditor, sv_popup);
546 gtk_widget_class_bind_template_child (widget_class, GtkColorEditor, s_entry);
547 gtk_widget_class_bind_template_child (widget_class, GtkColorEditor, v_entry);
548 gtk_widget_class_bind_template_child (widget_class, GtkColorEditor, h_adj);
549 gtk_widget_class_bind_template_child (widget_class, GtkColorEditor, s_adj);
550 gtk_widget_class_bind_template_child (widget_class, GtkColorEditor, v_adj);
551 gtk_widget_class_bind_template_child (widget_class, GtkColorEditor, a_adj);
552 gtk_widget_class_bind_template_child (widget_class, GtkColorEditor, picker_button);
553
554 gtk_widget_class_bind_template_callback (widget_class, hsv_changed);
555 gtk_widget_class_bind_template_callback (widget_class, dismiss_current_popup);
556 gtk_widget_class_bind_template_callback (widget_class, get_child_position);
557 gtk_widget_class_bind_template_callback (widget_class, entry_text_changed);
558 gtk_widget_class_bind_template_callback (widget_class, entry_apply);
559 gtk_widget_class_bind_template_callback (widget_class, entry_focus_changed);
560 gtk_widget_class_bind_template_callback (widget_class, pick_color);
561
562 /**
563 * GtkColorEditor|color.edit:
564 * @component: the component to edit, "h", "sv" or "a"
565 *
566 * Opens the edit popup for one of the color components.
567 */
568 gtk_widget_class_install_action (widget_class, action_name: "color.edit", parameter_type: "s", activate: popup_edit);
569}
570
571static void
572gtk_color_editor_get_rgba (GtkColorChooser *chooser,
573 GdkRGBA *color)
574{
575 GtkColorEditor *editor = GTK_COLOR_EDITOR (chooser);
576 float h, s, v;
577
578 h = gtk_adjustment_get_value (adjustment: editor->h_adj);
579 s = gtk_adjustment_get_value (adjustment: editor->s_adj);
580 v = gtk_adjustment_get_value (adjustment: editor->v_adj);
581 gtk_hsv_to_rgb (h, s, v, r: &color->red, g: &color->green, b: &color->blue);
582 color->alpha = gtk_adjustment_get_value (adjustment: editor->a_adj);
583}
584
585static void
586gtk_color_editor_set_rgba (GtkColorChooser *chooser,
587 const GdkRGBA *color)
588{
589 GtkColorEditor *editor = GTK_COLOR_EDITOR (chooser);
590 float h, s, v;
591
592 gtk_rgb_to_hsv (r: color->red, g: color->green, b: color->blue, h: &h, s: &s, v: &v);
593
594 gtk_adjustment_set_value (adjustment: editor->h_adj, value: h);
595 gtk_adjustment_set_value (adjustment: editor->s_adj, value: s);
596 gtk_adjustment_set_value (adjustment: editor->v_adj, value: v);
597 gtk_adjustment_set_value (adjustment: editor->a_adj, value: color->alpha);
598
599 gtk_color_swatch_set_rgba (GTK_COLOR_SWATCH (editor->swatch), color);
600 gtk_color_scale_set_rgba (GTK_COLOR_SCALE (editor->a_slider), color);
601 entry_set_rgba (editor, color);
602
603 g_object_notify (G_OBJECT (editor), property_name: "rgba");
604}
605
606static void
607gtk_color_editor_iface_init (GtkColorChooserInterface *iface)
608{
609 iface->get_rgba = gtk_color_editor_get_rgba;
610 iface->set_rgba = gtk_color_editor_set_rgba;
611}
612
613GtkWidget *
614gtk_color_editor_new (void)
615{
616 return (GtkWidget *) g_object_new (GTK_TYPE_COLOR_EDITOR, NULL);
617}
618

source code of gtk/gtk/gtkcoloreditor.c