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