]> Pileus Git - ~andy/gtk/blob - gtk/gtkcolorsel.c
Add gdk_rgb_find_color() to get a pixel value using GdkRGB functionality
[~andy/gtk] / gtk / gtkcolorsel.c
1 /* GTK - The GIMP Toolkit
2  * Copyright (C) 2000 Red Hat, Inc.
3  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18  * Boston, MA 02111-1307, USA.
19  */
20
21 /*
22  * Modified by the GTK+ Team and others 1997-1999.  See the AUTHORS
23  * file for a list of people on the GTK+ Team.  See the ChangeLog
24  * files for a list of changes.  These files are distributed with
25  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
26  */
27
28 #include "gdkconfig.h"
29
30 #if defined (GDK_WINDOWING_X11)
31 #include "x11/gdkx.h"
32 #endif
33 #include "gdk/gdkkeysyms.h"
34 #include "gtkcolorsel.h"
35 #include "gtkhsv.h"
36 #include "gtkwindow.h"
37 #include "gtkselection.h"
38 #include "gtkdnd.h"
39 #include "gtkdrawingarea.h"
40 #include "gtksignal.h"
41 #include "gtkhbox.h"
42 #include "gtkhbbox.h"
43 #include "gtkrc.h"
44 #include "gtkframe.h"
45 #include "gtktable.h"
46 #include "gtklabel.h"
47 #include "gtkpixmap.h"
48 #include "gtkspinbutton.h"
49 #include "gtkrange.h"
50 #include "gtkhscale.h"
51 #include "gtkentry.h"
52 #include "gtkbutton.h"
53 #include "gtkhseparator.h"
54 #include "gtkintl.h"
55
56 enum {
57   COLOR_CHANGED,
58   LAST_SIGNAL
59 };
60
61
62
63 enum {
64   COLORSEL_RED = 0,
65   COLORSEL_GREEN = 1,
66   COLORSEL_BLUE = 2,
67   COLORSEL_OPACITY = 3,
68   COLORSEL_HUE,
69   COLORSEL_SATURATION,
70   COLORSEL_VALUE,
71   COLORSEL_NUM_CHANNELS
72 };
73
74 typedef struct _ColorSelectionPrivate ColorSelectionPrivate;
75
76 struct _ColorSelectionPrivate
77 {
78   guint use_opacity : 1;
79   guint use_palette : 1;
80   guint changing : 1;
81   guint default_set : 1;
82   
83   /* The color dropper */
84   guint moving_dropper : 1;
85   
86   gdouble color[COLORSEL_NUM_CHANNELS];
87   gdouble old_color[COLORSEL_NUM_CHANNELS];
88   
89   GtkWidget *triangle_colorsel;
90   GtkWidget *hue_spinbutton;
91   GtkWidget *sat_spinbutton;
92   GtkWidget *val_spinbutton;
93   GtkWidget *red_spinbutton;
94   GtkWidget *green_spinbutton;
95   GtkWidget *blue_spinbutton;
96   GtkWidget *opacity_slider;
97   GtkWidget *opacity_label;
98   GtkWidget *opacity_entry;
99   GtkWidget *palette_frame;
100   GtkWidget *hex_entry;
101   
102   /* The Palette code */
103   GtkWidget *custom_palette [GTK_CUSTOM_PALETTE_WIDTH][GTK_CUSTOM_PALETTE_HEIGHT];
104   GtkWidget *last_palette;
105   
106   /* The color_sample stuff */
107   GtkWidget *sample_area;
108   GtkWidget *old_sample;
109   GtkWidget *cur_sample;
110   GtkWidget *colorsel;
111 };
112
113
114 static void gtk_color_selection_init            (GtkColorSelection       *colorsel);
115 static void gtk_color_selection_class_init      (GtkColorSelectionClass  *klass);
116 static void gtk_color_selection_destroy         (GtkObject               *object);
117 static void update_color                        (GtkColorSelection       *colorsel);
118
119 static gpointer parent_class = NULL;
120 static guint color_selection_signals[LAST_SIGNAL] = { 0 };
121
122
123 /* The cursor for the dropper */
124 #define DROPPER_WIDTH 17
125 #define DROPPER_HEIGHT 17
126 #define DROPPER_X_HOT 2
127 #define DROPPER_Y_HOT 16
128
129
130 static char dropper_bits[] = {
131   0xff, 0x8f, 0x01, 0xff, 0x77, 0x01, 0xff, 0xfb, 0x00, 0xff, 0xf8, 0x00,
132   0x7f, 0xff, 0x00, 0xff, 0x7e, 0x01, 0xff, 0x9d, 0x01, 0xff, 0xd8, 0x01,
133   0x7f, 0xd4, 0x01, 0x3f, 0xee, 0x01, 0x1f, 0xff, 0x01, 0x8f, 0xff, 0x01,
134   0xc7, 0xff, 0x01, 0xe3, 0xff, 0x01, 0xf3, 0xff, 0x01, 0xfd, 0xff, 0x01,
135   0xff, 0xff, 0x01, };
136
137 static char dropper_mask[] = {
138   0x00, 0x70, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xfc, 0x01, 0x00, 0xff, 0x01,
139   0x80, 0xff, 0x01, 0x00, 0xff, 0x00, 0x00, 0x7f, 0x00, 0x80, 0x3f, 0x00,
140   0xc0, 0x3f, 0x00, 0xe0, 0x13, 0x00, 0xf0, 0x01, 0x00, 0xf8, 0x00, 0x00,
141   0x7c, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x0d, 0x00, 0x00,
142   0x02, 0x00, 0x00, };
143
144 static GdkCursor *picker_cursor = NULL;
145
146
147 /* XPM */
148 static char *picker[] = {
149   /* columns rows colors chars-per-pixel */
150   "25 25 8 1",
151   "  c Gray0",
152   ". c #020202",
153   "X c Gray12",
154   "o c Gray13",
155   "O c Gray52",
156   "+ c #929292",
157   "@ c Gray100",
158   "# c None",
159   /* pixels */
160   "#########################",
161   "#########################",
162   "#########################",
163   "#########################",
164   "#########################",
165   "#################   #####",
166   "################     ####",
167   "################     +###",
168   "#############        +###",
169   "##############      ++###",
170   "#############+@   +++####",
171   "############+@@@  +######",
172   "###########+@@@ + +######",
173   "##########+@@@ ++#+######",
174   "#########+@@@ ++#########",
175   "########+@@@ ++##########",
176   "#######+@@@ ++###########",
177   "######+@@@ ++############",
178   "######+@@ ++#############",
179   "#####+@  ++##############",
180   "###### +++###############",
181   "#########################",
182   "#########################",
183   "#########################",
184   "#########################"
185 };
186
187
188 /*
189  *
190  * The Sample Color
191  *
192  */
193 #define SAMPLE_WIDTH  64
194 #define SAMPLE_HEIGHT 28
195
196 static void color_sample_draw_sample (GtkColorSelection *colorsel, int which);
197 static void color_sample_draw_samples (GtkColorSelection *colorsel);
198
199 static void
200 color_sample_drag_begin (GtkWidget      *widget,
201                          GdkDragContext *context,
202                          gpointer        data)
203 {
204   GtkColorSelection *colorsel = data;
205   ColorSelectionPrivate *priv;
206   GtkWidget *window;
207   gdouble colors[4];
208   gdouble *colsrc;
209   GdkColor bg;
210   gint n, i;
211   
212   priv = colorsel->private_data;
213   window = gtk_window_new (GTK_WINDOW_POPUP);
214   gtk_widget_set_app_paintable (GTK_WIDGET (window), TRUE);
215   gtk_widget_set_usize (window, 48, 32);
216   gtk_widget_realize (window);
217   gtk_object_set_data_full (GTK_OBJECT (widget),
218                             "gtk-color-selection-drag-window",
219                             window,
220                             (GtkDestroyNotify) gtk_widget_destroy);
221   
222   if (widget == priv->old_sample)
223     colsrc = priv->old_color;
224   else
225     colsrc = priv->color;
226   
227   for (i=0, n = COLORSEL_RED; n <= COLORSEL_BLUE; n++)
228     {
229       colors[i++] = colsrc[n];
230     }
231   
232   if (priv->use_opacity)
233     {
234       colors[i] = colsrc[COLORSEL_OPACITY];
235     }
236   
237   bg.red = 0xffff * colors[0];
238   bg.green = 0xffff * colors[1];
239   bg.blue = 0xffff * colors[2];
240   
241   gdk_color_alloc (gtk_widget_get_colormap (window), &bg);
242   gdk_window_set_background (window->window, &bg);
243   
244   gtk_drag_set_icon_widget (context, window, -2, -2);
245 }
246
247 static void
248 color_sample_drag_end (GtkWidget      *widget,
249                        GdkDragContext *context,
250                        gpointer        data)
251 {
252   gtk_object_set_data (GTK_OBJECT (widget), "gtk-color-selection-drag-window", NULL);
253 }
254
255 static void
256 color_sample_drop_handle (GtkWidget        *widget,
257                           GdkDragContext   *context,
258                           gint              x,
259                           gint              y,
260                           GtkSelectionData *selection_data,
261                           guint             info,
262                           guint             time,
263                           gpointer          data)
264 {
265   GtkColorSelection *colorsel = data;
266   ColorSelectionPrivate *priv;
267   guint16 *vals;
268   gdouble color[4];
269   priv = colorsel->private_data;
270   
271   /* This is currently a guint16 array of the format:
272    * R
273    * G
274    * B
275    * opacity
276    */
277   
278   if (selection_data->length < 0)
279     return;
280   
281   if ((selection_data->format != 16) ||
282       (selection_data->length != 8))
283     {
284       g_warning ("Received invalid color data\n");
285       return;
286     }
287   
288   vals = (guint16 *)selection_data->data;
289   
290   if (widget == priv->cur_sample)
291     {
292       color[0] = (gdouble)vals[0] / 0xffff;
293       color[1] = (gdouble)vals[1] / 0xffff;
294       color[2] = (gdouble)vals[2] / 0xffff;
295       color[3] = (gdouble)vals[3] / 0xffff;
296       
297       gtk_color_selection_set_color (colorsel, color);
298     }
299 }
300
301 static void
302 color_sample_drag_handle (GtkWidget        *widget,
303                           GdkDragContext   *context,
304                           GtkSelectionData *selection_data,
305                           guint             info,
306                           guint             time,
307                           gpointer          data)
308 {
309   GtkColorSelection *colorsel = data;
310   ColorSelectionPrivate *priv;
311   guint16 vals[4];
312   gdouble *colsrc;
313   
314   priv = colorsel->private_data;
315   
316   if (widget == priv->old_sample)
317     colsrc = priv->old_color;
318   else
319     colsrc = priv->color;
320   
321   vals[0] = colsrc[COLORSEL_RED] * 0xffff;
322   vals[1] = colsrc[COLORSEL_GREEN] * 0xffff;
323   vals[2] = colsrc[COLORSEL_BLUE] * 0xffff;
324   vals[3] = priv->use_opacity ? colsrc[COLORSEL_OPACITY] * 0xffff : 0xffff;
325   
326   gtk_selection_data_set (selection_data,
327                           gdk_atom_intern ("application/x-color", FALSE),
328                           16, (guchar *)vals, 8);
329 }
330
331 /* which = 0 means draw old sample, which = 1 means draw new */
332 static void
333 color_sample_draw_sample (GtkColorSelection *colorsel, int which)
334 {
335   GtkWidget *da;
336   gint x, y, i, wid, heig, f, n, goff;
337   guchar c[3 * 2], cc[3 * 4], *cp = c;
338   gdouble o;
339   guchar *buf;
340   ColorSelectionPrivate *priv;
341   
342   g_return_if_fail (colorsel != NULL);
343   priv = colorsel->private_data;
344   
345   g_return_if_fail (priv->sample_area != NULL);
346   if (!GTK_WIDGET_DRAWABLE (priv->sample_area))
347     return;
348   
349   if (which == 0)
350     {
351       da = priv->old_sample;
352       for (n = 0, i = COLORSEL_RED; n < 3; n++, i++)
353         c[n] = (guchar) (255.0 * priv->old_color[i]);
354       goff = 0;
355     }
356   else
357     {
358       da = priv->cur_sample;
359       for (n = 0, i = COLORSEL_RED; n < 3; n++, i++)
360         c[n] = (guchar) (255.0 * priv->color[i]);
361       goff =  priv->old_sample->allocation.width % 32;
362     }
363   
364   wid = da->allocation.width;
365   heig = da->allocation.height;
366   
367   buf = g_new(guchar, 3 * wid * heig);
368   
369 #if 0
370   i = COLORSEL_RED;
371   for (n = 0; n < 3; n++)
372     {
373       c[n] = (guchar) (255.0 * priv->old_color[i]);
374       c[n + 3] = (guchar) (255.0 * priv->color[i++]);
375     }
376 #endif
377   
378   if (priv->use_opacity)
379     {
380       o = (which) ? priv->color[COLORSEL_OPACITY] : priv->old_color[COLORSEL_OPACITY];
381       
382       for (n = 0; n < 3; n++)
383         {
384           cc[n] = (guchar) ((1.0 - o) * 192 + (o * (gdouble) c[n]));
385           cc[n + 3] = (guchar) ((1.0 - o) * 128 + (o * (gdouble) c[n]));
386         }
387       cp = cc;
388     }
389   
390   i = 0;
391   for (y = 0; y < heig; y++)
392     {
393       for (x = 0; x < wid; x++)
394         {
395           if (priv->use_opacity)
396             f = 3 * ((((goff + x) % 32) < 16) ^ ((y % 32) < 16));
397           else
398             f = 0;
399           
400           for (n = 0; n < 3; n++)
401             buf[i++] = cp[n + f];
402         }
403     }
404   
405   gdk_draw_rgb_image(da->window,
406                      da->style->black_gc,
407                      0, 0,
408                      wid, heig,
409                      GDK_RGB_DITHER_NORMAL,
410                      buf,
411                      3*wid);
412   
413   
414   g_free (buf);
415 }
416
417
418 static void
419 color_sample_draw_samples (GtkColorSelection *colorsel)
420 {
421   color_sample_draw_sample (colorsel, 0);
422   color_sample_draw_sample (colorsel, 1);
423 }
424
425 static void
426 color_old_sample_expose(GtkWidget* da, GdkEventExpose* event, GtkColorSelection *colorsel)
427 {
428   color_sample_draw_sample (colorsel, 0);
429 }
430
431
432 static void
433 color_cur_sample_expose(GtkWidget* da, GdkEventExpose* event, GtkColorSelection *colorsel)
434 {
435   color_sample_draw_sample (colorsel, 1);
436 }
437
438 static void
439 color_sample_setup_dnd (GtkColorSelection *colorsel, GtkWidget *sample)
440 {
441   static const GtkTargetEntry targets[] = {
442     { "application/x-color", 0 }
443   };
444   ColorSelectionPrivate *priv;
445   priv = colorsel->private_data;
446   
447   gtk_drag_source_set (sample,
448                        GDK_BUTTON1_MASK | GDK_BUTTON3_MASK,
449                        targets, 1,
450                        GDK_ACTION_COPY | GDK_ACTION_MOVE);
451   
452   gtk_signal_connect (GTK_OBJECT (sample),
453                       "drag_begin",
454                       GTK_SIGNAL_FUNC (color_sample_drag_begin),
455                       colorsel);
456   if (sample == priv->cur_sample)
457     {
458       
459       gtk_drag_dest_set (sample,
460                          GTK_DEST_DEFAULT_HIGHLIGHT |
461                          GTK_DEST_DEFAULT_MOTION |
462                          GTK_DEST_DEFAULT_DROP,
463                          targets, 1,
464                          GDK_ACTION_COPY);
465       
466       gtk_signal_connect (GTK_OBJECT (sample),
467                           "drag_end",
468                           GTK_SIGNAL_FUNC (color_sample_drag_end),
469                           colorsel);
470     }
471   
472   gtk_signal_connect (GTK_OBJECT (sample),
473                       "drag_data_get",
474                       GTK_SIGNAL_FUNC (color_sample_drag_handle),
475                       colorsel);
476   gtk_signal_connect (GTK_OBJECT (sample),
477                       "drag_data_received",
478                       GTK_SIGNAL_FUNC (color_sample_drop_handle),
479                       colorsel);
480   
481 }
482
483
484 static void
485 color_sample_new (GtkColorSelection *colorsel)
486 {
487   ColorSelectionPrivate *priv;
488   
489   priv = colorsel->private_data;
490   
491   priv->sample_area = gtk_hbox_new (FALSE, 0);
492   priv->old_sample = gtk_drawing_area_new ();
493   priv->cur_sample = gtk_drawing_area_new ();
494   
495   gtk_box_pack_start (GTK_BOX (priv->sample_area), priv->old_sample,
496                       TRUE, TRUE, 0);
497   gtk_box_pack_start (GTK_BOX (priv->sample_area), priv->cur_sample,
498                       TRUE, TRUE, 0);
499   
500   gtk_signal_connect(GTK_OBJECT (priv->old_sample), "expose_event",
501                      GTK_SIGNAL_FUNC (color_old_sample_expose),
502                      colorsel);
503   gtk_signal_connect(GTK_OBJECT (priv->cur_sample), "expose_event",
504                      GTK_SIGNAL_FUNC (color_cur_sample_expose),
505                      colorsel);
506   
507   color_sample_setup_dnd (colorsel, priv->old_sample);
508   color_sample_setup_dnd (colorsel, priv->cur_sample);
509   
510   gtk_widget_show_all (priv->sample_area);
511 }
512
513
514 /*
515  *
516  * The palette area code
517  *
518  */
519 #define CUSTOM_PALETTE_ENTRY_WIDTH   16
520 #define CUSTOM_PALETTE_ENTRY_HEIGHT  16
521
522 static void
523 palette_get_color (GtkWidget *drawing_area, gdouble *color)
524 {
525   gdouble *color_val;
526   
527   g_return_if_fail (color != NULL);
528   
529   color_val = gtk_object_get_data (GTK_OBJECT (drawing_area), "color_val");
530   if (color_val == NULL)
531     {
532       /* Default to white for no good reason */
533       color[0] = 1.0;
534       color[1] = 1.0;
535       color[2] = 1.0;
536       color[3] = 1.0;
537       return;
538     }
539   
540   color[0] = color_val[0];
541   color[1] = color_val[1];
542   color[2] = color_val[2];
543   color[3] = 1.0;
544 }
545
546 #define INTENSITY(r, g, b) ((r) * 0.30 + (g) * 0.59 + (b) * 0.11)
547 static void
548 palette_paint (GtkWidget    *drawing_area,
549                GdkRectangle *area,
550                gpointer      data)
551 {
552   GtkColorSelection *colorsel = GTK_COLOR_SELECTION (data); 
553   ColorSelectionPrivate *priv = colorsel->private_data; 
554
555   if (drawing_area->window == NULL)
556     return;
557   
558   gdk_window_clear_area (drawing_area->window,
559                          area->x,
560                          area->y,
561                          area->width, 
562                          area->height);
563   
564   if (priv->last_palette == drawing_area)
565     {
566       GdkGC *gc;
567       gdouble color[4];
568       
569       palette_get_color (drawing_area, color);
570       
571       if (INTENSITY (color[0], color[1], color[2]) > 0.5)
572         gc = drawing_area->style->black_gc;
573       else
574         gc = drawing_area->style->white_gc;
575
576       gdk_draw_rectangle (drawing_area->window,
577                           gc, FALSE, 0, 0,
578                           drawing_area->allocation.width - 1,
579                           drawing_area->allocation.height - 1);
580     }
581 }
582
583 static void
584 palette_expose (GtkWidget      *drawing_area,
585                 GdkEventExpose *event,
586                 gpointer        data)
587 {
588   if (drawing_area->window == NULL)
589     return;
590   
591   palette_paint (drawing_area, &(event->area), data);
592 }
593
594 static void
595 palette_press (GtkWidget      *drawing_area,
596                GdkEventButton *event,
597                gpointer        data)
598 {
599   GtkColorSelection *colorsel = GTK_COLOR_SELECTION (data); 
600   ColorSelectionPrivate *priv = colorsel->private_data; 
601  
602   if (priv->last_palette != NULL) 
603     gtk_widget_queue_clear (priv->last_palette);
604   
605   priv->last_palette = drawing_area;
606
607   if (GPOINTER_TO_INT (gtk_object_get_data (GTK_OBJECT (drawing_area), "color_set")) != 0)
608     {
609       gdouble color[4];
610       palette_get_color (drawing_area, color);
611       gtk_color_selection_set_color (GTK_COLOR_SELECTION (data), color);
612     }
613
614   gtk_widget_queue_clear (priv->last_palette);
615 }
616
617 static void
618 palette_draw (GtkWidget    *drawing_area,
619               GdkRectangle *area,
620               gpointer      data)
621 {
622   palette_paint (drawing_area, area, data);
623 }
624
625 static void
626 palette_unset_color (GtkWidget *drawing_area)
627 {
628   if (GPOINTER_TO_INT (gtk_object_get_data (GTK_OBJECT (drawing_area), "color_set")) == 0)
629     return;
630   
631   gtk_widget_reset_rc_styles (drawing_area);
632   gtk_object_set_data (GTK_OBJECT (drawing_area), "color_set", GINT_TO_POINTER (0));
633 }
634
635 static void
636 palette_drag_begin (GtkWidget      *widget,
637                     GdkDragContext *context,
638                     gpointer        data)
639 {
640   GtkColorSelection *colorsel = data;
641   ColorSelectionPrivate *priv;
642   GtkWidget *window;
643   gdouble colors[4];
644   GdkColor bg;
645   
646   priv = colorsel->private_data;
647   window = gtk_window_new (GTK_WINDOW_POPUP);
648   gtk_widget_set_app_paintable (GTK_WIDGET (window), TRUE);
649   gtk_widget_set_usize (window, 48, 32);
650   gtk_widget_realize (window);
651   gtk_object_set_data_full (GTK_OBJECT (widget),
652                             "gtk-color-selection-drag-window",
653                             window,
654                             (GtkDestroyNotify) gtk_widget_destroy);
655   
656   palette_get_color (widget, colors);
657   bg.red = 0xffff * colors[0];
658   bg.green = 0xffff * colors[1];
659   bg.blue = 0xffff * colors[2];
660   
661   gdk_color_alloc (gtk_widget_get_colormap (window), &bg);
662   gdk_window_set_background (window->window, &bg);
663   
664   gtk_drag_set_icon_widget (context, window, -2, -2);
665 }
666
667 static void
668 palette_drag_handle (GtkWidget        *widget,
669                      GdkDragContext   *context,
670                      GtkSelectionData *selection_data,
671                      guint             info,
672                      guint             time,
673                      gpointer          data)
674 {
675   guint16 vals[4];
676   gdouble colsrc[4];
677   
678   palette_get_color (widget, colsrc);
679   
680   vals[0] = colsrc[COLORSEL_RED] * 0xffff;
681   vals[1] = colsrc[COLORSEL_GREEN] * 0xffff;
682   vals[2] = colsrc[COLORSEL_BLUE] * 0xffff;
683   vals[3] = 0xffff;
684   
685   gtk_selection_data_set (selection_data,
686                           gdk_atom_intern ("application/x-color", FALSE),
687                           16, (guchar *)vals, 8);
688 }
689
690 static void
691 palette_set_color (GtkWidget         *drawing_area,
692                    GtkColorSelection *colorsel,
693                    gdouble           *color)
694 {
695   GtkRcStyle *rc_style;
696   gdouble *new_color = g_new (double, 4);
697   gdouble *old_color;
698   
699   rc_style = gtk_rc_style_new ();
700   rc_style->bg[GTK_STATE_NORMAL].red = color[0]*65535;
701   rc_style->bg[GTK_STATE_NORMAL].green = color[1]*65535;
702   rc_style->bg[GTK_STATE_NORMAL].blue = color[2]*65535;
703   rc_style->color_flags[GTK_STATE_NORMAL] = GTK_RC_BG;
704   gtk_rc_style_ref (rc_style);
705   gtk_widget_modify_style (drawing_area, rc_style);
706   
707   if (GPOINTER_TO_INT (gtk_object_get_data (GTK_OBJECT (drawing_area), "color_set")) == 0)
708     {
709       static const GtkTargetEntry targets[] = {
710         { "application/x-color", 0 }
711       };
712       gtk_drag_source_set (drawing_area,
713                            GDK_BUTTON1_MASK | GDK_BUTTON3_MASK,
714                            targets, 1,
715                            GDK_ACTION_COPY | GDK_ACTION_MOVE);
716       
717       gtk_signal_connect (GTK_OBJECT (drawing_area),
718                           "drag_begin",
719                           GTK_SIGNAL_FUNC (palette_drag_begin),
720                           colorsel);
721       gtk_signal_connect (GTK_OBJECT (drawing_area),
722                           "drag_data_get",
723                           GTK_SIGNAL_FUNC (palette_drag_handle),
724                           colorsel);
725       
726       gtk_object_set_data (GTK_OBJECT (drawing_area), "color_set", GINT_TO_POINTER (1));
727     }
728   else
729     {
730       old_color = (gdouble *) gtk_object_get_data (GTK_OBJECT (drawing_area), "color_val");
731       if (old_color)
732         {
733           g_free (old_color);
734         }
735     }
736   new_color[0] = color[0];
737   new_color[1] = color[1];
738   new_color[2] = color[2];
739   new_color[3] = 1.0;
740   
741   gtk_object_set_data (GTK_OBJECT (drawing_area), "color_val", new_color);
742 }
743
744 static void
745 palette_drag_end (GtkWidget      *widget,
746                   GdkDragContext *context,
747                   gpointer        data)
748 {
749   gtk_object_set_data (GTK_OBJECT (widget), "gtk-color-selection-drag-window", NULL);
750 }
751
752 static void
753 palette_drop_handle (GtkWidget        *widget,
754                      GdkDragContext   *context,
755                      gint              x,
756                      gint              y,
757                      GtkSelectionData *selection_data,
758                      guint             info,
759                      guint             time,
760                      gpointer          data)
761 {
762   guint16 *vals;
763   gdouble color[4];
764   
765   if (selection_data->length < 0)
766     return;
767   
768   if ((selection_data->format != 16) ||
769       (selection_data->length != 8))
770     {
771       g_warning ("Received invalid color data\n");
772       return;
773     }
774   
775   vals = (guint16 *)selection_data->data;
776   
777   color[0] = (gdouble)vals[0] / 0xffff;
778   color[1] = (gdouble)vals[1] / 0xffff;
779   color[2] = (gdouble)vals[2] / 0xffff;
780   color[3] = (gdouble)vals[3] / 0xffff;
781   palette_set_color (widget, GTK_COLOR_SELECTION (data), color);
782   gtk_color_selection_set_color (GTK_COLOR_SELECTION (data), color);
783 }
784
785 static gint
786 palette_activate (GtkWidget   *widget,
787                   GdkEventKey *event,
788                   gpointer     data)
789 {
790   GtkColorSelection *colorsel = data;
791   ColorSelectionPrivate *priv;
792   
793   if ((event->keyval == ' ') || (event->keyval == GDK_Return))
794     {
795       priv = colorsel->private_data;
796       palette_set_color (widget, GTK_COLOR_SELECTION (data), priv->color);
797     }
798   
799   return TRUE;
800 }
801
802 static GtkWidget*
803 palette_new (GtkColorSelection *colorsel)
804 {
805   GtkWidget *retval;
806   
807   static const GtkTargetEntry targets[] = {
808     { "application/x-color", 0 }
809   };
810   
811   retval = gtk_drawing_area_new ();
812   gtk_object_set_data (GTK_OBJECT (retval), "color_set", GINT_TO_POINTER (0)); 
813   gtk_widget_set_events (retval, GDK_BUTTON_PRESS_MASK | GDK_EXPOSURE_MASK);
814   
815   gtk_signal_connect (GTK_OBJECT (retval), "draw", palette_draw, colorsel);
816   gtk_signal_connect (GTK_OBJECT (retval), "expose_event", palette_expose, colorsel);
817   gtk_signal_connect (GTK_OBJECT (retval), "button_press_event", palette_press, colorsel);
818   
819   gtk_drag_dest_set (retval,
820                      GTK_DEST_DEFAULT_HIGHLIGHT |
821                      GTK_DEST_DEFAULT_MOTION |
822                      GTK_DEST_DEFAULT_DROP,
823                      targets, 1,
824                      GDK_ACTION_COPY);
825   
826   gtk_signal_connect (GTK_OBJECT (retval), "drag_end", palette_drag_end, NULL);
827   gtk_signal_connect (GTK_OBJECT (retval), "drag_data_received", palette_drop_handle, colorsel);
828   gtk_signal_connect (GTK_OBJECT (retval), "key_press_event", GTK_SIGNAL_FUNC (palette_activate), colorsel);
829   
830   return retval;
831 }
832
833
834 /*
835  *
836  * The actual GtkColorSelection widget
837  *
838  */
839
840 static void
841 initialize_cursor (void)
842 {
843   GdkColor fg, bg;
844   
845   GdkPixmap *pixmap =
846     gdk_bitmap_create_from_data (NULL,
847                                  dropper_bits,
848                                  DROPPER_WIDTH, DROPPER_HEIGHT);
849   GdkPixmap *mask =
850     gdk_bitmap_create_from_data (NULL,
851                                  dropper_mask,
852                                  DROPPER_WIDTH, DROPPER_HEIGHT);
853   
854   gdk_color_white (gdk_colormap_get_system (), &bg);
855   gdk_color_black (gdk_colormap_get_system (), &fg);
856   
857   picker_cursor = gdk_cursor_new_from_pixmap (pixmap, mask, &fg, &bg, DROPPER_X_HOT ,DROPPER_Y_HOT);
858   
859   gdk_pixmap_unref (pixmap);
860   gdk_pixmap_unref (mask);
861   
862 }
863
864 static void
865 grab_color_at_mouse (GtkWidget *button,
866                      gint       x_root,
867                      gint       y_root,
868                      gpointer   data)
869 {
870   GdkImage *image;
871   guint32 pixel;
872   GdkVisual *visual;
873   GtkColorSelection *colorsel = data;
874   ColorSelectionPrivate *priv;
875   GdkColormap *colormap = gdk_colormap_get_system ();
876 #if defined (GDK_WINDOWING_X11)
877   XColor xcolor;
878 #endif
879   
880   priv = colorsel->private_data;
881   
882   image = gdk_image_get (GDK_ROOT_PARENT (), x_root, y_root, 1, 1);
883   pixel = gdk_image_get_pixel (image, 0, 0);
884   visual = gdk_colormap_get_visual (colormap);
885   
886   switch (visual->type) {
887   case GDK_VISUAL_DIRECT_COLOR:
888   case GDK_VISUAL_TRUE_COLOR:
889     priv->color[COLORSEL_RED] = (double)((pixel & visual->red_mask)>>visual->red_shift)/((1<<visual->red_prec) - 1);
890     priv->color[COLORSEL_GREEN] = (double)((pixel & visual->green_mask)>>visual->green_shift)/((1<<visual->green_prec) - 1);
891     priv->color[COLORSEL_BLUE] = (double)((pixel & visual->blue_mask)>>visual->blue_shift)/((1<<visual->blue_prec) - 1);
892     break;
893   case GDK_VISUAL_STATIC_GRAY:
894   case GDK_VISUAL_GRAYSCALE:
895     priv->color[COLORSEL_RED] = (double)pixel/((1<<visual->depth) - 1);
896     priv->color[COLORSEL_GREEN] = (double)pixel/((1<<visual->depth) - 1);
897     priv->color[COLORSEL_BLUE] = (double)pixel/((1<<visual->depth) - 1);
898     break;
899 #if defined (GDK_WINDOWING_X11)
900   case GDK_VISUAL_STATIC_COLOR:
901     xcolor.pixel = pixel;
902     XQueryColor (GDK_DISPLAY (), GDK_COLORMAP_XCOLORMAP (colormap), &xcolor);
903     priv->color[COLORSEL_RED] = xcolor.red/65535.0;
904     priv->color[COLORSEL_GREEN] = xcolor.green/65535.0;
905     priv->color[COLORSEL_BLUE] = xcolor.blue/65535.0;
906     break;
907 #endif
908   case GDK_VISUAL_PSEUDO_COLOR:
909     priv->color[COLORSEL_RED] = colormap->colors[pixel].red/(double)0xffffff;
910     priv->color[COLORSEL_GREEN] = colormap->colors[pixel].green/(double)0xffffff;
911     priv->color[COLORSEL_BLUE] = colormap->colors[pixel].blue/(double)0xffffff;
912     break;
913   default:
914     g_assert_not_reached ();
915     break;
916   }
917   
918   gtk_rgb_to_hsv (priv->color[COLORSEL_RED],
919                   priv->color[COLORSEL_GREEN],
920                   priv->color[COLORSEL_BLUE],
921                   &priv->color[COLORSEL_HUE],
922                   &priv->color[COLORSEL_SATURATION],
923                   &priv->color[COLORSEL_VALUE]);
924   update_color (colorsel);
925 }
926
927 static void
928 mouse_motion (GtkWidget      *button,
929               GdkEventMotion *event,
930               gpointer        data)
931 {
932   grab_color_at_mouse (button, event->x_root, event->y_root, data); 
933 }
934
935 static void
936 mouse_release (GtkWidget      *button,
937                GdkEventButton *event,
938                gpointer        data)
939 {
940   GtkColorSelection *colorsel = data;
941   ColorSelectionPrivate *priv;
942   priv = colorsel->private_data;
943   
944   gtk_signal_disconnect_by_func (GTK_OBJECT (button), mouse_motion, data);
945   gtk_signal_disconnect_by_func (GTK_OBJECT (button), mouse_release, data);
946   
947   grab_color_at_mouse (button, event->x_root, event->y_root, data);
948   gdk_pointer_ungrab (0);
949 }
950
951 /* Helper Functions */
952 static void
953 mouse_press (GtkWidget      *button,
954              GdkEventButton *event,
955              gpointer        data)
956 {
957   GtkColorSelection *colorsel = data;
958   ColorSelectionPrivate *priv;
959   priv = colorsel->private_data;
960   
961   gtk_signal_connect (GTK_OBJECT (button), "motion_notify_event", mouse_motion, data);
962   gtk_signal_connect (GTK_OBJECT (button), "button_release_event", mouse_release, data);
963   gtk_signal_disconnect_by_func (GTK_OBJECT (button), mouse_press, data); 
964 }
965
966 /* when the button is clicked */
967 static void
968 get_screen_color (GtkWidget *button)
969 {
970   GtkColorSelection *colorsel = gtk_object_get_data (GTK_OBJECT (button), "COLORSEL");
971   ColorSelectionPrivate *priv = colorsel->private_data; 
972   
973   if (picker_cursor == NULL)
974     {
975       initialize_cursor ();
976     }
977   
978   /* Why do we do this? Because the "clicked" signal will be emitted after the "button_released"
979      signal. We don't want to do this stuff again, though, or else it will get trapped here. So, 
980      priv->moving_dropper is initialized to FALSE at the initialization of the colorselector, 
981      it is initialized to true when we start waiting for the user to click the the dropper on a 
982      color, and whenver it is true when this function starts to execute, we set it to false. */
983   if (priv->moving_dropper == FALSE)
984     {
985       priv->moving_dropper = TRUE;
986       gtk_signal_connect (GTK_OBJECT (button), "button_press_event", mouse_press, colorsel); 
987       
988       gdk_pointer_grab (button->window,
989                         FALSE,
990                         GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_PRESS_MASK | GDK_POINTER_MOTION_MASK,
991                         NULL,
992                         picker_cursor,
993                         0);
994     }
995   else
996     {
997       priv->moving_dropper = FALSE; 
998     }
999 }
1000
1001 void
1002 hex_changed (GtkWidget *hex_entry,
1003              gpointer   data)
1004 {
1005   GtkColorSelection *colorsel;
1006   ColorSelectionPrivate *priv;
1007   GdkColor color;
1008   gchar *text;
1009   
1010   colorsel = GTK_COLOR_SELECTION (data);
1011   priv = colorsel->private_data;
1012   
1013   if (priv->changing)
1014     return;
1015   
1016   text = gtk_editable_get_chars (GTK_EDITABLE (priv->hex_entry), 0, -1);
1017   if (gdk_color_parse (text, &color))
1018     {
1019       priv->color[COLORSEL_RED] = CLAMP (color.red/65280.0, 0.0, 1.0);
1020       priv->color[COLORSEL_GREEN] = CLAMP (color.green/65280.0, 0.0, 1.0);
1021       priv->color[COLORSEL_BLUE] = CLAMP (color.blue/65280.0, 0.0, 1.0);
1022       gtk_rgb_to_hsv (priv->color[COLORSEL_RED],
1023                       priv->color[COLORSEL_GREEN],
1024                       priv->color[COLORSEL_BLUE],
1025                       &priv->color[COLORSEL_HUE],
1026                       &priv->color[COLORSEL_SATURATION],
1027                       &priv->color[COLORSEL_VALUE]);
1028       update_color (colorsel);
1029     }
1030   g_free (text);
1031 }
1032
1033 void
1034 hsv_changed (GtkWidget *hsv,
1035              gpointer   data)
1036 {
1037   GtkColorSelection *colorsel;
1038   ColorSelectionPrivate *priv;
1039   
1040   colorsel = GTK_COLOR_SELECTION (data);
1041   priv = colorsel->private_data;
1042   
1043   if (priv->changing)
1044     return;
1045   
1046   gtk_hsv_get_color (GTK_HSV (hsv),
1047                      &priv->color[COLORSEL_HUE],
1048                      &priv->color[COLORSEL_SATURATION],
1049                      &priv->color[COLORSEL_VALUE]);
1050   gtk_hsv_to_rgb (priv->color[COLORSEL_HUE],
1051                   priv->color[COLORSEL_SATURATION],
1052                   priv->color[COLORSEL_VALUE],
1053                   &priv->color[COLORSEL_RED],
1054                   &priv->color[COLORSEL_GREEN],
1055                   &priv->color[COLORSEL_BLUE]);
1056   update_color (colorsel);
1057 }
1058
1059 void
1060 adjustment_changed (GtkAdjustment *adjustment,
1061                     gpointer       data)
1062 {
1063   GtkColorSelection *colorsel;
1064   ColorSelectionPrivate *priv;
1065   
1066   colorsel = GTK_COLOR_SELECTION (gtk_object_get_data (GTK_OBJECT (adjustment), "COLORSEL"));
1067   priv = colorsel->private_data;
1068   
1069   if (priv->changing)
1070     return;
1071   
1072   switch (GPOINTER_TO_INT (data))
1073     {
1074     case COLORSEL_SATURATION:
1075     case COLORSEL_VALUE:
1076       priv->color[GPOINTER_TO_INT (data)] = adjustment->value / 255;
1077       gtk_hsv_to_rgb (priv->color[COLORSEL_HUE],
1078                       priv->color[COLORSEL_SATURATION],
1079                       priv->color[COLORSEL_VALUE],
1080                       &priv->color[COLORSEL_RED],
1081                       &priv->color[COLORSEL_GREEN],
1082                       &priv->color[COLORSEL_BLUE]);
1083       break;
1084     case COLORSEL_HUE:
1085       priv->color[GPOINTER_TO_INT (data)] = adjustment->value / 360;
1086       gtk_hsv_to_rgb (priv->color[COLORSEL_HUE],
1087                       priv->color[COLORSEL_SATURATION],
1088                       priv->color[COLORSEL_VALUE],
1089                       &priv->color[COLORSEL_RED],
1090                       &priv->color[COLORSEL_GREEN],
1091                       &priv->color[COLORSEL_BLUE]);
1092       break;
1093     case COLORSEL_RED:
1094     case COLORSEL_GREEN:
1095     case COLORSEL_BLUE:
1096       priv->color[GPOINTER_TO_INT (data)] = adjustment->value / 255;
1097       
1098       gtk_rgb_to_hsv (priv->color[COLORSEL_RED],
1099                       priv->color[COLORSEL_GREEN],
1100                       priv->color[COLORSEL_BLUE],
1101                       &priv->color[COLORSEL_HUE],
1102                       &priv->color[COLORSEL_SATURATION],
1103                       &priv->color[COLORSEL_VALUE]);
1104       break;
1105     default:
1106       priv->color[GPOINTER_TO_INT (data)] = adjustment->value / 255;
1107       break;
1108     }
1109   update_color (colorsel);
1110 }
1111
1112 void 
1113 opacity_entry_changed (GtkWidget *opacity_entry,
1114                        gpointer   data)
1115 {
1116   GtkColorSelection *colorsel;
1117   ColorSelectionPrivate *priv;
1118   GtkAdjustment *adj;
1119   gchar *text;
1120   
1121   colorsel = GTK_COLOR_SELECTION (data);
1122   priv = colorsel->private_data;
1123   
1124   if (priv->changing)
1125     return;
1126   
1127   text = gtk_editable_get_chars (GTK_EDITABLE (priv->opacity_entry), 0, -1);
1128   adj = gtk_range_get_adjustment (GTK_RANGE (priv->opacity_slider));
1129   gtk_adjustment_set_value (adj, g_strtod (text, NULL)); 
1130   
1131   update_color (colorsel);
1132   
1133   g_free (text);
1134 }
1135
1136 static void
1137 widget_focus_in (GtkWidget     *drawing_area,
1138                  GdkEventFocus *event,
1139                  gpointer       data)
1140 {
1141   GtkColorSelection *colorsel = GTK_COLOR_SELECTION (data);
1142   ColorSelectionPrivate *priv = colorsel->private_data;
1143   
1144   /* This signal is connected to by all of the widgets except the "Set Color" button
1145    * This will let you add a color to the currently selected palette
1146    */
1147   
1148   priv->last_palette = NULL;
1149 }
1150
1151
1152 static void
1153 make_label_spinbutton (GtkColorSelection *colorsel,
1154                        GtkWidget        **spinbutton,
1155                        gchar             *text,
1156                        GtkWidget         *table,
1157                        gint               i,
1158                        gint               j,
1159                        gint               channel_type)
1160 {
1161   GtkWidget *label;
1162   GtkAdjustment *adjust;
1163   
1164   if (channel_type == COLORSEL_HUE)
1165     {
1166       adjust = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 360.0, 1.0, 1.0, 1.0));
1167     }
1168   else
1169     {
1170       adjust = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 255.0, 1.0, 1.0, 1.0));
1171     }
1172   gtk_object_set_data (GTK_OBJECT (adjust), "COLORSEL", colorsel);
1173   *spinbutton = gtk_spin_button_new (adjust, 10.0, 0);
1174   gtk_signal_connect (GTK_OBJECT (*spinbutton), "focus_in_event", widget_focus_in, colorsel);
1175   gtk_signal_connect (GTK_OBJECT (adjust), "value_changed", adjustment_changed, GINT_TO_POINTER (channel_type));
1176   label = gtk_label_new (text);
1177   gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5);
1178   gtk_table_attach_defaults (GTK_TABLE (table), label, i, i+1, j, j+1);
1179   gtk_table_attach_defaults (GTK_TABLE (table), *spinbutton, i+1, i+2, j, j+1);
1180   
1181 }
1182
1183 static void
1184 make_palette_frame (GtkColorSelection *colorsel,
1185                     GtkWidget         *table,
1186                     gint               i,
1187                     gint               j)
1188 {
1189   GtkWidget *frame;
1190   ColorSelectionPrivate *priv;
1191   
1192   priv = colorsel->private_data;
1193   frame = gtk_frame_new (NULL);
1194   gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
1195   priv->custom_palette[i][j] = palette_new (colorsel);
1196   gtk_widget_set_usize (priv->custom_palette[i][j], CUSTOM_PALETTE_ENTRY_WIDTH, CUSTOM_PALETTE_ENTRY_HEIGHT);
1197   gtk_container_add (GTK_CONTAINER (frame), priv->custom_palette[i][j]);
1198   gtk_table_attach_defaults (GTK_TABLE (table), frame, i, i+1, j, j+1);
1199 }
1200
1201 /* Set the palette entry [x][y] to be the currently selected one. */
1202 static void 
1203 set_selected_palette (GtkColorSelection *colorsel, int x, int y)
1204 {
1205   ColorSelectionPrivate *priv = colorsel->private_data; 
1206
1207   if (priv->last_palette != NULL) 
1208     gtk_widget_queue_clear (priv->last_palette);
1209
1210   priv->last_palette = priv->custom_palette[x][y]; 
1211
1212   gtk_widget_queue_clear (priv->last_palette);
1213 }
1214
1215 static void
1216 update_color (GtkColorSelection *colorsel)
1217 {
1218   ColorSelectionPrivate *priv = colorsel->private_data;
1219   gchar entryval[12];
1220   gchar opacity_text[32];
1221   gchar *ptr;
1222   
1223   priv->changing = TRUE;
1224   color_sample_draw_samples (colorsel);
1225   
1226   gtk_hsv_set_color (GTK_HSV (priv->triangle_colorsel),
1227                      priv->color[COLORSEL_HUE],
1228                      priv->color[COLORSEL_SATURATION],
1229                      priv->color[COLORSEL_VALUE]);
1230   gtk_adjustment_set_value (gtk_spin_button_get_adjustment
1231                             (GTK_SPIN_BUTTON (priv->hue_spinbutton)),
1232                             priv->color[COLORSEL_HUE] * 360);
1233   gtk_adjustment_set_value (gtk_spin_button_get_adjustment
1234                             (GTK_SPIN_BUTTON (priv->sat_spinbutton)),
1235                             priv->color[COLORSEL_SATURATION] * 255);
1236   gtk_adjustment_set_value (gtk_spin_button_get_adjustment
1237                             (GTK_SPIN_BUTTON (priv->val_spinbutton)),
1238                             priv->color[COLORSEL_VALUE] * 255);
1239   gtk_adjustment_set_value (gtk_spin_button_get_adjustment
1240                             (GTK_SPIN_BUTTON (priv->red_spinbutton)),
1241                             priv->color[COLORSEL_RED] * 255);
1242   gtk_adjustment_set_value (gtk_spin_button_get_adjustment
1243                             (GTK_SPIN_BUTTON (priv->green_spinbutton)),
1244                             priv->color[COLORSEL_GREEN] * 255);
1245   gtk_adjustment_set_value (gtk_spin_button_get_adjustment
1246                             (GTK_SPIN_BUTTON (priv->blue_spinbutton)),
1247                             priv->color[COLORSEL_BLUE] * 255);
1248   gtk_adjustment_set_value (gtk_range_get_adjustment
1249                             (GTK_RANGE (priv->opacity_slider)),
1250                             priv->color[COLORSEL_OPACITY] * 255);
1251   
1252   g_snprintf (opacity_text, 32, "%.0f", priv->color[COLORSEL_OPACITY] * 255);
1253   gtk_entry_set_text (GTK_ENTRY (priv->opacity_entry), opacity_text);
1254   
1255   g_snprintf (entryval, 11, "#%2X%2X%2X",
1256               (guint) (255 * priv->color[COLORSEL_RED]),
1257               (guint) (255 * priv->color[COLORSEL_GREEN]),
1258               (guint) (255 * priv->color[COLORSEL_BLUE]));
1259   
1260   for (ptr = entryval; *ptr; ptr++)
1261     if (*ptr == ' ')
1262       *ptr = '0';
1263   gtk_entry_set_text (GTK_ENTRY (priv->hex_entry), entryval);
1264   priv->changing = FALSE;
1265 }
1266
1267 static void
1268 add_button_pressed (GtkWidget         *button,
1269                     GtkColorSelection *colorsel)
1270 {
1271   ColorSelectionPrivate *priv;
1272   gint i, j;
1273   
1274   priv = colorsel->private_data;
1275   
1276   for (j = 0; j < GTK_CUSTOM_PALETTE_HEIGHT; j++)
1277     {
1278       for (i = 0; i < GTK_CUSTOM_PALETTE_WIDTH; i++)
1279         {
1280           /* Either last_palette is set and we're on it, or it's an empty palette */
1281           if ((priv->last_palette && priv->last_palette == priv->custom_palette[i][j]) ||
1282               ((priv->last_palette == NULL) &&
1283                (GPOINTER_TO_INT (gtk_object_get_data (GTK_OBJECT (priv->custom_palette[i][j]),
1284                                                       "color_set")) == 0)))
1285             {
1286               palette_set_color (priv->custom_palette[i][j], colorsel, priv->color);
1287
1288               /* forward the selection */
1289               if ((i == GTK_CUSTOM_PALETTE_WIDTH - 1) && (j == GTK_CUSTOM_PALETTE_HEIGHT - 1))
1290                 set_selected_palette (colorsel, 0, 0);
1291               else if (i == GTK_CUSTOM_PALETTE_WIDTH - 1)
1292                 set_selected_palette (colorsel, 0, j + 1);
1293               else
1294                 set_selected_palette (colorsel, i + 1, j);
1295
1296               return;
1297             }
1298         }
1299     }
1300
1301   /* the palette is totally full.  Add to the first one totally arbitrarily */
1302   palette_set_color (priv->custom_palette[0][0], colorsel, priv->color);
1303
1304   /* forward the selection */
1305   set_selected_palette (colorsel, 1, 0);
1306 }
1307
1308 GtkType
1309 gtk_color_selection_get_type (void)
1310 {
1311   static GtkType color_selection_type = 0;
1312   
1313   if (!color_selection_type)
1314     {
1315       static const GtkTypeInfo color_selection_info =
1316       {
1317         "GtkColorSelection",
1318         sizeof (GtkColorSelection),
1319         sizeof (GtkColorSelectionClass),
1320         (GtkClassInitFunc) gtk_color_selection_class_init,
1321         (GtkObjectInitFunc) gtk_color_selection_init,
1322         /* reserved_1 */ NULL,
1323         /* reserved_2 */ NULL,
1324         (GtkClassInitFunc) NULL,
1325       };
1326       
1327       color_selection_type = gtk_type_unique (GTK_TYPE_VBOX, &color_selection_info);
1328     }
1329   
1330   return color_selection_type;
1331 }
1332
1333 static void
1334 gtk_color_selection_class_init (GtkColorSelectionClass *klass)
1335 {
1336   GtkObjectClass *object_class;
1337   
1338   object_class = (GtkObjectClass*) klass;
1339   
1340   parent_class = gtk_type_class (GTK_TYPE_VBOX);
1341   
1342   color_selection_signals[COLOR_CHANGED] =
1343     gtk_signal_new ("color_changed",
1344                     GTK_RUN_FIRST,
1345                     GTK_CLASS_TYPE (object_class),
1346                     GTK_SIGNAL_OFFSET (GtkColorSelectionClass, color_changed),
1347                     gtk_marshal_NONE__NONE,
1348                     GTK_TYPE_NONE, 0);
1349   
1350   
1351   gtk_object_class_add_signals (object_class, color_selection_signals, LAST_SIGNAL);
1352   
1353   object_class->destroy = gtk_color_selection_destroy;
1354 }
1355
1356 /* widget functions */
1357 static void
1358 gtk_color_selection_init (GtkColorSelection *colorsel)
1359 {
1360   GtkWidget *top_hbox;
1361   GtkWidget *top_right_vbox;
1362   GtkWidget *table, *label, *hbox, *frame, *vbox;
1363   GtkAdjustment *adjust;
1364   GdkPixmap *dropper_pixmap;
1365   GtkWidget *dropper_image;
1366   GtkWidget *button;
1367   GdkBitmap *mask = NULL;
1368   gint i, j;
1369   ColorSelectionPrivate *priv;
1370   
1371   priv = colorsel->private_data = g_new0 (ColorSelectionPrivate, 1);
1372   priv->changing = FALSE;
1373   priv->default_set = FALSE;
1374   priv->last_palette = NULL;
1375   priv->moving_dropper = FALSE;
1376   
1377   gtk_box_set_spacing (GTK_BOX (colorsel), 4);
1378   top_hbox = gtk_hbox_new (FALSE, 8);
1379   gtk_box_pack_start (GTK_BOX (colorsel), top_hbox, FALSE, FALSE, 0);
1380   
1381   vbox = gtk_vbox_new (FALSE, 4);
1382   priv->triangle_colorsel = gtk_hsv_new ();
1383   gtk_signal_connect (GTK_OBJECT (priv->triangle_colorsel), "changed", hsv_changed, colorsel);
1384   gtk_hsv_set_metrics (GTK_HSV (priv->triangle_colorsel), 174, 15);
1385   gtk_box_pack_start (GTK_BOX (top_hbox), vbox, FALSE, FALSE, 0);
1386   gtk_box_pack_start (GTK_BOX (vbox), priv->triangle_colorsel, FALSE, FALSE, 0);
1387   
1388   hbox = gtk_hbox_new (FALSE, 4);
1389   gtk_box_pack_end (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
1390   
1391   frame = gtk_frame_new (NULL);
1392   gtk_widget_set_usize (frame, -1, 30);
1393   gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
1394   color_sample_new (colorsel);
1395   gtk_container_add (GTK_CONTAINER (frame), priv->sample_area);
1396   gtk_box_pack_start (GTK_BOX (hbox), frame, TRUE, TRUE, 0);
1397   
1398   button = gtk_button_new ();
1399   gtk_signal_connect (GTK_OBJECT (button), "focus_in_event", widget_focus_in, colorsel);
1400   gtk_widget_set_events (button, GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK);
1401   gtk_object_set_data (GTK_OBJECT (button), "COLORSEL", colorsel); 
1402   gtk_signal_connect (GTK_OBJECT (button), "clicked", get_screen_color, NULL);
1403   dropper_pixmap = gdk_pixmap_colormap_create_from_xpm_d (NULL, gtk_widget_get_colormap (button), &mask, NULL, picker);
1404   dropper_image = gtk_pixmap_new (dropper_pixmap, mask);
1405   gtk_container_add (GTK_CONTAINER (button), dropper_image);
1406   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
1407   
1408   top_right_vbox = gtk_vbox_new (FALSE, 4);
1409   gtk_box_pack_start (GTK_BOX (top_hbox), top_right_vbox, FALSE, FALSE, 0);
1410   table = gtk_table_new (8, 6, FALSE);
1411   gtk_box_pack_start (GTK_BOX (top_right_vbox), table, FALSE, FALSE, 0);
1412   gtk_table_set_row_spacings (GTK_TABLE (table), 4);
1413   gtk_table_set_col_spacings (GTK_TABLE (table), 4);
1414   
1415   make_label_spinbutton (colorsel, &priv->hue_spinbutton, _("Hue:"), table, 0, 0, COLORSEL_HUE);
1416   make_label_spinbutton (colorsel, &priv->sat_spinbutton, _("Saturation:"), table, 0, 1, COLORSEL_SATURATION);
1417   make_label_spinbutton (colorsel, &priv->val_spinbutton, _("Value:"), table, 0, 2, COLORSEL_VALUE);
1418   make_label_spinbutton (colorsel, &priv->red_spinbutton, _("Red:"), table, 6, 0, COLORSEL_RED);
1419   make_label_spinbutton (colorsel, &priv->green_spinbutton, _("Green:"), table, 6, 1, COLORSEL_GREEN);
1420   make_label_spinbutton (colorsel, &priv->blue_spinbutton, _("Blue:"), table, 6, 2, COLORSEL_BLUE);
1421   gtk_table_attach_defaults (GTK_TABLE (table), gtk_hseparator_new (), 0, 8, 3, 4); 
1422   
1423   priv->opacity_label = gtk_label_new (_("Opacity:")); 
1424   gtk_misc_set_alignment (GTK_MISC (priv->opacity_label), 1.0, 0.5); 
1425   gtk_table_attach_defaults (GTK_TABLE (table), priv->opacity_label, 0, 1, 4, 5); 
1426   adjust = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 255.0, 1.0, 1.0, 0.0)); 
1427   gtk_object_set_data (GTK_OBJECT (adjust), "COLORSEL", colorsel); 
1428   priv->opacity_slider = gtk_hscale_new (adjust); 
1429   gtk_scale_set_draw_value (GTK_SCALE (priv->opacity_slider), FALSE);
1430   gtk_signal_connect (GTK_OBJECT(adjust), "value_changed", adjustment_changed, GINT_TO_POINTER (COLORSEL_OPACITY));
1431   gtk_table_attach_defaults (GTK_TABLE (table), priv->opacity_slider, 1, 7, 4, 5); 
1432   priv->opacity_entry = gtk_entry_new (); 
1433   gtk_widget_set_usize (priv->opacity_entry, 40, 0); 
1434   gtk_signal_connect (GTK_OBJECT (priv->opacity_entry), "focus_in_event", widget_focus_in, colorsel);
1435   gtk_signal_connect (GTK_OBJECT (priv->opacity_entry), "activate", opacity_entry_changed, colorsel);
1436   gtk_table_attach_defaults (GTK_TABLE (table), priv->opacity_entry, 7, 8, 4, 5);
1437   
1438   label = gtk_label_new (_("Hex Value:"));
1439   gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 5, 6);
1440   gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5);
1441   priv->hex_entry = gtk_entry_new ();
1442   gtk_signal_connect (GTK_OBJECT (priv->hex_entry), "activate", hex_changed, colorsel);
1443   gtk_widget_set_usize (priv->hex_entry, 75, -1);  
1444   gtk_table_set_col_spacing (GTK_TABLE (table), 3, 15);
1445   gtk_table_attach_defaults (GTK_TABLE (table), priv->hex_entry, 1, 5, 5, 6);
1446   
1447   /* Set up the palette */
1448   table = gtk_table_new (GTK_CUSTOM_PALETTE_HEIGHT, GTK_CUSTOM_PALETTE_WIDTH, TRUE);
1449   gtk_table_set_row_spacings (GTK_TABLE (table), 1);
1450   gtk_table_set_col_spacings (GTK_TABLE (table), 1);
1451   for (i = 0; i < GTK_CUSTOM_PALETTE_WIDTH; i++)
1452     {
1453       for (j = 0; j < GTK_CUSTOM_PALETTE_HEIGHT; j++)
1454         {
1455           make_palette_frame (colorsel, table, i, j);
1456         }
1457     }
1458   set_selected_palette (colorsel, 0, 0);
1459   priv->palette_frame = gtk_frame_new (_("Custom Palette"));
1460   gtk_box_pack_end (GTK_BOX (top_right_vbox), priv->palette_frame, FALSE, FALSE, 0);
1461   vbox = gtk_vbox_new (FALSE, 4);
1462   gtk_container_add (GTK_CONTAINER (priv->palette_frame), vbox);
1463   gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0);
1464   button = gtk_button_new_with_label (_("Set Color"));
1465   gtk_signal_connect (GTK_OBJECT (button), "clicked", add_button_pressed, colorsel);
1466   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
1467   gtk_container_set_border_width (GTK_CONTAINER (vbox), 4);
1468   
1469   gtk_widget_show_all (top_hbox);
1470   
1471   if (priv->use_opacity == FALSE)
1472     {
1473       gtk_widget_hide (priv->opacity_label);
1474       gtk_widget_hide (priv->opacity_slider);
1475       gtk_widget_hide (priv->opacity_entry);
1476     }
1477   
1478   if (priv->use_palette == FALSE)
1479     {
1480       gtk_widget_hide (priv->palette_frame);
1481     }
1482 }
1483
1484 static void
1485 gtk_color_selection_destroy (GtkObject *object)
1486 {
1487   GtkColorSelection *cselection = GTK_COLOR_SELECTION (object);
1488   
1489   if (cselection->private_data)
1490     {
1491       g_free (cselection->private_data);
1492       cselection->private_data = NULL;
1493     }
1494   
1495   GTK_OBJECT_CLASS (parent_class)->destroy (object);
1496 }
1497
1498
1499
1500 /**
1501  * gtk_color_selection_new:
1502  * @void: 
1503  * 
1504  * Creates a new GtkColorSelection.
1505  * 
1506  * Return value: The new GtkColorSelection.
1507  **/
1508 GtkWidget *
1509 gtk_color_selection_new (void)
1510 {
1511   GtkColorSelection *colorsel;
1512   ColorSelectionPrivate *priv;
1513   gdouble color[4];
1514   color[0] = 1.0;
1515   color[1] = 1.0;
1516   color[2] = 1.0;
1517   color[3] = 1.0;
1518   
1519   colorsel = gtk_type_new (GTK_TYPE_COLOR_SELECTION);
1520   priv = colorsel->private_data;
1521   gtk_color_selection_set_color (colorsel, color);
1522   gtk_color_selection_set_use_opacity (colorsel, FALSE);
1523   
1524   /* We want to make sure that default_set is FALSE */
1525   /* This way the user can still set it */
1526   priv->default_set = FALSE;
1527   
1528   return GTK_WIDGET (colorsel);
1529 }
1530
1531
1532 void
1533 gtk_color_selection_set_update_policy (GtkColorSelection *colorsel,
1534                                        GtkUpdateType      policy)
1535 {
1536   g_return_if_fail (colorsel != NULL);
1537   g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
1538   /* */
1539   g_warning (G_STRLOC ": This function is deprecated.");
1540 }
1541
1542 /**
1543  * gtk_color_selection_get_use_opacity:
1544  * @colorsel: A GtkColorSelection.
1545  * 
1546  * Determines whether the colorsel can use opacity.
1547  * 
1548  * Return value: TRUE if the @colorsel uses opacity.  FALSE if it does't.
1549  **/
1550 gboolean
1551 gtk_color_selection_get_use_opacity (GtkColorSelection *colorsel)
1552 {
1553   ColorSelectionPrivate *priv;
1554   
1555   g_return_val_if_fail (colorsel != NULL, FALSE);
1556   g_return_val_if_fail (GTK_IS_COLOR_SELECTION (colorsel), FALSE);
1557   
1558   priv = colorsel->private_data;
1559   
1560   return priv->use_opacity;
1561 }
1562
1563 /**
1564  * gtk_color_selection_set_use_opacity:
1565  * @colorsel: A GtkColorSelection.
1566  * @use_opacity: TRUE if @colorsel can set the opacity, FALSE otherwise.
1567  *
1568  * Sets the @colorsel to use or not use opacity.
1569  * 
1570  **/
1571 void
1572 gtk_color_selection_set_use_opacity (GtkColorSelection *colorsel,
1573                                      gboolean           use_opacity)
1574 {
1575   ColorSelectionPrivate *priv;
1576   
1577   g_return_if_fail (colorsel != NULL);
1578   g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
1579   
1580   priv = colorsel->private_data;
1581   use_opacity = use_opacity != FALSE;
1582   
1583   if (priv->use_opacity != use_opacity)
1584     {
1585       priv->use_opacity = use_opacity;
1586       if (use_opacity)
1587         {
1588           gtk_widget_show (priv->opacity_slider);
1589           gtk_widget_show (priv->opacity_label);
1590           gtk_widget_show (priv->opacity_entry);
1591         }
1592       else
1593         {
1594           gtk_widget_hide (priv->opacity_slider);
1595           gtk_widget_hide (priv->opacity_label);
1596           gtk_widget_hide (priv->opacity_entry);
1597         }
1598       color_sample_draw_samples (colorsel);
1599     }
1600 }
1601
1602 /**
1603  * gtk_color_selection_get_use_palette:
1604  * @colorsel: A GtkColorSelection.
1605  * 
1606  * Determines whether the palette is used.
1607  * 
1608  * Return value: TRUE if the palette is used.  FALSE if it isn't.
1609  **/
1610 gboolean
1611 gtk_color_selection_get_use_palette (GtkColorSelection *colorsel)
1612 {
1613   ColorSelectionPrivate *priv;
1614   
1615   g_return_val_if_fail (GTK_IS_COLOR_SELECTION (colorsel), FALSE);
1616   
1617   priv = colorsel->private_data;
1618   
1619   return priv->use_palette;
1620 }
1621
1622 /**
1623  * gtk_color_selection_set_use_palette:
1624  * @colorsel: A GtkColorSelection.
1625  * @use_palette: TRUE if palette is to be visible, FALSE otherwise.
1626  *
1627  * Shows and hides the palette based upon the value of @use_palette.
1628  * 
1629  **/
1630 void
1631 gtk_color_selection_set_use_palette (GtkColorSelection *colorsel,
1632                                      gboolean           use_palette)
1633 {
1634   ColorSelectionPrivate *priv;
1635   g_return_if_fail (colorsel != NULL);
1636   g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
1637   
1638   priv = colorsel->private_data;
1639   use_palette = use_palette != FALSE;
1640   
1641   if (priv->use_palette != use_palette)
1642     {
1643       priv->use_palette = use_palette;
1644       if (use_palette)
1645         gtk_widget_show (priv->palette_frame);
1646       else
1647         gtk_widget_hide (priv->palette_frame);
1648     }
1649 }
1650
1651 /**
1652  * gtk_color_selection_set_color:
1653  * @colorsel: A GtkColorSelection.
1654  * @color: A color to set the current color with.
1655  *
1656  * Sets the current color to be @color.  The first time this is called, it will
1657  * also set the original color to be @color too.
1658  * 
1659  **/
1660 void
1661 gtk_color_selection_set_color (GtkColorSelection    *colorsel,
1662                                gdouble              *color)
1663 {
1664   ColorSelectionPrivate *priv;
1665   gint i;
1666   
1667   g_return_if_fail (colorsel != NULL);
1668   g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
1669   
1670   priv = colorsel->private_data;
1671   priv->changing = TRUE;
1672   priv->color[COLORSEL_RED] = color[0];
1673   priv->color[COLORSEL_GREEN] = color[1];
1674   priv->color[COLORSEL_BLUE] = color[2];
1675   priv->color[COLORSEL_OPACITY] = color[3];
1676   gtk_rgb_to_hsv (priv->color[COLORSEL_RED],
1677                   priv->color[COLORSEL_GREEN],
1678                   priv->color[COLORSEL_BLUE],
1679                   &priv->color[COLORSEL_HUE],
1680                   &priv->color[COLORSEL_SATURATION],
1681                   &priv->color[COLORSEL_VALUE]);
1682   if (priv->default_set == FALSE)
1683     {
1684       for (i = 0; i < COLORSEL_NUM_CHANNELS; i++)
1685         priv->old_color[i] = priv->color[i];
1686     }
1687   update_color (colorsel);
1688   priv->default_set = TRUE;
1689 }
1690
1691 /**
1692  * gtk_color_selection_get_color:
1693  * @colorsel: A GtkColorSelection.
1694  * @color: A color to fill in with the current color.
1695  *
1696  * Sets @color to be the current color in the GtkColorSelection widget.
1697  * 
1698  **/
1699 void
1700 gtk_color_selection_get_color (GtkColorSelection *colorsel,
1701                                gdouble           *color)
1702 {
1703   ColorSelectionPrivate *priv;
1704   
1705   g_return_if_fail (colorsel != NULL);
1706   g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
1707   
1708   priv = colorsel->private_data;
1709   color[0] = priv->color[COLORSEL_RED];
1710   color[1] = priv->color[COLORSEL_GREEN];
1711   color[2] = priv->color[COLORSEL_BLUE];
1712   color[3] = priv->use_opacity ? priv->color[COLORSEL_OPACITY] : 1.0;
1713 }
1714
1715 /**
1716  * gtk_color_selection_get_old_color:
1717  * @colorsel: A GtkColorSelection.
1718  * @color: A color to set the original color with.
1719  *
1720  * Sets the 'original' color to be @color.  This function should be called with
1721  * some hesitations, as it might seem confusing to have that color change.
1722  * Calling gtk_color_selection_set_color will also set this color the first
1723  * time it is called.
1724  * 
1725  **/
1726 void
1727 gtk_color_selection_set_old_color (GtkColorSelection *colorsel,
1728                                    gdouble          *color)
1729 {
1730   ColorSelectionPrivate *priv;
1731   
1732   g_return_if_fail (colorsel != NULL);
1733   g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
1734   
1735   priv = colorsel->private_data;
1736   priv->changing = TRUE;
1737   priv->old_color[COLORSEL_RED] = color[0];
1738   priv->old_color[COLORSEL_GREEN] = color[1];
1739   priv->old_color[COLORSEL_BLUE] = color[2];
1740   priv->old_color[COLORSEL_OPACITY] = color[3];
1741   gtk_rgb_to_hsv (priv->old_color[COLORSEL_RED],
1742                   priv->old_color[COLORSEL_GREEN],
1743                   priv->old_color[COLORSEL_BLUE],
1744                   &priv->old_color[COLORSEL_HUE],
1745                   &priv->old_color[COLORSEL_SATURATION],
1746                   &priv->old_color[COLORSEL_VALUE]);
1747   color_sample_draw_samples (colorsel);
1748   priv->default_set = TRUE;
1749 }
1750
1751 /**
1752  * gtk_color_selection_get_old_color:
1753  * @colorsel: A GtkColorSelection.
1754  * @color: A color to fill in with the original color value.
1755  *
1756  * Fills @color in with the original color value.
1757  * 
1758  **/
1759 void
1760 gtk_color_selection_get_old_color (GtkColorSelection *colorsel,
1761                                    gdouble           *color)
1762 {
1763   ColorSelectionPrivate *priv;
1764   
1765   g_return_if_fail (colorsel != NULL);
1766   g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
1767   
1768   priv = colorsel->private_data;
1769   color[0] = priv->old_color[COLORSEL_RED];
1770   color[1] = priv->old_color[COLORSEL_GREEN];
1771   color[2] = priv->old_color[COLORSEL_BLUE];
1772   color[3] = priv->use_opacity ? priv->old_color[COLORSEL_OPACITY] : 1.0;
1773 }
1774
1775 /**
1776  * gtk_color_selection_set_palette_color:
1777  * @colorsel: A GtkColorSelection.
1778  * @x: The x coordinate of the palette.
1779  * @y: The y coordinate of the palette.
1780  * @color: A color to set the palette with.
1781  *
1782  * Set the palette located at (@x, @y) to have @color set as its color.
1783  * 
1784  **/
1785 void
1786 gtk_color_selection_set_palette_color (GtkColorSelection   *colorsel,
1787                                        gint                 x,
1788                                        gint                 y,
1789                                        gdouble             *color)
1790 {
1791   ColorSelectionPrivate *priv;
1792   
1793   g_return_if_fail (colorsel != NULL);
1794   g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
1795   g_return_if_fail (x >= 0 && y >= 0 && x < GTK_CUSTOM_PALETTE_WIDTH && y < GTK_CUSTOM_PALETTE_HEIGHT);
1796   
1797   priv = colorsel->private_data;
1798   palette_set_color (priv->custom_palette[x][y], colorsel, color);
1799 }
1800
1801 /**
1802  * gtk_color_selection_get_palette_color:
1803  * @colorsel: A GtkColorSelection.
1804  * @x: The x coordinate of the palette.
1805  * @y: The y coordinate of the palette.
1806  * @color: A color to fill in with the color value.
1807  * 
1808  * Set @color to have the color found in the palette located at (@x, @y).  If
1809  * the palette is unset, it will leave the color unset.
1810  * 
1811  * Return value: TRUE if the palette located at (@x, @y) has a color set.  FALSE
1812  * if it doesn't.
1813  **/
1814 gboolean
1815 gtk_color_selection_get_palette_color (GtkColorSelection   *colorsel,
1816                                        gint                 x,
1817                                        gint                 y,
1818                                        gdouble             *color)
1819 {
1820   ColorSelectionPrivate *priv;
1821   
1822   g_return_val_if_fail (colorsel != NULL, FALSE);
1823   g_return_val_if_fail (GTK_IS_COLOR_SELECTION (colorsel), FALSE);
1824   g_return_val_if_fail (x >= 0 && y >= 0 && x < GTK_CUSTOM_PALETTE_WIDTH && y < GTK_CUSTOM_PALETTE_HEIGHT, FALSE);
1825   
1826   priv = colorsel->private_data;
1827   
1828   if (GPOINTER_TO_INT (gtk_object_get_data (GTK_OBJECT (priv->custom_palette[x][y]), "color_set")) == 0)
1829     return FALSE;
1830   
1831   palette_get_color (priv->custom_palette[x][y], color);
1832   return TRUE;
1833 }
1834
1835 /**
1836  * gtk_color_selection_unset_palette_color:
1837  * @colorsel: A GtkColorSelection.
1838  * @x: The x coordinate of the palette.
1839  * @y: The y coordinate of the palette.
1840  *
1841  * Change the palette located at (@x, @y) to have no color set.
1842  * 
1843  **/
1844 void
1845 gtk_color_selection_unset_palette_color (GtkColorSelection   *colorsel,
1846                                          gint                 x,
1847                                          gint                 y)
1848 {
1849   ColorSelectionPrivate *priv;
1850   
1851   g_return_if_fail (colorsel != NULL);
1852   g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
1853   g_return_if_fail (x >= 0 && y >= 0 && x < GTK_CUSTOM_PALETTE_WIDTH && y < GTK_CUSTOM_PALETTE_HEIGHT);
1854   
1855   priv = colorsel->private_data;
1856   palette_unset_color (priv->custom_palette[x][y]);
1857 }
1858
1859 /**
1860  * gtk_color_selection_is_adjusting:
1861  * @colorsel: A GtkColorSelection.
1862  *
1863  * Gets the current state of the @colorsel.
1864  *
1865  * Return value: TRUE if the user is currently dragging a color around, and FALSE
1866  * if the selection has stopped.
1867  **/
1868 gboolean
1869 gtk_color_selection_is_adjusting (GtkColorSelection *colorsel)
1870 {
1871   ColorSelectionPrivate *priv;
1872   
1873   g_return_val_if_fail (colorsel != NULL, FALSE);
1874   g_return_val_if_fail (GTK_IS_COLOR_SELECTION (colorsel), FALSE);
1875   
1876   priv = colorsel->private_data;
1877   
1878   return (gtk_hsv_is_adjusting (GTK_HSV (priv->triangle_colorsel)));
1879 }