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