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 | |
72 | typedef struct _GtkColorButtonClass GtkColorButtonClass; |
73 | |
74 | struct _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 | |
90 | struct _GtkColorButtonClass { |
91 | GtkWidgetClass parent_class; |
92 | |
93 | void (* color_set) (GtkColorButton *cp); |
94 | void (* activate) (GtkColorButton *self); |
95 | }; |
96 | |
97 | /* Properties */ |
98 | enum |
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 */ |
109 | enum |
110 | { |
111 | COLOR_SET, |
112 | ACTIVATE, |
113 | LAST_SIGNAL |
114 | }; |
115 | |
116 | /* gobject signals */ |
117 | static void gtk_color_button_finalize (GObject *object); |
118 | static void gtk_color_button_set_property (GObject *object, |
119 | guint param_id, |
120 | const GValue *value, |
121 | GParamSpec *pspec); |
122 | static void gtk_color_button_get_property (GObject *object, |
123 | guint param_id, |
124 | GValue *value, |
125 | GParamSpec *pspec); |
126 | |
127 | static void gtk_color_button_root (GtkWidget *widget); |
128 | |
129 | /* gtkbutton signals */ |
130 | static void gtk_color_button_clicked (GtkButton *button, |
131 | gpointer user_data); |
132 | |
133 | |
134 | static guint color_button_signals[LAST_SIGNAL] = { 0 }; |
135 | |
136 | static void gtk_color_button_iface_init (GtkColorChooserInterface *iface); |
137 | |
138 | G_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 | |
142 | static void |
143 | gtk_color_button_activate (GtkColorButton *self) |
144 | { |
145 | gtk_widget_activate (widget: self->button); |
146 | } |
147 | |
148 | static void |
149 | gtk_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 | |
261 | static gboolean |
262 | gtk_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 | |
274 | static GdkContentProvider * |
275 | gtk_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 | |
283 | static void |
284 | gtk_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 | |
333 | static void |
334 | gtk_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 | */ |
361 | GtkWidget * |
362 | gtk_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 | */ |
375 | GtkWidget * |
376 | gtk_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 | |
381 | static gboolean |
382 | dialog_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 | |
392 | static void |
393 | dialog_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 */ |
418 | static void |
419 | ensure_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 | |
447 | static void |
448 | gtk_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 | |
469 | static void |
470 | gtk_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 | |
487 | static guint |
488 | scale_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 | |
496 | static char * |
497 | accessible_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 | |
512 | static void |
513 | gtk_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 | |
534 | static void |
535 | gtk_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 | |
546 | static void |
547 | set_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 | */ |
569 | void |
570 | gtk_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 | */ |
595 | const char * |
596 | gtk_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 | */ |
610 | void |
611 | gtk_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 | */ |
635 | gboolean |
636 | gtk_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 | |
643 | static void |
644 | gtk_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 | |
681 | static void |
682 | gtk_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 | |
717 | static void |
718 | gtk_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 | |
732 | static void |
733 | gtk_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 | |