]> Pileus Git - ~andy/gtk/blob - gtk/gtkcolorbutton.c
Add API to set palettes
[~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 #define GDK_DISABLE_DEPRECATION_WARNINGS
32 #include "config.h"
33
34 #include "gtkcolorbutton.h"
35
36 #include "gtkbutton.h"
37 #include "gtkmain.h"
38 #include "gtkalignment.h"
39 #include "gtkcolorchooser.h"
40 #include "gtkcolorchooserdialog.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
56  * color an allows to open a color selection dialog to change the color.
57  * It is suitable 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   *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   *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 static void gtk_color_button_iface_init (GtkColorChooserInterface *iface);
141
142 G_DEFINE_TYPE_WITH_CODE (GtkColorButton, gtk_color_button, GTK_TYPE_BUTTON,
143                          G_IMPLEMENT_INTERFACE (GTK_TYPE_COLOR_CHOOSER,
144                                                 gtk_color_button_iface_init))
145
146 static void
147 gtk_color_button_class_init (GtkColorButtonClass *klass)
148 {
149   GObjectClass *gobject_class;
150   GtkWidgetClass *widget_class;
151   GtkButtonClass *button_class;
152
153   gobject_class = G_OBJECT_CLASS (klass);
154   widget_class = GTK_WIDGET_CLASS (klass);
155   button_class = GTK_BUTTON_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   widget_class->state_changed = gtk_color_button_state_changed;
161   button_class->clicked = gtk_color_button_clicked;
162   klass->color_set = NULL;
163
164   /**
165    * GtkColorButton:use-alpha:
166    *
167    * If this property is set to %TRUE, the color swatch on the button is
168    * rendered against a checkerboard background to show its opacity and
169    * the opacity slider is displayed in the color selection dialog.
170    *
171    * Since: 2.4
172    */
173   g_object_class_install_property (gobject_class,
174                                    PROP_USE_ALPHA,
175                                    g_param_spec_boolean ("use-alpha", P_("Use alpha"),
176                                                          P_("Whether to give the color an alpha value"),
177                                                          FALSE,
178                                                          GTK_PARAM_READWRITE));
179
180   /**
181    * GtkColorButton:title:
182    *
183    * The title of the color selection dialog
184    *
185    * Since: 2.4
186    */
187   g_object_class_install_property (gobject_class,
188                                    PROP_TITLE,
189                                    g_param_spec_string ("title",
190                                                         P_("Title"),
191                                                         P_("The title of the color selection dialog"),
192                                                         _("Pick a Color"),
193                                                         GTK_PARAM_READWRITE));
194
195   /**
196    * GtkColorButton:color:
197    *
198    * The selected color.
199    *
200    * Since: 2.4
201    *
202    * Deprecated: 3.4: Use #GtkColorButton:rgba instead.
203    */
204   g_object_class_install_property (gobject_class,
205                                    PROP_COLOR,
206                                    g_param_spec_boxed ("color",
207                                                        P_("Current Color"),
208                                                        P_("The selected color"),
209                                                        GDK_TYPE_COLOR,
210                                                        GTK_PARAM_READWRITE | G_PARAM_DEPRECATED));
211
212   /**
213    * GtkColorButton:alpha:
214    *
215    * The selected opacity value (0 fully transparent, 65535 fully opaque).
216    *
217    * Since: 2.4
218    */
219   g_object_class_install_property (gobject_class,
220                                    PROP_ALPHA,
221                                    g_param_spec_uint ("alpha",
222                                                       P_("Current Alpha"),
223                                                       P_("The selected opacity value (0 fully transparent, 65535 fully opaque)"),
224                                                       0, 65535, 65535,
225                                                       GTK_PARAM_READWRITE));
226
227   /**
228    * GtkColorButton:rgba:
229    *
230    * The RGBA color.
231    *
232    * Since: 3.0
233    */
234   g_object_class_install_property (gobject_class,
235                                    PROP_RGBA,
236                                    g_param_spec_boxed ("rgba",
237                                                        P_("Current RGBA Color"),
238                                                        P_("The selected RGBA color"),
239                                                        GDK_TYPE_RGBA,
240                                                        GTK_PARAM_READWRITE));
241
242
243   /**
244    * GtkColorButton::color-set:
245    * @widget: the object which received the signal.
246    *
247    * The ::color-set signal is emitted when the user selects a color.
248    * When handling this signal, use gtk_color_button_get_color() and
249    * gtk_color_button_get_alpha() (or gtk_color_button_get_rgba()) to
250    * find out which color was just selected.
251    *
252    * Note that this signal is only emitted when the <emphasis>user</emphasis>
253    * changes the color. If you need to react to programmatic color changes
254    * as well, use the notify::color signal.
255    *
256    * Since: 2.4
257    */
258   color_button_signals[COLOR_SET] = g_signal_new (I_("color-set"),
259                                                   G_TYPE_FROM_CLASS (gobject_class),
260                                                   G_SIGNAL_RUN_FIRST,
261                                                   G_STRUCT_OFFSET (GtkColorButtonClass, color_set),
262                                                   NULL, NULL,
263                                                   _gtk_marshal_VOID__VOID,
264                                                   G_TYPE_NONE, 0);
265
266   g_type_class_add_private (gobject_class, sizeof (GtkColorButtonPrivate));
267 }
268
269 static gboolean
270 gtk_color_button_has_alpha (GtkColorButton *button)
271 {
272   return button->priv->use_alpha && button->priv->rgba.alpha < 1;
273 }
274
275 static cairo_pattern_t *
276 gtk_color_button_get_checkered (void)
277 {
278   /* need to respect pixman's stride being a multiple of 4 */
279   static unsigned char data[8] = { 0xFF, 0x00, 0x00, 0x00,
280                                    0x00, 0xFF, 0x00, 0x00 };
281   static cairo_surface_t *checkered = NULL;
282   cairo_pattern_t *pattern;
283
284   if (checkered == NULL)
285     {
286       checkered = cairo_image_surface_create_for_data (data,
287                                                        CAIRO_FORMAT_A8,
288                                                        2, 2, 4);
289     }
290
291   pattern = cairo_pattern_create_for_surface (checkered);
292   cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REPEAT);
293   cairo_pattern_set_filter (pattern, CAIRO_FILTER_NEAREST);
294
295   return pattern;
296 }
297
298 /* Handle exposure events for the color picker's drawing area */
299 static gint
300 gtk_color_button_draw_cb (GtkWidget *widget,
301                           cairo_t   *cr,
302                           gpointer   data)
303 {
304   GtkColorButton *button = GTK_COLOR_BUTTON (data);
305   cairo_pattern_t *checkered;
306
307   if (gtk_color_button_has_alpha (button))
308     {
309       cairo_set_source_rgb (cr, CHECK_DARK, CHECK_DARK, CHECK_DARK);
310       cairo_paint (cr);
311
312       cairo_set_source_rgb (cr, CHECK_LIGHT, CHECK_LIGHT, CHECK_LIGHT);
313       cairo_scale (cr, CHECK_SIZE, CHECK_SIZE);
314
315       checkered = gtk_color_button_get_checkered ();
316       cairo_mask (cr, checkered);
317       cairo_pattern_destroy (checkered);
318
319       gdk_cairo_set_source_rgba (cr, &button->priv->rgba);
320     }
321   else
322     {
323       cairo_set_source_rgb (cr,
324                             button->priv->rgba.red,
325                             button->priv->rgba.green,
326                             button->priv->rgba.blue);
327     }
328
329   cairo_paint (cr);
330
331   if (!gtk_widget_is_sensitive (GTK_WIDGET (button)))
332     {
333       GtkStyleContext *context;
334       GdkRGBA color;
335
336       context = gtk_widget_get_style_context (widget);
337       gtk_style_context_get_background_color (context, GTK_STATE_FLAG_INSENSITIVE, &color);
338
339       gdk_cairo_set_source_rgba (cr, &color);
340       checkered = gtk_color_button_get_checkered ();
341       cairo_mask (cr, checkered);
342       cairo_pattern_destroy (checkered);
343     }
344
345   return FALSE;
346 }
347
348 static void
349 gtk_color_button_state_changed (GtkWidget   *widget,
350                                 GtkStateType previous_state)
351 {
352   gtk_widget_queue_draw (widget);
353 }
354
355 static void
356 gtk_color_button_drag_data_received (GtkWidget        *widget,
357                                      GdkDragContext   *context,
358                                      gint              x,
359                                      gint              y,
360                                      GtkSelectionData *selection_data,
361                                      guint             info,
362                                      guint32           time,
363                                      GtkColorButton   *button)
364 {
365   gint length;
366   guint16 *dropped;
367
368   length = gtk_selection_data_get_length (selection_data);
369
370   if (length < 0)
371     return;
372
373   /* We accept drops with the wrong format, since the KDE color
374    * chooser incorrectly drops application/x-color with format 8.
375    */
376   if (length != 8)
377     {
378       g_warning ("%s: Received invalid color data", G_STRFUNC);
379       return;
380     }
381
382
383   dropped = (guint16 *) gtk_selection_data_get_data (selection_data);
384
385   button->priv->rgba.red = dropped[0] / 65535.;
386   button->priv->rgba.green = dropped[1] / 65535.;
387   button->priv->rgba.blue = dropped[2] / 65535.;
388   button->priv->rgba.alpha = dropped[3] / 65535.;
389
390   gtk_widget_queue_draw (button->priv->draw_area);
391
392   g_signal_emit (button, color_button_signals[COLOR_SET], 0);
393
394   g_object_freeze_notify (G_OBJECT (button));
395   g_object_notify (G_OBJECT (button), "color");
396   g_object_notify (G_OBJECT (button), "alpha");
397   g_object_notify (G_OBJECT (button), "rgba");
398   g_object_thaw_notify (G_OBJECT (button));
399 }
400
401 static void
402 set_color_icon (GdkDragContext *context,
403                 GdkRGBA        *rgba)
404 {
405   cairo_surface_t *surface;
406   cairo_t *cr;
407
408   surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24,
409                                         48, 32);
410   cr = cairo_create (surface);
411
412   gdk_cairo_set_source_rgba (cr, rgba);
413   cairo_paint (cr);
414
415   gtk_drag_set_icon_surface (context, surface);
416
417   cairo_destroy (cr);
418   cairo_surface_destroy (surface);
419 }
420
421 static void
422 gtk_color_button_drag_begin (GtkWidget      *widget,
423                              GdkDragContext *context,
424                              gpointer        data)
425 {
426   GtkColorButton *button = data;
427
428   set_color_icon (context, &button->priv->rgba);
429 }
430
431 static void
432 gtk_color_button_drag_data_get (GtkWidget        *widget,
433                                 GdkDragContext   *context,
434                                 GtkSelectionData *selection_data,
435                                 guint             info,
436                                 guint             time,
437                                 GtkColorButton   *button)
438 {
439   guint16 dropped[4];
440
441   dropped[0] = (guint16) (button->priv->rgba.red * 65535);
442   dropped[1] = (guint16) (button->priv->rgba.green * 65535);
443   dropped[2] = (guint16) (button->priv->rgba.blue * 65535);
444   dropped[3] = (guint16) (button->priv->rgba.alpha * 65535);
445
446   gtk_selection_data_set (selection_data,
447                           gtk_selection_data_get_target (selection_data),
448                           16, (guchar *)dropped, 8);
449 }
450
451 static void
452 gtk_color_button_init (GtkColorButton *button)
453 {
454   GtkWidget *alignment;
455   GtkWidget *frame;
456   PangoLayout *layout;
457   PangoRectangle rect;
458
459   /* Create the widgets */
460   button->priv = G_TYPE_INSTANCE_GET_PRIVATE (button,
461                                               GTK_TYPE_COLOR_BUTTON,
462                                               GtkColorButtonPrivate);
463
464   gtk_widget_push_composite_child ();
465
466   alignment = gtk_alignment_new (0.5, 0.5, 0.5, 1.0);
467   gtk_container_set_border_width (GTK_CONTAINER (alignment), 1);
468   gtk_container_add (GTK_CONTAINER (button), alignment);
469   gtk_widget_show (alignment);
470
471   frame = gtk_frame_new (NULL);
472   gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_OUT);
473   gtk_container_add (GTK_CONTAINER (alignment), frame);
474   gtk_widget_show (frame);
475
476   /* Just some widget we can hook to expose-event on */
477   button->priv->draw_area = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
478
479   layout = gtk_widget_create_pango_layout (GTK_WIDGET (button), "Black");
480   pango_layout_get_pixel_extents (layout, NULL, &rect);
481   g_object_unref (layout);
482
483   gtk_widget_set_size_request (button->priv->draw_area, rect.width - 2, rect.height - 2);
484   g_signal_connect (button->priv->draw_area, "draw",
485                     G_CALLBACK (gtk_color_button_draw_cb), button);
486   gtk_container_add (GTK_CONTAINER (frame), button->priv->draw_area);
487   gtk_widget_show (button->priv->draw_area);
488
489   button->priv->title = g_strdup (_("Pick a Color")); /* default title */
490
491   /* Start with opaque black, alpha disabled */
492   button->priv->rgba.red = 0;
493   button->priv->rgba.green = 0;
494   button->priv->rgba.blue = 0;
495   button->priv->rgba.alpha = 1;
496   button->priv->use_alpha = FALSE;
497
498   gtk_drag_dest_set (GTK_WIDGET (button),
499                      GTK_DEST_DEFAULT_MOTION |
500                      GTK_DEST_DEFAULT_HIGHLIGHT |
501                      GTK_DEST_DEFAULT_DROP,
502                      drop_types, 1, GDK_ACTION_COPY);
503   gtk_drag_source_set (GTK_WIDGET (button),
504                        GDK_BUTTON1_MASK|GDK_BUTTON3_MASK,
505                        drop_types, 1,
506                        GDK_ACTION_COPY);
507   g_signal_connect (button, "drag-begin",
508                     G_CALLBACK (gtk_color_button_drag_begin), button);
509   g_signal_connect (button, "drag-data-received",
510                     G_CALLBACK (gtk_color_button_drag_data_received), button);
511   g_signal_connect (button, "drag-data-get",
512                     G_CALLBACK (gtk_color_button_drag_data_get), button);
513
514   gtk_widget_pop_composite_child ();
515 }
516
517 static void
518 gtk_color_button_finalize (GObject *object)
519 {
520   GtkColorButton *button = GTK_COLOR_BUTTON (object);
521
522   if (button->priv->cs_dialog != NULL)
523     gtk_widget_destroy (button->priv->cs_dialog);
524   button->priv->cs_dialog = NULL;
525
526   g_free (button->priv->title);
527   button->priv->title = NULL;
528
529   G_OBJECT_CLASS (gtk_color_button_parent_class)->finalize (object);
530 }
531
532
533 /**
534  * gtk_color_button_new:
535  *
536  * Creates a new color button.
537  *
538  * This returns a widget in the form of a small button containing
539  * a swatch representing the current selected color. When the button
540  * is clicked, a color-selection dialog will open, allowing the user
541  * to select a color. The swatch will be updated to reflect the new
542  * color when the user finishes.
543  *
544  * Returns: a new color button
545  *
546  * Since: 2.4
547  */
548 GtkWidget *
549 gtk_color_button_new (void)
550 {
551   return g_object_new (GTK_TYPE_COLOR_BUTTON, NULL);
552 }
553
554 /**
555  * gtk_color_button_new_with_color:
556  * @color: A #GdkColor to set the current color with
557  *
558  * Creates a new color button.
559  *
560  * Returns: a new color button
561  *
562  * Since: 2.4
563  *
564  * Deprecated: 3.4: Use gtk_color_button_new_with_rgba() instead.
565  */
566 GtkWidget *
567 gtk_color_button_new_with_color (const GdkColor *color)
568 {
569   return g_object_new (GTK_TYPE_COLOR_BUTTON, "color", color, NULL);
570 }
571
572 /**
573  * gtk_color_button_new_with_rgba:
574  * @rgba: A #GdkRGBA to set the current color with
575  *
576  * Creates a new color button.
577  *
578  * Returns: a new color button
579  *
580  * Since: 3.0
581  */
582 GtkWidget *
583 gtk_color_button_new_with_rgba (const GdkRGBA *rgba)
584 {
585   return g_object_new (GTK_TYPE_COLOR_BUTTON, "rgba", rgba, NULL);
586 }
587
588 static gboolean
589 dialog_destroy (GtkWidget *widget,
590                 gpointer   data)
591 {
592   GtkColorButton *button = GTK_COLOR_BUTTON (data);
593
594   button->priv->cs_dialog = NULL;
595
596   return FALSE;
597 }
598
599 static void
600 dialog_response (GtkDialog *dialog,
601                  gint       response,
602                  gpointer   data)
603 {
604   if (response == GTK_RESPONSE_CANCEL)
605     gtk_widget_hide (GTK_WIDGET (dialog));
606   else if (response == GTK_RESPONSE_OK)
607     {
608       GtkColorButton *button = GTK_COLOR_BUTTON (data);
609
610       gtk_color_chooser_get_rgba (GTK_COLOR_CHOOSER (dialog),
611                                   &button->priv->rgba);
612
613       gtk_widget_hide (GTK_WIDGET (dialog));
614
615       gtk_widget_queue_draw (button->priv->draw_area);
616
617       g_signal_emit (button, color_button_signals[COLOR_SET], 0);
618
619       g_object_freeze_notify (G_OBJECT (button));
620       g_object_notify (G_OBJECT (button), "color");
621       g_object_notify (G_OBJECT (button), "alpha");
622       g_object_notify (G_OBJECT (button), "rgba");
623       g_object_thaw_notify (G_OBJECT (button));
624     }
625 }
626
627 static void
628 gtk_color_button_clicked (GtkButton *b)
629 {
630   GtkColorButton *button = GTK_COLOR_BUTTON (b);
631   GtkWidget *dialog;
632
633   /* if dialog already exists, make sure it's shown and raised */
634   if (!button->priv->cs_dialog)
635     {
636       /* Create the dialog and connects its buttons */
637       GtkWidget *parent;
638
639       parent = gtk_widget_get_toplevel (GTK_WIDGET (button));
640
641       button->priv->cs_dialog = dialog = gtk_color_chooser_dialog_new (button->priv->title, NULL);
642
643       if (gtk_widget_is_toplevel (parent) && GTK_IS_WINDOW (parent))
644         {
645           if (GTK_WINDOW (parent) != gtk_window_get_transient_for (GTK_WINDOW (dialog)))
646             gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (parent));
647
648           gtk_window_set_modal (GTK_WINDOW (dialog),
649                                 gtk_window_get_modal (GTK_WINDOW (parent)));
650         }
651
652       g_signal_connect (dialog, "response",
653                         G_CALLBACK (dialog_response), button);
654       g_signal_connect (dialog, "destroy",
655                         G_CALLBACK (dialog_destroy), button);
656     }
657
658   gtk_color_chooser_set_use_alpha (GTK_COLOR_CHOOSER (button->priv->cs_dialog),
659                                    button->priv->use_alpha);
660
661   gtk_window_present (GTK_WINDOW (button->priv->cs_dialog));
662 }
663
664 /**
665  * gtk_color_button_set_color:
666  * @button: a #GtkColorButton
667  * @color: A #GdkColor to set the current color with
668  *
669  * Sets the current color to be @color.
670  *
671  * Since: 2.4
672  *
673  * Deprecated: Use gtk_color_chooser_set_rgba() instead.
674  */
675 void
676 gtk_color_button_set_color (GtkColorButton *button,
677                             const GdkColor *color)
678 {
679   g_return_if_fail (GTK_IS_COLOR_BUTTON (button));
680   g_return_if_fail (color != NULL);
681
682   button->priv->rgba.red = color->red / 65535.;
683   button->priv->rgba.green = color->green / 65535.;
684   button->priv->rgba.blue = color->blue / 65535.;
685
686   gtk_widget_queue_draw (button->priv->draw_area);
687
688   g_object_notify (G_OBJECT (button), "color");
689   g_object_notify (G_OBJECT (button), "rgba");
690 }
691
692
693 /**
694  * gtk_color_button_set_alpha:
695  * @button: a #GtkColorButton
696  * @alpha: an integer between 0 and 65535
697  *
698  * Sets the current opacity to be @alpha.
699  *
700  * Since: 2.4
701  *
702  * Deprecated: 3.4: Use gtk_color_chooser_set_rgba() instead.
703  */
704 void
705 gtk_color_button_set_alpha (GtkColorButton *button,
706                             guint16         alpha)
707 {
708   g_return_if_fail (GTK_IS_COLOR_BUTTON (button));
709
710   button->priv->rgba.alpha = alpha / 65535.;
711
712   gtk_widget_queue_draw (button->priv->draw_area);
713
714   g_object_notify (G_OBJECT (button), "alpha");
715   g_object_notify (G_OBJECT (button), "rgba");
716 }
717
718 /**
719  * gtk_color_button_get_color:
720  * @button: a #GtkColorButton
721  * @color: (out): a #GdkColor to fill in with the current color
722  *
723  * Sets @color to be the current color in the #GtkColorButton widget.
724  *
725  * Since: 2.4
726  *
727  * Deprecated: 3.4: Use gtk_color_chooser_get_rgba() instead.
728  */
729 void
730 gtk_color_button_get_color (GtkColorButton *button,
731                             GdkColor       *color)
732 {
733   g_return_if_fail (GTK_IS_COLOR_BUTTON (button));
734
735   color->red = (guint16) (button->priv->rgba.red * 65535);
736   color->green = (guint16) (button->priv->rgba.green * 65535);
737   color->blue = (guint16) (button->priv->rgba.blue * 65535);
738 }
739
740 /**
741  * gtk_color_button_get_alpha:
742  * @button: a #GtkColorButton
743  *
744  * Returns the current alpha value.
745  *
746  * Return value: an integer between 0 and 65535
747  *
748  * Since: 2.4
749  *
750  * Deprecated: 3.4: Use gtk_color_chooser_get_rgba() instead.
751  */
752 guint16
753 gtk_color_button_get_alpha (GtkColorButton *button)
754 {
755   g_return_val_if_fail (GTK_IS_COLOR_BUTTON (button), 0);
756
757   return (guint16) (button->priv->rgba.alpha * 65535);
758 }
759
760 /**
761  * gtk_color_button_set_rgba:
762  * @button: a #GtkColorButton
763  * @rgba: a #GdkRGBA to set the current color with
764  *
765  * Sets the current color to be @rgba.
766  *
767  * Since: 3.0
768  *
769  * Deprecated: 3.4: Use gtk_color_chooser_set_rgba() instead.
770  */
771 void
772 gtk_color_button_set_rgba (GtkColorButton *button,
773                            const GdkRGBA  *rgba)
774 {
775   g_return_if_fail (GTK_IS_COLOR_BUTTON (button));
776   g_return_if_fail (rgba != NULL);
777
778   button->priv->rgba = *rgba;
779   gtk_widget_queue_draw (button->priv->draw_area);
780
781   g_object_notify (G_OBJECT (button), "color");
782   g_object_notify (G_OBJECT (button), "alpha");
783   g_object_notify (G_OBJECT (button), "rgba");
784 }
785
786 /**
787  * gtk_color_button_get_rgba:
788  * @button: a #GtkColorButton
789  * @rgba: (out): a #GdkRGBA to fill in with the current color
790  *
791  * Sets @rgba to be the current color in the #GtkColorButton widget.
792  *
793  * Since: 3.0
794  *
795  * Deprecated: 3.4: Use gtk_color_chooser_get_rgba() instead.
796  */
797 void
798 gtk_color_button_get_rgba (GtkColorButton *button,
799                            GdkRGBA        *rgba)
800 {
801   g_return_if_fail (GTK_IS_COLOR_BUTTON (button));
802   g_return_if_fail (rgba != NULL);
803
804   *rgba = button->priv->rgba;
805 }
806
807 /**
808  * gtk_color_button_set_use_alpha:
809  * @button: a #GtkColorButton
810  * @use_alpha: %TRUE if color button should use alpha channel, %FALSE if not
811  *
812  * Sets whether or not the color button should use the alpha channel.
813  *
814  * Since: 2.4
815  *
816  * Deprecated: 3.4: Use gtk_color_chooser_set_use_alpha() instead.
817  */
818 void
819 gtk_color_button_set_use_alpha (GtkColorButton *button,
820                                 gboolean        use_alpha)
821 {
822   g_return_if_fail (GTK_IS_COLOR_BUTTON (button));
823
824   use_alpha = (use_alpha != FALSE);
825
826   if (button->priv->use_alpha != use_alpha)
827     {
828       button->priv->use_alpha = use_alpha;
829
830       gtk_widget_queue_draw (button->priv->draw_area);
831
832       g_object_notify (G_OBJECT (button), "use-alpha");
833     }
834 }
835
836 /**
837  * gtk_color_button_get_use_alpha:
838  * @button: a #GtkColorButton
839  *
840  * Does the color selection dialog use the alpha channel ?
841  *
842  * Returns: %TRUE if the color sample uses alpha channel, %FALSE if not
843  *
844  * Since: 2.4
845  *
846  * Deprecated: 3.4: Use gtk_color_chooser_get_use_alpha() instead.
847  */
848 gboolean
849 gtk_color_button_get_use_alpha (GtkColorButton *button)
850 {
851   g_return_val_if_fail (GTK_IS_COLOR_BUTTON (button), FALSE);
852
853   return button->priv->use_alpha;
854 }
855
856
857 /**
858  * gtk_color_button_set_title:
859  * @button: a #GtkColorButton
860  * @title: String containing new window title
861  *
862  * Sets the title for the color selection dialog.
863  *
864  * Since: 2.4
865  */
866 void
867 gtk_color_button_set_title (GtkColorButton *button,
868                             const gchar    *title)
869 {
870   gchar *old_title;
871
872   g_return_if_fail (GTK_IS_COLOR_BUTTON (button));
873
874   old_title = button->priv->title;
875   button->priv->title = g_strdup (title);
876   g_free (old_title);
877
878   if (button->priv->cs_dialog)
879     gtk_window_set_title (GTK_WINDOW (button->priv->cs_dialog),
880                           button->priv->title);
881
882   g_object_notify (G_OBJECT (button), "title");
883 }
884
885 /**
886  * gtk_color_button_get_title:
887  * @button: a #GtkColorButton
888  *
889  * Gets the title of the color selection dialog.
890  *
891  * Returns: An internal string, do not free the return value
892  *
893  * Since: 2.4
894  */
895 const gchar *
896 gtk_color_button_get_title (GtkColorButton *button)
897 {
898   g_return_val_if_fail (GTK_IS_COLOR_BUTTON (button), NULL);
899
900   return button->priv->title;
901 }
902
903 static void
904 gtk_color_button_set_property (GObject      *object,
905                                guint         param_id,
906                                const GValue *value,
907                                GParamSpec   *pspec)
908 {
909   GtkColorButton *button = GTK_COLOR_BUTTON (object);
910
911   switch (param_id)
912     {
913     case PROP_USE_ALPHA:
914       gtk_color_button_set_use_alpha (button, g_value_get_boolean (value));
915       break;
916     case PROP_TITLE:
917       gtk_color_button_set_title (button, g_value_get_string (value));
918       break;
919     case PROP_COLOR:
920       {
921         GdkColor *color;
922         GdkRGBA rgba;
923
924         color = g_value_get_boxed (value);
925
926         rgba.red = color->red / 65535.0;
927         rgba.green = color->green / 65535.0;
928         rgba.blue = color->blue / 65535.0;
929         rgba.alpha = 1.0;
930
931         gtk_color_button_set_rgba (button, &rgba);
932       }
933       break;
934     case PROP_ALPHA:
935       gtk_color_button_set_alpha (button, g_value_get_uint (value));
936       break;
937     case PROP_RGBA:
938       gtk_color_button_set_rgba (button, g_value_get_boxed (value));
939       break;
940     default:
941       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
942       break;
943     }
944 }
945
946 static void
947 gtk_color_button_get_property (GObject    *object,
948                                guint       param_id,
949                                GValue     *value,
950                                GParamSpec *pspec)
951 {
952   GtkColorButton *button = GTK_COLOR_BUTTON (object);
953
954   switch (param_id)
955     {
956     case PROP_USE_ALPHA:
957       g_value_set_boolean (value, gtk_color_button_get_use_alpha (button));
958       break;
959     case PROP_TITLE:
960       g_value_set_string (value, gtk_color_button_get_title (button));
961       break;
962     case PROP_COLOR:
963       {
964         GdkColor color;
965         GdkRGBA rgba;
966
967         gtk_color_button_get_rgba (button, &rgba);
968
969         color.red = (guint16) (rgba.red * 65535 + 0.5);
970         color.green = (guint16) (rgba.green * 65535 + 0.5);
971         color.blue = (guint16) (rgba.blue * 65535 + 0.5);
972
973         g_value_set_boxed (value, &color);
974       }
975       break;
976     case PROP_ALPHA:
977       g_value_set_uint (value, gtk_color_button_get_alpha (button));
978       break;
979     case PROP_RGBA:
980       {
981         GdkRGBA rgba;
982
983         gtk_color_button_get_rgba (button, &rgba);
984         g_value_set_boxed (value, &rgba);
985       }
986       break;
987     default:
988       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
989       break;
990     }
991 }
992
993 static void
994 gtk_color_button_add_palette (GtkColorChooser *chooser,
995                               gboolean         horizontal,
996                               gint             colors_per_line,
997                               gint             n_colors,
998                               GdkRGBA         *colors)
999 {
1000   GtkColorButton *button = GTK_COLOR_BUTTON (chooser);
1001
1002   if (button->priv->cs_dialog)
1003     gtk_color_chooser_add_palette (GTK_COLOR_CHOOSER (button->priv->cs_dialog),
1004                                    horizontal, colors_per_line, n_colors, colors);
1005 }
1006
1007 typedef void (* get_rgba) (GtkColorChooser *, GdkRGBA *);
1008 typedef void (* set_rgba) (GtkColorChooser *, const GdkRGBA *);
1009
1010 static void
1011 gtk_color_button_iface_init (GtkColorChooserInterface *iface)
1012 {
1013   iface->get_rgba = (get_rgba)gtk_color_button_get_rgba;
1014   iface->set_rgba = (set_rgba)gtk_color_button_set_rgba;
1015   iface->add_palette = gtk_color_button_add_palette;
1016 }
1017