1/*
2 * GTK - The GIMP Toolkit
3 * Copyright (C) 1998, 1999 Red Hat, Inc.
4 * All rights reserved.
5 *
6 * This Library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public License as
8 * published by the Free Software Foundation; either version 2 of the
9 * License, or (at your option) any later version.
10 *
11 * This Library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
15 *
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
18 */
19/* Color picker button for GNOME
20 *
21 * Author: Federico Mena <federico@nuclecu.unam.mx>
22 *
23 * Modified by the GTK+ Team and others 2003. See the AUTHORS
24 * file for a list of people on the GTK+ Team. See the ChangeLog
25 * files for a list of changes. These files are distributed with
26 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
27 */
28
29#include "config.h"
30
31#include "gtkcolorbutton.h"
32
33#include "gtkbinlayout.h"
34#include "gtkbutton.h"
35#include "gtkcolorchooser.h"
36#include "gtkcolorchooserprivate.h"
37#include "gtkcolorchooserdialog.h"
38#include "gtkcolorswatchprivate.h"
39#include "gtkdragsource.h"
40#include "gtkdroptarget.h"
41#include "gtkintl.h"
42#include "gtkmain.h"
43#include "gtkmarshalers.h"
44#include "gtkprivate.h"
45#include "gtksnapshot.h"
46#include "gtkwidgetprivate.h"
47
48
49/**
50 * GtkColorButton:
51 *
52 * The `GtkColorButton` allows to open a color chooser dialog to change
53 * the color.
54 *
55 * ![An example GtkColorButton](color-button.png)
56 *
57 * It is suitable widget for selecting a color in a preference dialog.
58 *
59 * # CSS nodes
60 *
61 * ```
62 * colorbutton
63 * ╰── button.color
64 * ╰── [content]
65 * ```
66 *
67 * `GtkColorButton` has a single CSS node with name colorbutton which
68 * contains a button node. To differentiate it from a plain `GtkButton`,
69 * it gets the .color style class.
70 */
71
72typedef struct _GtkColorButtonClass GtkColorButtonClass;
73
74struct _GtkColorButton {
75 GtkWidget parent_instance;
76
77 GtkWidget *button;
78
79 GtkWidget *swatch; /* Widget where we draw the color sample */
80 GtkWidget *cs_dialog; /* Color selection dialog */
81
82 char *title; /* Title for the color chooser dialog */
83 GdkRGBA rgba;
84
85 guint use_alpha : 1; /* Use alpha or not */
86 guint show_editor : 1;
87 guint modal : 1;
88};
89
90struct _GtkColorButtonClass {
91 GtkWidgetClass parent_class;
92
93 void (* color_set) (GtkColorButton *cp);
94 void (* activate) (GtkColorButton *self);
95};
96
97/* Properties */
98enum
99{
100 PROP_0,
101 PROP_USE_ALPHA,
102 PROP_TITLE,
103 PROP_RGBA,
104 PROP_SHOW_EDITOR,
105 PROP_MODAL
106};
107
108/* Signals */
109enum
110{
111 COLOR_SET,
112 ACTIVATE,
113 LAST_SIGNAL
114};
115
116/* gobject signals */
117static void gtk_color_button_finalize (GObject *object);
118static void gtk_color_button_set_property (GObject *object,
119 guint param_id,
120 const GValue *value,
121 GParamSpec *pspec);
122static void gtk_color_button_get_property (GObject *object,
123 guint param_id,
124 GValue *value,
125 GParamSpec *pspec);
126
127static void gtk_color_button_root (GtkWidget *widget);
128
129/* gtkbutton signals */
130static void gtk_color_button_clicked (GtkButton *button,
131 gpointer user_data);
132
133
134static guint color_button_signals[LAST_SIGNAL] = { 0 };
135
136static void gtk_color_button_iface_init (GtkColorChooserInterface *iface);
137
138G_DEFINE_TYPE_WITH_CODE (GtkColorButton, gtk_color_button, GTK_TYPE_WIDGET,
139 G_IMPLEMENT_INTERFACE (GTK_TYPE_COLOR_CHOOSER,
140 gtk_color_button_iface_init))
141
142static void
143gtk_color_button_activate (GtkColorButton *self)
144{
145 gtk_widget_activate (widget: self->button);
146}
147
148static void
149gtk_color_button_class_init (GtkColorButtonClass *klass)
150{
151 GObjectClass *gobject_class;
152 GtkWidgetClass *widget_class;
153
154 gobject_class = G_OBJECT_CLASS (klass);
155 widget_class = GTK_WIDGET_CLASS (klass);
156
157 gobject_class->get_property = gtk_color_button_get_property;
158 gobject_class->set_property = gtk_color_button_set_property;
159 gobject_class->finalize = gtk_color_button_finalize;
160
161 widget_class->grab_focus = gtk_widget_grab_focus_child;
162 widget_class->focus = gtk_widget_focus_child;
163 widget_class->root = gtk_color_button_root;
164
165 klass->color_set = NULL;
166 klass->activate = gtk_color_button_activate;
167
168 g_object_class_override_property (oclass: gobject_class, property_id: PROP_RGBA, name: "rgba");
169 g_object_class_override_property (oclass: gobject_class, property_id: PROP_USE_ALPHA, name: "use-alpha");
170
171 /**
172 * GtkColorButton:title: (attributes org.gtk.Property.get=gtk_color_button_get_title org.gtk.Property.set=gtk_color_button_set_title)
173 *
174 * The title of the color chooser dialog
175 */
176 g_object_class_install_property (oclass: gobject_class,
177 property_id: PROP_TITLE,
178 pspec: g_param_spec_string (name: "title",
179 P_("Title"),
180 P_("The title of the color selection dialog"),
181 _("Pick a Color"),
182 GTK_PARAM_READWRITE));
183
184
185 /**
186 * GtkColorButton::color-set:
187 * @widget: the object which received the signal.
188 *
189 * Emitted when the user selects a color.
190 *
191 * When handling this signal, use [method@Gtk.ColorChooser.get_rgba]
192 * to find out which color was just selected.
193 *
194 * Note that this signal is only emitted when the user changes the color.
195 * If you need to react to programmatic color changes as well, use
196 * the notify::rgba signal.
197 */
198 color_button_signals[COLOR_SET] = g_signal_new (I_("color-set"),
199 G_TYPE_FROM_CLASS (gobject_class),
200 signal_flags: G_SIGNAL_RUN_FIRST,
201 G_STRUCT_OFFSET (GtkColorButtonClass, color_set),
202 NULL, NULL,
203 NULL,
204 G_TYPE_NONE, n_params: 0);
205
206 /**
207 * GtkColorButton::activate:
208 * @widget: the object which received the signal.
209 *
210 * Emitted to when the color button is activated.
211 *
212 * The `::activate` signal on `GtkMenuButton` is an action signal and
213 * emitting it causes the button to pop up its dialog.
214 *
215 * Since: 4.4
216 */
217 color_button_signals[ACTIVATE] =
218 g_signal_new (I_ ("activate"),
219 G_OBJECT_CLASS_TYPE (gobject_class),
220 signal_flags: G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
221 G_STRUCT_OFFSET (GtkColorButtonClass, activate),
222 NULL, NULL,
223 NULL,
224 G_TYPE_NONE, n_params: 0);
225
226 gtk_widget_class_set_activate_signal (widget_class, signal_id: color_button_signals[ACTIVATE]);
227
228 /**
229 * GtkColorButton:show-editor:
230 *
231 * Whether the color chooser should open in editor mode.
232 *
233 * This property should be used in cases where the palette
234 * in the editor would be redundant, such as when the color
235 * button is already part of a palette.
236 */
237 g_object_class_install_property (oclass: gobject_class,
238 property_id: PROP_SHOW_EDITOR,
239 pspec: g_param_spec_boolean (name: "show-editor", P_("Show Editor"),
240 P_("Whether to show the color editor right away"),
241 FALSE,
242 GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY));
243
244 /**
245 * GtkColorButton:modal: (attributes org.gtk.Property.get=gtk_color_button_get_modal org.gtk.Property.set=gtk_color_button_set_modal)
246 *
247 * Whether the color chooser dialog should be modal.
248 */
249 g_object_class_install_property (oclass: gobject_class,
250 property_id: PROP_MODAL,
251 pspec: g_param_spec_boolean (name: "modal", P_("Modal"),
252 P_("Whether the dialog is modal"),
253 TRUE,
254 GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY));
255
256
257 gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BIN_LAYOUT);
258 gtk_widget_class_set_css_name (widget_class, name: "colorbutton");
259}
260
261static gboolean
262gtk_color_button_drop (GtkDropTarget *dest,
263 const GValue *value,
264 double x,
265 double y,
266 GtkColorButton *button)
267{
268 GdkRGBA *color = g_value_get_boxed (value);
269
270 gtk_color_chooser_set_rgba (GTK_COLOR_CHOOSER (button), color);
271 return TRUE;
272}
273
274static GdkContentProvider *
275gtk_color_button_drag_prepare (GtkDragSource *source,
276 double x,
277 double y,
278 GtkColorButton *button)
279{
280 return gdk_content_provider_new_typed (GDK_TYPE_RGBA, &button->rgba);
281}
282
283static void
284gtk_color_button_init (GtkColorButton *button)
285{
286 PangoLayout *layout;
287 PangoRectangle rect;
288 GtkDragSource *source;
289 GtkDropTarget *dest;
290
291 button->button = gtk_button_new ();
292 g_signal_connect (button->button, "clicked", G_CALLBACK (gtk_color_button_clicked), button);
293 gtk_widget_set_parent (widget: button->button, GTK_WIDGET (button));
294
295 button->swatch = g_object_new (GTK_TYPE_COLOR_SWATCH,
296 first_property_name: "accessible-role", GTK_ACCESSIBLE_ROLE_IMG,
297 "selectable", FALSE,
298 "has-menu", FALSE,
299 "can-drag", FALSE,
300 NULL);
301 gtk_widget_set_can_focus (widget: button->swatch, FALSE);
302 gtk_widget_remove_css_class (widget: button->swatch, css_class: "activatable");
303 layout = gtk_widget_create_pango_layout (GTK_WIDGET (button), text: "Black");
304 pango_layout_get_pixel_extents (layout, NULL, logical_rect: &rect);
305 g_object_unref (object: layout);
306
307 gtk_widget_set_size_request (widget: button->swatch, width: rect.width, height: rect.height);
308
309 gtk_button_set_child (GTK_BUTTON (button->button), child: button->swatch);
310
311 button->title = g_strdup (_("Pick a Color")); /* default title */
312
313 /* Start with opaque black, alpha disabled */
314 button->rgba.red = 0;
315 button->rgba.green = 0;
316 button->rgba.blue = 0;
317 button->rgba.alpha = 1;
318 button->use_alpha = FALSE;
319 button->modal = TRUE;
320
321 dest = gtk_drop_target_new (GDK_TYPE_RGBA, actions: GDK_ACTION_COPY);
322 g_signal_connect (dest, "drop", G_CALLBACK (gtk_color_button_drop), button);
323 gtk_widget_add_controller (GTK_WIDGET (button), GTK_EVENT_CONTROLLER (dest));
324
325 source = gtk_drag_source_new ();
326 g_signal_connect (source, "prepare", G_CALLBACK (gtk_color_button_drag_prepare), button);
327 gtk_event_controller_set_propagation_phase (GTK_EVENT_CONTROLLER (source), phase: GTK_PHASE_CAPTURE);
328 gtk_widget_add_controller (widget: button->button, GTK_EVENT_CONTROLLER (source));
329
330 gtk_widget_add_css_class (widget: button->button, css_class: "color");
331}
332
333static void
334gtk_color_button_finalize (GObject *object)
335{
336 GtkColorButton *button = GTK_COLOR_BUTTON (object);
337
338 if (button->cs_dialog != NULL)
339 gtk_window_destroy (GTK_WINDOW (button->cs_dialog));
340
341 g_free (mem: button->title);
342 gtk_widget_unparent (widget: button->button);
343
344 G_OBJECT_CLASS (gtk_color_button_parent_class)->finalize (object);
345}
346
347
348/**
349 * gtk_color_button_new:
350 *
351 * Creates a new color button.
352 *
353 * This returns a widget in the form of a small button containing
354 * a swatch representing the current selected color. When the button
355 * is clicked, a color chooser dialog will open, allowing the user
356 * to select a color. The swatch will be updated to reflect the new
357 * color when the user finishes.
358 *
359 * Returns: a new color button
360 */
361GtkWidget *
362gtk_color_button_new (void)
363{
364 return g_object_new (GTK_TYPE_COLOR_BUTTON, NULL);
365}
366
367/**
368 * gtk_color_button_new_with_rgba:
369 * @rgba: A `GdkRGBA` to set the current color with
370 *
371 * Creates a new color button showing the given color.
372 *
373 * Returns: a new color button
374 */
375GtkWidget *
376gtk_color_button_new_with_rgba (const GdkRGBA *rgba)
377{
378 return g_object_new (GTK_TYPE_COLOR_BUTTON, first_property_name: "rgba", rgba, NULL);
379}
380
381static gboolean
382dialog_destroy (GtkWidget *widget,
383 gpointer data)
384{
385 GtkColorButton *button = GTK_COLOR_BUTTON (data);
386
387 button->cs_dialog = NULL;
388
389 return FALSE;
390}
391
392static void
393dialog_response (GtkDialog *dialog,
394 int response,
395 gpointer data)
396{
397 if (response == GTK_RESPONSE_CANCEL)
398 gtk_widget_hide (GTK_WIDGET (dialog));
399 else if (response == GTK_RESPONSE_OK)
400 {
401 GtkColorButton *button = GTK_COLOR_BUTTON (data);
402
403 gtk_color_chooser_get_rgba (GTK_COLOR_CHOOSER (dialog), color: &button->rgba);
404 gtk_color_swatch_set_rgba (GTK_COLOR_SWATCH (button->swatch), color: &button->rgba);
405
406 gtk_widget_hide (GTK_WIDGET (dialog));
407 g_object_ref (button);
408 g_signal_emit (instance: button, signal_id: color_button_signals[COLOR_SET], detail: 0);
409
410 g_object_freeze_notify (G_OBJECT (button));
411 g_object_notify (G_OBJECT (button), property_name: "rgba");
412 g_object_thaw_notify (G_OBJECT (button));
413 g_object_unref (object: button);
414 }
415}
416
417/* Create the dialog and connects its buttons */
418static void
419ensure_dialog (GtkColorButton *button)
420{
421 GtkWidget *parent, *dialog;
422
423 if (button->cs_dialog != NULL)
424 return;
425
426 parent = GTK_WIDGET (gtk_widget_get_root (GTK_WIDGET (button)));
427
428 button->cs_dialog = dialog = gtk_color_chooser_dialog_new (title: button->title, NULL);
429 gtk_window_set_hide_on_close (GTK_WINDOW (dialog), TRUE);
430 gtk_window_set_modal (GTK_WINDOW (dialog), modal: button->modal);
431
432 if (GTK_IS_WINDOW (parent))
433 {
434 if (GTK_WINDOW (parent) != gtk_window_get_transient_for (GTK_WINDOW (dialog)))
435 gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (parent));
436
437 if (gtk_window_get_modal (GTK_WINDOW (parent)))
438 gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
439 }
440
441 g_signal_connect (dialog, "response",
442 G_CALLBACK (dialog_response), button);
443 g_signal_connect (dialog, "destroy",
444 G_CALLBACK (dialog_destroy), button);
445}
446
447static void
448gtk_color_button_root (GtkWidget *widget)
449{
450 GtkColorButton *button = GTK_COLOR_BUTTON (widget);
451 GtkWidget *parent;
452
453 GTK_WIDGET_CLASS (gtk_color_button_parent_class)->root (widget);
454
455 if (!button->cs_dialog)
456 return;
457
458 parent = GTK_WIDGET (gtk_widget_get_root (GTK_WIDGET (button)));
459 if (GTK_IS_WINDOW (parent))
460 {
461 if (GTK_WINDOW (parent) != gtk_window_get_transient_for (GTK_WINDOW (button->cs_dialog)))
462 gtk_window_set_transient_for (GTK_WINDOW (button->cs_dialog), GTK_WINDOW (parent));
463
464 if (gtk_window_get_modal (GTK_WINDOW (parent)))
465 gtk_window_set_modal (GTK_WINDOW (button->cs_dialog), TRUE);
466 }
467}
468
469static void
470gtk_color_button_clicked (GtkButton *b,
471 gpointer user_data)
472{
473 GtkColorButton *button = user_data;
474
475 /* if dialog already exists, make sure it's shown and raised */
476 ensure_dialog (button);
477
478 g_object_set (object: button->cs_dialog, first_property_name: "show-editor", button->show_editor, NULL);
479
480 gtk_color_chooser_set_use_alpha (GTK_COLOR_CHOOSER (button->cs_dialog), use_alpha: button->use_alpha);
481
482 gtk_color_chooser_set_rgba (GTK_COLOR_CHOOSER (button->cs_dialog), color: &button->rgba);
483
484 gtk_window_present (GTK_WINDOW (button->cs_dialog));
485}
486
487static guint
488scale_round (double value,
489 double scale)
490{
491 value = floor (x: value * scale + 0.5);
492 value = CLAMP (value, 0, scale);
493 return (guint)value;
494}
495
496static char *
497accessible_color_name (const GdkRGBA *color)
498{
499 if (color->alpha < 1.0)
500 return g_strdup_printf (_("Red %d%%, Green %d%%, Blue %d%%, Alpha %d%%"),
501 scale_round (value: color->red, scale: 100),
502 scale_round (value: color->green, scale: 100),
503 scale_round (value: color->blue, scale: 100),
504 scale_round (value: color->alpha, scale: 100));
505 else
506 return g_strdup_printf (_("Red %d%%, Green %d%%, Blue %d%%"),
507 scale_round (value: color->red, scale: 100),
508 scale_round (value: color->green, scale: 100),
509 scale_round (value: color->blue, scale: 100));
510}
511
512static void
513gtk_color_button_set_rgba (GtkColorChooser *chooser,
514 const GdkRGBA *rgba)
515{
516 GtkColorButton *button = GTK_COLOR_BUTTON (chooser);
517 char *text;
518
519 g_return_if_fail (GTK_IS_COLOR_BUTTON (chooser));
520 g_return_if_fail (rgba != NULL);
521
522 button->rgba = *rgba;
523 gtk_color_swatch_set_rgba (GTK_COLOR_SWATCH (button->swatch), color: &button->rgba);
524
525 text = accessible_color_name (color: rgba);
526 gtk_accessible_update_property (self: GTK_ACCESSIBLE (ptr: button->swatch),
527 first_property: GTK_ACCESSIBLE_PROPERTY_LABEL, text,
528 -1);
529 g_free (mem: text);
530
531 g_object_notify (G_OBJECT (chooser), property_name: "rgba");
532}
533
534static void
535gtk_color_button_get_rgba (GtkColorChooser *chooser,
536 GdkRGBA *rgba)
537{
538 GtkColorButton *button = GTK_COLOR_BUTTON (chooser);
539
540 g_return_if_fail (GTK_IS_COLOR_BUTTON (chooser));
541 g_return_if_fail (rgba != NULL);
542
543 *rgba = button->rgba;
544}
545
546static void
547set_use_alpha (GtkColorButton *button,
548 gboolean use_alpha)
549{
550 use_alpha = (use_alpha != FALSE);
551
552 if (button->use_alpha != use_alpha)
553 {
554 button->use_alpha = use_alpha;
555
556 gtk_color_swatch_set_use_alpha (GTK_COLOR_SWATCH (button->swatch), use_alpha);
557
558 g_object_notify (G_OBJECT (button), property_name: "use-alpha");
559 }
560}
561
562/**
563 * gtk_color_button_set_title: (attributes org.gtk.Method.set_property=title)
564 * @button: a `GtkColorButton`
565 * @title: String containing new window title
566 *
567 * Sets the title for the color chooser dialog.
568 */
569void
570gtk_color_button_set_title (GtkColorButton *button,
571 const char *title)
572{
573 char *old_title;
574
575 g_return_if_fail (GTK_IS_COLOR_BUTTON (button));
576
577 old_title = button->title;
578 button->title = g_strdup (str: title);
579 g_free (mem: old_title);
580
581 if (button->cs_dialog)
582 gtk_window_set_title (GTK_WINDOW (button->cs_dialog), title: button->title);
583
584 g_object_notify (G_OBJECT (button), property_name: "title");
585}
586
587/**
588 * gtk_color_button_get_title: (attributes org.gtk.Method.get_property=title)
589 * @button: a `GtkColorButton`
590 *
591 * Gets the title of the color chooser dialog.
592 *
593 * Returns: An internal string, do not free the return value
594 */
595const char *
596gtk_color_button_get_title (GtkColorButton *button)
597{
598 g_return_val_if_fail (GTK_IS_COLOR_BUTTON (button), NULL);
599
600 return button->title;
601}
602
603/**
604 * gtk_color_button_set_modal: (attributes org.gtk.Method.set_property=modal)
605 * @button: a `GtkColorButton`
606 * @modal: %TRUE to make the dialog modal
607 *
608 * Sets whether the dialog should be modal.
609 */
610void
611gtk_color_button_set_modal (GtkColorButton *button,
612 gboolean modal)
613{
614 g_return_if_fail (GTK_IS_COLOR_BUTTON (button));
615
616 if (button->modal == modal)
617 return;
618
619 button->modal = modal;
620
621 if (button->cs_dialog)
622 gtk_window_set_modal (GTK_WINDOW (button->cs_dialog), modal: button->modal);
623
624 g_object_notify (G_OBJECT (button), property_name: "modal");
625}
626
627/**
628 * gtk_color_button_get_modal: (attributes org.gtk.Method.get_property=modal)
629 * @button: a `GtkColorButton`
630 *
631 * Gets whether the dialog is modal.
632 *
633 * Returns: %TRUE if the dialog is modal
634 */
635gboolean
636gtk_color_button_get_modal (GtkColorButton *button)
637{
638 g_return_val_if_fail (GTK_IS_COLOR_BUTTON (button), FALSE);
639
640 return button->modal;
641}
642
643static void
644gtk_color_button_set_property (GObject *object,
645 guint param_id,
646 const GValue *value,
647 GParamSpec *pspec)
648{
649 GtkColorButton *button = GTK_COLOR_BUTTON (object);
650
651 switch (param_id)
652 {
653 case PROP_USE_ALPHA:
654 set_use_alpha (button, use_alpha: g_value_get_boolean (value));
655 break;
656 case PROP_TITLE:
657 gtk_color_button_set_title (button, title: g_value_get_string (value));
658 break;
659 case PROP_RGBA:
660 gtk_color_chooser_set_rgba (GTK_COLOR_CHOOSER (button), color: g_value_get_boxed (value));
661 break;
662 case PROP_SHOW_EDITOR:
663 {
664 gboolean show_editor = g_value_get_boolean (value);
665 if (button->show_editor != show_editor)
666 {
667 button->show_editor = show_editor;
668 g_object_notify (object, property_name: "show-editor");
669 }
670 }
671 break;
672 case PROP_MODAL:
673 gtk_color_button_set_modal (button, modal: g_value_get_boolean (value));
674 break;
675 default:
676 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
677 break;
678 }
679}
680
681static void
682gtk_color_button_get_property (GObject *object,
683 guint param_id,
684 GValue *value,
685 GParamSpec *pspec)
686{
687 GtkColorButton *button = GTK_COLOR_BUTTON (object);
688
689 switch (param_id)
690 {
691 case PROP_USE_ALPHA:
692 g_value_set_boolean (value, v_boolean: button->use_alpha);
693 break;
694 case PROP_TITLE:
695 g_value_set_string (value, v_string: gtk_color_button_get_title (button));
696 break;
697 case PROP_RGBA:
698 {
699 GdkRGBA rgba;
700
701 gtk_color_chooser_get_rgba (GTK_COLOR_CHOOSER (button), color: &rgba);
702 g_value_set_boxed (value, v_boxed: &rgba);
703 }
704 break;
705 case PROP_SHOW_EDITOR:
706 g_value_set_boolean (value, v_boolean: button->show_editor);
707 break;
708 case PROP_MODAL:
709 g_value_set_boolean (value, v_boolean: button->modal);
710 break;
711 default:
712 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
713 break;
714 }
715}
716
717static void
718gtk_color_button_add_palette (GtkColorChooser *chooser,
719 GtkOrientation orientation,
720 int colors_per_line,
721 int n_colors,
722 GdkRGBA *colors)
723{
724 GtkColorButton *button = GTK_COLOR_BUTTON (chooser);
725
726 ensure_dialog (button);
727
728 gtk_color_chooser_add_palette (GTK_COLOR_CHOOSER (button->cs_dialog),
729 orientation, colors_per_line, n_colors, colors);
730}
731
732static void
733gtk_color_button_iface_init (GtkColorChooserInterface *iface)
734{
735 iface->get_rgba = gtk_color_button_get_rgba;
736 iface->set_rgba = gtk_color_button_set_rgba;
737 iface->add_palette = gtk_color_button_add_palette;
738}
739

source code of gtk/gtk/gtkcolorbutton.c