]> Pileus Git - ~andy/gtk/blob - gtk/gtkcolorbutton.c
GtkStyleContext: Use correct type for animation duration.
[~andy/gtk] / gtk / gtkcolorbutton.c
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 the Gnome Library; see the file COPYING.LIB.  If not,
18  * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  */
21 /* Color picker button for GNOME
22  *
23  * Author: Federico Mena <federico@nuclecu.unam.mx>
24  *
25  * Modified by the GTK+ Team and others 2003.  See the AUTHORS
26  * file for a list of people on the GTK+ Team.  See the ChangeLog
27  * files for a list of changes.  These files are distributed with
28  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
29  */
30
31 #include "config.h"
32
33 #include "gtkcolorbutton.h"
34 #include "gdk/gdkkeysyms.h"
35 #include "gdk-pixbuf/gdk-pixbuf.h"
36 #include "gtkbutton.h"
37 #include "gtkmain.h"
38 #include "gtkalignment.h"
39 #include "gtkcolorsel.h"
40 #include "gtkcolorseldialog.h"
41 #include "gtkdnd.h"
42 #include "gtkdrawingarea.h"
43 #include "gtkframe.h"
44 #include "gtkmarshalers.h"
45 #include "gtkprivate.h"
46 #include "gtkintl.h"
47
48
49 /**
50  * SECTION:gtkcolorbutton
51  * @Short_description: A button to launch a color selection dialog
52  * @Title: GtkColorButton
53  * @See_also: #GtkColorSelectionDialog, #GtkFontButton
54  *
55  * The #GtkColorButton is a button which displays the currently selected color
56  * an allows to open a color selection dialog to change the color. It is suitable
57  * widget for selecting a color in a preference dialog.
58  */
59
60
61 /* Size of checks and gray levels for alpha compositing checkerboard */
62 #define CHECK_SIZE  4
63 #define CHECK_DARK  (1.0 / 3.0)
64 #define CHECK_LIGHT (2.0 / 3.0)
65
66
67 struct _GtkColorButtonPrivate 
68 {
69   GtkWidget *draw_area; /* Widget where we draw the color sample */
70   GtkWidget *cs_dialog; /* Color selection dialog */
71   
72   gchar *title;         /* Title for the color selection window */
73   GdkRGBA rgba;
74
75   guint use_alpha : 1;  /* Use alpha or not */
76 };
77
78 /* Properties */
79 enum 
80 {
81   PROP_0,
82   PROP_USE_ALPHA,
83   PROP_TITLE,
84   PROP_COLOR,
85   PROP_ALPHA,
86   PROP_RGBA
87 };
88
89 /* Signals */
90 enum 
91 {
92   COLOR_SET,
93   LAST_SIGNAL
94 };
95
96 /* gobject signals */
97 static void gtk_color_button_finalize      (GObject             *object);
98 static void gtk_color_button_set_property  (GObject        *object,
99                                             guint           param_id,
100                                             const GValue   *value,
101                                             GParamSpec     *pspec);
102 static void gtk_color_button_get_property  (GObject        *object,
103                                             guint           param_id,
104                                             GValue         *value,
105                                             GParamSpec     *pspec);
106
107 /* gtkwidget signals */
108 static void gtk_color_button_state_changed (GtkWidget           *widget, 
109                                             GtkStateType         previous_state);
110
111 /* gtkbutton signals */
112 static void gtk_color_button_clicked       (GtkButton           *button);
113
114 /* source side drag signals */
115 static void gtk_color_button_drag_begin (GtkWidget        *widget,
116                                          GdkDragContext   *context,
117                                          gpointer          data);
118 static void gtk_color_button_drag_data_get (GtkWidget        *widget,
119                                             GdkDragContext   *context,
120                                             GtkSelectionData *selection_data,
121                                             guint             info,
122                                             guint             time,
123                                             GtkColorButton   *color_button);
124
125 /* target side drag signals */
126 static void gtk_color_button_drag_data_received (GtkWidget        *widget,
127                                                  GdkDragContext   *context,
128                                                  gint              x,
129                                                  gint              y,
130                                                  GtkSelectionData *selection_data,
131                                                  guint             info,
132                                                  guint32           time,
133                                                  GtkColorButton   *color_button);
134
135
136 static guint color_button_signals[LAST_SIGNAL] = { 0 };
137
138 static const GtkTargetEntry drop_types[] = { { "application/x-color", 0, 0 } };
139
140 G_DEFINE_TYPE (GtkColorButton, gtk_color_button, GTK_TYPE_BUTTON)
141
142 static void
143 gtk_color_button_class_init (GtkColorButtonClass *klass)
144 {
145   GObjectClass *gobject_class;
146   GtkWidgetClass *widget_class;
147   GtkButtonClass *button_class;
148
149   gobject_class = G_OBJECT_CLASS (klass);
150   widget_class = GTK_WIDGET_CLASS (klass);
151   button_class = GTK_BUTTON_CLASS (klass);
152
153   gobject_class->get_property = gtk_color_button_get_property;
154   gobject_class->set_property = gtk_color_button_set_property;
155   gobject_class->finalize = gtk_color_button_finalize;
156   widget_class->state_changed = gtk_color_button_state_changed;
157   button_class->clicked = gtk_color_button_clicked;
158   klass->color_set = NULL;
159
160   /**
161    * GtkColorButton:use-alpha:
162    *
163    * If this property is set to %TRUE, the color swatch on the button is rendered against a 
164    * checkerboard background to show its opacity and the opacity slider is displayed in the 
165    * color selection dialog. 
166    *
167    * Since: 2.4
168    */
169   g_object_class_install_property (gobject_class,
170                                    PROP_USE_ALPHA,
171                                    g_param_spec_boolean ("use-alpha", P_("Use alpha"), 
172                                                          P_("Whether to give the color an alpha value"),
173                                                          FALSE,
174                                                          GTK_PARAM_READWRITE));
175
176   /**
177    * GtkColorButton:title:
178    *
179    * The title of the color selection dialog
180    *
181    * Since: 2.4
182    */
183   g_object_class_install_property (gobject_class,
184                                    PROP_TITLE,
185                                    g_param_spec_string ("title", 
186                                                         P_("Title"), 
187                                                         P_("The title of the color selection dialog"),
188                                                         _("Pick a Color"),
189                                                         GTK_PARAM_READWRITE));
190
191   /**
192    * GtkColorButton:color:
193    *
194    * The selected color.
195    *
196    * Since: 2.4
197    */
198   g_object_class_install_property (gobject_class,
199                                    PROP_COLOR,
200                                    g_param_spec_boxed ("color",
201                                                        P_("Current Color"),
202                                                        P_("The selected color"),
203                                                        GDK_TYPE_COLOR,
204                                                        GTK_PARAM_READWRITE));
205
206   /**
207    * GtkColorButton:alpha:
208    *
209    * The selected opacity value (0 fully transparent, 65535 fully opaque). 
210    *
211    * Since: 2.4
212    */
213   g_object_class_install_property (gobject_class,
214                                    PROP_ALPHA,
215                                    g_param_spec_uint ("alpha",
216                                                       P_("Current Alpha"),
217                                                       P_("The selected opacity value (0 fully transparent, 65535 fully opaque)"),
218                                                       0, 65535, 65535,
219                                                       GTK_PARAM_READWRITE));
220
221   /**
222    * GtkColorButton::rgba
223    *
224    * The RGBA color.
225    *
226    * Since: 3.0
227    */
228   g_object_class_install_property (gobject_class,
229                                    PROP_RGBA,
230                                    g_param_spec_boxed ("rgba",
231                                                        P_("Current RGBA Color"),
232                                                        P_("The selected RGBA color"),
233                                                        GDK_TYPE_RGBA,
234                                                        GTK_PARAM_READWRITE));
235
236
237   /**
238    * GtkColorButton::color-set:
239    * @widget: the object which received the signal.
240    * 
241    * The ::color-set signal is emitted when the user selects a color. 
242    * When handling this signal, use gtk_color_button_get_color() and 
243    * gtk_color_button_get_alpha() to find out which color was just selected.
244    *
245    * Note that this signal is only emitted when the <emphasis>user</emphasis>
246    * changes the color. If you need to react to programmatic color changes
247    * as well, use the notify::color signal.
248    *
249    * Since: 2.4
250    */
251   color_button_signals[COLOR_SET] = g_signal_new (I_("color-set"),
252                                                   G_TYPE_FROM_CLASS (gobject_class),
253                                                   G_SIGNAL_RUN_FIRST,
254                                                   G_STRUCT_OFFSET (GtkColorButtonClass, color_set),
255                                                   NULL, NULL,
256                                                   _gtk_marshal_VOID__VOID,
257                                                   G_TYPE_NONE, 0);
258
259   g_type_class_add_private (gobject_class, sizeof (GtkColorButtonPrivate));
260 }
261
262 static gboolean
263 gtk_color_button_has_alpha (GtkColorButton *color_button)
264 {
265   return color_button->priv->use_alpha &&
266       color_button->priv->rgba.alpha < 1;
267 }
268
269 static cairo_pattern_t *
270 gtk_color_button_get_checkered (void)
271 {
272   /* need to respect pixman's stride being a multiple of 4 */
273   static unsigned char data[8] = { 0xFF, 0x00, 0x00, 0x00,
274                                    0x00, 0xFF, 0x00, 0x00 };
275   static cairo_surface_t *checkered = NULL;
276   cairo_pattern_t *pattern;
277
278   if (checkered == NULL)
279     {
280       checkered = cairo_image_surface_create_for_data (data,
281                                                        CAIRO_FORMAT_A8,
282                                                        2, 2, 4);
283     }
284
285   pattern = cairo_pattern_create_for_surface (checkered);
286   cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REPEAT);
287   cairo_pattern_set_filter (pattern, CAIRO_FILTER_NEAREST);
288
289   return pattern;
290 }
291
292 /* Handle exposure events for the color picker's drawing area */
293 static gint
294 gtk_color_button_draw_cb (GtkWidget *widget, 
295                           cairo_t   *cr,
296                           gpointer   data)
297 {
298   GtkColorButton *color_button = GTK_COLOR_BUTTON (data);
299   cairo_pattern_t *checkered;
300
301   if (gtk_color_button_has_alpha (color_button))
302     {
303       cairo_set_source_rgb (cr, CHECK_DARK, CHECK_DARK, CHECK_DARK);
304       cairo_paint (cr);
305
306       cairo_set_source_rgb (cr, CHECK_LIGHT, CHECK_LIGHT, CHECK_LIGHT);
307       cairo_scale (cr, CHECK_SIZE, CHECK_SIZE);
308
309       checkered = gtk_color_button_get_checkered ();
310       cairo_mask (cr, checkered);
311       cairo_pattern_destroy (checkered);
312
313       gdk_cairo_set_source_rgba (cr, &color_button->priv->rgba);
314     }
315   else
316     {
317       cairo_set_source_rgb (cr,
318                             color_button->priv->rgba.red,
319                             color_button->priv->rgba.green,
320                             color_button->priv->rgba.blue);
321     }
322
323   cairo_paint (cr);
324
325   if (!gtk_widget_is_sensitive (GTK_WIDGET (color_button)))
326     {
327       gdk_cairo_set_source_color (cr, &gtk_widget_get_style (GTK_WIDGET(color_button))->bg[GTK_STATE_INSENSITIVE]);
328       checkered = gtk_color_button_get_checkered ();
329       cairo_mask (cr, checkered);
330       cairo_pattern_destroy (checkered);
331     }
332
333   return FALSE;
334 }
335
336 static void
337 gtk_color_button_state_changed (GtkWidget   *widget, 
338                                 GtkStateType previous_state)
339 {
340   gtk_widget_queue_draw (widget);
341 }
342
343 static void
344 gtk_color_button_drag_data_received (GtkWidget        *widget,
345                                      GdkDragContext   *context,
346                                      gint              x,
347                                      gint              y,
348                                      GtkSelectionData *selection_data,
349                                      guint             info,
350                                      guint32           time,
351                                      GtkColorButton   *color_button)
352 {
353   guint16 *dropped;
354
355   if (selection_data->length < 0)
356     return;
357
358   /* We accept drops with the wrong format, since the KDE color
359    * chooser incorrectly drops application/x-color with format 8.
360    */
361   if (selection_data->length != 8) 
362     {
363       g_warning (_("Received invalid color data\n"));
364       return;
365     }
366
367
368   dropped = (guint16 *)selection_data->data;
369
370   color_button->priv->rgba.red = dropped[0] / 65535.;
371   color_button->priv->rgba.green = dropped[1] / 65535.;
372   color_button->priv->rgba.blue = dropped[2] / 65535.;
373   color_button->priv->rgba.alpha = dropped[3] / 65535.;
374
375   gtk_widget_queue_draw (color_button->priv->draw_area);
376
377   g_signal_emit (color_button, color_button_signals[COLOR_SET], 0);
378
379   g_object_freeze_notify (G_OBJECT (color_button));
380   g_object_notify (G_OBJECT (color_button), "color");
381   g_object_notify (G_OBJECT (color_button), "alpha");
382   g_object_notify (G_OBJECT (color_button), "rgba");
383   g_object_thaw_notify (G_OBJECT (color_button));
384 }
385
386 static void
387 set_color_icon (GdkDragContext *context,
388                 GdkRGBA        *rgba)
389 {
390   cairo_surface_t *surface;
391   cairo_t *cr;
392
393   surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24,
394                                         48, 32);
395   cr = cairo_create (surface);
396
397   gdk_cairo_set_source_rgba (cr, rgba);
398   cairo_paint (cr);
399
400   gtk_drag_set_icon_surface (context, surface);
401
402   cairo_destroy (cr);
403   cairo_surface_destroy (surface);
404 }
405
406 static void
407 gtk_color_button_drag_begin (GtkWidget      *widget,
408                              GdkDragContext *context,
409                              gpointer        data)
410 {
411   GtkColorButton *color_button = data;
412
413   set_color_icon (context, &color_button->priv->rgba);
414 }
415
416 static void
417 gtk_color_button_drag_data_get (GtkWidget        *widget,
418                                 GdkDragContext   *context,
419                                 GtkSelectionData *selection_data,
420                                 guint             info,
421                                 guint             time,
422                                 GtkColorButton   *color_button)
423 {
424   guint16 dropped[4];
425
426   dropped[0] = (guint16) (color_button->priv->rgba.red * 65535);
427   dropped[1] = (guint16) (color_button->priv->rgba.green * 65535);
428   dropped[2] = (guint16) (color_button->priv->rgba.blue * 65535);
429   dropped[3] = (guint16) (color_button->priv->rgba.alpha * 65535);
430
431   gtk_selection_data_set (selection_data, selection_data->target,
432                           16, (guchar *)dropped, 8);
433 }
434
435 static void
436 gtk_color_button_init (GtkColorButton *color_button)
437 {
438   GtkWidget *alignment;
439   GtkWidget *frame;
440   PangoLayout *layout;
441   PangoRectangle rect;
442
443   /* Create the widgets */
444   color_button->priv = G_TYPE_INSTANCE_GET_PRIVATE (color_button,
445                                                     GTK_TYPE_COLOR_BUTTON,
446                                                     GtkColorButtonPrivate);
447
448   gtk_widget_push_composite_child ();
449
450   alignment = gtk_alignment_new (0.5, 0.5, 0.5, 1.0);
451   gtk_container_set_border_width (GTK_CONTAINER (alignment), 1);
452   gtk_container_add (GTK_CONTAINER (color_button), alignment);
453   gtk_widget_show (alignment);
454
455   frame = gtk_frame_new (NULL);
456   gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_OUT);
457   gtk_container_add (GTK_CONTAINER (alignment), frame);
458   gtk_widget_show (frame);
459
460   /* Just some widget we can hook to expose-event on */
461   color_button->priv->draw_area = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
462
463   layout = gtk_widget_create_pango_layout (GTK_WIDGET (color_button), "Black");
464   pango_layout_get_pixel_extents (layout, NULL, &rect);
465   g_object_unref (layout);
466
467   gtk_widget_set_size_request (color_button->priv->draw_area, rect.width - 2, rect.height - 2);
468   g_signal_connect (color_button->priv->draw_area, "draw",
469                     G_CALLBACK (gtk_color_button_draw_cb), color_button);
470   gtk_container_add (GTK_CONTAINER (frame), color_button->priv->draw_area);
471   gtk_widget_show (color_button->priv->draw_area);
472
473   color_button->priv->title = g_strdup (_("Pick a Color")); /* default title */
474
475   /* Start with opaque black, alpha disabled */
476
477   color_button->priv->rgba.red = 0;
478   color_button->priv->rgba.green = 0;
479   color_button->priv->rgba.blue = 0;
480   color_button->priv->rgba.alpha = 1;
481   color_button->priv->use_alpha = FALSE;
482
483   gtk_drag_dest_set (GTK_WIDGET (color_button),
484                      GTK_DEST_DEFAULT_MOTION |
485                      GTK_DEST_DEFAULT_HIGHLIGHT |
486                      GTK_DEST_DEFAULT_DROP,
487                      drop_types, 1, GDK_ACTION_COPY);
488   gtk_drag_source_set (GTK_WIDGET(color_button),
489                        GDK_BUTTON1_MASK|GDK_BUTTON3_MASK,
490                        drop_types, 1,
491                        GDK_ACTION_COPY);
492   g_signal_connect (color_button, "drag-begin",
493                     G_CALLBACK (gtk_color_button_drag_begin), color_button);
494   g_signal_connect (color_button, "drag-data-received",
495                     G_CALLBACK (gtk_color_button_drag_data_received), color_button);
496   g_signal_connect (color_button, "drag-data-get",
497                     G_CALLBACK (gtk_color_button_drag_data_get), color_button);
498
499   gtk_widget_pop_composite_child ();
500 }
501
502 static void
503 gtk_color_button_finalize (GObject *object)
504 {
505   GtkColorButton *color_button = GTK_COLOR_BUTTON (object);
506
507   if (color_button->priv->cs_dialog != NULL)
508     gtk_widget_destroy (color_button->priv->cs_dialog);
509   color_button->priv->cs_dialog = NULL;
510
511   g_free (color_button->priv->title);
512   color_button->priv->title = NULL;
513
514   G_OBJECT_CLASS (gtk_color_button_parent_class)->finalize (object);
515 }
516
517
518 /**
519  * gtk_color_button_new:
520  *
521  * Creates a new color button. This returns a widget in the form of
522  * a small button containing a swatch representing the current selected 
523  * color. When the button is clicked, a color-selection dialog will open, 
524  * allowing the user to select a color. The swatch will be updated to reflect 
525  * the new color when the user finishes.
526  *
527  * Returns: a new color button.
528  *
529  * Since: 2.4
530  */
531 GtkWidget *
532 gtk_color_button_new (void)
533 {
534   return g_object_new (GTK_TYPE_COLOR_BUTTON, NULL);
535 }
536
537 /**
538  * gtk_color_button_new_with_color:
539  * @color: A #GdkColor to set the current color with.
540  *
541  * Creates a new color button. 
542  *
543  * Returns: a new color button.
544  *
545  * Since: 2.4
546  */
547 GtkWidget *
548 gtk_color_button_new_with_color (const GdkColor *color)
549 {
550   return g_object_new (GTK_TYPE_COLOR_BUTTON, "color", color, NULL);
551 }
552
553 /**
554  * gtk_color_button_new_with_rgba:
555  * @rgba: A #GdkRGBA to set the current color with.
556  *
557  * Creates a new color button.
558  *
559  * Returns: a new color button
560  *
561  * Since: 3.0
562  */
563 GtkWidget *
564 gtk_color_button_new_with_rgba (const GdkRGBA *rgba)
565 {
566   return g_object_new (GTK_TYPE_COLOR_BUTTON, "rgba", rgba, NULL);
567 }
568
569 static void
570 dialog_ok_clicked (GtkWidget *widget, 
571                    gpointer   data)
572 {
573   GtkColorButton *color_button = GTK_COLOR_BUTTON (data);
574   GtkColorSelection *color_selection;
575   GtkColorSelectionDialog *selection_dialog;
576
577   selection_dialog = GTK_COLOR_SELECTION_DIALOG (color_button->priv->cs_dialog);
578   color_selection = GTK_COLOR_SELECTION (gtk_color_selection_dialog_get_color_selection (selection_dialog));
579
580   gtk_color_selection_get_current_rgba (color_selection, &color_button->priv->rgba);
581
582   gtk_widget_hide (color_button->priv->cs_dialog);
583
584   gtk_widget_queue_draw (color_button->priv->draw_area);
585
586   g_signal_emit (color_button, color_button_signals[COLOR_SET], 0);
587
588   g_object_freeze_notify (G_OBJECT (color_button));
589   g_object_notify (G_OBJECT (color_button), "color");
590   g_object_notify (G_OBJECT (color_button), "alpha");
591   g_object_notify (G_OBJECT (color_button), "rgba");
592   g_object_thaw_notify (G_OBJECT (color_button));
593 }
594
595 static gboolean
596 dialog_destroy (GtkWidget *widget, 
597                 gpointer   data)
598 {
599   GtkColorButton *color_button = GTK_COLOR_BUTTON (data);
600   
601   color_button->priv->cs_dialog = NULL;
602
603   return FALSE;
604 }
605
606 static void
607 dialog_cancel_clicked (GtkWidget *widget,
608                        gpointer   data)
609 {
610   GtkColorButton *color_button = GTK_COLOR_BUTTON (data);
611   
612   gtk_widget_hide (color_button->priv->cs_dialog);  
613 }
614
615 static void
616 gtk_color_button_clicked (GtkButton *button)
617 {
618   GtkColorButton *color_button = GTK_COLOR_BUTTON (button);
619   GtkColorSelection *color_selection;
620   GtkColorSelectionDialog *color_dialog;
621
622   /* if dialog already exists, make sure it's shown and raised */
623   if (!color_button->priv->cs_dialog) 
624     {
625       /* Create the dialog and connects its buttons */
626       GtkWidget *parent;
627       GtkWidget *ok_button, *cancel_button;
628       
629       parent = gtk_widget_get_toplevel (GTK_WIDGET (color_button));
630       
631       color_button->priv->cs_dialog = gtk_color_selection_dialog_new (color_button->priv->title);
632       
633       color_dialog = GTK_COLOR_SELECTION_DIALOG (color_button->priv->cs_dialog);
634
635       if (gtk_widget_is_toplevel (parent) && GTK_IS_WINDOW (parent))
636         {
637           if (GTK_WINDOW (parent) != gtk_window_get_transient_for (GTK_WINDOW (color_dialog)))
638             gtk_window_set_transient_for (GTK_WINDOW (color_dialog), GTK_WINDOW (parent));
639                
640           gtk_window_set_modal (GTK_WINDOW (color_dialog),
641                                 gtk_window_get_modal (GTK_WINDOW (parent)));
642         }
643
644       g_object_get (color_dialog,
645                     "ok-button", &ok_button,
646                     "cancel-button", &cancel_button,
647                     NULL);
648       
649       g_signal_connect (ok_button, "clicked",
650                         G_CALLBACK (dialog_ok_clicked), color_button);
651       g_signal_connect (cancel_button, "clicked",
652                         G_CALLBACK (dialog_cancel_clicked), color_button);
653       g_signal_connect (color_dialog, "destroy",
654                         G_CALLBACK (dialog_destroy), color_button);
655     }
656
657   color_dialog = GTK_COLOR_SELECTION_DIALOG (color_button->priv->cs_dialog);
658   color_selection = GTK_COLOR_SELECTION (gtk_color_selection_dialog_get_color_selection (color_dialog));
659
660   gtk_color_selection_set_has_opacity_control (color_selection,
661                                                color_button->priv->use_alpha);
662
663   gtk_color_selection_set_previous_rgba (color_selection,
664                                          &color_button->priv->rgba);
665   gtk_color_selection_set_current_rgba (color_selection,
666                                         &color_button->priv->rgba);
667
668   gtk_window_present (GTK_WINDOW (color_button->priv->cs_dialog));
669 }
670
671 /**
672  * gtk_color_button_set_color:
673  * @color_button: a #GtkColorButton.
674  * @color: A #GdkColor to set the current color with.
675  *
676  * Sets the current color to be @color.
677  *
678  * Since: 2.4
679  **/
680 void
681 gtk_color_button_set_color (GtkColorButton *color_button,
682                             const GdkColor *color)
683 {
684   g_return_if_fail (GTK_IS_COLOR_BUTTON (color_button));
685   g_return_if_fail (color != NULL);
686
687   color_button->priv->rgba.red = color->red / 65535.;
688   color_button->priv->rgba.green = color->green / 65535.;
689   color_button->priv->rgba.blue = color->blue / 65535.;
690
691   gtk_widget_queue_draw (color_button->priv->draw_area);
692   
693   g_object_notify (G_OBJECT (color_button), "color");
694   g_object_notify (G_OBJECT (color_button), "rgba");
695 }
696
697
698 /**
699  * gtk_color_button_set_alpha:
700  * @color_button: a #GtkColorButton.
701  * @alpha: an integer between 0 and 65535.
702  *
703  * Sets the current opacity to be @alpha. 
704  *
705  * Since: 2.4
706  **/
707 void
708 gtk_color_button_set_alpha (GtkColorButton *color_button,
709                             guint16         alpha)
710 {
711   g_return_if_fail (GTK_IS_COLOR_BUTTON (color_button));
712
713   color_button->priv->rgba.alpha = alpha / 65535.;
714
715   gtk_widget_queue_draw (color_button->priv->draw_area);
716
717   g_object_notify (G_OBJECT (color_button), "alpha");
718   g_object_notify (G_OBJECT (color_button), "rgba");
719 }
720
721 /**
722  * gtk_color_button_get_color:
723  * @color_button: a #GtkColorButton.
724  * @color: a #GdkColor to fill in with the current color.
725  *
726  * Sets @color to be the current color in the #GtkColorButton widget.
727  *
728  * Since: 2.4
729  **/
730 void
731 gtk_color_button_get_color (GtkColorButton *color_button,
732                             GdkColor       *color)
733 {
734   g_return_if_fail (GTK_IS_COLOR_BUTTON (color_button));
735
736   color->red = (guint16) (color_button->priv->rgba.red * 65535);
737   color->green = (guint16) (color_button->priv->rgba.green * 65535);
738   color->blue = (guint16) (color_button->priv->rgba.blue * 65535);
739 }
740
741 /**
742  * gtk_color_button_get_alpha:
743  * @color_button: a #GtkColorButton.
744  *
745  * Returns the current alpha value. 
746  *
747  * Return value: an integer between 0 and 65535.
748  *
749  * Since: 2.4
750  **/
751 guint16
752 gtk_color_button_get_alpha (GtkColorButton *color_button)
753 {
754   g_return_val_if_fail (GTK_IS_COLOR_BUTTON (color_button), 0);
755
756   return (guint16) (color_button->priv->rgba.alpha * 65535);
757 }
758
759 /**
760  * gtk_color_button_set_rgba:
761  * @color_button: a #GtkColorButton.
762  * @rgba: a #GdkRGBA to set the current color with
763  *
764  * Sets the current color to be @rgba.
765  *
766  * Since: 3.0
767  **/
768 void
769 gtk_color_button_set_rgba (GtkColorButton *color_button,
770                            const GdkRGBA  *rgba)
771 {
772   g_return_if_fail (GTK_IS_COLOR_BUTTON (color_button));
773   g_return_if_fail (rgba != NULL);
774
775   color_button->priv->rgba = *rgba;
776
777   g_object_notify (G_OBJECT (color_button), "rgba");
778 }
779
780 /**
781  * gtk_color_button_get_rgba:
782  * @color_button: a #GtkColorButton.
783  * @rgba: a #GdkRGBA to fill in with the current color
784  *
785  * Sets @rgba to be the current color in the #GtkColorButton widget.
786  *
787  * Since: 3.0
788  **/
789 void
790 gtk_color_button_get_rgba (GtkColorButton *color_button,
791                            GdkRGBA        *rgba)
792 {
793   g_return_if_fail (GTK_IS_COLOR_BUTTON (color_button));
794   g_return_if_fail (rgba != NULL);
795
796   *rgba = color_button->priv->rgba;
797 }
798
799 /**
800  * gtk_color_button_set_use_alpha:
801  * @color_button: a #GtkColorButton.
802  * @use_alpha: %TRUE if color button should use alpha channel, %FALSE if not.
803  *
804  * Sets whether or not the color button should use the alpha channel.
805  *
806  * Since: 2.4
807  */
808 void
809 gtk_color_button_set_use_alpha (GtkColorButton *color_button, 
810                                 gboolean        use_alpha)
811 {
812   g_return_if_fail (GTK_IS_COLOR_BUTTON (color_button));
813
814   use_alpha = (use_alpha != FALSE);
815
816   if (color_button->priv->use_alpha != use_alpha) 
817     {
818       color_button->priv->use_alpha = use_alpha;
819
820       gtk_widget_queue_draw (color_button->priv->draw_area);
821
822       g_object_notify (G_OBJECT (color_button), "use-alpha");
823     }
824 }
825
826 /**
827  * gtk_color_button_get_use_alpha:
828  * @color_button: a #GtkColorButton.
829  *
830  * Does the color selection dialog use the alpha channel?
831  *
832  * Returns: %TRUE if the color sample uses alpha channel, %FALSE if not.
833  *
834  * Since: 2.4
835  */
836 gboolean
837 gtk_color_button_get_use_alpha (GtkColorButton *color_button)
838 {
839   g_return_val_if_fail (GTK_IS_COLOR_BUTTON (color_button), FALSE);
840
841   return color_button->priv->use_alpha;
842 }
843
844
845 /**
846  * gtk_color_button_set_title:
847  * @color_button: a #GtkColorButton
848  * @title: String containing new window title.
849  *
850  * Sets the title for the color selection dialog.
851  *
852  * Since: 2.4
853  */
854 void
855 gtk_color_button_set_title (GtkColorButton *color_button, 
856                             const gchar    *title)
857 {
858   gchar *old_title;
859
860   g_return_if_fail (GTK_IS_COLOR_BUTTON (color_button));
861
862   old_title = color_button->priv->title;
863   color_button->priv->title = g_strdup (title);
864   g_free (old_title);
865
866   if (color_button->priv->cs_dialog)
867     gtk_window_set_title (GTK_WINDOW (color_button->priv->cs_dialog), 
868                           color_button->priv->title);
869   
870   g_object_notify (G_OBJECT (color_button), "title");
871 }
872
873 /**
874  * gtk_color_button_get_title:
875  * @color_button: a #GtkColorButton
876  *
877  * Gets the title of the color selection dialog.
878  *
879  * Returns: An internal string, do not free the return value
880  *
881  * Since: 2.4
882  */
883 G_CONST_RETURN gchar *
884 gtk_color_button_get_title (GtkColorButton *color_button)
885 {
886   g_return_val_if_fail (GTK_IS_COLOR_BUTTON (color_button), NULL);
887
888   return color_button->priv->title;
889 }
890
891 static void
892 gtk_color_button_set_property (GObject      *object,
893                                guint         param_id,
894                                const GValue *value,
895                                GParamSpec   *pspec)
896 {
897   GtkColorButton *color_button = GTK_COLOR_BUTTON (object);
898
899   switch (param_id) 
900     {
901     case PROP_USE_ALPHA:
902       gtk_color_button_set_use_alpha (color_button, g_value_get_boolean (value));
903       break;
904     case PROP_TITLE:
905       gtk_color_button_set_title (color_button, g_value_get_string (value));
906       break;
907     case PROP_COLOR:
908       gtk_color_button_set_color (color_button, g_value_get_boxed (value));
909       break;
910     case PROP_ALPHA:
911       gtk_color_button_set_alpha (color_button, g_value_get_uint (value));
912       break;
913     case PROP_RGBA:
914       gtk_color_button_set_rgba (color_button, g_value_get_boxed (value));
915       break;
916     default:
917       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
918       break;
919     }
920 }
921
922 static void
923 gtk_color_button_get_property (GObject    *object,
924                                guint       param_id,
925                                GValue     *value,
926                                GParamSpec *pspec)
927 {
928   GtkColorButton *color_button = GTK_COLOR_BUTTON (object);
929   GdkColor color;
930
931   switch (param_id) 
932     {
933     case PROP_USE_ALPHA:
934       g_value_set_boolean (value, gtk_color_button_get_use_alpha (color_button));
935       break;
936     case PROP_TITLE:
937       g_value_set_string (value, gtk_color_button_get_title (color_button));
938       break;
939     case PROP_COLOR:
940       gtk_color_button_get_color (color_button, &color);
941       g_value_set_boxed (value, &color);
942       break;
943     case PROP_ALPHA:
944       g_value_set_uint (value, gtk_color_button_get_alpha (color_button));
945       break;
946     case PROP_RGBA:
947       {
948         GdkRGBA rgba;
949
950         gtk_color_button_get_rgba (color_button, &rgba);
951         g_value_set_boxed (value, &rgba);
952       }
953       break;
954     default:
955       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
956       break;
957     }
958 }