1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 2000 Red Hat, Inc.
3 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser 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.
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 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser 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.
22 * Modified by the GTK+ Team and others 1997-2001. 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/.
29 #include "gdkconfig.h"
32 #include "gdk/gdkkeysyms.h"
33 #include "gtkcolorsel.h"
35 #include "gtkwindow.h"
36 #include "gtkselection.h"
38 #include "gtkdrawingarea.h"
45 #include "gtkmarshalers.h"
47 #include "gtkspinbutton.h"
49 #include "gtkhscale.h"
51 #include "gtkbutton.h"
52 #include "gtkhseparator.h"
53 #include "gtktooltips.h"
54 #include "gtkinvisible.h"
55 #include "gtkmenuitem.h"
57 #include "gtksettings.h"
60 #include "gtkaccessible.h"
61 #include "gtkprivate.h"
67 /* Number of elements in the custom palatte */
68 #define GTK_CUSTOM_PALETTE_WIDTH 10
69 #define GTK_CUSTOM_PALETTE_HEIGHT 2
71 /* Conversion between 0->1 double and and guint16. See
72 * scale_round() below for more general conversions
74 #define SCALE(i) (i / 65535.)
75 #define UNSCALE(d) ((guint16)(d * 65535 + 0.5))
86 PROP_HAS_OPACITY_CONTROL,
102 typedef struct _ColorSelectionPrivate ColorSelectionPrivate;
104 struct _ColorSelectionPrivate
106 guint has_opacity : 1;
107 guint has_palette : 1;
109 guint default_set : 1;
110 guint default_alpha_set : 1;
113 gdouble color[COLORSEL_NUM_CHANNELS];
114 gdouble old_color[COLORSEL_NUM_CHANNELS];
116 GtkWidget *triangle_colorsel;
117 GtkWidget *hue_spinbutton;
118 GtkWidget *sat_spinbutton;
119 GtkWidget *val_spinbutton;
120 GtkWidget *red_spinbutton;
121 GtkWidget *green_spinbutton;
122 GtkWidget *blue_spinbutton;
123 GtkWidget *opacity_slider;
124 GtkWidget *opacity_label;
125 GtkWidget *opacity_entry;
126 GtkWidget *palette_frame;
127 GtkWidget *hex_entry;
129 /* The Palette code */
130 GtkWidget *custom_palette [GTK_CUSTOM_PALETTE_WIDTH][GTK_CUSTOM_PALETTE_HEIGHT];
132 /* The color_sample stuff */
133 GtkWidget *sample_area;
134 GtkWidget *old_sample;
135 GtkWidget *cur_sample;
139 GtkTooltips *tooltips;
141 /* Window for grabbing on */
142 GtkWidget *dropper_grab_widget;
145 /* Connection to settings */
146 gulong settings_connection;
150 static void gtk_color_selection_init (GtkColorSelection *colorsel);
151 static void gtk_color_selection_class_init (GtkColorSelectionClass *klass);
152 static void gtk_color_selection_destroy (GtkObject *object);
153 static void gtk_color_selection_finalize (GObject *object);
154 static void update_color (GtkColorSelection *colorsel);
155 static void gtk_color_selection_set_property (GObject *object,
159 static void gtk_color_selection_get_property (GObject *object,
164 static void gtk_color_selection_realize (GtkWidget *widget);
165 static void gtk_color_selection_unrealize (GtkWidget *widget);
166 static void gtk_color_selection_show_all (GtkWidget *widget);
167 static gboolean gtk_color_selection_grab_broken (GtkWidget *widget,
168 GdkEventGrabBroken *event);
170 static void gtk_color_selection_set_palette_color (GtkColorSelection *colorsel,
173 static void set_focus_line_attributes (GtkWidget *drawing_area,
176 static void default_noscreen_change_palette_func (const GdkColor *colors,
178 static void default_change_palette_func (GdkScreen *screen,
179 const GdkColor *colors,
181 static void make_control_relations (AtkObject *atk_obj,
183 static void make_all_relations (AtkObject *atk_obj,
184 ColorSelectionPrivate *priv);
186 static gpointer parent_class = NULL;
187 static guint color_selection_signals[LAST_SIGNAL] = { 0 };
189 static const gchar default_colors[] = "black:white:gray50:red:purple:blue:light blue:green:yellow:orange:lavender:brown:goldenrod4:dodger blue:pink:light green:gray10:gray30:gray75:gray90";
191 static GtkColorSelectionChangePaletteFunc noscreen_change_palette_hook = default_noscreen_change_palette_func;
192 static GtkColorSelectionChangePaletteWithScreenFunc change_palette_hook = default_change_palette_func;
194 /* The cursor for the dropper */
195 #define DROPPER_WIDTH 17
196 #define DROPPER_HEIGHT 17
197 #define DROPPER_X_HOT 2
198 #define DROPPER_Y_HOT 16
201 static const guchar dropper_bits[] = {
202 0xff, 0x8f, 0x01, 0xff, 0x77, 0x01, 0xff, 0xfb, 0x00, 0xff, 0xf8, 0x00,
203 0x7f, 0xff, 0x00, 0xff, 0x7e, 0x01, 0xff, 0x9d, 0x01, 0xff, 0xd8, 0x01,
204 0x7f, 0xd4, 0x01, 0x3f, 0xee, 0x01, 0x1f, 0xff, 0x01, 0x8f, 0xff, 0x01,
205 0xc7, 0xff, 0x01, 0xe3, 0xff, 0x01, 0xf3, 0xff, 0x01, 0xfd, 0xff, 0x01,
208 static const guchar dropper_mask[] = {
209 0x00, 0x70, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xfc, 0x01, 0x00, 0xff, 0x01,
210 0x80, 0xff, 0x01, 0x00, 0xff, 0x00, 0x00, 0x7f, 0x00, 0x80, 0x3f, 0x00,
211 0xc0, 0x3f, 0x00, 0xe0, 0x13, 0x00, 0xf0, 0x01, 0x00, 0xf8, 0x00, 0x00,
212 0x7c, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x0d, 0x00, 0x00,
221 #define SAMPLE_WIDTH 64
222 #define SAMPLE_HEIGHT 28
224 static void color_sample_draw_sample (GtkColorSelection *colorsel, int which);
225 static void color_sample_update_samples (GtkColorSelection *colorsel);
228 set_color_internal (GtkColorSelection *colorsel,
231 ColorSelectionPrivate *priv;
234 priv = colorsel->private_data;
235 priv->changing = TRUE;
236 priv->color[COLORSEL_RED] = color[0];
237 priv->color[COLORSEL_GREEN] = color[1];
238 priv->color[COLORSEL_BLUE] = color[2];
239 priv->color[COLORSEL_OPACITY] = color[3];
240 gtk_rgb_to_hsv (priv->color[COLORSEL_RED],
241 priv->color[COLORSEL_GREEN],
242 priv->color[COLORSEL_BLUE],
243 &priv->color[COLORSEL_HUE],
244 &priv->color[COLORSEL_SATURATION],
245 &priv->color[COLORSEL_VALUE]);
246 if (priv->default_set == FALSE)
248 for (i = 0; i < COLORSEL_NUM_CHANNELS; i++)
249 priv->old_color[i] = priv->color[i];
251 priv->default_set = TRUE;
252 priv->default_alpha_set = TRUE;
253 update_color (colorsel);
257 set_color_icon (GdkDragContext *context,
263 pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE,
266 pixel = (((UNSCALE (colors[COLORSEL_RED]) & 0xff00) << 16) |
267 ((UNSCALE (colors[COLORSEL_GREEN]) & 0xff00) << 8) |
268 ((UNSCALE (colors[COLORSEL_BLUE]) & 0xff00)));
270 gdk_pixbuf_fill (pixbuf, pixel);
272 gtk_drag_set_icon_pixbuf (context, pixbuf, -2, -2);
273 g_object_unref (pixbuf);
277 color_sample_drag_begin (GtkWidget *widget,
278 GdkDragContext *context,
281 GtkColorSelection *colorsel = data;
282 ColorSelectionPrivate *priv;
285 priv = colorsel->private_data;
287 if (widget == priv->old_sample)
288 colsrc = priv->old_color;
290 colsrc = priv->color;
292 set_color_icon (context, colsrc);
296 color_sample_drag_end (GtkWidget *widget,
297 GdkDragContext *context,
300 g_object_set_data (G_OBJECT (widget), I_("gtk-color-selection-drag-window"), NULL);
304 color_sample_drop_handle (GtkWidget *widget,
305 GdkDragContext *context,
308 GtkSelectionData *selection_data,
313 GtkColorSelection *colorsel = data;
314 ColorSelectionPrivate *priv;
317 priv = colorsel->private_data;
319 /* This is currently a guint16 array of the format:
326 if (selection_data->length < 0)
329 /* We accept drops with the wrong format, since the KDE color
330 * chooser incorrectly drops application/x-color with format 8.
332 if (selection_data->length != 8)
334 g_warning ("Received invalid color data\n");
338 vals = (guint16 *)selection_data->data;
340 if (widget == priv->cur_sample)
342 color[0] = (gdouble)vals[0] / 0xffff;
343 color[1] = (gdouble)vals[1] / 0xffff;
344 color[2] = (gdouble)vals[2] / 0xffff;
345 color[3] = (gdouble)vals[3] / 0xffff;
347 set_color_internal (colorsel, color);
352 color_sample_drag_handle (GtkWidget *widget,
353 GdkDragContext *context,
354 GtkSelectionData *selection_data,
359 GtkColorSelection *colorsel = data;
360 ColorSelectionPrivate *priv;
364 priv = colorsel->private_data;
366 if (widget == priv->old_sample)
367 colsrc = priv->old_color;
369 colsrc = priv->color;
371 vals[0] = colsrc[COLORSEL_RED] * 0xffff;
372 vals[1] = colsrc[COLORSEL_GREEN] * 0xffff;
373 vals[2] = colsrc[COLORSEL_BLUE] * 0xffff;
374 vals[3] = priv->has_opacity ? colsrc[COLORSEL_OPACITY] * 0xffff : 0xffff;
376 gtk_selection_data_set (selection_data,
377 gdk_atom_intern_static_string ("application/x-color"),
378 16, (guchar *)vals, 8);
381 /* which = 0 means draw old sample, which = 1 means draw new */
383 color_sample_draw_sample (GtkColorSelection *colorsel, int which)
386 gint x, y, wid, heig, goff;
387 ColorSelectionPrivate *priv;
390 g_return_if_fail (colorsel != NULL);
391 priv = colorsel->private_data;
393 g_return_if_fail (priv->sample_area != NULL);
394 if (!GTK_WIDGET_DRAWABLE (priv->sample_area))
399 da = priv->old_sample;
404 da = priv->cur_sample;
405 goff = priv->old_sample->allocation.width % 32;
408 cr = gdk_cairo_create (da->window);
410 wid = da->allocation.width;
411 heig = da->allocation.height;
413 /* Below needs tweaking for non-power-of-two */
414 #define CHECK_SIZE 16
416 if (priv->has_opacity)
418 /* Draw checks in background */
420 cairo_set_source_rgb (cr, 0.5, 0.5, 0.5);
421 cairo_rectangle (cr, 0, 0, wid, heig);
424 cairo_set_source_rgb (cr, 0.75, 0.75, 0.75);
425 for (x = goff & -CHECK_SIZE; x < goff + wid; x += CHECK_SIZE)
426 for (y = 0; y < heig; y += CHECK_SIZE)
427 if ((x / CHECK_SIZE + y / CHECK_SIZE) % 2 == 0)
428 cairo_rectangle (cr, x - goff, y, CHECK_SIZE, CHECK_SIZE);
434 cairo_set_source_rgba (cr,
435 priv->old_color[COLORSEL_RED],
436 priv->old_color[COLORSEL_GREEN],
437 priv->old_color[COLORSEL_BLUE],
439 priv->old_color[COLORSEL_OPACITY] : 1.0);
443 cairo_set_source_rgba (cr,
444 priv->color[COLORSEL_RED],
445 priv->color[COLORSEL_GREEN],
446 priv->color[COLORSEL_BLUE],
448 priv->color[COLORSEL_OPACITY] : 1.0);
451 cairo_rectangle (cr, 0, 0, wid, heig);
459 color_sample_update_samples (GtkColorSelection *colorsel)
461 ColorSelectionPrivate *priv = colorsel->private_data;
462 gtk_widget_queue_draw (priv->old_sample);
463 gtk_widget_queue_draw (priv->cur_sample);
467 color_old_sample_expose (GtkWidget *da,
468 GdkEventExpose *event,
469 GtkColorSelection *colorsel)
471 color_sample_draw_sample (colorsel, 0);
477 color_cur_sample_expose (GtkWidget *da,
478 GdkEventExpose *event,
479 GtkColorSelection *colorsel)
481 color_sample_draw_sample (colorsel, 1);
486 color_sample_setup_dnd (GtkColorSelection *colorsel, GtkWidget *sample)
488 static const GtkTargetEntry targets[] = {
489 { "application/x-color", 0 }
491 ColorSelectionPrivate *priv;
492 priv = colorsel->private_data;
494 gtk_drag_source_set (sample,
495 GDK_BUTTON1_MASK | GDK_BUTTON3_MASK,
497 GDK_ACTION_COPY | GDK_ACTION_MOVE);
499 g_signal_connect (sample,
501 G_CALLBACK (color_sample_drag_begin),
503 if (sample == priv->cur_sample)
506 gtk_drag_dest_set (sample,
507 GTK_DEST_DEFAULT_HIGHLIGHT |
508 GTK_DEST_DEFAULT_MOTION |
509 GTK_DEST_DEFAULT_DROP,
513 g_signal_connect (sample,
515 G_CALLBACK (color_sample_drag_end),
519 g_signal_connect (sample,
521 G_CALLBACK (color_sample_drag_handle),
523 g_signal_connect (sample,
524 "drag_data_received",
525 G_CALLBACK (color_sample_drop_handle),
532 color_sample_new (GtkColorSelection *colorsel)
534 ColorSelectionPrivate *priv;
536 priv = colorsel->private_data;
538 priv->sample_area = gtk_hbox_new (FALSE, 0);
539 priv->old_sample = gtk_drawing_area_new ();
540 priv->cur_sample = gtk_drawing_area_new ();
542 /* We need enter/leave to do tooltips */
543 gtk_widget_add_events (priv->old_sample,
544 GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK);
545 gtk_widget_add_events (priv->cur_sample,
546 GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK);
548 gtk_box_pack_start (GTK_BOX (priv->sample_area), priv->old_sample,
550 gtk_box_pack_start (GTK_BOX (priv->sample_area), priv->cur_sample,
553 g_signal_connect (priv->old_sample, "expose_event",
554 G_CALLBACK (color_old_sample_expose),
556 g_signal_connect (priv->cur_sample, "expose_event",
557 G_CALLBACK (color_cur_sample_expose),
560 color_sample_setup_dnd (colorsel, priv->old_sample);
561 color_sample_setup_dnd (colorsel, priv->cur_sample);
563 gtk_tooltips_set_tip (priv->tooltips,
565 _("The previously-selected color, for comparison to the color you're selecting now. You can drag this color to a palette entry, or select this color as current by dragging it to the other color swatch alongside."), NULL);
568 gtk_tooltips_set_tip (priv->tooltips,
570 _("The color you've chosen. You can drag this color to a palette entry to save it for use in the future."), NULL);
572 gtk_widget_show_all (priv->sample_area);
578 * The palette area code
581 #define CUSTOM_PALETTE_ENTRY_WIDTH 20
582 #define CUSTOM_PALETTE_ENTRY_HEIGHT 20
585 palette_get_color (GtkWidget *drawing_area, gdouble *color)
589 g_return_if_fail (color != NULL);
591 color_val = g_object_get_data (G_OBJECT (drawing_area), "color_val");
592 if (color_val == NULL)
594 /* Default to white for no good reason */
602 color[0] = color_val[0];
603 color[1] = color_val[1];
604 color[2] = color_val[2];
608 #define INTENSITY(r, g, b) ((r) * 0.30 + (g) * 0.59 + (b) * 0.11)
610 palette_paint (GtkWidget *drawing_area,
617 if (drawing_area->window == NULL)
620 cr = gdk_cairo_create (drawing_area->window);
622 gdk_cairo_set_source_color (cr, &drawing_area->style->bg[GTK_STATE_NORMAL]);
623 gdk_cairo_rectangle (cr, area);
626 if (GTK_WIDGET_HAS_FOCUS (drawing_area))
628 set_focus_line_attributes (drawing_area, cr, &focus_width);
629 g_print ("%g %g %g %g\n",
630 focus_width / 2., focus_width / 2.,
631 (double)drawing_area->allocation.width - focus_width,
632 (double)drawing_area->allocation.height - focus_width);
635 focus_width / 2., focus_width / 2.,
636 drawing_area->allocation.width - focus_width,
637 drawing_area->allocation.height - focus_width);
645 set_focus_line_attributes (GtkWidget *drawing_area,
652 gtk_widget_style_get (drawing_area,
653 "focus-line-width", focus_width,
654 "focus-line-pattern", (gchar *)&dash_list,
657 palette_get_color (drawing_area, color);
659 if (INTENSITY (color[0], color[1], color[2]) > 0.5)
660 cairo_set_source_rgb (cr, 0., 0., 0.);
662 cairo_set_source_rgb (cr, 1., 1., 1.);
664 cairo_set_line_width (cr, *focus_width);
668 gint n_dashes = strlen (dash_list);
669 gdouble *dashes = g_new (gdouble, n_dashes);
670 gdouble total_length = 0;
674 for (i = 0; i < n_dashes; i++)
676 dashes[i] = dash_list[i];
677 total_length += dash_list[i];
680 /* The dash offset here aligns the pattern to integer pixels
681 * by starting the dash at the right side of the left border
682 * Negative dash offsets in cairo don't work
683 * (https://bugs.freedesktop.org/show_bug.cgi?id=2729)
685 dash_offset = - *focus_width / 2.;
686 while (dash_offset < 0)
687 dash_offset += total_length;
689 cairo_set_dash (cr, dashes, n_dashes, dash_offset);
697 palette_drag_begin (GtkWidget *widget,
698 GdkDragContext *context,
703 palette_get_color (widget, colors);
704 set_color_icon (context, colors);
708 palette_drag_handle (GtkWidget *widget,
709 GdkDragContext *context,
710 GtkSelectionData *selection_data,
718 palette_get_color (widget, colsrc);
720 vals[0] = colsrc[COLORSEL_RED] * 0xffff;
721 vals[1] = colsrc[COLORSEL_GREEN] * 0xffff;
722 vals[2] = colsrc[COLORSEL_BLUE] * 0xffff;
725 gtk_selection_data_set (selection_data,
726 gdk_atom_intern_static_string ("application/x-color"),
727 16, (guchar *)vals, 8);
731 palette_drag_end (GtkWidget *widget,
732 GdkDragContext *context,
735 g_object_set_data (G_OBJECT (widget), I_("gtk-color-selection-drag-window"), NULL);
739 get_current_colors (GtkColorSelection *colorsel)
741 GtkSettings *settings;
742 GdkColor *colors = NULL;
746 settings = gtk_widget_get_settings (GTK_WIDGET (colorsel));
747 g_object_get (settings,
748 "gtk-color-palette", &palette,
751 if (!gtk_color_selection_palette_from_string (palette, &colors, &n_colors))
753 gtk_color_selection_palette_from_string (default_colors, &colors, &n_colors);
757 /* If there are less colors provided than the number of slots in the
758 * color selection, we fill in the rest from the defaults.
760 if (n_colors < (GTK_CUSTOM_PALETTE_WIDTH * GTK_CUSTOM_PALETTE_HEIGHT))
762 GdkColor *tmp_colors = colors;
763 gint tmp_n_colors = n_colors;
765 gtk_color_selection_palette_from_string (default_colors, &colors, &n_colors);
766 memcpy (colors, tmp_colors, sizeof (GdkColor) * tmp_n_colors);
772 g_assert (n_colors >= GTK_CUSTOM_PALETTE_WIDTH * GTK_CUSTOM_PALETTE_HEIGHT);
778 /* Changes the model color */
780 palette_change_color (GtkWidget *drawing_area,
781 GtkColorSelection *colorsel,
785 ColorSelectionPrivate *priv;
787 GdkColor *current_colors;
790 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
791 g_return_if_fail (GTK_IS_DRAWING_AREA (drawing_area));
793 priv = colorsel->private_data;
795 gdk_color.red = UNSCALE (color[0]);
796 gdk_color.green = UNSCALE (color[1]);
797 gdk_color.blue = UNSCALE (color[2]);
800 y = 0; /* Quiet GCC */
801 while (x < GTK_CUSTOM_PALETTE_WIDTH)
804 while (y < GTK_CUSTOM_PALETTE_HEIGHT)
806 if (priv->custom_palette[x][y] == drawing_area)
817 g_assert (x < GTK_CUSTOM_PALETTE_WIDTH || y < GTK_CUSTOM_PALETTE_HEIGHT);
819 current_colors = get_current_colors (colorsel);
820 current_colors[y * GTK_CUSTOM_PALETTE_WIDTH + x] = gdk_color;
822 screen = gtk_widget_get_screen (GTK_WIDGET (colorsel));
823 if (change_palette_hook != default_change_palette_func)
824 (* change_palette_hook) (screen, current_colors,
825 GTK_CUSTOM_PALETTE_WIDTH * GTK_CUSTOM_PALETTE_HEIGHT);
826 else if (noscreen_change_palette_hook != default_noscreen_change_palette_func)
828 if (screen != gdk_screen_get_default ())
829 g_warning ("gtk_color_selection_set_change_palette_hook used by widget is not on the default screen.");
830 (* noscreen_change_palette_hook) (current_colors,
831 GTK_CUSTOM_PALETTE_WIDTH * GTK_CUSTOM_PALETTE_HEIGHT);
834 (* change_palette_hook) (screen, current_colors,
835 GTK_CUSTOM_PALETTE_WIDTH * GTK_CUSTOM_PALETTE_HEIGHT);
837 g_free (current_colors);
840 /* Changes the view color */
842 palette_set_color (GtkWidget *drawing_area,
843 GtkColorSelection *colorsel,
846 gdouble *new_color = g_new (double, 4);
849 gdk_color.red = UNSCALE (color[0]);
850 gdk_color.green = UNSCALE (color[1]);
851 gdk_color.blue = UNSCALE (color[2]);
853 gtk_widget_modify_bg (drawing_area, GTK_STATE_NORMAL, &gdk_color);
855 if (GPOINTER_TO_INT (g_object_get_data (G_OBJECT (drawing_area), "color_set")) == 0)
857 static const GtkTargetEntry targets[] = {
858 { "application/x-color", 0 }
860 gtk_drag_source_set (drawing_area,
861 GDK_BUTTON1_MASK | GDK_BUTTON3_MASK,
863 GDK_ACTION_COPY | GDK_ACTION_MOVE);
865 g_signal_connect (drawing_area,
867 G_CALLBACK (palette_drag_begin),
869 g_signal_connect (drawing_area,
871 G_CALLBACK (palette_drag_handle),
874 g_object_set_data (G_OBJECT (drawing_area), I_("color_set"),
875 GINT_TO_POINTER (1));
878 new_color[0] = color[0];
879 new_color[1] = color[1];
880 new_color[2] = color[2];
883 g_object_set_data_full (G_OBJECT (drawing_area), I_("color_val"), new_color, (GDestroyNotify)g_free);
887 palette_expose (GtkWidget *drawing_area,
888 GdkEventExpose *event,
891 if (drawing_area->window == NULL)
894 palette_paint (drawing_area, &(event->area), data);
900 popup_position_func (GtkMenu *menu,
911 widget = GTK_WIDGET (user_data);
913 g_return_if_fail (GTK_WIDGET_REALIZED (widget));
915 gdk_window_get_origin (widget->window, &root_x, &root_y);
917 gtk_widget_size_request (GTK_WIDGET (menu), &req);
919 /* Put corner of menu centered on color cell */
920 *x = root_x + widget->allocation.width / 2;
921 *y = root_y + widget->allocation.height / 2;
924 screen = gtk_widget_get_screen (widget);
925 *x = CLAMP (*x, 0, MAX (0, gdk_screen_get_width (screen) - req.width));
926 *y = CLAMP (*y, 0, MAX (0, gdk_screen_get_height (screen) - req.height));
930 save_color_selected (GtkWidget *menuitem,
933 GtkColorSelection *colorsel;
934 GtkWidget *drawing_area;
935 ColorSelectionPrivate *priv;
937 drawing_area = GTK_WIDGET (data);
939 colorsel = GTK_COLOR_SELECTION (g_object_get_data (G_OBJECT (drawing_area),
942 priv = colorsel->private_data;
944 palette_change_color (drawing_area, colorsel, priv->color);
948 do_popup (GtkColorSelection *colorsel,
949 GtkWidget *drawing_area,
955 g_object_set_data (G_OBJECT (drawing_area),
959 menu = gtk_menu_new ();
961 mi = gtk_menu_item_new_with_mnemonic (_("_Save color here"));
963 g_signal_connect (mi, "activate",
964 G_CALLBACK (save_color_selected),
967 gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
969 gtk_widget_show_all (mi);
971 gtk_menu_popup (GTK_MENU (menu), NULL, NULL,
972 popup_position_func, drawing_area,
978 palette_enter (GtkWidget *drawing_area,
979 GdkEventCrossing *event,
982 g_object_set_data (G_OBJECT (drawing_area),
983 I_("gtk-colorsel-have-pointer"),
984 GUINT_TO_POINTER (TRUE));
990 palette_leave (GtkWidget *drawing_area,
991 GdkEventCrossing *event,
994 g_object_set_data (G_OBJECT (drawing_area),
995 I_("gtk-colorsel-have-pointer"),
1002 palette_press (GtkWidget *drawing_area,
1003 GdkEventButton *event,
1006 GtkColorSelection *colorsel = GTK_COLOR_SELECTION (data);
1008 gtk_widget_grab_focus (drawing_area);
1010 if (event->button == 3 &&
1011 event->type == GDK_BUTTON_PRESS)
1013 do_popup (colorsel, drawing_area, event->time);
1021 palette_release (GtkWidget *drawing_area,
1022 GdkEventButton *event,
1025 GtkColorSelection *colorsel = GTK_COLOR_SELECTION (data);
1027 gtk_widget_grab_focus (drawing_area);
1029 if (event->button == 1 &&
1030 g_object_get_data (G_OBJECT (drawing_area),
1031 "gtk-colorsel-have-pointer") != NULL)
1033 if (GPOINTER_TO_INT (g_object_get_data (G_OBJECT (drawing_area), "color_set")) != 0)
1036 palette_get_color (drawing_area, color);
1037 set_color_internal (colorsel, color);
1045 palette_drop_handle (GtkWidget *widget,
1046 GdkDragContext *context,
1049 GtkSelectionData *selection_data,
1054 GtkColorSelection *colorsel = GTK_COLOR_SELECTION (data);
1058 if (selection_data->length < 0)
1061 /* We accept drops with the wrong format, since the KDE color
1062 * chooser incorrectly drops application/x-color with format 8.
1064 if (selection_data->length != 8)
1066 g_warning ("Received invalid color data\n");
1070 vals = (guint16 *)selection_data->data;
1072 color[0] = (gdouble)vals[0] / 0xffff;
1073 color[1] = (gdouble)vals[1] / 0xffff;
1074 color[2] = (gdouble)vals[2] / 0xffff;
1075 color[3] = (gdouble)vals[3] / 0xffff;
1076 palette_change_color (widget, colorsel, color);
1077 set_color_internal (colorsel, color);
1081 palette_activate (GtkWidget *widget,
1085 /* should have a drawing area subclass with an activate signal */
1086 if ((event->keyval == GDK_space) ||
1087 (event->keyval == GDK_Return) ||
1088 (event->keyval == GDK_KP_Enter) ||
1089 (event->keyval == GDK_KP_Space))
1091 if (GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget), "color_set")) != 0)
1094 palette_get_color (widget, color);
1095 set_color_internal (GTK_COLOR_SELECTION (data), color);
1104 palette_popup (GtkWidget *widget,
1107 GtkColorSelection *colorsel = GTK_COLOR_SELECTION (data);
1109 do_popup (colorsel, widget, GDK_CURRENT_TIME);
1115 palette_new (GtkColorSelection *colorsel)
1118 ColorSelectionPrivate *priv;
1120 static const GtkTargetEntry targets[] = {
1121 { "application/x-color", 0 }
1124 priv = colorsel->private_data;
1126 retval = gtk_drawing_area_new ();
1128 GTK_WIDGET_SET_FLAGS (retval, GTK_CAN_FOCUS);
1130 g_object_set_data (G_OBJECT (retval), I_("color_set"), GINT_TO_POINTER (0));
1131 gtk_widget_set_events (retval, GDK_BUTTON_PRESS_MASK
1132 | GDK_BUTTON_RELEASE_MASK
1134 | GDK_ENTER_NOTIFY_MASK
1135 | GDK_LEAVE_NOTIFY_MASK);
1137 g_signal_connect (retval, "expose_event",
1138 G_CALLBACK (palette_expose), colorsel);
1139 g_signal_connect (retval, "button_press_event",
1140 G_CALLBACK (palette_press), colorsel);
1141 g_signal_connect (retval, "button_release_event",
1142 G_CALLBACK (palette_release), colorsel);
1143 g_signal_connect (retval, "enter_notify_event",
1144 G_CALLBACK (palette_enter), colorsel);
1145 g_signal_connect (retval, "leave_notify_event",
1146 G_CALLBACK (palette_leave), colorsel);
1147 g_signal_connect (retval, "key_press_event",
1148 G_CALLBACK (palette_activate), colorsel);
1149 g_signal_connect (retval, "popup_menu",
1150 G_CALLBACK (palette_popup), colorsel);
1152 gtk_drag_dest_set (retval,
1153 GTK_DEST_DEFAULT_HIGHLIGHT |
1154 GTK_DEST_DEFAULT_MOTION |
1155 GTK_DEST_DEFAULT_DROP,
1159 g_signal_connect (retval, "drag_end",
1160 G_CALLBACK (palette_drag_end), NULL);
1161 g_signal_connect (retval, "drag_data_received",
1162 G_CALLBACK (palette_drop_handle), colorsel);
1164 gtk_tooltips_set_tip (priv->tooltips,
1166 _("Click this palette entry to make it the current color. To change this entry, drag a color swatch here or right-click it and select \"Save color here.\""),
1174 * The actual GtkColorSelection widget
1179 make_picker_cursor (GdkScreen *screen)
1183 cursor = gdk_cursor_new_from_name (gdk_screen_get_display (screen),
1188 GdkColor bg = { 0, 0xffff, 0xffff, 0xffff };
1189 GdkColor fg = { 0, 0x0000, 0x0000, 0x0000 };
1191 GdkPixmap *pixmap, *mask;
1193 window = gdk_screen_get_root_window (screen);
1196 gdk_bitmap_create_from_data (window, (gchar *) dropper_bits,
1197 DROPPER_WIDTH, DROPPER_HEIGHT);
1200 gdk_bitmap_create_from_data (window, (gchar *) dropper_mask,
1201 DROPPER_WIDTH, DROPPER_HEIGHT);
1203 cursor = gdk_cursor_new_from_pixmap (pixmap, mask, &fg, &bg,
1204 DROPPER_X_HOT, DROPPER_Y_HOT);
1206 g_object_unref (pixmap);
1207 g_object_unref (mask);
1214 grab_color_at_mouse (GdkScreen *screen,
1221 GtkColorSelection *colorsel = data;
1222 ColorSelectionPrivate *priv;
1224 GdkColormap *colormap = gdk_screen_get_system_colormap (screen);
1225 GdkWindow *root_window = gdk_screen_get_root_window (screen);
1227 priv = colorsel->private_data;
1229 image = gdk_drawable_get_image (root_window, x_root, y_root, 1, 1);
1230 pixel = gdk_image_get_pixel (image, 0, 0);
1231 g_object_unref (image);
1233 gdk_colormap_query_color (colormap, pixel, &color);
1235 priv->color[COLORSEL_RED] = SCALE (color.red);
1236 priv->color[COLORSEL_GREEN] = SCALE (color.green);
1237 priv->color[COLORSEL_BLUE] = SCALE (color.blue);
1239 gtk_rgb_to_hsv (priv->color[COLORSEL_RED],
1240 priv->color[COLORSEL_GREEN],
1241 priv->color[COLORSEL_BLUE],
1242 &priv->color[COLORSEL_HUE],
1243 &priv->color[COLORSEL_SATURATION],
1244 &priv->color[COLORSEL_VALUE]);
1246 update_color (colorsel);
1250 shutdown_eyedropper (GtkWidget *widget)
1252 GtkColorSelection *colorsel;
1253 ColorSelectionPrivate *priv;
1254 GdkDisplay *display = gtk_widget_get_display (widget);
1256 colorsel = GTK_COLOR_SELECTION (widget);
1257 priv = colorsel->private_data;
1261 gdk_display_keyboard_ungrab (display, priv->grab_time);
1262 gdk_display_pointer_ungrab (display, priv->grab_time);
1263 gtk_grab_remove (priv->dropper_grab_widget);
1265 priv->has_grab = FALSE;
1270 gtk_color_selection_grab_broken (GtkWidget *widget,
1271 GdkEventGrabBroken *event)
1273 shutdown_eyedropper (widget);
1279 mouse_motion (GtkWidget *invisible,
1280 GdkEventMotion *event,
1283 grab_color_at_mouse (gdk_event_get_screen ((GdkEvent *)event),
1284 event->x_root, event->y_root, data);
1288 mouse_release (GtkWidget *invisible,
1289 GdkEventButton *event,
1292 /* GtkColorSelection *colorsel = data; */
1294 if (event->button != 1)
1297 grab_color_at_mouse (gdk_event_get_screen ((GdkEvent *)event),
1298 event->x_root, event->y_root, data);
1300 shutdown_eyedropper (GTK_WIDGET (data));
1302 g_signal_handlers_disconnect_by_func (invisible,
1305 g_signal_handlers_disconnect_by_func (invisible,
1312 /* Helper Functions */
1314 static gboolean mouse_press (GtkWidget *invisible,
1315 GdkEventButton *event,
1321 key_press (GtkWidget *invisible,
1325 GdkDisplay *display = gtk_widget_get_display (invisible);
1326 GdkScreen *screen = gdk_event_get_screen ((GdkEvent *)event);
1327 guint state = event->state & gtk_accelerator_get_default_mod_mask ();
1331 gdk_display_get_pointer (display, NULL, &x, &y, NULL);
1336 switch (event->keyval)
1342 grab_color_at_mouse (screen, x, y, data);
1346 shutdown_eyedropper (data);
1348 g_signal_handlers_disconnect_by_func (invisible,
1351 g_signal_handlers_disconnect_by_func (invisible,
1357 #if defined GDK_WINDOWING_X11 || defined GDK_WINDOWING_WIN32
1360 dy = state == GDK_MOD1_MASK ? -BIG_STEP : -1;
1365 dy = state == GDK_MOD1_MASK ? BIG_STEP : 1;
1370 dx = state == GDK_MOD1_MASK ? -BIG_STEP : -1;
1375 dx = state == GDK_MOD1_MASK ? BIG_STEP : 1;
1383 gdk_display_warp_pointer (display, screen, x + dx, y + dy);
1390 mouse_press (GtkWidget *invisible,
1391 GdkEventButton *event,
1394 /* GtkColorSelection *colorsel = data; */
1396 if (event->type == GDK_BUTTON_PRESS &&
1399 g_signal_connect (invisible, "motion_notify_event",
1400 G_CALLBACK (mouse_motion),
1402 g_signal_connect (invisible, "button_release_event",
1403 G_CALLBACK (mouse_release),
1405 g_signal_handlers_disconnect_by_func (invisible,
1408 g_signal_handlers_disconnect_by_func (invisible,
1417 /* when the button is clicked */
1419 get_screen_color (GtkWidget *button)
1421 GtkColorSelection *colorsel = g_object_get_data (G_OBJECT (button), "COLORSEL");
1422 ColorSelectionPrivate *priv = colorsel->private_data;
1423 GdkScreen *screen = gtk_widget_get_screen (GTK_WIDGET (button));
1424 GdkCursor *picker_cursor;
1425 GdkGrabStatus grab_status;
1426 guint32 time = gtk_get_current_event_time ();
1428 if (priv->dropper_grab_widget == NULL)
1430 priv->dropper_grab_widget = gtk_invisible_new_for_screen (screen);
1432 gtk_widget_add_events (priv->dropper_grab_widget,
1433 GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_PRESS_MASK | GDK_POINTER_MOTION_MASK);
1435 gtk_widget_show (priv->dropper_grab_widget);
1437 gdk_window_set_user_data (priv->dropper_grab_widget->window, colorsel);
1438 gdk_window_reparent (priv->dropper_grab_widget->window,
1439 GTK_WIDGET (colorsel)->window, 0, 0);
1442 if (gdk_keyboard_grab (priv->dropper_grab_widget->window,
1443 FALSE, time) != GDK_GRAB_SUCCESS)
1446 picker_cursor = make_picker_cursor (screen);
1447 grab_status = gdk_pointer_grab (priv->dropper_grab_widget->window,
1449 GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_PRESS_MASK | GDK_POINTER_MOTION_MASK,
1453 gdk_cursor_unref (picker_cursor);
1455 if (grab_status != GDK_GRAB_SUCCESS)
1457 gdk_display_keyboard_ungrab (gtk_widget_get_display (button), time);
1461 gtk_grab_add (priv->dropper_grab_widget);
1462 priv->grab_time = time;
1463 priv->has_grab = TRUE;
1465 g_signal_connect (priv->dropper_grab_widget, "button_press_event",
1466 G_CALLBACK (mouse_press), colorsel);
1467 g_signal_connect (priv->dropper_grab_widget, "key_press_event",
1468 G_CALLBACK (key_press), colorsel);
1472 hex_changed (GtkWidget *hex_entry,
1475 GtkColorSelection *colorsel;
1476 ColorSelectionPrivate *priv;
1480 colorsel = GTK_COLOR_SELECTION (data);
1481 priv = colorsel->private_data;
1486 text = gtk_editable_get_chars (GTK_EDITABLE (priv->hex_entry), 0, -1);
1487 if (gdk_color_parse (text, &color))
1489 priv->color[COLORSEL_RED] = CLAMP (color.red/65535.0, 0.0, 1.0);
1490 priv->color[COLORSEL_GREEN] = CLAMP (color.green/65535.0, 0.0, 1.0);
1491 priv->color[COLORSEL_BLUE] = CLAMP (color.blue/65535.0, 0.0, 1.0);
1492 gtk_rgb_to_hsv (priv->color[COLORSEL_RED],
1493 priv->color[COLORSEL_GREEN],
1494 priv->color[COLORSEL_BLUE],
1495 &priv->color[COLORSEL_HUE],
1496 &priv->color[COLORSEL_SATURATION],
1497 &priv->color[COLORSEL_VALUE]);
1498 update_color (colorsel);
1504 hex_focus_out (GtkWidget *hex_entry,
1505 GdkEventFocus *event,
1508 hex_changed (hex_entry, data);
1514 hsv_changed (GtkWidget *hsv,
1517 GtkColorSelection *colorsel;
1518 ColorSelectionPrivate *priv;
1520 colorsel = GTK_COLOR_SELECTION (data);
1521 priv = colorsel->private_data;
1526 gtk_hsv_get_color (GTK_HSV (hsv),
1527 &priv->color[COLORSEL_HUE],
1528 &priv->color[COLORSEL_SATURATION],
1529 &priv->color[COLORSEL_VALUE]);
1530 gtk_hsv_to_rgb (priv->color[COLORSEL_HUE],
1531 priv->color[COLORSEL_SATURATION],
1532 priv->color[COLORSEL_VALUE],
1533 &priv->color[COLORSEL_RED],
1534 &priv->color[COLORSEL_GREEN],
1535 &priv->color[COLORSEL_BLUE]);
1536 update_color (colorsel);
1540 adjustment_changed (GtkAdjustment *adjustment,
1543 GtkColorSelection *colorsel;
1544 ColorSelectionPrivate *priv;
1546 colorsel = GTK_COLOR_SELECTION (g_object_get_data (G_OBJECT (adjustment), "COLORSEL"));
1547 priv = colorsel->private_data;
1552 switch (GPOINTER_TO_INT (data))
1554 case COLORSEL_SATURATION:
1555 case COLORSEL_VALUE:
1556 priv->color[GPOINTER_TO_INT (data)] = adjustment->value / 100;
1557 gtk_hsv_to_rgb (priv->color[COLORSEL_HUE],
1558 priv->color[COLORSEL_SATURATION],
1559 priv->color[COLORSEL_VALUE],
1560 &priv->color[COLORSEL_RED],
1561 &priv->color[COLORSEL_GREEN],
1562 &priv->color[COLORSEL_BLUE]);
1565 priv->color[GPOINTER_TO_INT (data)] = adjustment->value / 360;
1566 gtk_hsv_to_rgb (priv->color[COLORSEL_HUE],
1567 priv->color[COLORSEL_SATURATION],
1568 priv->color[COLORSEL_VALUE],
1569 &priv->color[COLORSEL_RED],
1570 &priv->color[COLORSEL_GREEN],
1571 &priv->color[COLORSEL_BLUE]);
1574 case COLORSEL_GREEN:
1576 priv->color[GPOINTER_TO_INT (data)] = adjustment->value / 255;
1578 gtk_rgb_to_hsv (priv->color[COLORSEL_RED],
1579 priv->color[COLORSEL_GREEN],
1580 priv->color[COLORSEL_BLUE],
1581 &priv->color[COLORSEL_HUE],
1582 &priv->color[COLORSEL_SATURATION],
1583 &priv->color[COLORSEL_VALUE]);
1586 priv->color[GPOINTER_TO_INT (data)] = adjustment->value / 255;
1589 update_color (colorsel);
1593 opacity_entry_changed (GtkWidget *opacity_entry,
1596 GtkColorSelection *colorsel;
1597 ColorSelectionPrivate *priv;
1601 colorsel = GTK_COLOR_SELECTION (data);
1602 priv = colorsel->private_data;
1607 text = gtk_editable_get_chars (GTK_EDITABLE (priv->opacity_entry), 0, -1);
1608 adj = gtk_range_get_adjustment (GTK_RANGE (priv->opacity_slider));
1609 gtk_adjustment_set_value (adj, g_strtod (text, NULL));
1611 update_color (colorsel);
1617 make_label_spinbutton (GtkColorSelection *colorsel,
1618 GtkWidget **spinbutton,
1624 const gchar *tooltip)
1627 GtkAdjustment *adjust;
1628 ColorSelectionPrivate *priv = colorsel->private_data;
1630 if (channel_type == COLORSEL_HUE)
1632 adjust = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 360.0, 1.0, 1.0, 1.0));
1634 else if (channel_type == COLORSEL_SATURATION ||
1635 channel_type == COLORSEL_VALUE)
1637 adjust = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 100.0, 1.0, 1.0, 1.0));
1641 adjust = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 255.0, 1.0, 1.0, 1.0));
1643 g_object_set_data (G_OBJECT (adjust), I_("COLORSEL"), colorsel);
1644 *spinbutton = gtk_spin_button_new (adjust, 10.0, 0);
1646 gtk_tooltips_set_tip (priv->tooltips, *spinbutton, tooltip, NULL);
1648 g_signal_connect (adjust, "value_changed",
1649 G_CALLBACK (adjustment_changed),
1650 GINT_TO_POINTER (channel_type));
1651 label = gtk_label_new_with_mnemonic (text);
1652 gtk_label_set_mnemonic_widget (GTK_LABEL (label), *spinbutton);
1654 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
1655 gtk_table_attach_defaults (GTK_TABLE (table), label, i, i+1, j, j+1);
1656 gtk_table_attach_defaults (GTK_TABLE (table), *spinbutton, i+1, i+2, j, j+1);
1660 make_palette_frame (GtkColorSelection *colorsel,
1666 ColorSelectionPrivate *priv;
1668 priv = colorsel->private_data;
1669 frame = gtk_frame_new (NULL);
1670 gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
1671 priv->custom_palette[i][j] = palette_new (colorsel);
1672 gtk_widget_set_size_request (priv->custom_palette[i][j], CUSTOM_PALETTE_ENTRY_WIDTH, CUSTOM_PALETTE_ENTRY_HEIGHT);
1673 gtk_container_add (GTK_CONTAINER (frame), priv->custom_palette[i][j]);
1674 gtk_table_attach_defaults (GTK_TABLE (table), frame, i, i+1, j, j+1);
1677 /* Set the palette entry [x][y] to be the currently selected one. */
1679 set_selected_palette (GtkColorSelection *colorsel, int x, int y)
1681 ColorSelectionPrivate *priv = colorsel->private_data;
1683 gtk_widget_grab_focus (priv->custom_palette[x][y]);
1687 scale_round (double val, double factor)
1689 val = floor (val * factor + 0.5);
1691 val = MIN (val, factor);
1696 update_color (GtkColorSelection *colorsel)
1698 ColorSelectionPrivate *priv = colorsel->private_data;
1700 gchar opacity_text[32];
1703 priv->changing = TRUE;
1704 color_sample_update_samples (colorsel);
1706 gtk_hsv_set_color (GTK_HSV (priv->triangle_colorsel),
1707 priv->color[COLORSEL_HUE],
1708 priv->color[COLORSEL_SATURATION],
1709 priv->color[COLORSEL_VALUE]);
1710 gtk_adjustment_set_value (gtk_spin_button_get_adjustment
1711 (GTK_SPIN_BUTTON (priv->hue_spinbutton)),
1712 scale_round (priv->color[COLORSEL_HUE], 360));
1713 gtk_adjustment_set_value (gtk_spin_button_get_adjustment
1714 (GTK_SPIN_BUTTON (priv->sat_spinbutton)),
1715 scale_round (priv->color[COLORSEL_SATURATION], 100));
1716 gtk_adjustment_set_value (gtk_spin_button_get_adjustment
1717 (GTK_SPIN_BUTTON (priv->val_spinbutton)),
1718 scale_round (priv->color[COLORSEL_VALUE], 100));
1719 gtk_adjustment_set_value (gtk_spin_button_get_adjustment
1720 (GTK_SPIN_BUTTON (priv->red_spinbutton)),
1721 scale_round (priv->color[COLORSEL_RED], 255));
1722 gtk_adjustment_set_value (gtk_spin_button_get_adjustment
1723 (GTK_SPIN_BUTTON (priv->green_spinbutton)),
1724 scale_round (priv->color[COLORSEL_GREEN], 255));
1725 gtk_adjustment_set_value (gtk_spin_button_get_adjustment
1726 (GTK_SPIN_BUTTON (priv->blue_spinbutton)),
1727 scale_round (priv->color[COLORSEL_BLUE], 255));
1728 gtk_adjustment_set_value (gtk_range_get_adjustment
1729 (GTK_RANGE (priv->opacity_slider)),
1730 scale_round (priv->color[COLORSEL_OPACITY], 255));
1732 g_snprintf (opacity_text, 32, "%.0f", scale_round (priv->color[COLORSEL_OPACITY], 255));
1733 gtk_entry_set_text (GTK_ENTRY (priv->opacity_entry), opacity_text);
1735 g_snprintf (entryval, 11, "#%2X%2X%2X",
1736 (guint) (scale_round (priv->color[COLORSEL_RED], 255)),
1737 (guint) (scale_round (priv->color[COLORSEL_GREEN], 255)),
1738 (guint) (scale_round (priv->color[COLORSEL_BLUE], 255)));
1740 for (ptr = entryval; *ptr; ptr++)
1743 gtk_entry_set_text (GTK_ENTRY (priv->hex_entry), entryval);
1744 priv->changing = FALSE;
1746 g_object_ref (colorsel);
1748 g_signal_emit (colorsel, color_selection_signals[COLOR_CHANGED], 0);
1750 g_object_freeze_notify (G_OBJECT (colorsel));
1751 g_object_notify (G_OBJECT (colorsel), "current-color");
1752 g_object_notify (G_OBJECT (colorsel), "current-alpha");
1753 g_object_thaw_notify (G_OBJECT (colorsel));
1755 g_object_unref (colorsel);
1759 update_palette (GtkColorSelection *colorsel)
1761 GdkColor *current_colors;
1764 current_colors = get_current_colors (colorsel);
1766 for (i = 0; i < GTK_CUSTOM_PALETTE_HEIGHT; i++)
1768 for (j = 0; j < GTK_CUSTOM_PALETTE_WIDTH; j++)
1772 index = i * GTK_CUSTOM_PALETTE_WIDTH + j;
1774 gtk_color_selection_set_palette_color (colorsel,
1776 ¤t_colors[index]);
1780 g_free (current_colors);
1784 palette_change_notify_instance (GObject *object,
1788 update_palette (GTK_COLOR_SELECTION (data));
1792 default_noscreen_change_palette_func (const GdkColor *colors,
1795 default_change_palette_func (gdk_screen_get_default (), colors, n_colors);
1799 default_change_palette_func (GdkScreen *screen,
1800 const GdkColor *colors,
1805 str = gtk_color_selection_palette_to_string (colors, n_colors);
1807 gtk_settings_set_string_property (gtk_settings_get_for_screen (screen),
1808 "gtk-color-palette",
1810 "gtk_color_selection_palette_to_string");
1816 gtk_color_selection_get_type (void)
1818 static GType color_selection_type = 0;
1820 if (!color_selection_type)
1822 static const GTypeInfo color_selection_info =
1824 sizeof (GtkColorSelectionClass),
1825 NULL, /* base_init */
1826 NULL, /* base_finalize */
1827 (GClassInitFunc) gtk_color_selection_class_init,
1828 NULL, /* class_finalize */
1829 NULL, /* class_data */
1830 sizeof (GtkColorSelection),
1831 0, /* n_preallocs */
1832 (GInstanceInitFunc) gtk_color_selection_init,
1835 color_selection_type =
1836 g_type_register_static (GTK_TYPE_VBOX, I_("GtkColorSelection"),
1837 &color_selection_info, 0);
1840 return color_selection_type;
1844 gtk_color_selection_class_init (GtkColorSelectionClass *klass)
1846 GObjectClass *gobject_class;
1847 GtkObjectClass *object_class;
1848 GtkWidgetClass *widget_class;
1850 gobject_class = G_OBJECT_CLASS (klass);
1851 object_class = GTK_OBJECT_CLASS (klass);
1852 widget_class = GTK_WIDGET_CLASS (klass);
1854 parent_class = g_type_class_peek_parent (klass);
1856 object_class->destroy = gtk_color_selection_destroy;
1857 gobject_class->finalize = gtk_color_selection_finalize;
1859 gobject_class->set_property = gtk_color_selection_set_property;
1860 gobject_class->get_property = gtk_color_selection_get_property;
1862 widget_class->realize = gtk_color_selection_realize;
1863 widget_class->unrealize = gtk_color_selection_unrealize;
1864 widget_class->show_all = gtk_color_selection_show_all;
1865 widget_class->grab_broken_event = gtk_color_selection_grab_broken;
1867 g_object_class_install_property (gobject_class,
1868 PROP_HAS_OPACITY_CONTROL,
1869 g_param_spec_boolean ("has-opacity-control",
1870 P_("Has Opacity Control"),
1871 P_("Whether the color selector should allow setting opacity"),
1873 GTK_PARAM_READWRITE));
1874 g_object_class_install_property (gobject_class,
1876 g_param_spec_boolean ("has-palette",
1878 P_("Whether a palette should be used"),
1880 GTK_PARAM_READWRITE));
1881 g_object_class_install_property (gobject_class,
1883 g_param_spec_boxed ("current-color",
1884 P_("Current Color"),
1885 P_("The current color"),
1887 GTK_PARAM_READWRITE));
1888 g_object_class_install_property (gobject_class,
1890 g_param_spec_uint ("current-alpha",
1891 P_("Current Alpha"),
1892 P_("The current opacity value (0 fully transparent, 65535 fully opaque)"),
1894 GTK_PARAM_READWRITE));
1896 color_selection_signals[COLOR_CHANGED] =
1897 g_signal_new (I_("color_changed"),
1898 G_OBJECT_CLASS_TYPE (object_class),
1900 G_STRUCT_OFFSET (GtkColorSelectionClass, color_changed),
1902 _gtk_marshal_VOID__VOID,
1905 gtk_settings_install_property (g_param_spec_string ("gtk-color-palette",
1906 P_("Custom palette"),
1907 P_("Palette to use in the color selector"),
1909 GTK_PARAM_READWRITE));
1911 g_type_class_add_private (gobject_class, sizeof (ColorSelectionPrivate));
1914 /* widget functions */
1917 gtk_color_selection_init (GtkColorSelection *colorsel)
1919 GtkWidget *top_hbox;
1920 GtkWidget *top_right_vbox;
1921 GtkWidget *table, *label, *hbox, *frame, *vbox, *button;
1922 GtkAdjustment *adjust;
1923 GtkWidget *picker_image;
1925 ColorSelectionPrivate *priv;
1927 GList *focus_chain = NULL;
1929 gtk_widget_push_composite_child ();
1931 priv = colorsel->private_data = G_TYPE_INSTANCE_GET_PRIVATE (colorsel, GTK_TYPE_COLOR_SELECTION, ColorSelectionPrivate);
1932 priv->changing = FALSE;
1933 priv->default_set = FALSE;
1934 priv->default_alpha_set = FALSE;
1936 priv->tooltips = gtk_tooltips_new ();
1937 g_object_ref_sink (priv->tooltips);
1939 top_hbox = gtk_hbox_new (FALSE, 12);
1940 gtk_box_pack_start (GTK_BOX (colorsel), top_hbox, FALSE, FALSE, 0);
1942 vbox = gtk_vbox_new (FALSE, 6);
1943 priv->triangle_colorsel = gtk_hsv_new ();
1944 g_signal_connect (priv->triangle_colorsel, "changed",
1945 G_CALLBACK (hsv_changed), colorsel);
1946 gtk_hsv_set_metrics (GTK_HSV (priv->triangle_colorsel), 174, 15);
1947 gtk_box_pack_start (GTK_BOX (top_hbox), vbox, FALSE, FALSE, 0);
1948 gtk_box_pack_start (GTK_BOX (vbox), priv->triangle_colorsel, FALSE, FALSE, 0);
1949 gtk_tooltips_set_tip (priv->tooltips, priv->triangle_colorsel,
1950 _("Select the color you want from the outer ring. Select the darkness or lightness of that color using the inner triangle."), NULL);
1952 hbox = gtk_hbox_new (FALSE, 6);
1953 gtk_box_pack_end (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
1955 frame = gtk_frame_new (NULL);
1956 gtk_widget_set_size_request (frame, -1, 30);
1957 gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
1958 color_sample_new (colorsel);
1959 gtk_container_add (GTK_CONTAINER (frame), priv->sample_area);
1960 gtk_box_pack_start (GTK_BOX (hbox), frame, TRUE, TRUE, 0);
1962 button = gtk_button_new ();
1964 gtk_widget_set_events (button, GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK);
1965 g_object_set_data (G_OBJECT (button), I_("COLORSEL"), colorsel);
1966 g_signal_connect (button, "clicked",
1967 G_CALLBACK (get_screen_color), NULL);
1968 picker_image = gtk_image_new_from_stock (GTK_STOCK_COLOR_PICKER, GTK_ICON_SIZE_BUTTON);
1969 gtk_container_add (GTK_CONTAINER (button), picker_image);
1970 gtk_widget_show (GTK_WIDGET (picker_image));
1971 gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
1973 gtk_tooltips_set_tip (priv->tooltips,
1975 _("Click the eyedropper, then click a color anywhere on your screen to select that color."), NULL);
1977 top_right_vbox = gtk_vbox_new (FALSE, 6);
1978 gtk_box_pack_start (GTK_BOX (top_hbox), top_right_vbox, FALSE, FALSE, 0);
1979 table = gtk_table_new (8, 6, FALSE);
1980 gtk_box_pack_start (GTK_BOX (top_right_vbox), table, FALSE, FALSE, 0);
1981 gtk_table_set_row_spacings (GTK_TABLE (table), 6);
1982 gtk_table_set_col_spacings (GTK_TABLE (table), 12);
1984 make_label_spinbutton (colorsel, &priv->hue_spinbutton, _("_Hue:"), table, 0, 0, COLORSEL_HUE,
1985 _("Position on the color wheel."));
1986 gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (priv->hue_spinbutton), TRUE);
1987 make_label_spinbutton (colorsel, &priv->sat_spinbutton, _("_Saturation:"), table, 0, 1, COLORSEL_SATURATION,
1988 _("\"Deepness\" of the color."));
1989 make_label_spinbutton (colorsel, &priv->val_spinbutton, _("_Value:"), table, 0, 2, COLORSEL_VALUE,
1990 _("Brightness of the color."));
1991 make_label_spinbutton (colorsel, &priv->red_spinbutton, _("_Red:"), table, 6, 0, COLORSEL_RED,
1992 _("Amount of red light in the color."));
1993 make_label_spinbutton (colorsel, &priv->green_spinbutton, _("_Green:"), table, 6, 1, COLORSEL_GREEN,
1994 _("Amount of green light in the color."));
1995 make_label_spinbutton (colorsel, &priv->blue_spinbutton, _("_Blue:"), table, 6, 2, COLORSEL_BLUE,
1996 _("Amount of blue light in the color."));
1997 gtk_table_attach_defaults (GTK_TABLE (table), gtk_hseparator_new (), 0, 8, 3, 4);
1999 priv->opacity_label = gtk_label_new_with_mnemonic (_("Op_acity:"));
2000 gtk_misc_set_alignment (GTK_MISC (priv->opacity_label), 0.0, 0.5);
2001 gtk_table_attach_defaults (GTK_TABLE (table), priv->opacity_label, 0, 1, 4, 5);
2002 adjust = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 255.0, 1.0, 1.0, 0.0));
2003 g_object_set_data (G_OBJECT (adjust), I_("COLORSEL"), colorsel);
2004 priv->opacity_slider = gtk_hscale_new (adjust);
2005 gtk_tooltips_set_tip (priv->tooltips,
2006 priv->opacity_slider,
2007 _("Transparency of the color."), NULL);
2008 gtk_label_set_mnemonic_widget (GTK_LABEL (priv->opacity_label),
2009 priv->opacity_slider);
2010 gtk_scale_set_draw_value (GTK_SCALE (priv->opacity_slider), FALSE);
2011 g_signal_connect (adjust, "value_changed",
2012 G_CALLBACK (adjustment_changed),
2013 GINT_TO_POINTER (COLORSEL_OPACITY));
2014 gtk_table_attach_defaults (GTK_TABLE (table), priv->opacity_slider, 1, 7, 4, 5);
2015 priv->opacity_entry = gtk_entry_new ();
2016 gtk_tooltips_set_tip (priv->tooltips,
2017 priv->opacity_entry,
2018 _("Transparency of the color."), NULL);
2019 gtk_widget_set_size_request (priv->opacity_entry, 40, -1);
2021 g_signal_connect (priv->opacity_entry, "activate",
2022 G_CALLBACK (opacity_entry_changed), colorsel);
2023 gtk_table_attach_defaults (GTK_TABLE (table), priv->opacity_entry, 7, 8, 4, 5);
2025 label = gtk_label_new_with_mnemonic (_("Color _name:"));
2026 gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 5, 6);
2027 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
2028 priv->hex_entry = gtk_entry_new ();
2030 gtk_label_set_mnemonic_widget (GTK_LABEL (label), priv->hex_entry);
2032 g_signal_connect (priv->hex_entry, "activate",
2033 G_CALLBACK (hex_changed), colorsel);
2035 g_signal_connect (priv->hex_entry, "focus_out_event",
2036 G_CALLBACK (hex_focus_out), colorsel);
2038 gtk_tooltips_set_tip (priv->tooltips,
2040 _("You can enter an HTML-style hexadecimal color value, or simply a color name such as 'orange' in this entry."), NULL);
2042 gtk_entry_set_width_chars (GTK_ENTRY (priv->hex_entry), 7);
2043 gtk_table_attach_defaults (GTK_TABLE (table), priv->hex_entry, 1, 5, 5, 6);
2045 focus_chain = g_list_append (focus_chain, priv->hue_spinbutton);
2046 focus_chain = g_list_append (focus_chain, priv->sat_spinbutton);
2047 focus_chain = g_list_append (focus_chain, priv->val_spinbutton);
2048 focus_chain = g_list_append (focus_chain, priv->red_spinbutton);
2049 focus_chain = g_list_append (focus_chain, priv->green_spinbutton);
2050 focus_chain = g_list_append (focus_chain, priv->blue_spinbutton);
2051 focus_chain = g_list_append (focus_chain, priv->opacity_slider);
2052 focus_chain = g_list_append (focus_chain, priv->opacity_entry);
2053 focus_chain = g_list_append (focus_chain, priv->hex_entry);
2054 gtk_container_set_focus_chain (GTK_CONTAINER (table), focus_chain);
2055 g_list_free (focus_chain);
2057 /* Set up the palette */
2058 table = gtk_table_new (GTK_CUSTOM_PALETTE_HEIGHT, GTK_CUSTOM_PALETTE_WIDTH, TRUE);
2059 gtk_table_set_row_spacings (GTK_TABLE (table), 1);
2060 gtk_table_set_col_spacings (GTK_TABLE (table), 1);
2061 for (i = 0; i < GTK_CUSTOM_PALETTE_WIDTH; i++)
2063 for (j = 0; j < GTK_CUSTOM_PALETTE_HEIGHT; j++)
2065 make_palette_frame (colorsel, table, i, j);
2068 set_selected_palette (colorsel, 0, 0);
2069 priv->palette_frame = gtk_vbox_new (FALSE, 6);
2070 label = gtk_label_new_with_mnemonic (_("_Palette:"));
2071 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
2072 gtk_box_pack_start (GTK_BOX (priv->palette_frame), label, FALSE, FALSE, 0);
2074 gtk_label_set_mnemonic_widget (GTK_LABEL (label),
2075 priv->custom_palette[0][0]);
2077 gtk_box_pack_end (GTK_BOX (top_right_vbox), priv->palette_frame, FALSE, FALSE, 0);
2078 gtk_box_pack_start (GTK_BOX (priv->palette_frame), table, FALSE, FALSE, 0);
2080 gtk_widget_show_all (top_hbox);
2082 /* hide unused stuff */
2084 if (priv->has_opacity == FALSE)
2086 gtk_widget_hide (priv->opacity_label);
2087 gtk_widget_hide (priv->opacity_slider);
2088 gtk_widget_hide (priv->opacity_entry);
2091 if (priv->has_palette == FALSE)
2093 gtk_widget_hide (priv->palette_frame);
2096 atk_obj = gtk_widget_get_accessible (priv->triangle_colorsel);
2097 if (GTK_IS_ACCESSIBLE (atk_obj))
2099 atk_object_set_name (atk_obj, _("Color Wheel"));
2100 atk_object_set_role (gtk_widget_get_accessible (GTK_WIDGET (colorsel)), ATK_ROLE_COLOR_CHOOSER);
2101 make_all_relations (atk_obj, priv);
2104 gtk_widget_pop_composite_child ();
2108 gtk_color_selection_destroy (GtkObject *object)
2110 GtkColorSelection *cselection = GTK_COLOR_SELECTION (object);
2111 ColorSelectionPrivate *priv = cselection->private_data;
2113 if (priv->dropper_grab_widget)
2115 gtk_widget_destroy (priv->dropper_grab_widget);
2116 priv->dropper_grab_widget = NULL;
2121 g_object_unref (priv->tooltips);
2122 priv->tooltips = NULL;
2125 GTK_OBJECT_CLASS (parent_class)->destroy (object);
2129 gtk_color_selection_finalize (GObject *object)
2131 G_OBJECT_CLASS (parent_class)->finalize (object);
2135 gtk_color_selection_realize (GtkWidget *widget)
2137 GtkColorSelection *colorsel = GTK_COLOR_SELECTION (widget);
2138 ColorSelectionPrivate *priv = colorsel->private_data;
2139 GtkSettings *settings = gtk_widget_get_settings (widget);
2141 priv->settings_connection = g_signal_connect (settings,
2142 "notify::gtk-color-palette",
2143 G_CALLBACK (palette_change_notify_instance),
2145 update_palette (colorsel);
2147 GTK_WIDGET_CLASS (parent_class)->realize (widget);
2151 gtk_color_selection_unrealize (GtkWidget *widget)
2153 GtkColorSelection *colorsel = GTK_COLOR_SELECTION (widget);
2154 ColorSelectionPrivate *priv = colorsel->private_data;
2155 GtkSettings *settings = gtk_widget_get_settings (widget);
2157 g_signal_handler_disconnect (settings, priv->settings_connection);
2159 GTK_WIDGET_CLASS (parent_class)->unrealize (widget);
2162 /* We override show-all since we have internal widgets that
2163 * shouldn't be shown when you call show_all(), like the
2164 * palette and opacity sliders.
2167 gtk_color_selection_show_all (GtkWidget *widget)
2169 gtk_widget_show (widget);
2173 * gtk_color_selection_new:
2175 * Creates a new GtkColorSelection.
2177 * Return value: a new #GtkColorSelection
2180 gtk_color_selection_new (void)
2182 GtkColorSelection *colorsel;
2183 ColorSelectionPrivate *priv;
2190 colorsel = g_object_new (GTK_TYPE_COLOR_SELECTION, NULL);
2191 priv = colorsel->private_data;
2192 set_color_internal (colorsel, color);
2193 gtk_color_selection_set_has_opacity_control (colorsel, TRUE);
2195 /* We want to make sure that default_set is FALSE */
2196 /* This way the user can still set it */
2197 priv->default_set = FALSE;
2198 priv->default_alpha_set = FALSE;
2200 return GTK_WIDGET (colorsel);
2205 gtk_color_selection_set_update_policy (GtkColorSelection *colorsel,
2206 GtkUpdateType policy)
2208 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2212 * gtk_color_selection_get_has_opacity_control:
2213 * @colorsel: a #GtkColorSelection.
2215 * Determines whether the colorsel has an opacity control.
2217 * Return value: %TRUE if the @colorsel has an opacity control. %FALSE if it does't.
2220 gtk_color_selection_get_has_opacity_control (GtkColorSelection *colorsel)
2222 ColorSelectionPrivate *priv;
2224 g_return_val_if_fail (GTK_IS_COLOR_SELECTION (colorsel), FALSE);
2226 priv = colorsel->private_data;
2228 return priv->has_opacity;
2232 * gtk_color_selection_set_has_opacity_control:
2233 * @colorsel: a #GtkColorSelection.
2234 * @has_opacity: %TRUE if @colorsel can set the opacity, %FALSE otherwise.
2236 * Sets the @colorsel to use or not use opacity.
2240 gtk_color_selection_set_has_opacity_control (GtkColorSelection *colorsel,
2241 gboolean has_opacity)
2243 ColorSelectionPrivate *priv;
2245 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2247 priv = colorsel->private_data;
2248 has_opacity = has_opacity != FALSE;
2250 if (priv->has_opacity != has_opacity)
2252 priv->has_opacity = has_opacity;
2255 gtk_widget_show (priv->opacity_slider);
2256 gtk_widget_show (priv->opacity_label);
2257 gtk_widget_show (priv->opacity_entry);
2261 gtk_widget_hide (priv->opacity_slider);
2262 gtk_widget_hide (priv->opacity_label);
2263 gtk_widget_hide (priv->opacity_entry);
2265 color_sample_update_samples (colorsel);
2267 g_object_notify (G_OBJECT (colorsel), "has-opacity-control");
2272 * gtk_color_selection_get_has_palette:
2273 * @colorsel: a #GtkColorSelection.
2275 * Determines whether the color selector has a color palette.
2277 * Return value: %TRUE if the selector has a palette. %FALSE if it hasn't.
2280 gtk_color_selection_get_has_palette (GtkColorSelection *colorsel)
2282 ColorSelectionPrivate *priv;
2284 g_return_val_if_fail (GTK_IS_COLOR_SELECTION (colorsel), FALSE);
2286 priv = colorsel->private_data;
2288 return priv->has_palette;
2292 * gtk_color_selection_set_has_palette:
2293 * @colorsel: a #GtkColorSelection.
2294 * @has_palette: %TRUE if palette is to be visible, %FALSE otherwise.
2296 * Shows and hides the palette based upon the value of @has_palette.
2300 gtk_color_selection_set_has_palette (GtkColorSelection *colorsel,
2301 gboolean has_palette)
2303 ColorSelectionPrivate *priv;
2304 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2306 priv = colorsel->private_data;
2307 has_palette = has_palette != FALSE;
2309 if (priv->has_palette != has_palette)
2311 priv->has_palette = has_palette;
2313 gtk_widget_show (priv->palette_frame);
2315 gtk_widget_hide (priv->palette_frame);
2317 g_object_notify (G_OBJECT (colorsel), "has-palette");
2322 * gtk_color_selection_set_current_color:
2323 * @colorsel: a #GtkColorSelection.
2324 * @color: A #GdkColor to set the current color with.
2326 * Sets the current color to be @color. The first time this is called, it will
2327 * also set the original color to be @color too.
2330 gtk_color_selection_set_current_color (GtkColorSelection *colorsel,
2331 const GdkColor *color)
2333 ColorSelectionPrivate *priv;
2336 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2337 g_return_if_fail (color != NULL);
2339 priv = colorsel->private_data;
2340 priv->changing = TRUE;
2341 priv->color[COLORSEL_RED] = SCALE (color->red);
2342 priv->color[COLORSEL_GREEN] = SCALE (color->green);
2343 priv->color[COLORSEL_BLUE] = SCALE (color->blue);
2344 gtk_rgb_to_hsv (priv->color[COLORSEL_RED],
2345 priv->color[COLORSEL_GREEN],
2346 priv->color[COLORSEL_BLUE],
2347 &priv->color[COLORSEL_HUE],
2348 &priv->color[COLORSEL_SATURATION],
2349 &priv->color[COLORSEL_VALUE]);
2350 if (priv->default_set == FALSE)
2352 for (i = 0; i < COLORSEL_NUM_CHANNELS; i++)
2353 priv->old_color[i] = priv->color[i];
2355 priv->default_set = TRUE;
2356 update_color (colorsel);
2360 * gtk_color_selection_set_current_alpha:
2361 * @colorsel: a #GtkColorSelection.
2362 * @alpha: an integer between 0 and 65535.
2364 * Sets the current opacity to be @alpha. The first time this is called, it will
2365 * also set the original opacity to be @alpha too.
2368 gtk_color_selection_set_current_alpha (GtkColorSelection *colorsel,
2371 ColorSelectionPrivate *priv;
2374 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2376 priv = colorsel->private_data;
2377 priv->changing = TRUE;
2378 priv->color[COLORSEL_OPACITY] = SCALE (alpha);
2379 if (priv->default_alpha_set == FALSE)
2381 for (i = 0; i < COLORSEL_NUM_CHANNELS; i++)
2382 priv->old_color[i] = priv->color[i];
2384 priv->default_alpha_set = TRUE;
2385 update_color (colorsel);
2389 * gtk_color_selection_set_color:
2390 * @colorsel: a #GtkColorSelection.
2391 * @color: an array of 4 doubles specifying the red, green, blue and opacity
2392 * to set the current color to.
2394 * Sets the current color to be @color. The first time this is called, it will
2395 * also set the original color to be @color too.
2397 * Deprecated: Use gtk_color_selection_set_current_color() instead.
2400 gtk_color_selection_set_color (GtkColorSelection *colorsel,
2403 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2405 set_color_internal (colorsel, color);
2409 * gtk_color_selection_get_current_color:
2410 * @colorsel: a #GtkColorSelection.
2411 * @color: a #GdkColor to fill in with the current color.
2413 * Sets @color to be the current color in the GtkColorSelection widget.
2416 gtk_color_selection_get_current_color (GtkColorSelection *colorsel,
2419 ColorSelectionPrivate *priv;
2421 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2422 g_return_if_fail (color != NULL);
2424 priv = colorsel->private_data;
2425 color->red = UNSCALE (priv->color[COLORSEL_RED]);
2426 color->green = UNSCALE (priv->color[COLORSEL_GREEN]);
2427 color->blue = UNSCALE (priv->color[COLORSEL_BLUE]);
2431 * gtk_color_selection_get_current_alpha:
2432 * @colorsel: a #GtkColorSelection.
2434 * Returns the current alpha value.
2436 * Return value: an integer between 0 and 65535.
2439 gtk_color_selection_get_current_alpha (GtkColorSelection *colorsel)
2441 ColorSelectionPrivate *priv;
2443 g_return_val_if_fail (GTK_IS_COLOR_SELECTION (colorsel), 0);
2445 priv = colorsel->private_data;
2446 return priv->has_opacity ? UNSCALE (priv->color[COLORSEL_OPACITY]) : 65535;
2450 * gtk_color_selection_get_color:
2451 * @colorsel: a #GtkColorSelection.
2452 * @color: an array of 4 #gdouble to fill in with the current color.
2454 * Sets @color to be the current color in the GtkColorSelection widget.
2456 * This function is deprecated, use gtk_color_selection_get_current_color() instead.
2459 gtk_color_selection_get_color (GtkColorSelection *colorsel,
2462 ColorSelectionPrivate *priv;
2464 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2466 priv = colorsel->private_data;
2467 color[0] = priv->color[COLORSEL_RED];
2468 color[1] = priv->color[COLORSEL_GREEN];
2469 color[2] = priv->color[COLORSEL_BLUE];
2470 color[3] = priv->has_opacity ? priv->color[COLORSEL_OPACITY] : 65535;
2474 * gtk_color_selection_set_previous_color:
2475 * @colorsel: a #GtkColorSelection.
2476 * @color: a #GdkColor to set the previous color with.
2478 * Sets the 'previous' color to be @color. This function should be called with
2479 * some hesitations, as it might seem confusing to have that color change.
2480 * Calling gtk_color_selection_set_current_color() will also set this color the first
2481 * time it is called.
2484 gtk_color_selection_set_previous_color (GtkColorSelection *colorsel,
2485 const GdkColor *color)
2487 ColorSelectionPrivate *priv;
2489 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2490 g_return_if_fail (color != NULL);
2492 priv = colorsel->private_data;
2493 priv->changing = TRUE;
2494 priv->old_color[COLORSEL_RED] = SCALE (color->red);
2495 priv->old_color[COLORSEL_GREEN] = SCALE (color->green);
2496 priv->old_color[COLORSEL_BLUE] = SCALE (color->blue);
2497 gtk_rgb_to_hsv (priv->old_color[COLORSEL_RED],
2498 priv->old_color[COLORSEL_GREEN],
2499 priv->old_color[COLORSEL_BLUE],
2500 &priv->old_color[COLORSEL_HUE],
2501 &priv->old_color[COLORSEL_SATURATION],
2502 &priv->old_color[COLORSEL_VALUE]);
2503 color_sample_update_samples (colorsel);
2504 priv->default_set = TRUE;
2505 priv->changing = FALSE;
2509 * gtk_color_selection_set_previous_alpha:
2510 * @colorsel: a #GtkColorSelection.
2511 * @alpha: an integer between 0 and 65535.
2513 * Sets the 'previous' alpha to be @alpha. This function should be called with
2514 * some hesitations, as it might seem confusing to have that alpha change.
2517 gtk_color_selection_set_previous_alpha (GtkColorSelection *colorsel,
2520 ColorSelectionPrivate *priv;
2522 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2524 priv = colorsel->private_data;
2525 priv->changing = TRUE;
2526 priv->old_color[COLORSEL_OPACITY] = SCALE (alpha);
2527 color_sample_update_samples (colorsel);
2528 priv->default_alpha_set = TRUE;
2529 priv->changing = FALSE;
2534 * gtk_color_selection_get_previous_color:
2535 * @colorsel: a #GtkColorSelection.
2536 * @color: a #GdkColor to fill in with the original color value.
2538 * Fills @color in with the original color value.
2541 gtk_color_selection_get_previous_color (GtkColorSelection *colorsel,
2544 ColorSelectionPrivate *priv;
2546 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2547 g_return_if_fail (color != NULL);
2549 priv = colorsel->private_data;
2550 color->red = UNSCALE (priv->old_color[COLORSEL_RED]);
2551 color->green = UNSCALE (priv->old_color[COLORSEL_GREEN]);
2552 color->blue = UNSCALE (priv->old_color[COLORSEL_BLUE]);
2556 * gtk_color_selection_get_previous_alpha:
2557 * @colorsel: a #GtkColorSelection.
2559 * Returns the previous alpha value.
2561 * Return value: an integer between 0 and 65535.
2564 gtk_color_selection_get_previous_alpha (GtkColorSelection *colorsel)
2566 ColorSelectionPrivate *priv;
2568 g_return_val_if_fail (GTK_IS_COLOR_SELECTION (colorsel), 0);
2570 priv = colorsel->private_data;
2571 return priv->has_opacity ? UNSCALE (priv->old_color[COLORSEL_OPACITY]) : 65535;
2575 * gtk_color_selection_set_palette_color:
2576 * @colorsel: a #GtkColorSelection.
2577 * @index: the color index of the palette.
2578 * @color: A #GdkColor to set the palette with.
2580 * Sets the palette located at @index to have @color as its color.
2584 gtk_color_selection_set_palette_color (GtkColorSelection *colorsel,
2588 ColorSelectionPrivate *priv;
2592 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2593 g_return_if_fail (index >= 0 && index < GTK_CUSTOM_PALETTE_WIDTH*GTK_CUSTOM_PALETTE_HEIGHT);
2595 x = index % GTK_CUSTOM_PALETTE_WIDTH;
2596 y = index / GTK_CUSTOM_PALETTE_WIDTH;
2598 priv = colorsel->private_data;
2599 col[0] = SCALE (color->red);
2600 col[1] = SCALE (color->green);
2601 col[2] = SCALE (color->blue);
2603 palette_set_color (priv->custom_palette[x][y], colorsel, col);
2607 * gtk_color_selection_is_adjusting:
2608 * @colorsel: a #GtkColorSelection.
2610 * Gets the current state of the @colorsel.
2612 * Return value: %TRUE if the user is currently dragging a color around, and %FALSE
2613 * if the selection has stopped.
2616 gtk_color_selection_is_adjusting (GtkColorSelection *colorsel)
2618 ColorSelectionPrivate *priv;
2620 g_return_val_if_fail (GTK_IS_COLOR_SELECTION (colorsel), FALSE);
2622 priv = colorsel->private_data;
2624 return (gtk_hsv_is_adjusting (GTK_HSV (priv->triangle_colorsel)));
2628 gtk_color_selection_set_property (GObject *object,
2630 const GValue *value,
2633 GtkColorSelection *colorsel = GTK_COLOR_SELECTION (object);
2637 case PROP_HAS_OPACITY_CONTROL:
2638 gtk_color_selection_set_has_opacity_control (colorsel,
2639 g_value_get_boolean (value));
2641 case PROP_HAS_PALETTE:
2642 gtk_color_selection_set_has_palette (colorsel,
2643 g_value_get_boolean (value));
2645 case PROP_CURRENT_COLOR:
2646 gtk_color_selection_set_current_color (colorsel, g_value_get_boxed (value));
2648 case PROP_CURRENT_ALPHA:
2649 gtk_color_selection_set_current_alpha (colorsel, g_value_get_uint (value));
2652 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
2659 gtk_color_selection_get_property (GObject *object,
2664 GtkColorSelection *colorsel = GTK_COLOR_SELECTION (object);
2669 case PROP_HAS_OPACITY_CONTROL:
2670 g_value_set_boolean (value, gtk_color_selection_get_has_opacity_control (colorsel));
2672 case PROP_HAS_PALETTE:
2673 g_value_set_boolean (value, gtk_color_selection_get_has_palette (colorsel));
2675 case PROP_CURRENT_COLOR:
2676 gtk_color_selection_get_current_color (colorsel, &color);
2677 g_value_set_boxed (value, &color);
2679 case PROP_CURRENT_ALPHA:
2680 g_value_set_uint (value, gtk_color_selection_get_current_alpha (colorsel));
2683 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
2690 * gtk_color_selection_palette_from_string:
2691 * @str: a string encoding a color palette.
2692 * @colors: return location for allocated array of #GdkColor.
2693 * @n_colors: return location for length of array.
2695 * Parses a color palette string; the string is a colon-separated
2696 * list of color names readable by gdk_color_parse().
2698 * Return value: %TRUE if a palette was successfully parsed.
2701 gtk_color_selection_palette_from_string (const gchar *str,
2713 copy = g_strdup (str);
2719 if (*p == ':' || *p == '\0')
2721 gboolean done = TRUE;
2725 goto failed; /* empty entry */
2734 retval = g_renew (GdkColor, retval, count + 1);
2735 if (!gdk_color_parse (start, retval + count))
2776 * gtk_color_selection_palette_to_string:
2777 * @colors: an array of colors.
2778 * @n_colors: length of the array.
2780 * Encodes a palette as a string, useful for persistent storage.
2782 * Return value: allocated string encoding the palette.
2785 gtk_color_selection_palette_to_string (const GdkColor *colors,
2789 gchar **strs = NULL;
2793 return g_strdup ("");
2795 strs = g_new0 (gchar*, n_colors + 1);
2798 while (i < n_colors)
2803 g_strdup_printf ("#%2X%2X%2X",
2804 colors[i].red / 256,
2805 colors[i].green / 256,
2806 colors[i].blue / 256);
2808 for (ptr = strs[i]; *ptr; ptr++)
2815 retval = g_strjoinv (":", strs);
2823 * gtk_color_selection_set_change_palette_hook:
2824 * @func: a function to call when the custom palette needs saving.
2826 * Installs a global function to be called whenever the user tries to
2827 * modify the palette in a color selection. This function should save
2828 * the new palette contents, and update the GtkSettings property
2829 * "gtk-color-palette" so all GtkColorSelection widgets will be modified.
2831 * Return value: the previous change palette hook (that was replaced).
2833 * Deprecated: This function is deprecated in favor of
2834 * gtk_color_selection_set_change_palette_with_screen_hook(), and does
2835 * not work in multihead environments.
2838 GtkColorSelectionChangePaletteFunc
2839 gtk_color_selection_set_change_palette_hook (GtkColorSelectionChangePaletteFunc func)
2841 GtkColorSelectionChangePaletteFunc old;
2843 old = noscreen_change_palette_hook;
2845 noscreen_change_palette_hook = func;
2851 * gtk_color_selection_set_change_palette_with_screen_hook:
2852 * @func: a function to call when the custom palette needs saving.
2854 * Installs a global function to be called whenever the user tries to
2855 * modify the palette in a color selection. This function should save
2856 * the new palette contents, and update the GtkSettings property
2857 * "gtk-color-palette" so all GtkColorSelection widgets will be modified.
2859 * Return value: the previous change palette hook (that was replaced).
2863 GtkColorSelectionChangePaletteWithScreenFunc
2864 gtk_color_selection_set_change_palette_with_screen_hook (GtkColorSelectionChangePaletteWithScreenFunc func)
2866 GtkColorSelectionChangePaletteWithScreenFunc old;
2868 old = change_palette_hook;
2870 change_palette_hook = func;
2876 make_control_relations (AtkObject *atk_obj,
2881 obj = gtk_widget_get_accessible (widget);
2882 atk_object_add_relationship (atk_obj, ATK_RELATION_CONTROLLED_BY, obj);
2883 atk_object_add_relationship (obj, ATK_RELATION_CONTROLLER_FOR, atk_obj);
2887 make_all_relations (AtkObject *atk_obj,
2888 ColorSelectionPrivate *priv)
2890 make_control_relations (atk_obj, priv->hue_spinbutton);
2891 make_control_relations (atk_obj, priv->sat_spinbutton);
2892 make_control_relations (atk_obj, priv->val_spinbutton);
2893 make_control_relations (atk_obj, priv->red_spinbutton);
2894 make_control_relations (atk_obj, priv->green_spinbutton);
2895 make_control_relations (atk_obj, priv->blue_spinbutton);
2898 #define __GTK_COLOR_SELECTION_C__
2899 #include "gtkaliasdef.c"