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"
61 #include "gtkaccessible.h"
66 /* Number of elements in the custom palatte */
67 #define GTK_CUSTOM_PALETTE_WIDTH 10
68 #define GTK_CUSTOM_PALETTE_HEIGHT 2
70 /* Conversion between 0->1 double and and guint16. See
71 * scale_round() below for more general conversions
73 #define SCALE(i) (i / 65535.)
74 #define UNSCALE(d) ((guint16)(d * 65535 + 0.5))
85 PROP_HAS_OPACITY_CONTROL,
101 typedef struct _ColorSelectionPrivate ColorSelectionPrivate;
103 struct _ColorSelectionPrivate
105 guint has_opacity : 1;
106 guint has_palette : 1;
108 guint default_set : 1;
109 guint default_alpha_set : 1;
111 gdouble color[COLORSEL_NUM_CHANNELS];
112 gdouble old_color[COLORSEL_NUM_CHANNELS];
114 GtkWidget *triangle_colorsel;
115 GtkWidget *hue_spinbutton;
116 GtkWidget *sat_spinbutton;
117 GtkWidget *val_spinbutton;
118 GtkWidget *red_spinbutton;
119 GtkWidget *green_spinbutton;
120 GtkWidget *blue_spinbutton;
121 GtkWidget *opacity_slider;
122 GtkWidget *opacity_label;
123 GtkWidget *opacity_entry;
124 GtkWidget *palette_frame;
125 GtkWidget *hex_entry;
127 /* The Palette code */
128 GtkWidget *custom_palette [GTK_CUSTOM_PALETTE_WIDTH][GTK_CUSTOM_PALETTE_HEIGHT];
130 /* The color_sample stuff */
131 GtkWidget *sample_area;
132 GtkWidget *old_sample;
133 GtkWidget *cur_sample;
137 GtkTooltips *tooltips;
139 /* Window for grabbing on */
140 GtkWidget *dropper_grab_widget;
142 /* Connection to settings */
143 gulong settings_connection;
147 static void gtk_color_selection_init (GtkColorSelection *colorsel);
148 static void gtk_color_selection_class_init (GtkColorSelectionClass *klass);
149 static void gtk_color_selection_destroy (GtkObject *object);
150 static void gtk_color_selection_finalize (GObject *object);
151 static void update_color (GtkColorSelection *colorsel);
152 static void gtk_color_selection_set_property (GObject *object,
156 static void gtk_color_selection_get_property (GObject *object,
161 static void gtk_color_selection_realize (GtkWidget *widget);
162 static void gtk_color_selection_unrealize (GtkWidget *widget);
163 static void gtk_color_selection_show_all (GtkWidget *widget);
165 static void gtk_color_selection_set_palette_color (GtkColorSelection *colorsel,
168 static void set_focus_line_attributes (GtkWidget *drawing_area,
171 static void default_noscreen_change_palette_func (const GdkColor *colors,
173 static void default_change_palette_func (GdkScreen *screen,
174 const GdkColor *colors,
176 static void make_control_relations (AtkObject *atk_obj,
178 static void make_all_relations (AtkObject *atk_obj,
179 ColorSelectionPrivate *priv);
181 static gpointer parent_class = NULL;
182 static guint color_selection_signals[LAST_SIGNAL] = { 0 };
184 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";
186 static GtkColorSelectionChangePaletteFunc noscreen_change_palette_hook = default_noscreen_change_palette_func;
187 static GtkColorSelectionChangePaletteWithScreenFunc change_palette_hook = default_change_palette_func;
189 /* The cursor for the dropper */
190 #define DROPPER_WIDTH 17
191 #define DROPPER_HEIGHT 17
192 #define DROPPER_X_HOT 2
193 #define DROPPER_Y_HOT 16
196 static const guchar dropper_bits[] = {
197 0xff, 0x8f, 0x01, 0xff, 0x77, 0x01, 0xff, 0xfb, 0x00, 0xff, 0xf8, 0x00,
198 0x7f, 0xff, 0x00, 0xff, 0x7e, 0x01, 0xff, 0x9d, 0x01, 0xff, 0xd8, 0x01,
199 0x7f, 0xd4, 0x01, 0x3f, 0xee, 0x01, 0x1f, 0xff, 0x01, 0x8f, 0xff, 0x01,
200 0xc7, 0xff, 0x01, 0xe3, 0xff, 0x01, 0xf3, 0xff, 0x01, 0xfd, 0xff, 0x01,
203 static const guchar dropper_mask[] = {
204 0x00, 0x70, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xfc, 0x01, 0x00, 0xff, 0x01,
205 0x80, 0xff, 0x01, 0x00, 0xff, 0x00, 0x00, 0x7f, 0x00, 0x80, 0x3f, 0x00,
206 0xc0, 0x3f, 0x00, 0xe0, 0x13, 0x00, 0xf0, 0x01, 0x00, 0xf8, 0x00, 0x00,
207 0x7c, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x0d, 0x00, 0x00,
216 #define SAMPLE_WIDTH 64
217 #define SAMPLE_HEIGHT 28
219 static void color_sample_draw_sample (GtkColorSelection *colorsel, int which);
220 static void color_sample_update_samples (GtkColorSelection *colorsel);
223 set_color_internal (GtkColorSelection *colorsel,
226 ColorSelectionPrivate *priv;
229 priv = colorsel->private_data;
230 priv->changing = TRUE;
231 priv->color[COLORSEL_RED] = color[0];
232 priv->color[COLORSEL_GREEN] = color[1];
233 priv->color[COLORSEL_BLUE] = color[2];
234 priv->color[COLORSEL_OPACITY] = color[3];
235 gtk_rgb_to_hsv (priv->color[COLORSEL_RED],
236 priv->color[COLORSEL_GREEN],
237 priv->color[COLORSEL_BLUE],
238 &priv->color[COLORSEL_HUE],
239 &priv->color[COLORSEL_SATURATION],
240 &priv->color[COLORSEL_VALUE]);
241 if (priv->default_set == FALSE)
243 for (i = 0; i < COLORSEL_NUM_CHANNELS; i++)
244 priv->old_color[i] = priv->color[i];
246 priv->default_set = TRUE;
247 priv->default_alpha_set = TRUE;
248 update_color (colorsel);
252 set_color_icon (GdkDragContext *context,
258 pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE,
261 pixel = (((UNSCALE (colors[COLORSEL_RED]) & 0xff00) << 16) |
262 ((UNSCALE (colors[COLORSEL_GREEN]) & 0xff00) << 8) |
263 ((UNSCALE (colors[COLORSEL_BLUE]) & 0xff00)));
265 gdk_pixbuf_fill (pixbuf, pixel);
267 gtk_drag_set_icon_pixbuf (context, pixbuf, -2, -2);
268 g_object_unref (pixbuf);
272 color_sample_drag_begin (GtkWidget *widget,
273 GdkDragContext *context,
276 GtkColorSelection *colorsel = data;
277 ColorSelectionPrivate *priv;
280 priv = colorsel->private_data;
282 if (widget == priv->old_sample)
283 colsrc = priv->old_color;
285 colsrc = priv->color;
287 set_color_icon (context, colsrc);
291 color_sample_drag_end (GtkWidget *widget,
292 GdkDragContext *context,
295 g_object_set_data (G_OBJECT (widget), "gtk-color-selection-drag-window", NULL);
299 color_sample_drop_handle (GtkWidget *widget,
300 GdkDragContext *context,
303 GtkSelectionData *selection_data,
308 GtkColorSelection *colorsel = data;
309 ColorSelectionPrivate *priv;
312 priv = colorsel->private_data;
314 /* This is currently a guint16 array of the format:
321 if (selection_data->length < 0)
324 /* We accept drops with the wrong format, since the KDE color
325 * chooser incorrectly drops application/x-color with format 8.
327 if (selection_data->length != 8)
329 g_warning ("Received invalid color data\n");
333 vals = (guint16 *)selection_data->data;
335 if (widget == priv->cur_sample)
337 color[0] = (gdouble)vals[0] / 0xffff;
338 color[1] = (gdouble)vals[1] / 0xffff;
339 color[2] = (gdouble)vals[2] / 0xffff;
340 color[3] = (gdouble)vals[3] / 0xffff;
342 set_color_internal (colorsel, color);
347 color_sample_drag_handle (GtkWidget *widget,
348 GdkDragContext *context,
349 GtkSelectionData *selection_data,
354 GtkColorSelection *colorsel = data;
355 ColorSelectionPrivate *priv;
359 priv = colorsel->private_data;
361 if (widget == priv->old_sample)
362 colsrc = priv->old_color;
364 colsrc = priv->color;
366 vals[0] = colsrc[COLORSEL_RED] * 0xffff;
367 vals[1] = colsrc[COLORSEL_GREEN] * 0xffff;
368 vals[2] = colsrc[COLORSEL_BLUE] * 0xffff;
369 vals[3] = priv->has_opacity ? colsrc[COLORSEL_OPACITY] * 0xffff : 0xffff;
371 gtk_selection_data_set (selection_data,
372 gdk_atom_intern ("application/x-color", FALSE),
373 16, (guchar *)vals, 8);
376 /* which = 0 means draw old sample, which = 1 means draw new */
378 color_sample_draw_sample (GtkColorSelection *colorsel, int which)
381 gint x, y, wid, heig, goff;
382 ColorSelectionPrivate *priv;
385 g_return_if_fail (colorsel != NULL);
386 priv = colorsel->private_data;
388 g_return_if_fail (priv->sample_area != NULL);
389 if (!GTK_WIDGET_DRAWABLE (priv->sample_area))
394 da = priv->old_sample;
399 da = priv->cur_sample;
400 goff = priv->old_sample->allocation.width % 32;
403 cr = gdk_drawable_create_cairo_context (da->window);
405 wid = da->allocation.width;
406 heig = da->allocation.height;
408 /* Below needs tweaking for non-power-of-two */
409 #define CHECK_SIZE 16
411 if (priv->has_opacity)
413 /* Draw checks in background */
415 cairo_set_rgb_color (cr, 0.5, 0.5, 0.5);
416 cairo_rectangle (cr, 0, 0, wid, heig);
419 cairo_set_rgb_color (cr, 0.75, 0.75, 0.75);
420 for (x = goff & -CHECK_SIZE; x < goff + wid; x += CHECK_SIZE)
421 for (y = 0; y < heig; y += CHECK_SIZE)
422 if ((x / CHECK_SIZE + y / CHECK_SIZE) % 2 == 0)
423 cairo_rectangle (cr, x - goff, y, CHECK_SIZE, CHECK_SIZE);
429 cairo_set_rgb_color (cr,
430 priv->old_color[COLORSEL_RED],
431 priv->old_color[COLORSEL_GREEN],
432 priv->old_color[COLORSEL_BLUE]);
433 if (priv->has_opacity)
434 cairo_set_alpha (cr, priv->old_color[COLORSEL_OPACITY]);
438 cairo_set_rgb_color (cr,
439 priv->color[COLORSEL_RED],
440 priv->color[COLORSEL_GREEN],
441 priv->color[COLORSEL_BLUE]);
442 if (priv->has_opacity)
443 cairo_set_alpha (cr, priv->color[COLORSEL_OPACITY]);
446 cairo_rectangle (cr, 0, 0, wid, heig);
454 color_sample_update_samples (GtkColorSelection *colorsel)
456 ColorSelectionPrivate *priv = colorsel->private_data;
457 gtk_widget_queue_draw (priv->old_sample);
458 gtk_widget_queue_draw (priv->cur_sample);
462 color_old_sample_expose (GtkWidget *da,
463 GdkEventExpose *event,
464 GtkColorSelection *colorsel)
466 color_sample_draw_sample (colorsel, 0);
472 color_cur_sample_expose (GtkWidget *da,
473 GdkEventExpose *event,
474 GtkColorSelection *colorsel)
476 color_sample_draw_sample (colorsel, 1);
481 color_sample_setup_dnd (GtkColorSelection *colorsel, GtkWidget *sample)
483 static const GtkTargetEntry targets[] = {
484 { "application/x-color", 0 }
486 ColorSelectionPrivate *priv;
487 priv = colorsel->private_data;
489 gtk_drag_source_set (sample,
490 GDK_BUTTON1_MASK | GDK_BUTTON3_MASK,
492 GDK_ACTION_COPY | GDK_ACTION_MOVE);
494 g_signal_connect (sample,
496 G_CALLBACK (color_sample_drag_begin),
498 if (sample == priv->cur_sample)
501 gtk_drag_dest_set (sample,
502 GTK_DEST_DEFAULT_HIGHLIGHT |
503 GTK_DEST_DEFAULT_MOTION |
504 GTK_DEST_DEFAULT_DROP,
508 g_signal_connect (sample,
510 G_CALLBACK (color_sample_drag_end),
514 g_signal_connect (sample,
516 G_CALLBACK (color_sample_drag_handle),
518 g_signal_connect (sample,
519 "drag_data_received",
520 G_CALLBACK (color_sample_drop_handle),
527 color_sample_new (GtkColorSelection *colorsel)
529 ColorSelectionPrivate *priv;
531 priv = colorsel->private_data;
533 priv->sample_area = gtk_hbox_new (FALSE, 0);
534 priv->old_sample = gtk_drawing_area_new ();
535 priv->cur_sample = gtk_drawing_area_new ();
537 /* We need enter/leave to do tooltips */
538 gtk_widget_add_events (priv->old_sample,
539 GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK);
540 gtk_widget_add_events (priv->cur_sample,
541 GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK);
543 gtk_box_pack_start (GTK_BOX (priv->sample_area), priv->old_sample,
545 gtk_box_pack_start (GTK_BOX (priv->sample_area), priv->cur_sample,
548 g_signal_connect (priv->old_sample, "expose_event",
549 G_CALLBACK (color_old_sample_expose),
551 g_signal_connect (priv->cur_sample, "expose_event",
552 G_CALLBACK (color_cur_sample_expose),
555 color_sample_setup_dnd (colorsel, priv->old_sample);
556 color_sample_setup_dnd (colorsel, priv->cur_sample);
558 gtk_tooltips_set_tip (priv->tooltips,
560 _("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);
563 gtk_tooltips_set_tip (priv->tooltips,
565 _("The color you've chosen. You can drag this color to a palette entry to save it for use in the future."), NULL);
567 gtk_widget_show_all (priv->sample_area);
573 * The palette area code
576 #define CUSTOM_PALETTE_ENTRY_WIDTH 20
577 #define CUSTOM_PALETTE_ENTRY_HEIGHT 20
580 palette_get_color (GtkWidget *drawing_area, gdouble *color)
584 g_return_if_fail (color != NULL);
586 color_val = g_object_get_data (G_OBJECT (drawing_area), "color_val");
587 if (color_val == NULL)
589 /* Default to white for no good reason */
597 color[0] = color_val[0];
598 color[1] = color_val[1];
599 color[2] = color_val[2];
603 #define INTENSITY(r, g, b) ((r) * 0.30 + (g) * 0.59 + (b) * 0.11)
605 palette_paint (GtkWidget *drawing_area,
612 if (drawing_area->window == NULL)
615 cr = gdk_drawable_create_cairo_context (drawing_area->window);
617 gdk_cairo_set_source_color (cr, &drawing_area->style->bg[GTK_STATE_NORMAL]);
619 area->x, area->y, area->width, area->height);
622 if (GTK_WIDGET_HAS_FOCUS (drawing_area))
624 set_focus_line_attributes (drawing_area, cr, &focus_width);
625 g_print ("%g %g %g %g\n",
626 focus_width / 2., focus_width / 2.,
627 (double)drawing_area->allocation.width - focus_width,
628 (double)drawing_area->allocation.height - focus_width);
631 focus_width / 2., focus_width / 2.,
632 drawing_area->allocation.width - focus_width,
633 drawing_area->allocation.height - focus_width);
641 set_focus_line_attributes (GtkWidget *drawing_area,
648 gtk_widget_style_get (drawing_area,
649 "focus-line-width", focus_width,
650 "focus-line-pattern", (gchar *)&dash_list,
653 palette_get_color (drawing_area, color);
655 if (INTENSITY (color[0], color[1], color[2]) > 0.5)
656 cairo_set_rgb_color (cr, 0., 0., 0.);
658 cairo_set_rgb_color (cr, 1., 1., 1.);
660 cairo_set_line_width (cr, *focus_width);
664 gint n_dashes = strlen (dash_list);
665 gdouble *dashes = g_new (gdouble, n_dashes);
666 gdouble total_length = 0;
670 for (i = 0; i < n_dashes; i++)
672 dashes[i] = dash_list[i];
673 total_length += dash_list[i];
676 /* The dash offset here aligns the pattern to integer pixels
677 * by starting the dash at the right side of the left border
678 * Negative dash offsets in cairo don't work
679 * (https://bugs.freedesktop.org/show_bug.cgi?id=2729)
681 dash_offset = - *focus_width / 2.;
682 while (dash_offset < 0)
683 dash_offset += total_length;
685 cairo_set_dash (cr, dashes, n_dashes, dash_offset);
693 palette_drag_begin (GtkWidget *widget,
694 GdkDragContext *context,
699 palette_get_color (widget, colors);
700 set_color_icon (context, colors);
704 palette_drag_handle (GtkWidget *widget,
705 GdkDragContext *context,
706 GtkSelectionData *selection_data,
714 palette_get_color (widget, colsrc);
716 vals[0] = colsrc[COLORSEL_RED] * 0xffff;
717 vals[1] = colsrc[COLORSEL_GREEN] * 0xffff;
718 vals[2] = colsrc[COLORSEL_BLUE] * 0xffff;
721 gtk_selection_data_set (selection_data,
722 gdk_atom_intern ("application/x-color", FALSE),
723 16, (guchar *)vals, 8);
727 palette_drag_end (GtkWidget *widget,
728 GdkDragContext *context,
731 g_object_set_data (G_OBJECT (widget), "gtk-color-selection-drag-window", NULL);
735 get_current_colors (GtkColorSelection *colorsel)
737 GtkSettings *settings;
738 GdkColor *colors = NULL;
742 settings = gtk_widget_get_settings (GTK_WIDGET (colorsel));
743 g_object_get (settings,
744 "gtk-color-palette", &palette,
747 if (!gtk_color_selection_palette_from_string (palette, &colors, &n_colors))
749 gtk_color_selection_palette_from_string (default_colors, &colors, &n_colors);
753 /* If there are less colors provided than the number of slots in the
754 * color selection, we fill in the rest from the defaults.
756 if (n_colors < (GTK_CUSTOM_PALETTE_WIDTH * GTK_CUSTOM_PALETTE_HEIGHT))
758 GdkColor *tmp_colors = colors;
759 gint tmp_n_colors = n_colors;
761 gtk_color_selection_palette_from_string (default_colors, &colors, &n_colors);
762 memcpy (colors, tmp_colors, sizeof (GdkColor) * tmp_n_colors);
768 g_assert (n_colors >= GTK_CUSTOM_PALETTE_WIDTH * GTK_CUSTOM_PALETTE_HEIGHT);
774 /* Changes the model color */
776 palette_change_color (GtkWidget *drawing_area,
777 GtkColorSelection *colorsel,
781 ColorSelectionPrivate *priv;
783 GdkColor *current_colors;
786 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
787 g_return_if_fail (GTK_IS_DRAWING_AREA (drawing_area));
789 priv = colorsel->private_data;
791 gdk_color.red = UNSCALE (color[0]);
792 gdk_color.green = UNSCALE (color[1]);
793 gdk_color.blue = UNSCALE (color[2]);
796 y = 0; /* Quiet GCC */
797 while (x < GTK_CUSTOM_PALETTE_WIDTH)
800 while (y < GTK_CUSTOM_PALETTE_HEIGHT)
802 if (priv->custom_palette[x][y] == drawing_area)
813 g_assert (x < GTK_CUSTOM_PALETTE_WIDTH || y < GTK_CUSTOM_PALETTE_HEIGHT);
815 current_colors = get_current_colors (colorsel);
816 current_colors[y * GTK_CUSTOM_PALETTE_WIDTH + x] = gdk_color;
818 screen = gtk_widget_get_screen (GTK_WIDGET (colorsel));
819 if (change_palette_hook != default_change_palette_func)
820 (* change_palette_hook) (screen, current_colors,
821 GTK_CUSTOM_PALETTE_WIDTH * GTK_CUSTOM_PALETTE_HEIGHT);
822 else if (noscreen_change_palette_hook != default_noscreen_change_palette_func)
824 if (screen != gdk_screen_get_default ())
825 g_warning ("gtk_color_selection_set_change_palette_hook used by widget is not on the default screen.");
826 (* noscreen_change_palette_hook) (current_colors,
827 GTK_CUSTOM_PALETTE_WIDTH * GTK_CUSTOM_PALETTE_HEIGHT);
830 (* change_palette_hook) (screen, current_colors,
831 GTK_CUSTOM_PALETTE_WIDTH * GTK_CUSTOM_PALETTE_HEIGHT);
833 g_free (current_colors);
836 /* Changes the view color */
838 palette_set_color (GtkWidget *drawing_area,
839 GtkColorSelection *colorsel,
842 gdouble *new_color = g_new (double, 4);
845 gdk_color.red = UNSCALE (color[0]);
846 gdk_color.green = UNSCALE (color[1]);
847 gdk_color.blue = UNSCALE (color[2]);
849 gtk_widget_modify_bg (drawing_area, GTK_STATE_NORMAL, &gdk_color);
851 if (GPOINTER_TO_INT (g_object_get_data (G_OBJECT (drawing_area), "color_set")) == 0)
853 static const GtkTargetEntry targets[] = {
854 { "application/x-color", 0 }
856 gtk_drag_source_set (drawing_area,
857 GDK_BUTTON1_MASK | GDK_BUTTON3_MASK,
859 GDK_ACTION_COPY | GDK_ACTION_MOVE);
861 g_signal_connect (drawing_area,
863 G_CALLBACK (palette_drag_begin),
865 g_signal_connect (drawing_area,
867 G_CALLBACK (palette_drag_handle),
870 g_object_set_data (G_OBJECT (drawing_area), "color_set",
871 GINT_TO_POINTER (1));
874 new_color[0] = color[0];
875 new_color[1] = color[1];
876 new_color[2] = color[2];
879 g_object_set_data_full (G_OBJECT (drawing_area), "color_val", new_color, (GDestroyNotify)g_free);
883 palette_expose (GtkWidget *drawing_area,
884 GdkEventExpose *event,
887 if (drawing_area->window == NULL)
890 palette_paint (drawing_area, &(event->area), data);
896 popup_position_func (GtkMenu *menu,
907 widget = GTK_WIDGET (user_data);
909 g_return_if_fail (GTK_WIDGET_REALIZED (widget));
911 gdk_window_get_origin (widget->window, &root_x, &root_y);
913 gtk_widget_size_request (GTK_WIDGET (menu), &req);
915 /* Put corner of menu centered on color cell */
916 *x = root_x + widget->allocation.width / 2;
917 *y = root_y + widget->allocation.height / 2;
920 screen = gtk_widget_get_screen (widget);
921 *x = CLAMP (*x, 0, MAX (0, gdk_screen_get_width (screen) - req.width));
922 *y = CLAMP (*y, 0, MAX (0, gdk_screen_get_height (screen) - req.height));
926 save_color_selected (GtkWidget *menuitem,
929 GtkColorSelection *colorsel;
930 GtkWidget *drawing_area;
931 ColorSelectionPrivate *priv;
933 drawing_area = GTK_WIDGET (data);
935 colorsel = GTK_COLOR_SELECTION (g_object_get_data (G_OBJECT (drawing_area),
938 priv = colorsel->private_data;
940 palette_change_color (drawing_area, colorsel, priv->color);
944 do_popup (GtkColorSelection *colorsel,
945 GtkWidget *drawing_area,
951 g_object_set_data (G_OBJECT (drawing_area),
955 menu = gtk_menu_new ();
957 mi = gtk_menu_item_new_with_mnemonic (_("_Save color here"));
959 g_signal_connect (mi, "activate",
960 G_CALLBACK (save_color_selected),
963 gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
965 gtk_widget_show_all (mi);
967 gtk_menu_popup (GTK_MENU (menu), NULL, NULL,
968 popup_position_func, drawing_area,
974 palette_enter (GtkWidget *drawing_area,
975 GdkEventCrossing *event,
978 g_object_set_data (G_OBJECT (drawing_area),
979 "gtk-colorsel-have-pointer",
980 GUINT_TO_POINTER (TRUE));
986 palette_leave (GtkWidget *drawing_area,
987 GdkEventCrossing *event,
990 g_object_set_data (G_OBJECT (drawing_area),
991 "gtk-colorsel-have-pointer",
998 palette_press (GtkWidget *drawing_area,
999 GdkEventButton *event,
1002 GtkColorSelection *colorsel = GTK_COLOR_SELECTION (data);
1004 gtk_widget_grab_focus (drawing_area);
1006 if (event->button == 3 &&
1007 event->type == GDK_BUTTON_PRESS)
1009 do_popup (colorsel, drawing_area, event->time);
1017 palette_release (GtkWidget *drawing_area,
1018 GdkEventButton *event,
1021 GtkColorSelection *colorsel = GTK_COLOR_SELECTION (data);
1023 gtk_widget_grab_focus (drawing_area);
1025 if (event->button == 1 &&
1026 g_object_get_data (G_OBJECT (drawing_area),
1027 "gtk-colorsel-have-pointer") != NULL)
1029 if (GPOINTER_TO_INT (g_object_get_data (G_OBJECT (drawing_area), "color_set")) != 0)
1032 palette_get_color (drawing_area, color);
1033 set_color_internal (colorsel, color);
1041 palette_drop_handle (GtkWidget *widget,
1042 GdkDragContext *context,
1045 GtkSelectionData *selection_data,
1050 GtkColorSelection *colorsel = GTK_COLOR_SELECTION (data);
1054 if (selection_data->length < 0)
1057 /* We accept drops with the wrong format, since the KDE color
1058 * chooser incorrectly drops application/x-color with format 8.
1060 if (selection_data->length != 8)
1062 g_warning ("Received invalid color data\n");
1066 vals = (guint16 *)selection_data->data;
1068 color[0] = (gdouble)vals[0] / 0xffff;
1069 color[1] = (gdouble)vals[1] / 0xffff;
1070 color[2] = (gdouble)vals[2] / 0xffff;
1071 color[3] = (gdouble)vals[3] / 0xffff;
1072 palette_change_color (widget, colorsel, color);
1073 set_color_internal (colorsel, color);
1077 palette_activate (GtkWidget *widget,
1081 /* should have a drawing area subclass with an activate signal */
1082 if ((event->keyval == GDK_space) ||
1083 (event->keyval == GDK_Return) ||
1084 (event->keyval == GDK_KP_Enter) ||
1085 (event->keyval == GDK_KP_Space))
1087 if (GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget), "color_set")) != 0)
1090 palette_get_color (widget, color);
1091 set_color_internal (GTK_COLOR_SELECTION (data), color);
1100 palette_popup (GtkWidget *widget,
1103 GtkColorSelection *colorsel = GTK_COLOR_SELECTION (data);
1105 do_popup (colorsel, widget, GDK_CURRENT_TIME);
1111 palette_new (GtkColorSelection *colorsel)
1114 ColorSelectionPrivate *priv;
1116 static const GtkTargetEntry targets[] = {
1117 { "application/x-color", 0 }
1120 priv = colorsel->private_data;
1122 retval = gtk_drawing_area_new ();
1124 GTK_WIDGET_SET_FLAGS (retval, GTK_CAN_FOCUS);
1126 g_object_set_data (G_OBJECT (retval), "color_set", GINT_TO_POINTER (0));
1127 gtk_widget_set_events (retval, GDK_BUTTON_PRESS_MASK
1128 | GDK_BUTTON_RELEASE_MASK
1130 | GDK_ENTER_NOTIFY_MASK
1131 | GDK_LEAVE_NOTIFY_MASK);
1133 g_signal_connect (retval, "expose_event",
1134 G_CALLBACK (palette_expose), colorsel);
1135 g_signal_connect (retval, "button_press_event",
1136 G_CALLBACK (palette_press), colorsel);
1137 g_signal_connect (retval, "button_release_event",
1138 G_CALLBACK (palette_release), colorsel);
1139 g_signal_connect (retval, "enter_notify_event",
1140 G_CALLBACK (palette_enter), colorsel);
1141 g_signal_connect (retval, "leave_notify_event",
1142 G_CALLBACK (palette_leave), colorsel);
1143 g_signal_connect (retval, "key_press_event",
1144 G_CALLBACK (palette_activate), colorsel);
1145 g_signal_connect (retval, "popup_menu",
1146 G_CALLBACK (palette_popup), colorsel);
1148 gtk_drag_dest_set (retval,
1149 GTK_DEST_DEFAULT_HIGHLIGHT |
1150 GTK_DEST_DEFAULT_MOTION |
1151 GTK_DEST_DEFAULT_DROP,
1155 g_signal_connect (retval, "drag_end",
1156 G_CALLBACK (palette_drag_end), NULL);
1157 g_signal_connect (retval, "drag_data_received",
1158 G_CALLBACK (palette_drop_handle), colorsel);
1160 gtk_tooltips_set_tip (priv->tooltips,
1162 _("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.\""),
1170 * The actual GtkColorSelection widget
1175 make_picker_cursor (GdkScreen *screen)
1178 GdkColor bg = { 0, 0xffff, 0xffff, 0xffff };
1179 GdkColor fg = { 0, 0x0000, 0x0000, 0x0000 };
1180 GdkWindow *window = gdk_screen_get_root_window (screen);
1183 gdk_bitmap_create_from_data (window, (gchar *) dropper_bits,
1184 DROPPER_WIDTH, DROPPER_HEIGHT);
1187 gdk_bitmap_create_from_data (window, (gchar *) dropper_mask,
1188 DROPPER_WIDTH, DROPPER_HEIGHT);
1190 cursor = gdk_cursor_new_from_pixmap (pixmap, mask, &fg, &bg,
1191 DROPPER_X_HOT, DROPPER_Y_HOT);
1193 g_object_unref (pixmap);
1194 g_object_unref (mask);
1200 grab_color_at_mouse (GdkScreen *screen,
1207 GtkColorSelection *colorsel = data;
1208 ColorSelectionPrivate *priv;
1210 GdkColormap *colormap = gdk_screen_get_system_colormap (screen);
1211 GdkWindow *root_window = gdk_screen_get_root_window (screen);
1213 priv = colorsel->private_data;
1215 image = gdk_drawable_get_image (root_window, x_root, y_root, 1, 1);
1216 pixel = gdk_image_get_pixel (image, 0, 0);
1217 g_object_unref (image);
1219 gdk_colormap_query_color (colormap, pixel, &color);
1221 priv->color[COLORSEL_RED] = SCALE (color.red);
1222 priv->color[COLORSEL_GREEN] = SCALE (color.green);
1223 priv->color[COLORSEL_BLUE] = SCALE (color.blue);
1225 gtk_rgb_to_hsv (priv->color[COLORSEL_RED],
1226 priv->color[COLORSEL_GREEN],
1227 priv->color[COLORSEL_BLUE],
1228 &priv->color[COLORSEL_HUE],
1229 &priv->color[COLORSEL_SATURATION],
1230 &priv->color[COLORSEL_VALUE]);
1232 update_color (colorsel);
1236 shutdown_eyedropper (GtkWidget *widget)
1238 GtkColorSelection *colorsel;
1239 ColorSelectionPrivate *priv;
1240 GdkDisplay *display = gtk_widget_get_display (widget);
1241 guint32 time = gtk_get_current_event_time ();
1243 colorsel = GTK_COLOR_SELECTION (widget);
1244 priv = colorsel->private_data;
1246 gdk_display_keyboard_ungrab (display, time);
1247 gdk_display_pointer_ungrab (display, time);
1248 gtk_grab_remove (priv->dropper_grab_widget);
1252 mouse_motion (GtkWidget *invisible,
1253 GdkEventMotion *event,
1256 grab_color_at_mouse (gdk_event_get_screen ((GdkEvent *)event),
1257 event->x_root, event->y_root, data);
1261 mouse_release (GtkWidget *invisible,
1262 GdkEventButton *event,
1265 GtkColorSelection *colorsel = data;
1266 ColorSelectionPrivate *priv;
1267 priv = colorsel->private_data;
1269 if (event->button != 1)
1272 grab_color_at_mouse (gdk_event_get_screen ((GdkEvent *)event),
1273 event->x_root, event->y_root, data);
1275 shutdown_eyedropper (GTK_WIDGET (data));
1277 g_signal_handlers_disconnect_by_func (invisible,
1280 g_signal_handlers_disconnect_by_func (invisible,
1287 /* Helper Functions */
1289 static gboolean mouse_press (GtkWidget *invisible,
1290 GdkEventButton *event,
1296 key_press (GtkWidget *invisible,
1300 GdkDisplay *display = gtk_widget_get_display (invisible);
1301 GdkScreen *screen = gdk_event_get_screen ((GdkEvent *)event);
1302 guint state = event->state & gtk_accelerator_get_default_mod_mask ();
1306 gdk_display_get_pointer (display, NULL, &x, &y, NULL);
1311 switch (event->keyval)
1317 grab_color_at_mouse (screen, x, y, data);
1321 shutdown_eyedropper (data);
1323 g_signal_handlers_disconnect_by_func (invisible,
1326 g_signal_handlers_disconnect_by_func (invisible,
1332 #if defined GDK_WINDOWING_X11 || defined GDK_WINDOWING_WIN32
1335 dy = state == GDK_MOD1_MASK ? -BIG_STEP : -1;
1340 dy = state == GDK_MOD1_MASK ? BIG_STEP : 1;
1345 dx = state == GDK_MOD1_MASK ? -BIG_STEP : -1;
1350 dx = state == GDK_MOD1_MASK ? BIG_STEP : 1;
1358 gdk_display_warp_pointer (display, screen, x + dx, y + dy);
1365 mouse_press (GtkWidget *invisible,
1366 GdkEventButton *event,
1369 GtkColorSelection *colorsel = data;
1370 ColorSelectionPrivate *priv;
1371 priv = colorsel->private_data;
1373 if (event->type == GDK_BUTTON_PRESS &&
1376 g_signal_connect (invisible, "motion_notify_event",
1377 G_CALLBACK (mouse_motion),
1379 g_signal_connect (invisible, "button_release_event",
1380 G_CALLBACK (mouse_release),
1382 g_signal_handlers_disconnect_by_func (invisible,
1385 g_signal_handlers_disconnect_by_func (invisible,
1394 /* when the button is clicked */
1396 get_screen_color (GtkWidget *button)
1398 GtkColorSelection *colorsel = g_object_get_data (G_OBJECT (button), "COLORSEL");
1399 ColorSelectionPrivate *priv = colorsel->private_data;
1400 GdkScreen *screen = gtk_widget_get_screen (GTK_WIDGET (button));
1401 GdkCursor *picker_cursor;
1402 GdkGrabStatus grab_status;
1404 if (priv->dropper_grab_widget == NULL)
1406 priv->dropper_grab_widget = gtk_invisible_new_for_screen (screen);
1408 gtk_widget_add_events (priv->dropper_grab_widget,
1409 GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_PRESS_MASK | GDK_POINTER_MOTION_MASK);
1411 gtk_widget_show (priv->dropper_grab_widget);
1414 if (gdk_keyboard_grab (priv->dropper_grab_widget->window,
1416 gtk_get_current_event_time ()) != GDK_GRAB_SUCCESS)
1419 picker_cursor = make_picker_cursor (screen);
1420 grab_status = gdk_pointer_grab (priv->dropper_grab_widget->window,
1422 GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_PRESS_MASK | GDK_POINTER_MOTION_MASK,
1425 gtk_get_current_event_time ());
1426 gdk_cursor_unref (picker_cursor);
1428 if (grab_status != GDK_GRAB_SUCCESS)
1430 gdk_display_keyboard_ungrab (gtk_widget_get_display (button), GDK_CURRENT_TIME);
1434 gtk_grab_add (priv->dropper_grab_widget);
1436 g_signal_connect (priv->dropper_grab_widget, "button_press_event",
1437 G_CALLBACK (mouse_press), colorsel);
1438 g_signal_connect (priv->dropper_grab_widget, "key_press_event",
1439 G_CALLBACK (key_press), colorsel);
1443 hex_changed (GtkWidget *hex_entry,
1446 GtkColorSelection *colorsel;
1447 ColorSelectionPrivate *priv;
1451 colorsel = GTK_COLOR_SELECTION (data);
1452 priv = colorsel->private_data;
1457 text = gtk_editable_get_chars (GTK_EDITABLE (priv->hex_entry), 0, -1);
1458 if (gdk_color_parse (text, &color))
1460 priv->color[COLORSEL_RED] = CLAMP (color.red/65535.0, 0.0, 1.0);
1461 priv->color[COLORSEL_GREEN] = CLAMP (color.green/65535.0, 0.0, 1.0);
1462 priv->color[COLORSEL_BLUE] = CLAMP (color.blue/65535.0, 0.0, 1.0);
1463 gtk_rgb_to_hsv (priv->color[COLORSEL_RED],
1464 priv->color[COLORSEL_GREEN],
1465 priv->color[COLORSEL_BLUE],
1466 &priv->color[COLORSEL_HUE],
1467 &priv->color[COLORSEL_SATURATION],
1468 &priv->color[COLORSEL_VALUE]);
1469 update_color (colorsel);
1475 hex_focus_out (GtkWidget *hex_entry,
1476 GdkEventFocus *event,
1479 hex_changed (hex_entry, data);
1485 hsv_changed (GtkWidget *hsv,
1488 GtkColorSelection *colorsel;
1489 ColorSelectionPrivate *priv;
1491 colorsel = GTK_COLOR_SELECTION (data);
1492 priv = colorsel->private_data;
1497 gtk_hsv_get_color (GTK_HSV (hsv),
1498 &priv->color[COLORSEL_HUE],
1499 &priv->color[COLORSEL_SATURATION],
1500 &priv->color[COLORSEL_VALUE]);
1501 gtk_hsv_to_rgb (priv->color[COLORSEL_HUE],
1502 priv->color[COLORSEL_SATURATION],
1503 priv->color[COLORSEL_VALUE],
1504 &priv->color[COLORSEL_RED],
1505 &priv->color[COLORSEL_GREEN],
1506 &priv->color[COLORSEL_BLUE]);
1507 update_color (colorsel);
1511 adjustment_changed (GtkAdjustment *adjustment,
1514 GtkColorSelection *colorsel;
1515 ColorSelectionPrivate *priv;
1517 colorsel = GTK_COLOR_SELECTION (g_object_get_data (G_OBJECT (adjustment), "COLORSEL"));
1518 priv = colorsel->private_data;
1523 switch (GPOINTER_TO_INT (data))
1525 case COLORSEL_SATURATION:
1526 case COLORSEL_VALUE:
1527 priv->color[GPOINTER_TO_INT (data)] = adjustment->value / 100;
1528 gtk_hsv_to_rgb (priv->color[COLORSEL_HUE],
1529 priv->color[COLORSEL_SATURATION],
1530 priv->color[COLORSEL_VALUE],
1531 &priv->color[COLORSEL_RED],
1532 &priv->color[COLORSEL_GREEN],
1533 &priv->color[COLORSEL_BLUE]);
1536 priv->color[GPOINTER_TO_INT (data)] = adjustment->value / 360;
1537 gtk_hsv_to_rgb (priv->color[COLORSEL_HUE],
1538 priv->color[COLORSEL_SATURATION],
1539 priv->color[COLORSEL_VALUE],
1540 &priv->color[COLORSEL_RED],
1541 &priv->color[COLORSEL_GREEN],
1542 &priv->color[COLORSEL_BLUE]);
1545 case COLORSEL_GREEN:
1547 priv->color[GPOINTER_TO_INT (data)] = adjustment->value / 255;
1549 gtk_rgb_to_hsv (priv->color[COLORSEL_RED],
1550 priv->color[COLORSEL_GREEN],
1551 priv->color[COLORSEL_BLUE],
1552 &priv->color[COLORSEL_HUE],
1553 &priv->color[COLORSEL_SATURATION],
1554 &priv->color[COLORSEL_VALUE]);
1557 priv->color[GPOINTER_TO_INT (data)] = adjustment->value / 255;
1560 update_color (colorsel);
1564 opacity_entry_changed (GtkWidget *opacity_entry,
1567 GtkColorSelection *colorsel;
1568 ColorSelectionPrivate *priv;
1572 colorsel = GTK_COLOR_SELECTION (data);
1573 priv = colorsel->private_data;
1578 text = gtk_editable_get_chars (GTK_EDITABLE (priv->opacity_entry), 0, -1);
1579 adj = gtk_range_get_adjustment (GTK_RANGE (priv->opacity_slider));
1580 gtk_adjustment_set_value (adj, g_strtod (text, NULL));
1582 update_color (colorsel);
1588 make_label_spinbutton (GtkColorSelection *colorsel,
1589 GtkWidget **spinbutton,
1595 const gchar *tooltip)
1598 GtkAdjustment *adjust;
1599 ColorSelectionPrivate *priv = colorsel->private_data;
1601 if (channel_type == COLORSEL_HUE)
1603 adjust = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 360.0, 1.0, 1.0, 1.0));
1605 else if (channel_type == COLORSEL_SATURATION ||
1606 channel_type == COLORSEL_VALUE)
1608 adjust = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 100.0, 1.0, 1.0, 1.0));
1612 adjust = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 255.0, 1.0, 1.0, 1.0));
1614 g_object_set_data (G_OBJECT (adjust), "COLORSEL", colorsel);
1615 *spinbutton = gtk_spin_button_new (adjust, 10.0, 0);
1617 gtk_tooltips_set_tip (priv->tooltips, *spinbutton, tooltip, NULL);
1619 g_signal_connect (adjust, "value_changed",
1620 G_CALLBACK (adjustment_changed),
1621 GINT_TO_POINTER (channel_type));
1622 label = gtk_label_new_with_mnemonic (text);
1623 gtk_label_set_mnemonic_widget (GTK_LABEL (label), *spinbutton);
1625 gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5);
1626 gtk_table_attach_defaults (GTK_TABLE (table), label, i, i+1, j, j+1);
1627 gtk_table_attach_defaults (GTK_TABLE (table), *spinbutton, i+1, i+2, j, j+1);
1631 make_palette_frame (GtkColorSelection *colorsel,
1637 ColorSelectionPrivate *priv;
1639 priv = colorsel->private_data;
1640 frame = gtk_frame_new (NULL);
1641 gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
1642 priv->custom_palette[i][j] = palette_new (colorsel);
1643 gtk_widget_set_size_request (priv->custom_palette[i][j], CUSTOM_PALETTE_ENTRY_WIDTH, CUSTOM_PALETTE_ENTRY_HEIGHT);
1644 gtk_container_add (GTK_CONTAINER (frame), priv->custom_palette[i][j]);
1645 gtk_table_attach_defaults (GTK_TABLE (table), frame, i, i+1, j, j+1);
1648 /* Set the palette entry [x][y] to be the currently selected one. */
1650 set_selected_palette (GtkColorSelection *colorsel, int x, int y)
1652 ColorSelectionPrivate *priv = colorsel->private_data;
1654 gtk_widget_grab_focus (priv->custom_palette[x][y]);
1658 scale_round (double val, double factor)
1660 val = floor (val * factor + 0.5);
1662 val = MIN (val, factor);
1667 update_color (GtkColorSelection *colorsel)
1669 ColorSelectionPrivate *priv = colorsel->private_data;
1671 gchar opacity_text[32];
1674 priv->changing = TRUE;
1675 color_sample_update_samples (colorsel);
1677 gtk_hsv_set_color (GTK_HSV (priv->triangle_colorsel),
1678 priv->color[COLORSEL_HUE],
1679 priv->color[COLORSEL_SATURATION],
1680 priv->color[COLORSEL_VALUE]);
1681 gtk_adjustment_set_value (gtk_spin_button_get_adjustment
1682 (GTK_SPIN_BUTTON (priv->hue_spinbutton)),
1683 scale_round (priv->color[COLORSEL_HUE], 360));
1684 gtk_adjustment_set_value (gtk_spin_button_get_adjustment
1685 (GTK_SPIN_BUTTON (priv->sat_spinbutton)),
1686 scale_round (priv->color[COLORSEL_SATURATION], 100));
1687 gtk_adjustment_set_value (gtk_spin_button_get_adjustment
1688 (GTK_SPIN_BUTTON (priv->val_spinbutton)),
1689 scale_round (priv->color[COLORSEL_VALUE], 100));
1690 gtk_adjustment_set_value (gtk_spin_button_get_adjustment
1691 (GTK_SPIN_BUTTON (priv->red_spinbutton)),
1692 scale_round (priv->color[COLORSEL_RED], 255));
1693 gtk_adjustment_set_value (gtk_spin_button_get_adjustment
1694 (GTK_SPIN_BUTTON (priv->green_spinbutton)),
1695 scale_round (priv->color[COLORSEL_GREEN], 255));
1696 gtk_adjustment_set_value (gtk_spin_button_get_adjustment
1697 (GTK_SPIN_BUTTON (priv->blue_spinbutton)),
1698 scale_round (priv->color[COLORSEL_BLUE], 255));
1699 gtk_adjustment_set_value (gtk_range_get_adjustment
1700 (GTK_RANGE (priv->opacity_slider)),
1701 scale_round (priv->color[COLORSEL_OPACITY], 255));
1703 g_snprintf (opacity_text, 32, "%.0f", scale_round (priv->color[COLORSEL_OPACITY], 255));
1704 gtk_entry_set_text (GTK_ENTRY (priv->opacity_entry), opacity_text);
1706 g_snprintf (entryval, 11, "#%2X%2X%2X",
1707 (guint) (scale_round (priv->color[COLORSEL_RED], 255)),
1708 (guint) (scale_round (priv->color[COLORSEL_GREEN], 255)),
1709 (guint) (scale_round (priv->color[COLORSEL_BLUE], 255)));
1711 for (ptr = entryval; *ptr; ptr++)
1714 gtk_entry_set_text (GTK_ENTRY (priv->hex_entry), entryval);
1715 priv->changing = FALSE;
1717 g_object_ref (colorsel);
1719 g_signal_emit (colorsel, color_selection_signals[COLOR_CHANGED], 0);
1721 g_object_freeze_notify (G_OBJECT (colorsel));
1722 g_object_notify (G_OBJECT (colorsel), "current_color");
1723 g_object_notify (G_OBJECT (colorsel), "current_alpha");
1724 g_object_thaw_notify (G_OBJECT (colorsel));
1726 g_object_unref (colorsel);
1730 update_palette (GtkColorSelection *colorsel)
1732 GdkColor *current_colors;
1735 current_colors = get_current_colors (colorsel);
1737 for (i = 0; i < GTK_CUSTOM_PALETTE_HEIGHT; i++)
1739 for (j = 0; j < GTK_CUSTOM_PALETTE_WIDTH; j++)
1743 index = i * GTK_CUSTOM_PALETTE_WIDTH + j;
1745 gtk_color_selection_set_palette_color (colorsel,
1747 ¤t_colors[index]);
1751 g_free (current_colors);
1755 palette_change_notify_instance (GObject *object,
1759 update_palette (GTK_COLOR_SELECTION (data));
1763 default_noscreen_change_palette_func (const GdkColor *colors,
1766 default_change_palette_func (gdk_screen_get_default (), colors, n_colors);
1770 default_change_palette_func (GdkScreen *screen,
1771 const GdkColor *colors,
1776 str = gtk_color_selection_palette_to_string (colors, n_colors);
1778 gtk_settings_set_string_property (gtk_settings_get_for_screen (screen),
1779 "gtk-color-palette",
1781 "gtk_color_selection_palette_to_string");
1787 gtk_color_selection_get_type (void)
1789 static GType color_selection_type = 0;
1791 if (!color_selection_type)
1793 static const GTypeInfo color_selection_info =
1795 sizeof (GtkColorSelectionClass),
1796 NULL, /* base_init */
1797 NULL, /* base_finalize */
1798 (GClassInitFunc) gtk_color_selection_class_init,
1799 NULL, /* class_finalize */
1800 NULL, /* class_data */
1801 sizeof (GtkColorSelection),
1802 0, /* n_preallocs */
1803 (GInstanceInitFunc) gtk_color_selection_init,
1806 color_selection_type =
1807 g_type_register_static (GTK_TYPE_VBOX, "GtkColorSelection",
1808 &color_selection_info, 0);
1811 return color_selection_type;
1815 gtk_color_selection_class_init (GtkColorSelectionClass *klass)
1817 GObjectClass *gobject_class;
1818 GtkObjectClass *object_class;
1819 GtkWidgetClass *widget_class;
1821 gobject_class = G_OBJECT_CLASS (klass);
1822 object_class = GTK_OBJECT_CLASS (klass);
1823 widget_class = GTK_WIDGET_CLASS (klass);
1825 parent_class = g_type_class_peek_parent (klass);
1827 object_class->destroy = gtk_color_selection_destroy;
1828 gobject_class->finalize = gtk_color_selection_finalize;
1830 gobject_class->set_property = gtk_color_selection_set_property;
1831 gobject_class->get_property = gtk_color_selection_get_property;
1833 widget_class->realize = gtk_color_selection_realize;
1834 widget_class->unrealize = gtk_color_selection_unrealize;
1835 widget_class->show_all = gtk_color_selection_show_all;
1837 g_object_class_install_property (gobject_class,
1838 PROP_HAS_OPACITY_CONTROL,
1839 g_param_spec_boolean ("has-opacity-control",
1840 P_("Has Opacity Control"),
1841 P_("Whether the color selector should allow setting opacity"),
1843 G_PARAM_READABLE | G_PARAM_WRITABLE));
1844 g_object_class_install_property (gobject_class,
1846 g_param_spec_boolean ("has-palette",
1848 P_("Whether a palette should be used"),
1850 G_PARAM_READABLE | G_PARAM_WRITABLE));
1851 g_object_class_install_property (gobject_class,
1853 g_param_spec_boxed ("current-color",
1854 P_("Current Color"),
1855 P_("The current color"),
1857 G_PARAM_READABLE | G_PARAM_WRITABLE));
1858 g_object_class_install_property (gobject_class,
1860 g_param_spec_uint ("current-alpha",
1861 P_("Current Alpha"),
1862 P_("The current opacity value (0 fully transparent, 65535 fully opaque)"),
1864 G_PARAM_READABLE | G_PARAM_WRITABLE));
1866 color_selection_signals[COLOR_CHANGED] =
1867 g_signal_new ("color_changed",
1868 G_OBJECT_CLASS_TYPE (object_class),
1870 G_STRUCT_OFFSET (GtkColorSelectionClass, color_changed),
1872 _gtk_marshal_VOID__VOID,
1875 gtk_settings_install_property (g_param_spec_string ("gtk-color-palette",
1876 P_("Custom palette"),
1877 P_("Palette to use in the color selector"),
1879 G_PARAM_READWRITE));
1882 /* widget functions */
1885 gtk_color_selection_init (GtkColorSelection *colorsel)
1887 GtkWidget *top_hbox;
1888 GtkWidget *top_right_vbox;
1889 GtkWidget *table, *label, *hbox, *frame, *vbox, *button;
1890 GtkAdjustment *adjust;
1891 GtkWidget *picker_image;
1893 ColorSelectionPrivate *priv;
1896 gtk_widget_push_composite_child ();
1898 priv = colorsel->private_data = g_new0 (ColorSelectionPrivate, 1);
1899 priv->changing = FALSE;
1900 priv->default_set = FALSE;
1901 priv->default_alpha_set = FALSE;
1903 priv->tooltips = gtk_tooltips_new ();
1904 g_object_ref (priv->tooltips);
1905 gtk_object_sink (GTK_OBJECT (priv->tooltips));
1907 gtk_box_set_spacing (GTK_BOX (colorsel), 4);
1908 top_hbox = gtk_hbox_new (FALSE, 8);
1909 gtk_box_pack_start (GTK_BOX (colorsel), top_hbox, FALSE, FALSE, 0);
1911 vbox = gtk_vbox_new (FALSE, 4);
1912 priv->triangle_colorsel = gtk_hsv_new ();
1913 g_signal_connect (priv->triangle_colorsel, "changed",
1914 G_CALLBACK (hsv_changed), colorsel);
1915 gtk_hsv_set_metrics (GTK_HSV (priv->triangle_colorsel), 174, 15);
1916 gtk_box_pack_start (GTK_BOX (top_hbox), vbox, FALSE, FALSE, 0);
1917 gtk_box_pack_start (GTK_BOX (vbox), priv->triangle_colorsel, FALSE, FALSE, 0);
1918 gtk_tooltips_set_tip (priv->tooltips, priv->triangle_colorsel,
1919 _("Select the color you want from the outer ring. Select the darkness or lightness of that color using the inner triangle."), NULL);
1921 hbox = gtk_hbox_new (FALSE, 4);
1922 gtk_box_pack_end (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
1924 frame = gtk_frame_new (NULL);
1925 gtk_widget_set_size_request (frame, -1, 30);
1926 gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
1927 color_sample_new (colorsel);
1928 gtk_container_add (GTK_CONTAINER (frame), priv->sample_area);
1929 gtk_box_pack_start (GTK_BOX (hbox), frame, TRUE, TRUE, 0);
1931 button = gtk_button_new ();
1933 gtk_widget_set_events (button, GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK);
1934 g_object_set_data (G_OBJECT (button), "COLORSEL", colorsel);
1935 g_signal_connect (button, "clicked",
1936 G_CALLBACK (get_screen_color), NULL);
1937 picker_image = gtk_image_new_from_stock (GTK_STOCK_COLOR_PICKER, GTK_ICON_SIZE_BUTTON);
1938 gtk_container_add (GTK_CONTAINER (button), picker_image);
1939 gtk_widget_show (GTK_WIDGET (picker_image));
1940 gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
1942 gtk_tooltips_set_tip (priv->tooltips,
1944 _("Click the eyedropper, then click a color anywhere on your screen to select that color."), NULL);
1946 top_right_vbox = gtk_vbox_new (FALSE, 4);
1947 gtk_box_pack_start (GTK_BOX (top_hbox), top_right_vbox, FALSE, FALSE, 0);
1948 table = gtk_table_new (8, 6, FALSE);
1949 gtk_box_pack_start (GTK_BOX (top_right_vbox), table, FALSE, FALSE, 0);
1950 gtk_table_set_row_spacings (GTK_TABLE (table), 4);
1951 gtk_table_set_col_spacings (GTK_TABLE (table), 4);
1953 make_label_spinbutton (colorsel, &priv->hue_spinbutton, _("_Hue:"), table, 0, 0, COLORSEL_HUE,
1954 _("Position on the color wheel."));
1955 gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (priv->hue_spinbutton), TRUE);
1956 make_label_spinbutton (colorsel, &priv->sat_spinbutton, _("_Saturation:"), table, 0, 1, COLORSEL_SATURATION,
1957 _("\"Deepness\" of the color."));
1958 make_label_spinbutton (colorsel, &priv->val_spinbutton, _("_Value:"), table, 0, 2, COLORSEL_VALUE,
1959 _("Brightness of the color."));
1960 make_label_spinbutton (colorsel, &priv->red_spinbutton, _("_Red:"), table, 6, 0, COLORSEL_RED,
1961 _("Amount of red light in the color."));
1962 make_label_spinbutton (colorsel, &priv->green_spinbutton, _("_Green:"), table, 6, 1, COLORSEL_GREEN,
1963 _("Amount of green light in the color."));
1964 make_label_spinbutton (colorsel, &priv->blue_spinbutton, _("_Blue:"), table, 6, 2, COLORSEL_BLUE,
1965 _("Amount of blue light in the color."));
1966 gtk_table_attach_defaults (GTK_TABLE (table), gtk_hseparator_new (), 0, 8, 3, 4);
1968 priv->opacity_label = gtk_label_new_with_mnemonic (_("_Opacity:"));
1969 gtk_misc_set_alignment (GTK_MISC (priv->opacity_label), 1.0, 0.5);
1970 gtk_table_attach_defaults (GTK_TABLE (table), priv->opacity_label, 0, 1, 4, 5);
1971 adjust = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 255.0, 1.0, 1.0, 0.0));
1972 g_object_set_data (G_OBJECT (adjust), "COLORSEL", colorsel);
1973 priv->opacity_slider = gtk_hscale_new (adjust);
1974 gtk_tooltips_set_tip (priv->tooltips,
1975 priv->opacity_slider,
1976 _("Transparency of the color."), NULL);
1977 gtk_label_set_mnemonic_widget (GTK_LABEL (priv->opacity_label),
1978 priv->opacity_slider);
1979 gtk_scale_set_draw_value (GTK_SCALE (priv->opacity_slider), FALSE);
1980 g_signal_connect (adjust, "value_changed",
1981 G_CALLBACK (adjustment_changed),
1982 GINT_TO_POINTER (COLORSEL_OPACITY));
1983 gtk_table_attach_defaults (GTK_TABLE (table), priv->opacity_slider, 1, 7, 4, 5);
1984 priv->opacity_entry = gtk_entry_new ();
1985 gtk_tooltips_set_tip (priv->tooltips,
1986 priv->opacity_entry,
1987 _("Transparency of the color."), NULL);
1988 gtk_widget_set_size_request (priv->opacity_entry, 40, -1);
1990 g_signal_connect (priv->opacity_entry, "activate",
1991 G_CALLBACK (opacity_entry_changed), colorsel);
1992 gtk_table_attach_defaults (GTK_TABLE (table), priv->opacity_entry, 7, 8, 4, 5);
1994 label = gtk_label_new_with_mnemonic (_("Color _Name:"));
1995 gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 5, 6);
1996 gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5);
1997 priv->hex_entry = gtk_entry_new ();
1999 gtk_label_set_mnemonic_widget (GTK_LABEL (label), priv->hex_entry);
2001 g_signal_connect (priv->hex_entry, "activate",
2002 G_CALLBACK (hex_changed), colorsel);
2004 g_signal_connect (priv->hex_entry, "focus_out_event",
2005 G_CALLBACK (hex_focus_out), colorsel);
2007 gtk_tooltips_set_tip (priv->tooltips,
2009 _("You can enter an HTML-style hexadecimal color value, or simply a color name such as 'orange' in this entry."), NULL);
2011 gtk_entry_set_width_chars (GTK_ENTRY (priv->hex_entry), 7);
2012 gtk_table_set_col_spacing (GTK_TABLE (table), 3, 15);
2013 gtk_table_attach_defaults (GTK_TABLE (table), priv->hex_entry, 1, 5, 5, 6);
2015 /* Set up the palette */
2016 table = gtk_table_new (GTK_CUSTOM_PALETTE_HEIGHT, GTK_CUSTOM_PALETTE_WIDTH, TRUE);
2017 gtk_table_set_row_spacings (GTK_TABLE (table), 1);
2018 gtk_table_set_col_spacings (GTK_TABLE (table), 1);
2019 for (i = 0; i < GTK_CUSTOM_PALETTE_WIDTH; i++)
2021 for (j = 0; j < GTK_CUSTOM_PALETTE_HEIGHT; j++)
2023 make_palette_frame (colorsel, table, i, j);
2026 set_selected_palette (colorsel, 0, 0);
2027 priv->palette_frame = gtk_frame_new (NULL);
2028 label = gtk_label_new_with_mnemonic (_("_Palette"));
2029 gtk_frame_set_label_widget (GTK_FRAME (priv->palette_frame), label);
2031 gtk_label_set_mnemonic_widget (GTK_LABEL (label),
2032 priv->custom_palette[0][0]);
2034 gtk_box_pack_end (GTK_BOX (top_right_vbox), priv->palette_frame, FALSE, FALSE, 0);
2035 vbox = gtk_vbox_new (FALSE, 4);
2036 gtk_container_add (GTK_CONTAINER (priv->palette_frame), vbox);
2037 gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0);
2039 gtk_container_set_border_width (GTK_CONTAINER (vbox), 4);
2041 gtk_widget_show_all (top_hbox);
2043 /* hide unused stuff */
2045 if (priv->has_opacity == FALSE)
2047 gtk_widget_hide (priv->opacity_label);
2048 gtk_widget_hide (priv->opacity_slider);
2049 gtk_widget_hide (priv->opacity_entry);
2052 if (priv->has_palette == FALSE)
2054 gtk_widget_hide (priv->palette_frame);
2057 atk_obj = gtk_widget_get_accessible (priv->triangle_colorsel);
2058 if (GTK_IS_ACCESSIBLE (atk_obj))
2060 atk_object_set_name (atk_obj, _("Color Wheel"));
2061 atk_object_set_role (gtk_widget_get_accessible (GTK_WIDGET (colorsel)), ATK_ROLE_COLOR_CHOOSER);
2062 make_all_relations (atk_obj, priv);
2065 gtk_widget_pop_composite_child ();
2069 gtk_color_selection_destroy (GtkObject *object)
2071 GtkColorSelection *cselection = GTK_COLOR_SELECTION (object);
2072 ColorSelectionPrivate *priv = cselection->private_data;
2074 if (priv->dropper_grab_widget)
2076 gtk_widget_destroy (priv->dropper_grab_widget);
2077 priv->dropper_grab_widget = NULL;
2082 g_object_unref (priv->tooltips);
2083 priv->tooltips = NULL;
2086 GTK_OBJECT_CLASS (parent_class)->destroy (object);
2090 gtk_color_selection_finalize (GObject *object)
2092 GtkColorSelection *cselection = GTK_COLOR_SELECTION (object);
2094 if (cselection->private_data)
2096 g_free (cselection->private_data);
2097 cselection->private_data = NULL;
2100 G_OBJECT_CLASS (parent_class)->finalize (object);
2104 gtk_color_selection_realize (GtkWidget *widget)
2106 GtkColorSelection *colorsel = GTK_COLOR_SELECTION (widget);
2107 ColorSelectionPrivate *priv = colorsel->private_data;
2108 GtkSettings *settings = gtk_widget_get_settings (widget);
2110 priv->settings_connection = g_signal_connect (settings,
2111 "notify::gtk-color-palette",
2112 G_CALLBACK (palette_change_notify_instance),
2114 update_palette (colorsel);
2116 GTK_WIDGET_CLASS (parent_class)->realize (widget);
2120 gtk_color_selection_unrealize (GtkWidget *widget)
2122 GtkColorSelection *colorsel = GTK_COLOR_SELECTION (widget);
2123 ColorSelectionPrivate *priv = colorsel->private_data;
2124 GtkSettings *settings = gtk_widget_get_settings (widget);
2126 g_signal_handler_disconnect (settings, priv->settings_connection);
2128 GTK_WIDGET_CLASS (parent_class)->unrealize (widget);
2131 /* We override show-all since we have internal widgets that
2132 * shouldn't be shown when you call show_all(), like the
2133 * palette and opacity sliders.
2136 gtk_color_selection_show_all (GtkWidget *widget)
2138 gtk_widget_show (widget);
2142 * gtk_color_selection_new:
2144 * Creates a new GtkColorSelection.
2146 * Return value: a new #GtkColorSelection
2149 gtk_color_selection_new (void)
2151 GtkColorSelection *colorsel;
2152 ColorSelectionPrivate *priv;
2159 colorsel = g_object_new (GTK_TYPE_COLOR_SELECTION, NULL);
2160 priv = colorsel->private_data;
2161 set_color_internal (colorsel, color);
2162 gtk_color_selection_set_has_opacity_control (colorsel, TRUE);
2164 /* We want to make sure that default_set is FALSE */
2165 /* This way the user can still set it */
2166 priv->default_set = FALSE;
2167 priv->default_alpha_set = FALSE;
2169 return GTK_WIDGET (colorsel);
2174 gtk_color_selection_set_update_policy (GtkColorSelection *colorsel,
2175 GtkUpdateType policy)
2177 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2181 * gtk_color_selection_get_has_opacity_control:
2182 * @colorsel: a #GtkColorSelection.
2184 * Determines whether the colorsel has an opacity control.
2186 * Return value: %TRUE if the @colorsel has an opacity control. %FALSE if it does't.
2189 gtk_color_selection_get_has_opacity_control (GtkColorSelection *colorsel)
2191 ColorSelectionPrivate *priv;
2193 g_return_val_if_fail (GTK_IS_COLOR_SELECTION (colorsel), FALSE);
2195 priv = colorsel->private_data;
2197 return priv->has_opacity;
2201 * gtk_color_selection_set_has_opacity_control:
2202 * @colorsel: a #GtkColorSelection.
2203 * @has_opacity: %TRUE if @colorsel can set the opacity, %FALSE otherwise.
2205 * Sets the @colorsel to use or not use opacity.
2209 gtk_color_selection_set_has_opacity_control (GtkColorSelection *colorsel,
2210 gboolean has_opacity)
2212 ColorSelectionPrivate *priv;
2214 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2216 priv = colorsel->private_data;
2217 has_opacity = has_opacity != FALSE;
2219 if (priv->has_opacity != has_opacity)
2221 priv->has_opacity = has_opacity;
2224 gtk_widget_show (priv->opacity_slider);
2225 gtk_widget_show (priv->opacity_label);
2226 gtk_widget_show (priv->opacity_entry);
2230 gtk_widget_hide (priv->opacity_slider);
2231 gtk_widget_hide (priv->opacity_label);
2232 gtk_widget_hide (priv->opacity_entry);
2234 color_sample_update_samples (colorsel);
2236 g_object_notify (G_OBJECT (colorsel), "has_opacity_control");
2241 * gtk_color_selection_get_has_palette:
2242 * @colorsel: a #GtkColorSelection.
2244 * Determines whether the color selector has a color palette.
2246 * Return value: %TRUE if the selector has a palette. %FALSE if it hasn't.
2249 gtk_color_selection_get_has_palette (GtkColorSelection *colorsel)
2251 ColorSelectionPrivate *priv;
2253 g_return_val_if_fail (GTK_IS_COLOR_SELECTION (colorsel), FALSE);
2255 priv = colorsel->private_data;
2257 return priv->has_palette;
2261 * gtk_color_selection_set_has_palette:
2262 * @colorsel: a #GtkColorSelection.
2263 * @has_palette: %TRUE if palette is to be visible, %FALSE otherwise.
2265 * Shows and hides the palette based upon the value of @has_palette.
2269 gtk_color_selection_set_has_palette (GtkColorSelection *colorsel,
2270 gboolean has_palette)
2272 ColorSelectionPrivate *priv;
2273 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2275 priv = colorsel->private_data;
2276 has_palette = has_palette != FALSE;
2278 if (priv->has_palette != has_palette)
2280 priv->has_palette = has_palette;
2282 gtk_widget_show (priv->palette_frame);
2284 gtk_widget_hide (priv->palette_frame);
2286 g_object_notify (G_OBJECT (colorsel), "has_palette");
2291 * gtk_color_selection_set_current_color:
2292 * @colorsel: a #GtkColorSelection.
2293 * @color: A #GdkColor to set the current color with.
2295 * Sets the current color to be @color. The first time this is called, it will
2296 * also set the original color to be @color too.
2299 gtk_color_selection_set_current_color (GtkColorSelection *colorsel,
2300 const GdkColor *color)
2302 ColorSelectionPrivate *priv;
2304 gboolean previous_changed;
2306 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2307 g_return_if_fail (color != NULL);
2309 priv = colorsel->private_data;
2310 priv->changing = TRUE;
2311 priv->color[COLORSEL_RED] = SCALE (color->red);
2312 priv->color[COLORSEL_GREEN] = SCALE (color->green);
2313 priv->color[COLORSEL_BLUE] = SCALE (color->blue);
2314 gtk_rgb_to_hsv (priv->color[COLORSEL_RED],
2315 priv->color[COLORSEL_GREEN],
2316 priv->color[COLORSEL_BLUE],
2317 &priv->color[COLORSEL_HUE],
2318 &priv->color[COLORSEL_SATURATION],
2319 &priv->color[COLORSEL_VALUE]);
2320 if (priv->default_set == FALSE)
2322 previous_changed = TRUE;
2323 for (i = 0; i < COLORSEL_NUM_CHANNELS; i++)
2324 priv->old_color[i] = priv->color[i];
2326 priv->default_set = TRUE;
2327 update_color (colorsel);
2331 * gtk_color_selection_set_current_alpha:
2332 * @colorsel: a #GtkColorSelection.
2333 * @alpha: an integer between 0 and 65535.
2335 * Sets the current opacity to be @alpha. The first time this is called, it will
2336 * also set the original opacity to be @alpha too.
2339 gtk_color_selection_set_current_alpha (GtkColorSelection *colorsel,
2342 ColorSelectionPrivate *priv;
2345 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2347 priv = colorsel->private_data;
2348 priv->changing = TRUE;
2349 priv->color[COLORSEL_OPACITY] = SCALE (alpha);
2350 if (priv->default_alpha_set == FALSE)
2352 for (i = 0; i < COLORSEL_NUM_CHANNELS; i++)
2353 priv->old_color[i] = priv->color[i];
2355 priv->default_alpha_set = TRUE;
2356 update_color (colorsel);
2360 * gtk_color_selection_set_color:
2361 * @colorsel: a #GtkColorSelection.
2362 * @color: an array of 4 doubles specifying the red, green, blue and opacity
2363 * to set the current color to.
2365 * Sets the current color to be @color. The first time this is called, it will
2366 * also set the original color to be @color too.
2368 * Deprecated: Use gtk_color_selection_set_current_color() instead.
2371 gtk_color_selection_set_color (GtkColorSelection *colorsel,
2374 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2376 set_color_internal (colorsel, color);
2380 * gtk_color_selection_get_current_color:
2381 * @colorsel: a #GtkColorSelection.
2382 * @color: a #GdkColor to fill in with the current color.
2384 * Sets @color to be the current color in the GtkColorSelection widget.
2387 gtk_color_selection_get_current_color (GtkColorSelection *colorsel,
2390 ColorSelectionPrivate *priv;
2392 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2393 g_return_if_fail (color != NULL);
2395 priv = colorsel->private_data;
2396 color->red = UNSCALE (priv->color[COLORSEL_RED]);
2397 color->green = UNSCALE (priv->color[COLORSEL_GREEN]);
2398 color->blue = UNSCALE (priv->color[COLORSEL_BLUE]);
2402 * gtk_color_selection_get_current_alpha:
2403 * @colorsel: a #GtkColorSelection.
2405 * Returns the current alpha value.
2407 * Return value: an integer between 0 and 65535.
2410 gtk_color_selection_get_current_alpha (GtkColorSelection *colorsel)
2412 ColorSelectionPrivate *priv;
2414 g_return_val_if_fail (GTK_IS_COLOR_SELECTION (colorsel), 0);
2416 priv = colorsel->private_data;
2417 return priv->has_opacity ? UNSCALE (priv->color[COLORSEL_OPACITY]) : 65535;
2421 * gtk_color_selection_get_color:
2422 * @colorsel: a #GtkColorSelection.
2423 * @color: an array of 4 #gdouble to fill in with the current color.
2425 * Sets @color to be the current color in the GtkColorSelection widget.
2427 * This function is deprecated, use gtk_color_selection_get_current_color() instead.
2430 gtk_color_selection_get_color (GtkColorSelection *colorsel,
2433 ColorSelectionPrivate *priv;
2435 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2437 priv = colorsel->private_data;
2438 color[0] = priv->color[COLORSEL_RED];
2439 color[1] = priv->color[COLORSEL_GREEN];
2440 color[2] = priv->color[COLORSEL_BLUE];
2441 color[3] = priv->has_opacity ? priv->color[COLORSEL_OPACITY] : 65535;
2445 * gtk_color_selection_set_previous_color:
2446 * @colorsel: a #GtkColorSelection.
2447 * @color: a #GdkColor to set the previous color with.
2449 * Sets the 'previous' color to be @color. This function should be called with
2450 * some hesitations, as it might seem confusing to have that color change.
2451 * Calling gtk_color_selection_set_current_color() will also set this color the first
2452 * time it is called.
2455 gtk_color_selection_set_previous_color (GtkColorSelection *colorsel,
2456 const GdkColor *color)
2458 ColorSelectionPrivate *priv;
2460 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2461 g_return_if_fail (color != NULL);
2463 priv = colorsel->private_data;
2464 priv->changing = TRUE;
2465 priv->old_color[COLORSEL_RED] = SCALE (color->red);
2466 priv->old_color[COLORSEL_GREEN] = SCALE (color->green);
2467 priv->old_color[COLORSEL_BLUE] = SCALE (color->blue);
2468 gtk_rgb_to_hsv (priv->old_color[COLORSEL_RED],
2469 priv->old_color[COLORSEL_GREEN],
2470 priv->old_color[COLORSEL_BLUE],
2471 &priv->old_color[COLORSEL_HUE],
2472 &priv->old_color[COLORSEL_SATURATION],
2473 &priv->old_color[COLORSEL_VALUE]);
2474 color_sample_update_samples (colorsel);
2475 priv->default_set = TRUE;
2476 priv->changing = FALSE;
2480 * gtk_color_selection_set_previous_alpha:
2481 * @colorsel: a #GtkColorSelection.
2482 * @alpha: an integer between 0 and 65535.
2484 * Sets the 'previous' alpha to be @alpha. This function should be called with
2485 * some hesitations, as it might seem confusing to have that alpha change.
2488 gtk_color_selection_set_previous_alpha (GtkColorSelection *colorsel,
2491 ColorSelectionPrivate *priv;
2493 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2495 priv = colorsel->private_data;
2496 priv->changing = TRUE;
2497 priv->old_color[COLORSEL_OPACITY] = SCALE (alpha);
2498 color_sample_update_samples (colorsel);
2499 priv->default_alpha_set = TRUE;
2500 priv->changing = FALSE;
2505 * gtk_color_selection_get_previous_color:
2506 * @colorsel: a #GtkColorSelection.
2507 * @color: a #GdkColor to fill in with the original color value.
2509 * Fills @color in with the original color value.
2512 gtk_color_selection_get_previous_color (GtkColorSelection *colorsel,
2515 ColorSelectionPrivate *priv;
2517 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2518 g_return_if_fail (color != NULL);
2520 priv = colorsel->private_data;
2521 color->red = UNSCALE (priv->old_color[COLORSEL_RED]);
2522 color->green = UNSCALE (priv->old_color[COLORSEL_GREEN]);
2523 color->blue = UNSCALE (priv->old_color[COLORSEL_BLUE]);
2527 * gtk_color_selection_get_previous_alpha:
2528 * @colorsel: a #GtkColorSelection.
2530 * Returns the previous alpha value.
2532 * Return value: an integer between 0 and 65535.
2535 gtk_color_selection_get_previous_alpha (GtkColorSelection *colorsel)
2537 ColorSelectionPrivate *priv;
2539 g_return_val_if_fail (GTK_IS_COLOR_SELECTION (colorsel), 0);
2541 priv = colorsel->private_data;
2542 return priv->has_opacity ? UNSCALE (priv->old_color[COLORSEL_OPACITY]) : 65535;
2546 * gtk_color_selection_set_palette_color:
2547 * @colorsel: a #GtkColorSelection.
2548 * @index: the color index of the palette.
2549 * @color: A #GdkColor to set the palette with.
2551 * Sets the palette located at @index to have @color as its color.
2555 gtk_color_selection_set_palette_color (GtkColorSelection *colorsel,
2559 ColorSelectionPrivate *priv;
2563 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2564 g_return_if_fail (index >= 0 && index < GTK_CUSTOM_PALETTE_WIDTH*GTK_CUSTOM_PALETTE_HEIGHT);
2566 x = index % GTK_CUSTOM_PALETTE_WIDTH;
2567 y = index / GTK_CUSTOM_PALETTE_WIDTH;
2569 priv = colorsel->private_data;
2570 col[0] = SCALE (color->red);
2571 col[1] = SCALE (color->green);
2572 col[2] = SCALE (color->blue);
2574 palette_set_color (priv->custom_palette[x][y], colorsel, col);
2578 * gtk_color_selection_is_adjusting:
2579 * @colorsel: a #GtkColorSelection.
2581 * Gets the current state of the @colorsel.
2583 * Return value: %TRUE if the user is currently dragging a color around, and %FALSE
2584 * if the selection has stopped.
2587 gtk_color_selection_is_adjusting (GtkColorSelection *colorsel)
2589 ColorSelectionPrivate *priv;
2591 g_return_val_if_fail (GTK_IS_COLOR_SELECTION (colorsel), FALSE);
2593 priv = colorsel->private_data;
2595 return (gtk_hsv_is_adjusting (GTK_HSV (priv->triangle_colorsel)));
2599 gtk_color_selection_set_property (GObject *object,
2601 const GValue *value,
2604 GtkColorSelection *colorsel = GTK_COLOR_SELECTION (object);
2608 case PROP_HAS_OPACITY_CONTROL:
2609 gtk_color_selection_set_has_opacity_control (colorsel,
2610 g_value_get_boolean (value));
2612 case PROP_HAS_PALETTE:
2613 gtk_color_selection_set_has_palette (colorsel,
2614 g_value_get_boolean (value));
2616 case PROP_CURRENT_COLOR:
2617 gtk_color_selection_set_current_color (colorsel, g_value_get_boxed (value));
2619 case PROP_CURRENT_ALPHA:
2620 gtk_color_selection_set_current_alpha (colorsel, g_value_get_uint (value));
2623 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
2630 gtk_color_selection_get_property (GObject *object,
2635 GtkColorSelection *colorsel = GTK_COLOR_SELECTION (object);
2640 case PROP_HAS_OPACITY_CONTROL:
2641 g_value_set_boolean (value, gtk_color_selection_get_has_opacity_control (colorsel));
2643 case PROP_HAS_PALETTE:
2644 g_value_set_boolean (value, gtk_color_selection_get_has_palette (colorsel));
2646 case PROP_CURRENT_COLOR:
2647 gtk_color_selection_get_current_color (colorsel, &color);
2648 g_value_set_boxed (value, &color);
2650 case PROP_CURRENT_ALPHA:
2651 g_value_set_uint (value, gtk_color_selection_get_current_alpha (colorsel));
2654 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
2661 * gtk_color_selection_palette_from_string:
2662 * @str: a string encoding a color palette.
2663 * @colors: return location for allocated array of #GdkColor.
2664 * @n_colors: return location for length of array.
2666 * Parses a color palette string; the string is a colon-separated
2667 * list of color names readable by gdk_color_parse().
2669 * Return value: %TRUE if a palette was successfully parsed.
2672 gtk_color_selection_palette_from_string (const gchar *str,
2684 copy = g_strdup (str);
2690 if (*p == ':' || *p == '\0')
2692 gboolean done = TRUE;
2696 goto failed; /* empty entry */
2705 retval = g_renew (GdkColor, retval, count + 1);
2706 if (!gdk_color_parse (start, retval + count))
2747 * gtk_color_selection_palette_to_string:
2748 * @colors: an array of colors.
2749 * @n_colors: length of the array.
2751 * Encodes a palette as a string, useful for persistent storage.
2753 * Return value: allocated string encoding the palette.
2756 gtk_color_selection_palette_to_string (const GdkColor *colors,
2760 gchar **strs = NULL;
2764 return g_strdup ("");
2766 strs = g_new0 (gchar*, n_colors + 1);
2769 while (i < n_colors)
2774 g_strdup_printf ("#%2X%2X%2X",
2775 colors[i].red / 256,
2776 colors[i].green / 256,
2777 colors[i].blue / 256);
2779 for (ptr = strs[i]; *ptr; ptr++)
2786 retval = g_strjoinv (":", strs);
2794 * gtk_color_selection_set_change_palette_hook:
2795 * @func: a function to call when the custom palette needs saving.
2797 * Installs a global function to be called whenever the user tries to
2798 * modify the palette in a color selection. This function should save
2799 * the new palette contents, and update the GtkSettings property
2800 * "gtk-color-palette" so all GtkColorSelection widgets will be modified.
2802 * Return value: the previous change palette hook (that was replaced).
2804 * Deprecated: This function is deprecated in favor of
2805 * gtk_color_selection_set_change_palette_with_screen_hook(), and does
2806 * not work in multihead environments.
2809 GtkColorSelectionChangePaletteFunc
2810 gtk_color_selection_set_change_palette_hook (GtkColorSelectionChangePaletteFunc func)
2812 GtkColorSelectionChangePaletteFunc old;
2814 old = noscreen_change_palette_hook;
2816 noscreen_change_palette_hook = func;
2822 * gtk_color_selection_set_change_palette_with_screen_hook:
2823 * @func: a function to call when the custom palette needs saving.
2825 * Installs a global function to be called whenever the user tries to
2826 * modify the palette in a color selection. This function should save
2827 * the new palette contents, and update the GtkSettings property
2828 * "gtk-color-palette" so all GtkColorSelection widgets will be modified.
2830 * Return value: the previous change palette hook (that was replaced).
2834 GtkColorSelectionChangePaletteWithScreenFunc
2835 gtk_color_selection_set_change_palette_with_screen_hook (GtkColorSelectionChangePaletteWithScreenFunc func)
2837 GtkColorSelectionChangePaletteWithScreenFunc old;
2839 old = change_palette_hook;
2841 change_palette_hook = func;
2847 make_control_relations (AtkObject *atk_obj,
2852 obj = gtk_widget_get_accessible (widget);
2853 atk_object_add_relationship (atk_obj, ATK_RELATION_CONTROLLED_BY, obj);
2854 atk_object_add_relationship (obj, ATK_RELATION_CONTROLLER_FOR, atk_obj);
2858 make_all_relations (AtkObject *atk_obj,
2859 ColorSelectionPrivate *priv)
2861 make_control_relations (atk_obj, priv->hue_spinbutton);
2862 make_control_relations (atk_obj, priv->sat_spinbutton);
2863 make_control_relations (atk_obj, priv->val_spinbutton);
2864 make_control_relations (atk_obj, priv->red_spinbutton);
2865 make_control_relations (atk_obj, priv->green_spinbutton);
2866 make_control_relations (atk_obj, priv->blue_spinbutton);
2869 #define __GTK_COLOR_SELECTION_C__
2870 #include "gtkaliasdef.c"