]> Pileus Git - ~andy/gtk/blob - gtk/gtkcolorswatch.c
8766ee6b23716f0599ab683d179f591e890addad
[~andy/gtk] / gtk / gtkcolorswatch.c
1 /* GTK - The GIMP Toolkit
2  * Copyright (C) 2012 Red Hat, Inc.
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 #include "config.h"
21
22 #include "gtkcolorswatchprivate.h"
23
24 #include "gtkroundedboxprivate.h"
25 #include "gtkthemingbackgroundprivate.h"
26 #include "gtkdnd.h"
27 #include "gtkicontheme.h"
28 #include "gtkmain.h"
29 #include "gtkmenu.h"
30 #include "gtkmenuitem.h"
31 #include "gtkmenushell.h"
32 #include "gtkprivate.h"
33 #include "gtkintl.h"
34
35
36 struct _GtkColorSwatchPrivate
37 {
38   GdkRGBA color;
39   gdouble radius[4];
40   gchar *icon;
41   guint    selected         : 1;
42   guint    has_color        : 1;
43   guint    contains_pointer : 1;
44   guint    use_alpha        : 1;
45 };
46
47 enum
48 {
49   PROP_ZERO,
50   PROP_RGBA,
51   PROP_SELECTED
52 };
53
54 enum
55 {
56   ACTIVATE,
57   CUSTOMIZE,
58   LAST_SIGNAL
59 };
60
61 static guint signals[LAST_SIGNAL];
62
63 G_DEFINE_TYPE (GtkColorSwatch, gtk_color_swatch, GTK_TYPE_DRAWING_AREA)
64
65 static void
66 gtk_color_swatch_init (GtkColorSwatch *swatch)
67 {
68   swatch->priv = G_TYPE_INSTANCE_GET_PRIVATE (swatch,
69                                               GTK_TYPE_COLOR_SWATCH,
70                                               GtkColorSwatchPrivate);
71
72   gtk_widget_set_can_focus (GTK_WIDGET (swatch), TRUE);
73   gtk_widget_set_events (GTK_WIDGET (swatch), GDK_BUTTON_PRESS_MASK
74                                               | GDK_BUTTON_RELEASE_MASK
75                                               | GDK_EXPOSURE_MASK
76                                               | GDK_ENTER_NOTIFY_MASK
77                                               | GDK_LEAVE_NOTIFY_MASK);
78   swatch->priv->use_alpha = TRUE;
79 }
80
81 #define INTENSITY(r, g, b) ((r) * 0.30 + (g) * 0.59 + (b) * 0.11)
82
83 static cairo_pattern_t *
84 get_checkered_pattern (void)
85 {
86   /* need to respect pixman's stride being a multiple of 4 */
87   static unsigned char data[8] = { 0xFF, 0x00, 0x00, 0x00,
88                                    0x00, 0xFF, 0x00, 0x00 };
89   static cairo_surface_t *checkered = NULL;
90   cairo_pattern_t *pattern;
91
92   if (checkered == NULL)
93     checkered = cairo_image_surface_create_for_data (data,
94                                                      CAIRO_FORMAT_A8,
95                                                      2, 2, 4);
96
97   pattern = cairo_pattern_create_for_surface (checkered);
98   cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REPEAT);
99   cairo_pattern_set_filter (pattern, CAIRO_FILTER_NEAREST);
100
101   return pattern;
102 }
103
104 static gboolean
105 swatch_draw (GtkWidget *widget,
106              cairo_t   *cr)
107 {
108   GtkColorSwatch *swatch = (GtkColorSwatch*)widget;
109   GtkThemingBackground background;
110   gdouble width, height;
111   GtkStyleContext *context;
112   GtkStateFlags state;
113   GtkIconTheme *theme;
114   GtkIconInfo *icon_info = NULL;
115
116   theme = gtk_icon_theme_get_default ();
117   context = gtk_widget_get_style_context (widget);
118   state = gtk_widget_get_state_flags (widget);
119   width = gtk_widget_get_allocated_width (widget);
120   height = gtk_widget_get_allocated_height (widget);
121
122   cairo_save (cr);
123
124   gtk_style_context_save (context);
125   gtk_style_context_set_state (context, state);
126
127   _gtk_theming_background_init_from_context (&background, context,
128                                              0, 0, width, height,
129                                              GTK_JUNCTION_NONE);
130
131   if (swatch->priv->has_color)
132     {
133       cairo_pattern_t *pattern;
134       cairo_matrix_t matrix;
135
136       if (swatch->priv->use_alpha)
137         {
138           cairo_save (cr);
139
140           _gtk_rounded_box_path (&background.clip_box, cr);
141           cairo_clip_preserve (cr);
142
143           cairo_set_source_rgb (cr, 0.33, 0.33, 0.33);
144           cairo_fill_preserve (cr);
145
146           pattern = get_checkered_pattern ();
147           cairo_matrix_init_scale (&matrix, 0.125, 0.125);
148           cairo_pattern_set_matrix (pattern, &matrix);
149
150           cairo_set_source_rgb (cr, 0.66, 0.66, 0.66);
151           cairo_mask (cr, pattern);
152           cairo_pattern_destroy (pattern);
153
154           cairo_restore (cr);
155
156           background.bg_color = swatch->priv->color;
157         }
158       else
159         {
160           background.bg_color = swatch->priv->color;
161           background.bg_color.alpha = 1.0;
162         }
163
164       _gtk_theming_background_render (&background, cr);
165     }
166
167   gtk_render_frame (context, cr,
168                     0, 0, width, height);
169
170   if (gtk_widget_has_visible_focus (widget))
171     {
172       cairo_set_line_width (cr, 2);
173       if (swatch->priv->has_color && INTENSITY (swatch->priv->color.red, swatch->priv->color.green, swatch->priv->color.blue) < 0.5)
174         cairo_set_source_rgba (cr, 1., 1., 1., 0.4);
175       else
176         cairo_set_source_rgba (cr, 0., 0., 0., 0.4);
177       _gtk_rounded_box_shrink (&background.clip_box, 3, 3, 3, 3);
178       _gtk_rounded_box_path (&background.clip_box, cr);
179       cairo_stroke (cr);
180     }
181
182   if (swatch->priv->icon)
183     {
184       icon_info = gtk_icon_theme_lookup_icon (theme, swatch->priv->icon, 16,
185                                               GTK_ICON_LOOKUP_GENERIC_FALLBACK
186                                               | GTK_ICON_LOOKUP_USE_BUILTIN);
187     }
188   else if (swatch->priv->selected)
189     {
190       GdkRGBA bg, border;
191       GtkBorder border_width;
192       GIcon *gicon;
193
194       gtk_style_context_add_class (context, "color-active-badge");
195       gtk_style_context_get_background_color (context, state, &bg);
196       gtk_style_context_get_border_color (context, state, &border);
197       gtk_style_context_get_border (context, state, &border_width);
198
199       cairo_new_sub_path (cr);
200       cairo_arc (cr, width / 2, height / 2, 10, 0, 2 * G_PI);
201       cairo_close_path (cr);
202       gdk_cairo_set_source_rgba (cr, &bg);
203       cairo_fill_preserve (cr);
204
205       gdk_cairo_set_source_rgba (cr, &border);
206       cairo_set_line_width (cr, border_width.left);
207       cairo_stroke (cr);
208
209       gicon = g_themed_icon_new ("object-select-symbolic");
210       /* fallback for themes that don't have object-select-symbolic */
211       g_themed_icon_append_name (G_THEMED_ICON (gicon), "gtk-apply");
212
213       icon_info = gtk_icon_theme_lookup_by_gicon (theme, gicon, 16,
214                                                   GTK_ICON_LOOKUP_GENERIC_FALLBACK
215                                                   | GTK_ICON_LOOKUP_USE_BUILTIN);
216       g_object_unref (gicon);
217     }
218
219   if (icon_info != NULL)
220     {
221       GdkPixbuf *pixbuf;
222
223       pixbuf = gtk_icon_info_load_symbolic_for_context (icon_info, context,
224                                                         NULL, NULL);
225
226       if (pixbuf != NULL)
227         {
228           gtk_render_icon (context, cr, pixbuf,
229                            (width - gdk_pixbuf_get_width (pixbuf)) / 2,
230                            (height - gdk_pixbuf_get_height (pixbuf)) / 2);
231           g_object_unref (pixbuf);
232         }
233
234       gtk_icon_info_free (icon_info);
235     }
236
237   cairo_restore (cr);
238   gtk_style_context_restore (context);
239
240   return FALSE;
241 }
242
243 static void
244 drag_set_color_icon (GdkDragContext *context,
245                      const GdkRGBA  *color)
246 {
247   cairo_surface_t *surface;
248   cairo_t *cr;
249
250   surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24, 48, 32);
251   cr = cairo_create (surface);
252   gdk_cairo_set_source_rgba (cr, color);
253   cairo_paint (cr);
254
255   cairo_surface_set_device_offset (surface, -4, -4);
256   gtk_drag_set_icon_surface (context, surface);
257
258   cairo_destroy (cr);
259   cairo_surface_destroy (surface);
260 }
261
262 static void
263 swatch_drag_begin (GtkWidget      *widget,
264                    GdkDragContext *context)
265 {
266   GtkColorSwatch *swatch = GTK_COLOR_SWATCH (widget);
267   GdkRGBA color;
268
269   gtk_color_swatch_get_rgba (swatch, &color);
270   drag_set_color_icon (context, &color);
271 }
272
273 static void
274 swatch_drag_data_get (GtkWidget        *widget,
275                       GdkDragContext   *context,
276                       GtkSelectionData *selection_data,
277                       guint             info,
278                       guint             time)
279 {
280   GtkColorSwatch *swatch = GTK_COLOR_SWATCH (widget);
281   guint16 vals[4];
282   GdkRGBA color;
283
284   gtk_color_swatch_get_rgba (swatch, &color);
285
286   vals[0] = color.red * 0xffff;
287   vals[1] = color.green * 0xffff;
288   vals[2] = color.blue * 0xffff;
289   vals[3] = color.alpha * 0xffff;
290
291   gtk_selection_data_set (selection_data,
292                           gdk_atom_intern_static_string ("application/x-color"),
293                           16, (guchar *)vals, 8);
294 }
295
296 static void
297 swatch_drag_data_received (GtkWidget        *widget,
298                            GdkDragContext   *context,
299                            gint              x,
300                            gint              y,
301                            GtkSelectionData *selection_data,
302                            guint             info,
303                            guint             time)
304 {
305   gint length;
306   guint16 *vals;
307   GdkRGBA color;
308
309   length = gtk_selection_data_get_length (selection_data);
310
311   if (length < 0)
312     return;
313
314   /* We accept drops with the wrong format, since the KDE color
315    * chooser incorrectly drops application/x-color with format 8.
316    */
317   if (length != 8)
318     {
319       g_warning ("Received invalid color data\n");
320       return;
321     }
322
323   vals = (guint16 *) gtk_selection_data_get_data (selection_data);
324
325   color.red   = (gdouble)vals[0] / 0xffff;
326   color.green = (gdouble)vals[1] / 0xffff;
327   color.blue  = (gdouble)vals[2] / 0xffff;
328   color.alpha = (gdouble)vals[3] / 0xffff;
329
330   gtk_color_swatch_set_rgba (GTK_COLOR_SWATCH (widget), &color);
331 }
332
333 static void
334 swatch_get_preferred_width (GtkWidget *widget,
335                             gint      *min,
336                             gint      *nat)
337 {
338   *min = *nat = 48;
339 }
340
341 static void
342 swatch_get_preferred_height (GtkWidget *widget,
343                              gint      *min,
344                              gint      *nat)
345 {
346   *min = *nat = 32;
347 }
348
349 static gboolean
350 swatch_key_press (GtkWidget   *widget,
351                   GdkEventKey *event)
352 {
353   GtkColorSwatch *swatch = GTK_COLOR_SWATCH (widget);
354
355   if (event->keyval == GDK_KEY_space ||
356       event->keyval == GDK_KEY_Return ||
357       event->keyval == GDK_KEY_ISO_Enter||
358       event->keyval == GDK_KEY_KP_Enter ||
359       event->keyval == GDK_KEY_KP_Space)
360     {
361       if (swatch->priv->has_color && !swatch->priv->selected)
362         gtk_color_swatch_set_selected (swatch, TRUE);
363       else
364         g_signal_emit (swatch, signals[ACTIVATE], 0);
365       return TRUE;
366     }
367
368   if (GTK_WIDGET_CLASS (gtk_color_swatch_parent_class)->key_press_event (widget, event))
369     return TRUE;
370
371   return FALSE;
372 }
373
374 static gboolean
375 swatch_enter_notify (GtkWidget        *widget,
376                      GdkEventCrossing *event)
377 {
378   GtkColorSwatch *swatch = GTK_COLOR_SWATCH (widget);
379   swatch->priv->contains_pointer = TRUE;
380   return FALSE;
381 }
382
383 static gboolean
384 swatch_leave_notify (GtkWidget        *widget,
385                      GdkEventCrossing *event)
386 {
387   GtkColorSwatch *swatch = GTK_COLOR_SWATCH (widget);
388   swatch->priv->contains_pointer = FALSE;
389   return FALSE;
390 }
391
392 static void
393 emit_customize (GtkColorSwatch *swatch)
394 {
395   g_signal_emit (swatch, signals[CUSTOMIZE], 0);
396 }
397
398 static void
399 popup_position_func (GtkMenu   *menu,
400                      gint      *x,
401                      gint      *y,
402                      gboolean  *push_in,
403                      gpointer   user_data)
404 {
405   GtkWidget *widget;
406   GtkRequisition req;
407   gint root_x, root_y;
408   GdkScreen *screen;
409   GdkWindow *window;
410   GdkRectangle monitor;
411   gint monitor_num;
412
413   widget = GTK_WIDGET (user_data);
414   g_return_if_fail (gtk_widget_get_realized (widget));
415   window = gtk_widget_get_window (widget);
416
417   screen = gtk_widget_get_screen (widget);
418   monitor_num = gdk_screen_get_monitor_at_window (screen, window);
419   if (monitor_num < 0)
420     monitor_num = 0;
421   gtk_menu_set_monitor (menu, monitor_num);
422
423   gdk_window_get_origin (window, &root_x, &root_y);
424   gtk_widget_get_preferred_size (GTK_WIDGET (menu), &req, NULL);
425
426   /* Put corner of menu centered on swatch */
427   *x = root_x + gtk_widget_get_allocated_width (widget) / 2;
428   *y = root_y + gtk_widget_get_allocated_height (widget) / 2;
429
430   /* Ensure sanity */
431   gdk_screen_get_monitor_workarea (screen, monitor_num, &monitor);
432   *x = CLAMP (*x, monitor.x, MAX (monitor.x, monitor.width - req.width));
433   *y = CLAMP (*y, monitor.y, MAX (monitor.y, monitor.height - req.height));
434 }
435
436 static void
437 do_popup (GtkWidget      *swatch,
438           GdkEventButton *event)
439 {
440   GtkWidget *menu;
441   GtkWidget *item;
442
443   menu = gtk_menu_new ();
444   item = gtk_menu_item_new_with_mnemonic (_("_Customize"));
445   gtk_menu_attach_to_widget (GTK_MENU (menu), swatch, NULL);
446
447   g_signal_connect_swapped (item, "activate",
448                             G_CALLBACK (emit_customize), swatch);
449
450   gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
451
452   gtk_widget_show_all (item);
453
454   if (event)
455     gtk_menu_popup (GTK_MENU (menu), NULL, NULL,
456                     NULL, NULL, event->button, event->time);
457   else
458     gtk_menu_popup (GTK_MENU (menu), NULL, NULL,
459                     popup_position_func, swatch,
460                     0, gtk_get_current_event_time ());
461 }
462
463 static gboolean
464 swatch_button_press (GtkWidget      *widget,
465                      GdkEventButton *event)
466 {
467   GtkColorSwatch *swatch = GTK_COLOR_SWATCH (widget);
468
469   gtk_widget_grab_focus (widget);
470
471   if (gdk_event_triggers_context_menu ((GdkEvent *) event) &&
472       swatch->priv->has_color)
473     {
474       do_popup (widget, event);
475       return TRUE;
476     }
477   else if (event->type == GDK_2BUTTON_PRESS &&
478            event->button == GDK_BUTTON_PRIMARY)
479     {
480       g_signal_emit (swatch, signals[ACTIVATE], 0);
481       return TRUE;
482     }
483
484   return FALSE;
485 }
486
487 static gboolean
488 swatch_button_release (GtkWidget      *widget,
489                        GdkEventButton *event)
490 {
491   GtkColorSwatch *swatch = GTK_COLOR_SWATCH (widget);
492
493   if (event->button == GDK_BUTTON_PRIMARY &&
494       swatch->priv->contains_pointer)
495     {
496       if (!swatch->priv->has_color)
497         {
498           g_signal_emit (swatch, signals[ACTIVATE], 0);
499           return TRUE;
500         }
501       else if (!swatch->priv->selected)
502         {
503           gtk_color_swatch_set_selected (swatch, TRUE);
504           return TRUE;
505         }
506     }
507
508   return FALSE;
509 }
510
511 static gboolean
512 swatch_popup_menu (GtkWidget *swatch)
513 {
514   do_popup (swatch, NULL);
515   return TRUE;
516 }
517
518 /* GObject implementation {{{1 */
519
520 static void
521 swatch_get_property (GObject    *object,
522                      guint       prop_id,
523                      GValue     *value,
524                      GParamSpec *pspec)
525 {
526   GtkColorSwatch *swatch = GTK_COLOR_SWATCH (object);
527   GdkRGBA color;
528
529   switch (prop_id)
530     {
531     case PROP_RGBA:
532       gtk_color_swatch_get_rgba (swatch, &color);
533       g_value_set_boxed (value, &color);
534       break;
535     case PROP_SELECTED:
536       g_value_set_boolean (value, swatch->priv->selected);
537       break;
538     default:
539       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
540       break;
541     }
542 }
543
544 static void
545 swatch_set_property (GObject      *object,
546                      guint         prop_id,
547                      const GValue *value,
548                      GParamSpec   *pspec)
549 {
550   GtkColorSwatch *swatch = GTK_COLOR_SWATCH (object);
551
552   switch (prop_id)
553     {
554     case PROP_RGBA:
555       gtk_color_swatch_set_rgba (swatch, g_value_get_boxed (value));
556       break;
557     case PROP_SELECTED:
558       gtk_color_swatch_set_selected (swatch, g_value_get_boolean (value));
559       break;
560     default:
561       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
562       break;
563     }
564 }
565
566 static void
567 swatch_finalize (GObject *object)
568 {
569   GtkColorSwatch *swatch = GTK_COLOR_SWATCH (object);
570
571   g_free (swatch->priv->icon);
572
573   G_OBJECT_CLASS (gtk_color_swatch_parent_class)->finalize (object);
574 }
575
576 static void
577 gtk_color_swatch_class_init (GtkColorSwatchClass *class)
578 {
579   GtkWidgetClass *widget_class = (GtkWidgetClass *)class;
580   GObjectClass *object_class = (GObjectClass *)class;
581
582   object_class->get_property = swatch_get_property;
583   object_class->set_property = swatch_set_property;
584   object_class->finalize = swatch_finalize;
585
586   widget_class->get_preferred_width = swatch_get_preferred_width;
587   widget_class->get_preferred_height = swatch_get_preferred_height;
588   widget_class->draw = swatch_draw;
589   widget_class->drag_begin = swatch_drag_begin;
590   widget_class->drag_data_get = swatch_drag_data_get;
591   widget_class->drag_data_received = swatch_drag_data_received;
592   widget_class->key_press_event = swatch_key_press;
593   widget_class->popup_menu = swatch_popup_menu;
594   widget_class->button_press_event = swatch_button_press;
595   widget_class->button_release_event = swatch_button_release;
596   widget_class->enter_notify_event = swatch_enter_notify;
597   widget_class->leave_notify_event = swatch_leave_notify;
598
599   signals[ACTIVATE] =
600     g_signal_new ("activate",
601                   GTK_TYPE_COLOR_SWATCH,
602                   G_SIGNAL_RUN_FIRST,
603                   G_STRUCT_OFFSET (GtkColorSwatchClass, activate),
604                   NULL, NULL, NULL, G_TYPE_NONE, 0);
605
606   signals[CUSTOMIZE] =
607     g_signal_new ("customize",
608                   GTK_TYPE_COLOR_SWATCH,
609                   G_SIGNAL_RUN_FIRST,
610                   G_STRUCT_OFFSET (GtkColorSwatchClass, customize),
611                   NULL, NULL, NULL, G_TYPE_NONE, 0);
612
613   g_object_class_install_property (object_class, PROP_RGBA,
614       g_param_spec_boxed ("rgba", P_("RGBA Color"), P_("Color as RGBA"),
615                           GDK_TYPE_RGBA, GTK_PARAM_READWRITE));
616
617   g_object_class_install_property (object_class, PROP_SELECTED,
618       g_param_spec_boolean ("selected", P_("Selected"), P_("Selected"),
619                             FALSE, GTK_PARAM_READWRITE));
620
621   g_type_class_add_private (object_class, sizeof (GtkColorSwatchPrivate));
622 }
623
624 /* Public API {{{1 */
625
626 GtkWidget *
627 gtk_color_swatch_new (void)
628 {
629   return (GtkWidget *) g_object_new (GTK_TYPE_COLOR_SWATCH, NULL);
630 }
631
632 static const GtkTargetEntry dnd_targets[] = {
633   { "application/x-color", 0 }
634 };
635
636 void
637 gtk_color_swatch_set_rgba (GtkColorSwatch *swatch,
638                            const GdkRGBA  *color)
639 {
640   GtkStyleContext *context;
641
642   context = gtk_widget_get_style_context (GTK_WIDGET (swatch));
643
644   if (!swatch->priv->has_color)
645     {
646       gtk_drag_source_set (GTK_WIDGET (swatch),
647                            GDK_BUTTON1_MASK | GDK_BUTTON3_MASK,
648                            dnd_targets, G_N_ELEMENTS (dnd_targets),
649                            GDK_ACTION_COPY | GDK_ACTION_MOVE);
650     }
651   else
652     {
653       gtk_style_context_remove_class (context, "color-light");
654       gtk_style_context_remove_class (context, "color-dark");
655     }
656
657   swatch->priv->has_color = TRUE;
658   swatch->priv->color = *color;
659
660   if (INTENSITY (swatch->priv->color.red, swatch->priv->color.green, swatch->priv->color.blue) > 0.5)
661     gtk_style_context_add_class (context, "color-light");
662   else
663     gtk_style_context_add_class (context, "color-dark");
664
665   gtk_widget_queue_draw (GTK_WIDGET (swatch));
666   g_object_notify (G_OBJECT (swatch), "rgba");
667 }
668
669 gboolean
670 gtk_color_swatch_get_rgba (GtkColorSwatch *swatch,
671                            GdkRGBA        *color)
672 {
673   if (swatch->priv->has_color)
674     {
675       color->red = swatch->priv->color.red;
676       color->green = swatch->priv->color.green;
677       color->blue = swatch->priv->color.blue;
678       color->alpha = swatch->priv->color.alpha;
679       return TRUE;
680     }
681   else
682     {
683       color->red = 1.0;
684       color->green = 1.0;
685       color->blue = 1.0;
686       color->alpha = 1.0;
687       return FALSE;
688     }
689 }
690
691 void
692 gtk_color_swatch_set_selected (GtkColorSwatch *swatch,
693                                gboolean        selected)
694 {
695   if (swatch->priv->selected != selected)
696     {
697       swatch->priv->selected = selected;
698       gtk_widget_queue_draw (GTK_WIDGET (swatch));
699       g_object_notify (G_OBJECT (swatch), "selected");
700     }
701 }
702
703 void
704 gtk_color_swatch_set_icon (GtkColorSwatch *swatch,
705                            const gchar    *icon)
706 {
707   swatch->priv->icon = g_strdup (icon);
708   gtk_widget_queue_draw (GTK_WIDGET (swatch));
709 }
710
711 void
712 gtk_color_swatch_set_can_drop (GtkColorSwatch *swatch,
713                                gboolean        can_drop)
714 {
715   if (can_drop)
716     {
717       gtk_drag_dest_set (GTK_WIDGET (swatch),
718                          GTK_DEST_DEFAULT_HIGHLIGHT |
719                          GTK_DEST_DEFAULT_MOTION |
720                          GTK_DEST_DEFAULT_DROP,
721                          dnd_targets, G_N_ELEMENTS (dnd_targets),
722                          GDK_ACTION_COPY);
723     }
724   else
725     {
726       gtk_drag_dest_unset (GTK_WIDGET (swatch));
727     }
728 }
729
730 void
731 gtk_color_swatch_set_use_alpha (GtkColorSwatch *swatch,
732                                 gboolean        use_alpha)
733 {
734   swatch->priv->use_alpha = use_alpha;
735   gtk_widget_queue_draw (GTK_WIDGET (swatch));
736 }
737
738 /* vim:set foldmethod=marker: */