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 "gtkinvisible.h"
54 #include "gtkmenuitem.h"
56 #include "gtksettings.h"
58 #include "gtkaccessible.h"
59 #include "gtkprivate.h"
65 /* Number of elements in the custom palatte */
66 #define GTK_CUSTOM_PALETTE_WIDTH 10
67 #define GTK_CUSTOM_PALETTE_HEIGHT 2
69 /* Conversion between 0->1 double and and guint16. See
70 * scale_round() below for more general conversions
72 #define SCALE(i) (i / 65535.)
73 #define UNSCALE(d) ((guint16)(d * 65535 + 0.5))
84 PROP_HAS_OPACITY_CONTROL,
100 typedef struct _ColorSelectionPrivate ColorSelectionPrivate;
102 struct _ColorSelectionPrivate
104 guint has_opacity : 1;
105 guint has_palette : 1;
107 guint default_set : 1;
108 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;
136 /* Window for grabbing on */
137 GtkWidget *dropper_grab_widget;
140 /* Connection to settings */
141 gulong settings_connection;
145 static void gtk_color_selection_destroy (GtkObject *object);
146 static void gtk_color_selection_finalize (GObject *object);
147 static void update_color (GtkColorSelection *colorsel);
148 static void gtk_color_selection_set_property (GObject *object,
152 static void gtk_color_selection_get_property (GObject *object,
157 static void gtk_color_selection_realize (GtkWidget *widget);
158 static void gtk_color_selection_unrealize (GtkWidget *widget);
159 static void gtk_color_selection_show_all (GtkWidget *widget);
160 static gboolean gtk_color_selection_grab_broken (GtkWidget *widget,
161 GdkEventGrabBroken *event);
163 static void gtk_color_selection_set_palette_color (GtkColorSelection *colorsel,
166 static void set_focus_line_attributes (GtkWidget *drawing_area,
169 static void default_noscreen_change_palette_func (const GdkColor *colors,
171 static void default_change_palette_func (GdkScreen *screen,
172 const GdkColor *colors,
174 static void make_control_relations (AtkObject *atk_obj,
176 static void make_all_relations (AtkObject *atk_obj,
177 ColorSelectionPrivate *priv);
179 static guint color_selection_signals[LAST_SIGNAL] = { 0 };
181 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";
183 static GtkColorSelectionChangePaletteFunc noscreen_change_palette_hook = default_noscreen_change_palette_func;
184 static GtkColorSelectionChangePaletteWithScreenFunc change_palette_hook = default_change_palette_func;
186 /* The cursor for the dropper */
187 #define DROPPER_WIDTH 17
188 #define DROPPER_HEIGHT 17
189 #define DROPPER_X_HOT 2
190 #define DROPPER_Y_HOT 16
193 static const guchar dropper_bits[] = {
194 0xff, 0x8f, 0x01, 0xff, 0x77, 0x01, 0xff, 0xfb, 0x00, 0xff, 0xf8, 0x00,
195 0x7f, 0xff, 0x00, 0xff, 0x7e, 0x01, 0xff, 0x9d, 0x01, 0xff, 0xd8, 0x01,
196 0x7f, 0xd4, 0x01, 0x3f, 0xee, 0x01, 0x1f, 0xff, 0x01, 0x8f, 0xff, 0x01,
197 0xc7, 0xff, 0x01, 0xe3, 0xff, 0x01, 0xf3, 0xff, 0x01, 0xfd, 0xff, 0x01,
200 static const guchar dropper_mask[] = {
201 0x00, 0x70, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xfc, 0x01, 0x00, 0xff, 0x01,
202 0x80, 0xff, 0x01, 0x00, 0xff, 0x00, 0x00, 0x7f, 0x00, 0x80, 0x3f, 0x00,
203 0xc0, 0x3f, 0x00, 0xe0, 0x13, 0x00, 0xf0, 0x01, 0x00, 0xf8, 0x00, 0x00,
204 0x7c, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x0d, 0x00, 0x00,
213 #define SAMPLE_WIDTH 64
214 #define SAMPLE_HEIGHT 28
216 static void color_sample_draw_sample (GtkColorSelection *colorsel, int which);
217 static void color_sample_update_samples (GtkColorSelection *colorsel);
220 set_color_internal (GtkColorSelection *colorsel,
223 ColorSelectionPrivate *priv;
226 priv = colorsel->private_data;
227 priv->changing = TRUE;
228 priv->color[COLORSEL_RED] = color[0];
229 priv->color[COLORSEL_GREEN] = color[1];
230 priv->color[COLORSEL_BLUE] = color[2];
231 priv->color[COLORSEL_OPACITY] = color[3];
232 gtk_rgb_to_hsv (priv->color[COLORSEL_RED],
233 priv->color[COLORSEL_GREEN],
234 priv->color[COLORSEL_BLUE],
235 &priv->color[COLORSEL_HUE],
236 &priv->color[COLORSEL_SATURATION],
237 &priv->color[COLORSEL_VALUE]);
238 if (priv->default_set == FALSE)
240 for (i = 0; i < COLORSEL_NUM_CHANNELS; i++)
241 priv->old_color[i] = priv->color[i];
243 priv->default_set = TRUE;
244 priv->default_alpha_set = TRUE;
245 update_color (colorsel);
249 set_color_icon (GdkDragContext *context,
255 pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE,
258 pixel = (((UNSCALE (colors[COLORSEL_RED]) & 0xff00) << 16) |
259 ((UNSCALE (colors[COLORSEL_GREEN]) & 0xff00) << 8) |
260 ((UNSCALE (colors[COLORSEL_BLUE]) & 0xff00)));
262 gdk_pixbuf_fill (pixbuf, pixel);
264 gtk_drag_set_icon_pixbuf (context, pixbuf, -2, -2);
265 g_object_unref (pixbuf);
269 color_sample_drag_begin (GtkWidget *widget,
270 GdkDragContext *context,
273 GtkColorSelection *colorsel = data;
274 ColorSelectionPrivate *priv;
277 priv = colorsel->private_data;
279 if (widget == priv->old_sample)
280 colsrc = priv->old_color;
282 colsrc = priv->color;
284 set_color_icon (context, colsrc);
288 color_sample_drag_end (GtkWidget *widget,
289 GdkDragContext *context,
292 g_object_set_data (G_OBJECT (widget), I_("gtk-color-selection-drag-window"), NULL);
296 color_sample_drop_handle (GtkWidget *widget,
297 GdkDragContext *context,
300 GtkSelectionData *selection_data,
305 GtkColorSelection *colorsel = data;
306 ColorSelectionPrivate *priv;
309 priv = colorsel->private_data;
311 /* This is currently a guint16 array of the format:
318 if (selection_data->length < 0)
321 /* We accept drops with the wrong format, since the KDE color
322 * chooser incorrectly drops application/x-color with format 8.
324 if (selection_data->length != 8)
326 g_warning ("Received invalid color data\n");
330 vals = (guint16 *)selection_data->data;
332 if (widget == priv->cur_sample)
334 color[0] = (gdouble)vals[0] / 0xffff;
335 color[1] = (gdouble)vals[1] / 0xffff;
336 color[2] = (gdouble)vals[2] / 0xffff;
337 color[3] = (gdouble)vals[3] / 0xffff;
339 set_color_internal (colorsel, color);
344 color_sample_drag_handle (GtkWidget *widget,
345 GdkDragContext *context,
346 GtkSelectionData *selection_data,
351 GtkColorSelection *colorsel = data;
352 ColorSelectionPrivate *priv;
356 priv = colorsel->private_data;
358 if (widget == priv->old_sample)
359 colsrc = priv->old_color;
361 colsrc = priv->color;
363 vals[0] = colsrc[COLORSEL_RED] * 0xffff;
364 vals[1] = colsrc[COLORSEL_GREEN] * 0xffff;
365 vals[2] = colsrc[COLORSEL_BLUE] * 0xffff;
366 vals[3] = priv->has_opacity ? colsrc[COLORSEL_OPACITY] * 0xffff : 0xffff;
368 gtk_selection_data_set (selection_data,
369 gdk_atom_intern_static_string ("application/x-color"),
370 16, (guchar *)vals, 8);
373 /* which = 0 means draw old sample, which = 1 means draw new */
375 color_sample_draw_sample (GtkColorSelection *colorsel, int which)
378 gint x, y, wid, heig, goff;
379 ColorSelectionPrivate *priv;
382 g_return_if_fail (colorsel != NULL);
383 priv = colorsel->private_data;
385 g_return_if_fail (priv->sample_area != NULL);
386 if (!GTK_WIDGET_DRAWABLE (priv->sample_area))
391 da = priv->old_sample;
396 da = priv->cur_sample;
397 goff = priv->old_sample->allocation.width % 32;
400 cr = gdk_cairo_create (da->window);
402 wid = da->allocation.width;
403 heig = da->allocation.height;
405 /* Below needs tweaking for non-power-of-two */
406 #define CHECK_SIZE 16
408 if (priv->has_opacity)
410 /* Draw checks in background */
412 cairo_set_source_rgb (cr, 0.5, 0.5, 0.5);
413 cairo_rectangle (cr, 0, 0, wid, heig);
416 cairo_set_source_rgb (cr, 0.75, 0.75, 0.75);
417 for (x = goff & -CHECK_SIZE; x < goff + wid; x += CHECK_SIZE)
418 for (y = 0; y < heig; y += CHECK_SIZE)
419 if ((x / CHECK_SIZE + y / CHECK_SIZE) % 2 == 0)
420 cairo_rectangle (cr, x - goff, y, CHECK_SIZE, CHECK_SIZE);
426 cairo_set_source_rgba (cr,
427 priv->old_color[COLORSEL_RED],
428 priv->old_color[COLORSEL_GREEN],
429 priv->old_color[COLORSEL_BLUE],
431 priv->old_color[COLORSEL_OPACITY] : 1.0);
435 cairo_set_source_rgba (cr,
436 priv->color[COLORSEL_RED],
437 priv->color[COLORSEL_GREEN],
438 priv->color[COLORSEL_BLUE],
440 priv->color[COLORSEL_OPACITY] : 1.0);
443 cairo_rectangle (cr, 0, 0, wid, heig);
451 color_sample_update_samples (GtkColorSelection *colorsel)
453 ColorSelectionPrivate *priv = colorsel->private_data;
454 gtk_widget_queue_draw (priv->old_sample);
455 gtk_widget_queue_draw (priv->cur_sample);
459 color_old_sample_expose (GtkWidget *da,
460 GdkEventExpose *event,
461 GtkColorSelection *colorsel)
463 color_sample_draw_sample (colorsel, 0);
469 color_cur_sample_expose (GtkWidget *da,
470 GdkEventExpose *event,
471 GtkColorSelection *colorsel)
473 color_sample_draw_sample (colorsel, 1);
478 color_sample_setup_dnd (GtkColorSelection *colorsel, GtkWidget *sample)
480 static const GtkTargetEntry targets[] = {
481 { "application/x-color", 0 }
483 ColorSelectionPrivate *priv;
484 priv = colorsel->private_data;
486 gtk_drag_source_set (sample,
487 GDK_BUTTON1_MASK | GDK_BUTTON3_MASK,
489 GDK_ACTION_COPY | GDK_ACTION_MOVE);
491 g_signal_connect (sample,
493 G_CALLBACK (color_sample_drag_begin),
495 if (sample == priv->cur_sample)
498 gtk_drag_dest_set (sample,
499 GTK_DEST_DEFAULT_HIGHLIGHT |
500 GTK_DEST_DEFAULT_MOTION |
501 GTK_DEST_DEFAULT_DROP,
505 g_signal_connect (sample,
507 G_CALLBACK (color_sample_drag_end),
511 g_signal_connect (sample,
513 G_CALLBACK (color_sample_drag_handle),
515 g_signal_connect (sample,
516 "drag_data_received",
517 G_CALLBACK (color_sample_drop_handle),
524 color_sample_new (GtkColorSelection *colorsel)
526 ColorSelectionPrivate *priv;
528 priv = colorsel->private_data;
530 priv->sample_area = gtk_hbox_new (FALSE, 0);
531 priv->old_sample = gtk_drawing_area_new ();
532 priv->cur_sample = gtk_drawing_area_new ();
534 gtk_box_pack_start (GTK_BOX (priv->sample_area), priv->old_sample,
536 gtk_box_pack_start (GTK_BOX (priv->sample_area), priv->cur_sample,
539 g_signal_connect (priv->old_sample, "expose_event",
540 G_CALLBACK (color_old_sample_expose),
542 g_signal_connect (priv->cur_sample, "expose_event",
543 G_CALLBACK (color_cur_sample_expose),
546 color_sample_setup_dnd (colorsel, priv->old_sample);
547 color_sample_setup_dnd (colorsel, priv->cur_sample);
549 gtk_widget_set_tooltip_text (priv->old_sample,
550 _("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."));
553 gtk_widget_set_tooltip_text (priv->cur_sample,
554 _("The color you've chosen. You can drag this color to a palette entry to save it for use in the future."));
556 gtk_widget_show_all (priv->sample_area);
562 * The palette area code
565 #define CUSTOM_PALETTE_ENTRY_WIDTH 20
566 #define CUSTOM_PALETTE_ENTRY_HEIGHT 20
569 palette_get_color (GtkWidget *drawing_area, gdouble *color)
573 g_return_if_fail (color != NULL);
575 color_val = g_object_get_data (G_OBJECT (drawing_area), "color_val");
576 if (color_val == NULL)
578 /* Default to white for no good reason */
586 color[0] = color_val[0];
587 color[1] = color_val[1];
588 color[2] = color_val[2];
592 #define INTENSITY(r, g, b) ((r) * 0.30 + (g) * 0.59 + (b) * 0.11)
594 palette_paint (GtkWidget *drawing_area,
601 if (drawing_area->window == NULL)
604 cr = gdk_cairo_create (drawing_area->window);
606 gdk_cairo_set_source_color (cr, &drawing_area->style->bg[GTK_STATE_NORMAL]);
607 gdk_cairo_rectangle (cr, area);
610 if (GTK_WIDGET_HAS_FOCUS (drawing_area))
612 set_focus_line_attributes (drawing_area, cr, &focus_width);
615 focus_width / 2., focus_width / 2.,
616 drawing_area->allocation.width - focus_width,
617 drawing_area->allocation.height - focus_width);
625 set_focus_line_attributes (GtkWidget *drawing_area,
632 gtk_widget_style_get (drawing_area,
633 "focus-line-width", focus_width,
634 "focus-line-pattern", (gchar *)&dash_list,
637 palette_get_color (drawing_area, color);
639 if (INTENSITY (color[0], color[1], color[2]) > 0.5)
640 cairo_set_source_rgb (cr, 0., 0., 0.);
642 cairo_set_source_rgb (cr, 1., 1., 1.);
644 cairo_set_line_width (cr, *focus_width);
648 gint n_dashes = strlen (dash_list);
649 gdouble *dashes = g_new (gdouble, n_dashes);
650 gdouble total_length = 0;
654 for (i = 0; i < n_dashes; i++)
656 dashes[i] = dash_list[i];
657 total_length += dash_list[i];
660 /* The dash offset here aligns the pattern to integer pixels
661 * by starting the dash at the right side of the left border
662 * Negative dash offsets in cairo don't work
663 * (https://bugs.freedesktop.org/show_bug.cgi?id=2729)
665 dash_offset = - *focus_width / 2.;
666 while (dash_offset < 0)
667 dash_offset += total_length;
669 cairo_set_dash (cr, dashes, n_dashes, dash_offset);
677 palette_drag_begin (GtkWidget *widget,
678 GdkDragContext *context,
683 palette_get_color (widget, colors);
684 set_color_icon (context, colors);
688 palette_drag_handle (GtkWidget *widget,
689 GdkDragContext *context,
690 GtkSelectionData *selection_data,
698 palette_get_color (widget, colsrc);
700 vals[0] = colsrc[COLORSEL_RED] * 0xffff;
701 vals[1] = colsrc[COLORSEL_GREEN] * 0xffff;
702 vals[2] = colsrc[COLORSEL_BLUE] * 0xffff;
705 gtk_selection_data_set (selection_data,
706 gdk_atom_intern_static_string ("application/x-color"),
707 16, (guchar *)vals, 8);
711 palette_drag_end (GtkWidget *widget,
712 GdkDragContext *context,
715 g_object_set_data (G_OBJECT (widget), I_("gtk-color-selection-drag-window"), NULL);
719 get_current_colors (GtkColorSelection *colorsel)
721 GtkSettings *settings;
722 GdkColor *colors = NULL;
726 settings = gtk_widget_get_settings (GTK_WIDGET (colorsel));
727 g_object_get (settings,
728 "gtk-color-palette", &palette,
731 if (!gtk_color_selection_palette_from_string (palette, &colors, &n_colors))
733 gtk_color_selection_palette_from_string (default_colors, &colors, &n_colors);
737 /* If there are less colors provided than the number of slots in the
738 * color selection, we fill in the rest from the defaults.
740 if (n_colors < (GTK_CUSTOM_PALETTE_WIDTH * GTK_CUSTOM_PALETTE_HEIGHT))
742 GdkColor *tmp_colors = colors;
743 gint tmp_n_colors = n_colors;
745 gtk_color_selection_palette_from_string (default_colors, &colors, &n_colors);
746 memcpy (colors, tmp_colors, sizeof (GdkColor) * tmp_n_colors);
752 g_assert (n_colors >= GTK_CUSTOM_PALETTE_WIDTH * GTK_CUSTOM_PALETTE_HEIGHT);
758 /* Changes the model color */
760 palette_change_color (GtkWidget *drawing_area,
761 GtkColorSelection *colorsel,
765 ColorSelectionPrivate *priv;
767 GdkColor *current_colors;
770 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
771 g_return_if_fail (GTK_IS_DRAWING_AREA (drawing_area));
773 priv = colorsel->private_data;
775 gdk_color.red = UNSCALE (color[0]);
776 gdk_color.green = UNSCALE (color[1]);
777 gdk_color.blue = UNSCALE (color[2]);
781 y = 0; /* Quiet GCC */
782 while (x < GTK_CUSTOM_PALETTE_WIDTH)
785 while (y < GTK_CUSTOM_PALETTE_HEIGHT)
787 if (priv->custom_palette[x][y] == drawing_area)
798 g_assert (x < GTK_CUSTOM_PALETTE_WIDTH || y < GTK_CUSTOM_PALETTE_HEIGHT);
800 current_colors = get_current_colors (colorsel);
801 current_colors[y * GTK_CUSTOM_PALETTE_WIDTH + x] = gdk_color;
803 screen = gtk_widget_get_screen (GTK_WIDGET (colorsel));
804 if (change_palette_hook != default_change_palette_func)
805 (* change_palette_hook) (screen, current_colors,
806 GTK_CUSTOM_PALETTE_WIDTH * GTK_CUSTOM_PALETTE_HEIGHT);
807 else if (noscreen_change_palette_hook != default_noscreen_change_palette_func)
809 if (screen != gdk_screen_get_default ())
810 g_warning ("gtk_color_selection_set_change_palette_hook used by widget is not on the default screen.");
811 (* noscreen_change_palette_hook) (current_colors,
812 GTK_CUSTOM_PALETTE_WIDTH * GTK_CUSTOM_PALETTE_HEIGHT);
815 (* change_palette_hook) (screen, current_colors,
816 GTK_CUSTOM_PALETTE_WIDTH * GTK_CUSTOM_PALETTE_HEIGHT);
818 g_free (current_colors);
821 /* Changes the view color */
823 palette_set_color (GtkWidget *drawing_area,
824 GtkColorSelection *colorsel,
827 gdouble *new_color = g_new (double, 4);
830 gdk_color.red = UNSCALE (color[0]);
831 gdk_color.green = UNSCALE (color[1]);
832 gdk_color.blue = UNSCALE (color[2]);
834 gtk_widget_modify_bg (drawing_area, GTK_STATE_NORMAL, &gdk_color);
836 if (GPOINTER_TO_INT (g_object_get_data (G_OBJECT (drawing_area), "color_set")) == 0)
838 static const GtkTargetEntry targets[] = {
839 { "application/x-color", 0 }
841 gtk_drag_source_set (drawing_area,
842 GDK_BUTTON1_MASK | GDK_BUTTON3_MASK,
844 GDK_ACTION_COPY | GDK_ACTION_MOVE);
846 g_signal_connect (drawing_area,
848 G_CALLBACK (palette_drag_begin),
850 g_signal_connect (drawing_area,
852 G_CALLBACK (palette_drag_handle),
855 g_object_set_data (G_OBJECT (drawing_area), I_("color_set"),
856 GINT_TO_POINTER (1));
859 new_color[0] = color[0];
860 new_color[1] = color[1];
861 new_color[2] = color[2];
864 g_object_set_data_full (G_OBJECT (drawing_area), I_("color_val"), new_color, (GDestroyNotify)g_free);
868 palette_expose (GtkWidget *drawing_area,
869 GdkEventExpose *event,
872 if (drawing_area->window == NULL)
875 palette_paint (drawing_area, &(event->area), data);
881 popup_position_func (GtkMenu *menu,
892 widget = GTK_WIDGET (user_data);
894 g_return_if_fail (GTK_WIDGET_REALIZED (widget));
896 gdk_window_get_origin (widget->window, &root_x, &root_y);
898 gtk_widget_size_request (GTK_WIDGET (menu), &req);
900 /* Put corner of menu centered on color cell */
901 *x = root_x + widget->allocation.width / 2;
902 *y = root_y + widget->allocation.height / 2;
905 screen = gtk_widget_get_screen (widget);
906 *x = CLAMP (*x, 0, MAX (0, gdk_screen_get_width (screen) - req.width));
907 *y = CLAMP (*y, 0, MAX (0, gdk_screen_get_height (screen) - req.height));
911 save_color_selected (GtkWidget *menuitem,
914 GtkColorSelection *colorsel;
915 GtkWidget *drawing_area;
916 ColorSelectionPrivate *priv;
918 drawing_area = GTK_WIDGET (data);
920 colorsel = GTK_COLOR_SELECTION (g_object_get_data (G_OBJECT (drawing_area),
923 priv = colorsel->private_data;
925 palette_change_color (drawing_area, colorsel, priv->color);
929 do_popup (GtkColorSelection *colorsel,
930 GtkWidget *drawing_area,
936 g_object_set_data (G_OBJECT (drawing_area),
940 menu = gtk_menu_new ();
942 mi = gtk_menu_item_new_with_mnemonic (_("_Save color here"));
944 g_signal_connect (mi, "activate",
945 G_CALLBACK (save_color_selected),
948 gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
950 gtk_widget_show_all (mi);
952 gtk_menu_popup (GTK_MENU (menu), NULL, NULL,
953 popup_position_func, drawing_area,
959 palette_enter (GtkWidget *drawing_area,
960 GdkEventCrossing *event,
963 g_object_set_data (G_OBJECT (drawing_area),
964 I_("gtk-colorsel-have-pointer"),
965 GUINT_TO_POINTER (TRUE));
971 palette_leave (GtkWidget *drawing_area,
972 GdkEventCrossing *event,
975 g_object_set_data (G_OBJECT (drawing_area),
976 I_("gtk-colorsel-have-pointer"),
983 palette_press (GtkWidget *drawing_area,
984 GdkEventButton *event,
987 GtkColorSelection *colorsel = GTK_COLOR_SELECTION (data);
989 gtk_widget_grab_focus (drawing_area);
991 if (event->button == 3 &&
992 event->type == GDK_BUTTON_PRESS)
994 do_popup (colorsel, drawing_area, event->time);
1002 palette_release (GtkWidget *drawing_area,
1003 GdkEventButton *event,
1006 GtkColorSelection *colorsel = GTK_COLOR_SELECTION (data);
1008 gtk_widget_grab_focus (drawing_area);
1010 if (event->button == 1 &&
1011 g_object_get_data (G_OBJECT (drawing_area),
1012 "gtk-colorsel-have-pointer") != NULL)
1014 if (GPOINTER_TO_INT (g_object_get_data (G_OBJECT (drawing_area), "color_set")) != 0)
1017 palette_get_color (drawing_area, color);
1018 set_color_internal (colorsel, color);
1026 palette_drop_handle (GtkWidget *widget,
1027 GdkDragContext *context,
1030 GtkSelectionData *selection_data,
1035 GtkColorSelection *colorsel = GTK_COLOR_SELECTION (data);
1039 if (selection_data->length < 0)
1042 /* We accept drops with the wrong format, since the KDE color
1043 * chooser incorrectly drops application/x-color with format 8.
1045 if (selection_data->length != 8)
1047 g_warning ("Received invalid color data\n");
1051 vals = (guint16 *)selection_data->data;
1053 color[0] = (gdouble)vals[0] / 0xffff;
1054 color[1] = (gdouble)vals[1] / 0xffff;
1055 color[2] = (gdouble)vals[2] / 0xffff;
1056 color[3] = (gdouble)vals[3] / 0xffff;
1057 palette_change_color (widget, colorsel, color);
1058 set_color_internal (colorsel, color);
1062 palette_activate (GtkWidget *widget,
1066 /* should have a drawing area subclass with an activate signal */
1067 if ((event->keyval == GDK_space) ||
1068 (event->keyval == GDK_Return) ||
1069 (event->keyval == GDK_ISO_Enter) ||
1070 (event->keyval == GDK_KP_Enter) ||
1071 (event->keyval == GDK_KP_Space))
1073 if (GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget), "color_set")) != 0)
1076 palette_get_color (widget, color);
1077 set_color_internal (GTK_COLOR_SELECTION (data), color);
1086 palette_popup (GtkWidget *widget,
1089 GtkColorSelection *colorsel = GTK_COLOR_SELECTION (data);
1091 do_popup (colorsel, widget, GDK_CURRENT_TIME);
1097 palette_new (GtkColorSelection *colorsel)
1100 ColorSelectionPrivate *priv;
1102 static const GtkTargetEntry targets[] = {
1103 { "application/x-color", 0 }
1106 priv = colorsel->private_data;
1108 retval = gtk_drawing_area_new ();
1110 GTK_WIDGET_SET_FLAGS (retval, GTK_CAN_FOCUS);
1112 g_object_set_data (G_OBJECT (retval), I_("color_set"), GINT_TO_POINTER (0));
1113 gtk_widget_set_events (retval, GDK_BUTTON_PRESS_MASK
1114 | GDK_BUTTON_RELEASE_MASK
1116 | GDK_ENTER_NOTIFY_MASK
1117 | GDK_LEAVE_NOTIFY_MASK);
1119 g_signal_connect (retval, "expose_event",
1120 G_CALLBACK (palette_expose), colorsel);
1121 g_signal_connect (retval, "button_press_event",
1122 G_CALLBACK (palette_press), colorsel);
1123 g_signal_connect (retval, "button_release_event",
1124 G_CALLBACK (palette_release), colorsel);
1125 g_signal_connect (retval, "enter_notify_event",
1126 G_CALLBACK (palette_enter), colorsel);
1127 g_signal_connect (retval, "leave_notify_event",
1128 G_CALLBACK (palette_leave), colorsel);
1129 g_signal_connect (retval, "key_press_event",
1130 G_CALLBACK (palette_activate), colorsel);
1131 g_signal_connect (retval, "popup_menu",
1132 G_CALLBACK (palette_popup), colorsel);
1134 gtk_drag_dest_set (retval,
1135 GTK_DEST_DEFAULT_HIGHLIGHT |
1136 GTK_DEST_DEFAULT_MOTION |
1137 GTK_DEST_DEFAULT_DROP,
1141 g_signal_connect (retval, "drag_end",
1142 G_CALLBACK (palette_drag_end), NULL);
1143 g_signal_connect (retval, "drag_data_received",
1144 G_CALLBACK (palette_drop_handle), colorsel);
1146 gtk_widget_set_tooltip_text (retval,
1147 _("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.\""));
1154 * The actual GtkColorSelection widget
1159 make_picker_cursor (GdkScreen *screen)
1163 cursor = gdk_cursor_new_from_name (gdk_screen_get_display (screen),
1168 GdkColor bg = { 0, 0xffff, 0xffff, 0xffff };
1169 GdkColor fg = { 0, 0x0000, 0x0000, 0x0000 };
1171 GdkPixmap *pixmap, *mask;
1173 window = gdk_screen_get_root_window (screen);
1176 gdk_bitmap_create_from_data (window, (gchar *) dropper_bits,
1177 DROPPER_WIDTH, DROPPER_HEIGHT);
1180 gdk_bitmap_create_from_data (window, (gchar *) dropper_mask,
1181 DROPPER_WIDTH, DROPPER_HEIGHT);
1183 cursor = gdk_cursor_new_from_pixmap (pixmap, mask, &fg, &bg,
1184 DROPPER_X_HOT, DROPPER_Y_HOT);
1186 g_object_unref (pixmap);
1187 g_object_unref (mask);
1194 grab_color_at_mouse (GdkScreen *screen,
1201 GtkColorSelection *colorsel = data;
1202 ColorSelectionPrivate *priv;
1204 GdkColormap *colormap = gdk_screen_get_system_colormap (screen);
1205 GdkWindow *root_window = gdk_screen_get_root_window (screen);
1207 priv = colorsel->private_data;
1209 image = gdk_drawable_get_image (root_window, x_root, y_root, 1, 1);
1213 GdkDisplay *display = gdk_screen_get_display (screen);
1214 GdkWindow *window = gdk_display_get_window_at_pointer (display, &x, &y);
1217 image = gdk_drawable_get_image (window, x, y, 1, 1);
1221 pixel = gdk_image_get_pixel (image, 0, 0);
1222 g_object_unref (image);
1224 gdk_colormap_query_color (colormap, pixel, &color);
1226 priv->color[COLORSEL_RED] = SCALE (color.red);
1227 priv->color[COLORSEL_GREEN] = SCALE (color.green);
1228 priv->color[COLORSEL_BLUE] = SCALE (color.blue);
1230 gtk_rgb_to_hsv (priv->color[COLORSEL_RED],
1231 priv->color[COLORSEL_GREEN],
1232 priv->color[COLORSEL_BLUE],
1233 &priv->color[COLORSEL_HUE],
1234 &priv->color[COLORSEL_SATURATION],
1235 &priv->color[COLORSEL_VALUE]);
1237 update_color (colorsel);
1241 shutdown_eyedropper (GtkWidget *widget)
1243 GtkColorSelection *colorsel;
1244 ColorSelectionPrivate *priv;
1245 GdkDisplay *display = gtk_widget_get_display (widget);
1247 colorsel = GTK_COLOR_SELECTION (widget);
1248 priv = colorsel->private_data;
1252 gdk_display_keyboard_ungrab (display, priv->grab_time);
1253 gdk_display_pointer_ungrab (display, priv->grab_time);
1254 gtk_grab_remove (priv->dropper_grab_widget);
1256 priv->has_grab = FALSE;
1261 gtk_color_selection_grab_broken (GtkWidget *widget,
1262 GdkEventGrabBroken *event)
1264 shutdown_eyedropper (widget);
1270 mouse_motion (GtkWidget *invisible,
1271 GdkEventMotion *event,
1274 grab_color_at_mouse (gdk_event_get_screen ((GdkEvent *)event),
1275 event->x_root, event->y_root, data);
1279 mouse_release (GtkWidget *invisible,
1280 GdkEventButton *event,
1283 /* GtkColorSelection *colorsel = data; */
1285 if (event->button != 1)
1288 grab_color_at_mouse (gdk_event_get_screen ((GdkEvent *)event),
1289 event->x_root, event->y_root, data);
1291 shutdown_eyedropper (GTK_WIDGET (data));
1293 g_signal_handlers_disconnect_by_func (invisible,
1296 g_signal_handlers_disconnect_by_func (invisible,
1303 /* Helper Functions */
1305 static gboolean mouse_press (GtkWidget *invisible,
1306 GdkEventButton *event,
1312 key_press (GtkWidget *invisible,
1316 GdkDisplay *display = gtk_widget_get_display (invisible);
1317 GdkScreen *screen = gdk_event_get_screen ((GdkEvent *)event);
1318 guint state = event->state & gtk_accelerator_get_default_mod_mask ();
1322 gdk_display_get_pointer (display, NULL, &x, &y, NULL);
1327 switch (event->keyval)
1334 grab_color_at_mouse (screen, x, y, data);
1338 shutdown_eyedropper (data);
1340 g_signal_handlers_disconnect_by_func (invisible,
1343 g_signal_handlers_disconnect_by_func (invisible,
1349 #if defined GDK_WINDOWING_X11 || defined GDK_WINDOWING_WIN32
1352 dy = state == GDK_MOD1_MASK ? -BIG_STEP : -1;
1357 dy = state == GDK_MOD1_MASK ? BIG_STEP : 1;
1362 dx = state == GDK_MOD1_MASK ? -BIG_STEP : -1;
1367 dx = state == GDK_MOD1_MASK ? BIG_STEP : 1;
1375 gdk_display_warp_pointer (display, screen, x + dx, y + dy);
1382 mouse_press (GtkWidget *invisible,
1383 GdkEventButton *event,
1386 /* GtkColorSelection *colorsel = data; */
1388 if (event->type == GDK_BUTTON_PRESS &&
1391 g_signal_connect (invisible, "motion_notify_event",
1392 G_CALLBACK (mouse_motion),
1394 g_signal_connect (invisible, "button_release_event",
1395 G_CALLBACK (mouse_release),
1397 g_signal_handlers_disconnect_by_func (invisible,
1400 g_signal_handlers_disconnect_by_func (invisible,
1409 /* when the button is clicked */
1411 get_screen_color (GtkWidget *button)
1413 GtkColorSelection *colorsel = g_object_get_data (G_OBJECT (button), "COLORSEL");
1414 ColorSelectionPrivate *priv = colorsel->private_data;
1415 GdkScreen *screen = gtk_widget_get_screen (GTK_WIDGET (button));
1416 GdkCursor *picker_cursor;
1417 GdkGrabStatus grab_status;
1418 GtkWidget *grab_widget, *toplevel;
1420 guint32 time = gtk_get_current_event_time ();
1422 if (priv->dropper_grab_widget == NULL)
1424 grab_widget = gtk_window_new (GTK_WINDOW_POPUP);
1425 gtk_window_set_screen (GTK_WINDOW (grab_widget), screen);
1426 gtk_window_resize (GTK_WINDOW (grab_widget), 1, 1);
1427 gtk_window_move (GTK_WINDOW (grab_widget), -100, -100);
1428 gtk_widget_show (grab_widget);
1430 gtk_widget_add_events (grab_widget,
1431 GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_PRESS_MASK | GDK_POINTER_MOTION_MASK);
1433 toplevel = gtk_widget_get_toplevel (GTK_WIDGET (colorsel));
1435 if (GTK_IS_WINDOW (toplevel))
1437 if (GTK_WINDOW (toplevel)->group)
1438 gtk_window_group_add_window (GTK_WINDOW (toplevel)->group,
1439 GTK_WINDOW (grab_widget));
1442 priv->dropper_grab_widget = grab_widget;
1445 if (gdk_keyboard_grab (priv->dropper_grab_widget->window,
1446 FALSE, time) != GDK_GRAB_SUCCESS)
1449 picker_cursor = make_picker_cursor (screen);
1450 grab_status = gdk_pointer_grab (priv->dropper_grab_widget->window,
1452 GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_PRESS_MASK | GDK_POINTER_MOTION_MASK,
1456 gdk_cursor_unref (picker_cursor);
1458 if (grab_status != GDK_GRAB_SUCCESS)
1460 gdk_display_keyboard_ungrab (gtk_widget_get_display (button), time);
1464 gtk_grab_add (priv->dropper_grab_widget);
1465 priv->grab_time = time;
1466 priv->has_grab = TRUE;
1468 g_signal_connect (priv->dropper_grab_widget, "button_press_event",
1469 G_CALLBACK (mouse_press), colorsel);
1470 g_signal_connect (priv->dropper_grab_widget, "key_press_event",
1471 G_CALLBACK (key_press), colorsel);
1475 hex_changed (GtkWidget *hex_entry,
1478 GtkColorSelection *colorsel;
1479 ColorSelectionPrivate *priv;
1483 colorsel = GTK_COLOR_SELECTION (data);
1484 priv = colorsel->private_data;
1489 text = gtk_editable_get_chars (GTK_EDITABLE (priv->hex_entry), 0, -1);
1490 if (gdk_color_parse (text, &color))
1492 priv->color[COLORSEL_RED] = CLAMP (color.red/65535.0, 0.0, 1.0);
1493 priv->color[COLORSEL_GREEN] = CLAMP (color.green/65535.0, 0.0, 1.0);
1494 priv->color[COLORSEL_BLUE] = CLAMP (color.blue/65535.0, 0.0, 1.0);
1495 gtk_rgb_to_hsv (priv->color[COLORSEL_RED],
1496 priv->color[COLORSEL_GREEN],
1497 priv->color[COLORSEL_BLUE],
1498 &priv->color[COLORSEL_HUE],
1499 &priv->color[COLORSEL_SATURATION],
1500 &priv->color[COLORSEL_VALUE]);
1501 update_color (colorsel);
1507 hex_focus_out (GtkWidget *hex_entry,
1508 GdkEventFocus *event,
1511 hex_changed (hex_entry, data);
1517 hsv_changed (GtkWidget *hsv,
1520 GtkColorSelection *colorsel;
1521 ColorSelectionPrivate *priv;
1523 colorsel = GTK_COLOR_SELECTION (data);
1524 priv = colorsel->private_data;
1529 gtk_hsv_get_color (GTK_HSV (hsv),
1530 &priv->color[COLORSEL_HUE],
1531 &priv->color[COLORSEL_SATURATION],
1532 &priv->color[COLORSEL_VALUE]);
1533 gtk_hsv_to_rgb (priv->color[COLORSEL_HUE],
1534 priv->color[COLORSEL_SATURATION],
1535 priv->color[COLORSEL_VALUE],
1536 &priv->color[COLORSEL_RED],
1537 &priv->color[COLORSEL_GREEN],
1538 &priv->color[COLORSEL_BLUE]);
1539 update_color (colorsel);
1543 adjustment_changed (GtkAdjustment *adjustment,
1546 GtkColorSelection *colorsel;
1547 ColorSelectionPrivate *priv;
1549 colorsel = GTK_COLOR_SELECTION (g_object_get_data (G_OBJECT (adjustment), "COLORSEL"));
1550 priv = colorsel->private_data;
1555 switch (GPOINTER_TO_INT (data))
1557 case COLORSEL_SATURATION:
1558 case COLORSEL_VALUE:
1559 priv->color[GPOINTER_TO_INT (data)] = adjustment->value / 100;
1560 gtk_hsv_to_rgb (priv->color[COLORSEL_HUE],
1561 priv->color[COLORSEL_SATURATION],
1562 priv->color[COLORSEL_VALUE],
1563 &priv->color[COLORSEL_RED],
1564 &priv->color[COLORSEL_GREEN],
1565 &priv->color[COLORSEL_BLUE]);
1568 priv->color[GPOINTER_TO_INT (data)] = adjustment->value / 360;
1569 gtk_hsv_to_rgb (priv->color[COLORSEL_HUE],
1570 priv->color[COLORSEL_SATURATION],
1571 priv->color[COLORSEL_VALUE],
1572 &priv->color[COLORSEL_RED],
1573 &priv->color[COLORSEL_GREEN],
1574 &priv->color[COLORSEL_BLUE]);
1577 case COLORSEL_GREEN:
1579 priv->color[GPOINTER_TO_INT (data)] = adjustment->value / 255;
1581 gtk_rgb_to_hsv (priv->color[COLORSEL_RED],
1582 priv->color[COLORSEL_GREEN],
1583 priv->color[COLORSEL_BLUE],
1584 &priv->color[COLORSEL_HUE],
1585 &priv->color[COLORSEL_SATURATION],
1586 &priv->color[COLORSEL_VALUE]);
1589 priv->color[GPOINTER_TO_INT (data)] = adjustment->value / 255;
1592 update_color (colorsel);
1596 opacity_entry_changed (GtkWidget *opacity_entry,
1599 GtkColorSelection *colorsel;
1600 ColorSelectionPrivate *priv;
1604 colorsel = GTK_COLOR_SELECTION (data);
1605 priv = colorsel->private_data;
1610 text = gtk_editable_get_chars (GTK_EDITABLE (priv->opacity_entry), 0, -1);
1611 adj = gtk_range_get_adjustment (GTK_RANGE (priv->opacity_slider));
1612 gtk_adjustment_set_value (adj, g_strtod (text, NULL));
1614 update_color (colorsel);
1620 make_label_spinbutton (GtkColorSelection *colorsel,
1621 GtkWidget **spinbutton,
1627 const gchar *tooltip)
1630 GtkAdjustment *adjust;
1632 if (channel_type == COLORSEL_HUE)
1634 adjust = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 360.0, 1.0, 1.0, 1.0));
1636 else if (channel_type == COLORSEL_SATURATION ||
1637 channel_type == COLORSEL_VALUE)
1639 adjust = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 100.0, 1.0, 1.0, 1.0));
1643 adjust = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 255.0, 1.0, 1.0, 1.0));
1645 g_object_set_data (G_OBJECT (adjust), I_("COLORSEL"), colorsel);
1646 *spinbutton = gtk_spin_button_new (adjust, 10.0, 0);
1648 gtk_widget_set_tooltip_text (*spinbutton, tooltip);
1650 g_signal_connect (adjust, "value_changed",
1651 G_CALLBACK (adjustment_changed),
1652 GINT_TO_POINTER (channel_type));
1653 label = gtk_label_new_with_mnemonic (text);
1654 gtk_label_set_mnemonic_widget (GTK_LABEL (label), *spinbutton);
1656 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
1657 gtk_table_attach_defaults (GTK_TABLE (table), label, i, i+1, j, j+1);
1658 gtk_table_attach_defaults (GTK_TABLE (table), *spinbutton, i+1, i+2, j, j+1);
1662 make_palette_frame (GtkColorSelection *colorsel,
1668 ColorSelectionPrivate *priv;
1670 priv = colorsel->private_data;
1671 frame = gtk_frame_new (NULL);
1672 gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
1673 priv->custom_palette[i][j] = palette_new (colorsel);
1674 gtk_widget_set_size_request (priv->custom_palette[i][j], CUSTOM_PALETTE_ENTRY_WIDTH, CUSTOM_PALETTE_ENTRY_HEIGHT);
1675 gtk_container_add (GTK_CONTAINER (frame), priv->custom_palette[i][j]);
1676 gtk_table_attach_defaults (GTK_TABLE (table), frame, i, i+1, j, j+1);
1679 /* Set the palette entry [x][y] to be the currently selected one. */
1681 set_selected_palette (GtkColorSelection *colorsel, int x, int y)
1683 ColorSelectionPrivate *priv = colorsel->private_data;
1685 gtk_widget_grab_focus (priv->custom_palette[x][y]);
1689 scale_round (double val, double factor)
1691 val = floor (val * factor + 0.5);
1693 val = MIN (val, factor);
1698 update_color (GtkColorSelection *colorsel)
1700 ColorSelectionPrivate *priv = colorsel->private_data;
1702 gchar opacity_text[32];
1705 priv->changing = TRUE;
1706 color_sample_update_samples (colorsel);
1708 gtk_hsv_set_color (GTK_HSV (priv->triangle_colorsel),
1709 priv->color[COLORSEL_HUE],
1710 priv->color[COLORSEL_SATURATION],
1711 priv->color[COLORSEL_VALUE]);
1712 gtk_adjustment_set_value (gtk_spin_button_get_adjustment
1713 (GTK_SPIN_BUTTON (priv->hue_spinbutton)),
1714 scale_round (priv->color[COLORSEL_HUE], 360));
1715 gtk_adjustment_set_value (gtk_spin_button_get_adjustment
1716 (GTK_SPIN_BUTTON (priv->sat_spinbutton)),
1717 scale_round (priv->color[COLORSEL_SATURATION], 100));
1718 gtk_adjustment_set_value (gtk_spin_button_get_adjustment
1719 (GTK_SPIN_BUTTON (priv->val_spinbutton)),
1720 scale_round (priv->color[COLORSEL_VALUE], 100));
1721 gtk_adjustment_set_value (gtk_spin_button_get_adjustment
1722 (GTK_SPIN_BUTTON (priv->red_spinbutton)),
1723 scale_round (priv->color[COLORSEL_RED], 255));
1724 gtk_adjustment_set_value (gtk_spin_button_get_adjustment
1725 (GTK_SPIN_BUTTON (priv->green_spinbutton)),
1726 scale_round (priv->color[COLORSEL_GREEN], 255));
1727 gtk_adjustment_set_value (gtk_spin_button_get_adjustment
1728 (GTK_SPIN_BUTTON (priv->blue_spinbutton)),
1729 scale_round (priv->color[COLORSEL_BLUE], 255));
1730 gtk_adjustment_set_value (gtk_range_get_adjustment
1731 (GTK_RANGE (priv->opacity_slider)),
1732 scale_round (priv->color[COLORSEL_OPACITY], 255));
1734 g_snprintf (opacity_text, 32, "%.0f", scale_round (priv->color[COLORSEL_OPACITY], 255));
1735 gtk_entry_set_text (GTK_ENTRY (priv->opacity_entry), opacity_text);
1737 g_snprintf (entryval, 11, "#%2X%2X%2X",
1738 (guint) (scale_round (priv->color[COLORSEL_RED], 255)),
1739 (guint) (scale_round (priv->color[COLORSEL_GREEN], 255)),
1740 (guint) (scale_round (priv->color[COLORSEL_BLUE], 255)));
1742 for (ptr = entryval; *ptr; ptr++)
1745 gtk_entry_set_text (GTK_ENTRY (priv->hex_entry), entryval);
1746 priv->changing = FALSE;
1748 g_object_ref (colorsel);
1750 g_signal_emit (colorsel, color_selection_signals[COLOR_CHANGED], 0);
1752 g_object_freeze_notify (G_OBJECT (colorsel));
1753 g_object_notify (G_OBJECT (colorsel), "current-color");
1754 g_object_notify (G_OBJECT (colorsel), "current-alpha");
1755 g_object_thaw_notify (G_OBJECT (colorsel));
1757 g_object_unref (colorsel);
1761 update_palette (GtkColorSelection *colorsel)
1763 GdkColor *current_colors;
1766 current_colors = get_current_colors (colorsel);
1768 for (i = 0; i < GTK_CUSTOM_PALETTE_HEIGHT; i++)
1770 for (j = 0; j < GTK_CUSTOM_PALETTE_WIDTH; j++)
1774 index = i * GTK_CUSTOM_PALETTE_WIDTH + j;
1776 gtk_color_selection_set_palette_color (colorsel,
1778 ¤t_colors[index]);
1782 g_free (current_colors);
1786 palette_change_notify_instance (GObject *object,
1790 update_palette (GTK_COLOR_SELECTION (data));
1794 default_noscreen_change_palette_func (const GdkColor *colors,
1797 default_change_palette_func (gdk_screen_get_default (), colors, n_colors);
1801 default_change_palette_func (GdkScreen *screen,
1802 const GdkColor *colors,
1807 str = gtk_color_selection_palette_to_string (colors, n_colors);
1809 gtk_settings_set_string_property (gtk_settings_get_for_screen (screen),
1810 "gtk-color-palette",
1812 "gtk_color_selection_palette_to_string");
1817 G_DEFINE_TYPE (GtkColorSelection, gtk_color_selection, GTK_TYPE_VBOX)
1820 gtk_color_selection_class_init (GtkColorSelectionClass *klass)
1822 GObjectClass *gobject_class;
1823 GtkObjectClass *object_class;
1824 GtkWidgetClass *widget_class;
1826 gobject_class = G_OBJECT_CLASS (klass);
1827 object_class = GTK_OBJECT_CLASS (klass);
1828 widget_class = GTK_WIDGET_CLASS (klass);
1830 object_class->destroy = gtk_color_selection_destroy;
1831 gobject_class->finalize = gtk_color_selection_finalize;
1833 gobject_class->set_property = gtk_color_selection_set_property;
1834 gobject_class->get_property = gtk_color_selection_get_property;
1836 widget_class->realize = gtk_color_selection_realize;
1837 widget_class->unrealize = gtk_color_selection_unrealize;
1838 widget_class->show_all = gtk_color_selection_show_all;
1839 widget_class->grab_broken_event = gtk_color_selection_grab_broken;
1841 g_object_class_install_property (gobject_class,
1842 PROP_HAS_OPACITY_CONTROL,
1843 g_param_spec_boolean ("has-opacity-control",
1844 P_("Has Opacity Control"),
1845 P_("Whether the color selector should allow setting opacity"),
1847 GTK_PARAM_READWRITE));
1848 g_object_class_install_property (gobject_class,
1850 g_param_spec_boolean ("has-palette",
1852 P_("Whether a palette should be used"),
1854 GTK_PARAM_READWRITE));
1855 g_object_class_install_property (gobject_class,
1857 g_param_spec_boxed ("current-color",
1858 P_("Current Color"),
1859 P_("The current color"),
1861 GTK_PARAM_READWRITE));
1862 g_object_class_install_property (gobject_class,
1864 g_param_spec_uint ("current-alpha",
1865 P_("Current Alpha"),
1866 P_("The current opacity value (0 fully transparent, 65535 fully opaque)"),
1868 GTK_PARAM_READWRITE));
1870 color_selection_signals[COLOR_CHANGED] =
1871 g_signal_new (I_("color_changed"),
1872 G_OBJECT_CLASS_TYPE (object_class),
1874 G_STRUCT_OFFSET (GtkColorSelectionClass, color_changed),
1876 _gtk_marshal_VOID__VOID,
1879 gtk_settings_install_property (g_param_spec_string ("gtk-color-palette",
1880 P_("Custom palette"),
1881 P_("Palette to use in the color selector"),
1883 GTK_PARAM_READWRITE));
1885 g_type_class_add_private (gobject_class, sizeof (ColorSelectionPrivate));
1888 /* widget functions */
1891 gtk_color_selection_init (GtkColorSelection *colorsel)
1893 GtkWidget *top_hbox;
1894 GtkWidget *top_right_vbox;
1895 GtkWidget *table, *label, *hbox, *frame, *vbox, *button;
1896 GtkAdjustment *adjust;
1897 GtkWidget *picker_image;
1899 ColorSelectionPrivate *priv;
1901 GList *focus_chain = NULL;
1903 gtk_widget_push_composite_child ();
1905 priv = colorsel->private_data = G_TYPE_INSTANCE_GET_PRIVATE (colorsel, GTK_TYPE_COLOR_SELECTION, ColorSelectionPrivate);
1906 priv->changing = FALSE;
1907 priv->default_set = FALSE;
1908 priv->default_alpha_set = FALSE;
1910 top_hbox = gtk_hbox_new (FALSE, 12);
1911 gtk_box_pack_start (GTK_BOX (colorsel), top_hbox, FALSE, FALSE, 0);
1913 vbox = gtk_vbox_new (FALSE, 6);
1914 priv->triangle_colorsel = gtk_hsv_new ();
1915 g_signal_connect (priv->triangle_colorsel, "changed",
1916 G_CALLBACK (hsv_changed), colorsel);
1917 gtk_hsv_set_metrics (GTK_HSV (priv->triangle_colorsel), 174, 15);
1918 gtk_box_pack_start (GTK_BOX (top_hbox), vbox, FALSE, FALSE, 0);
1919 gtk_box_pack_start (GTK_BOX (vbox), priv->triangle_colorsel, FALSE, FALSE, 0);
1920 gtk_widget_set_tooltip_text (priv->triangle_colorsel,
1921 _("Select the color you want from the outer ring. Select the darkness or lightness of that color using the inner triangle."));
1923 hbox = gtk_hbox_new (FALSE, 6);
1924 gtk_box_pack_end (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
1926 frame = gtk_frame_new (NULL);
1927 gtk_widget_set_size_request (frame, -1, 30);
1928 gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
1929 color_sample_new (colorsel);
1930 gtk_container_add (GTK_CONTAINER (frame), priv->sample_area);
1931 gtk_box_pack_start (GTK_BOX (hbox), frame, TRUE, TRUE, 0);
1933 button = gtk_button_new ();
1935 gtk_widget_set_events (button, GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK);
1936 g_object_set_data (G_OBJECT (button), I_("COLORSEL"), colorsel);
1937 g_signal_connect (button, "clicked",
1938 G_CALLBACK (get_screen_color), NULL);
1939 picker_image = gtk_image_new_from_stock (GTK_STOCK_COLOR_PICKER, GTK_ICON_SIZE_BUTTON);
1940 gtk_container_add (GTK_CONTAINER (button), picker_image);
1941 gtk_widget_show (GTK_WIDGET (picker_image));
1942 gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
1944 gtk_widget_set_tooltip_text (button,
1945 _("Click the eyedropper, then click a color anywhere on your screen to select that color."));
1947 top_right_vbox = gtk_vbox_new (FALSE, 6);
1948 gtk_box_pack_start (GTK_BOX (top_hbox), top_right_vbox, FALSE, FALSE, 0);
1949 table = gtk_table_new (8, 6, FALSE);
1950 gtk_box_pack_start (GTK_BOX (top_right_vbox), table, FALSE, FALSE, 0);
1951 gtk_table_set_row_spacings (GTK_TABLE (table), 6);
1952 gtk_table_set_col_spacings (GTK_TABLE (table), 12);
1954 make_label_spinbutton (colorsel, &priv->hue_spinbutton, _("_Hue:"), table, 0, 0, COLORSEL_HUE,
1955 _("Position on the color wheel."));
1956 gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (priv->hue_spinbutton), TRUE);
1957 make_label_spinbutton (colorsel, &priv->sat_spinbutton, _("_Saturation:"), table, 0, 1, COLORSEL_SATURATION,
1958 _("\"Deepness\" of the color."));
1959 make_label_spinbutton (colorsel, &priv->val_spinbutton, _("_Value:"), table, 0, 2, COLORSEL_VALUE,
1960 _("Brightness of the color."));
1961 make_label_spinbutton (colorsel, &priv->red_spinbutton, _("_Red:"), table, 6, 0, COLORSEL_RED,
1962 _("Amount of red light in the color."));
1963 make_label_spinbutton (colorsel, &priv->green_spinbutton, _("_Green:"), table, 6, 1, COLORSEL_GREEN,
1964 _("Amount of green light in the color."));
1965 make_label_spinbutton (colorsel, &priv->blue_spinbutton, _("_Blue:"), table, 6, 2, COLORSEL_BLUE,
1966 _("Amount of blue light in the color."));
1967 gtk_table_attach_defaults (GTK_TABLE (table), gtk_hseparator_new (), 0, 8, 3, 4);
1969 priv->opacity_label = gtk_label_new_with_mnemonic (_("Op_acity:"));
1970 gtk_misc_set_alignment (GTK_MISC (priv->opacity_label), 0.0, 0.5);
1971 gtk_table_attach_defaults (GTK_TABLE (table), priv->opacity_label, 0, 1, 4, 5);
1972 adjust = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 255.0, 1.0, 1.0, 0.0));
1973 g_object_set_data (G_OBJECT (adjust), I_("COLORSEL"), colorsel);
1974 priv->opacity_slider = gtk_hscale_new (adjust);
1975 gtk_widget_set_tooltip_text (priv->opacity_slider,
1976 _("Transparency of the color."));
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_widget_set_tooltip_text (priv->opacity_entry,
1986 _("Transparency of the color."));
1987 gtk_widget_set_size_request (priv->opacity_entry, 40, -1);
1989 g_signal_connect (priv->opacity_entry, "activate",
1990 G_CALLBACK (opacity_entry_changed), colorsel);
1991 gtk_table_attach_defaults (GTK_TABLE (table), priv->opacity_entry, 7, 8, 4, 5);
1993 label = gtk_label_new_with_mnemonic (_("Color _name:"));
1994 gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 5, 6);
1995 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
1996 priv->hex_entry = gtk_entry_new ();
1998 gtk_label_set_mnemonic_widget (GTK_LABEL (label), priv->hex_entry);
2000 g_signal_connect (priv->hex_entry, "activate",
2001 G_CALLBACK (hex_changed), colorsel);
2003 g_signal_connect (priv->hex_entry, "focus_out_event",
2004 G_CALLBACK (hex_focus_out), colorsel);
2006 gtk_widget_set_tooltip_text (priv->hex_entry,
2007 _("You can enter an HTML-style hexadecimal color value, or simply a color name such as 'orange' in this entry."));
2009 gtk_entry_set_width_chars (GTK_ENTRY (priv->hex_entry), 7);
2010 gtk_table_attach_defaults (GTK_TABLE (table), priv->hex_entry, 1, 5, 5, 6);
2012 focus_chain = g_list_append (focus_chain, priv->hue_spinbutton);
2013 focus_chain = g_list_append (focus_chain, priv->sat_spinbutton);
2014 focus_chain = g_list_append (focus_chain, priv->val_spinbutton);
2015 focus_chain = g_list_append (focus_chain, priv->red_spinbutton);
2016 focus_chain = g_list_append (focus_chain, priv->green_spinbutton);
2017 focus_chain = g_list_append (focus_chain, priv->blue_spinbutton);
2018 focus_chain = g_list_append (focus_chain, priv->opacity_slider);
2019 focus_chain = g_list_append (focus_chain, priv->opacity_entry);
2020 focus_chain = g_list_append (focus_chain, priv->hex_entry);
2021 gtk_container_set_focus_chain (GTK_CONTAINER (table), focus_chain);
2022 g_list_free (focus_chain);
2024 /* Set up the palette */
2025 table = gtk_table_new (GTK_CUSTOM_PALETTE_HEIGHT, GTK_CUSTOM_PALETTE_WIDTH, TRUE);
2026 gtk_table_set_row_spacings (GTK_TABLE (table), 1);
2027 gtk_table_set_col_spacings (GTK_TABLE (table), 1);
2028 for (i = 0; i < GTK_CUSTOM_PALETTE_WIDTH; i++)
2030 for (j = 0; j < GTK_CUSTOM_PALETTE_HEIGHT; j++)
2032 make_palette_frame (colorsel, table, i, j);
2035 set_selected_palette (colorsel, 0, 0);
2036 priv->palette_frame = gtk_vbox_new (FALSE, 6);
2037 label = gtk_label_new_with_mnemonic (_("_Palette:"));
2038 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
2039 gtk_box_pack_start (GTK_BOX (priv->palette_frame), label, FALSE, FALSE, 0);
2041 gtk_label_set_mnemonic_widget (GTK_LABEL (label),
2042 priv->custom_palette[0][0]);
2044 gtk_box_pack_end (GTK_BOX (top_right_vbox), priv->palette_frame, FALSE, FALSE, 0);
2045 gtk_box_pack_start (GTK_BOX (priv->palette_frame), table, FALSE, FALSE, 0);
2047 gtk_widget_show_all (top_hbox);
2049 /* hide unused stuff */
2051 if (priv->has_opacity == FALSE)
2053 gtk_widget_hide (priv->opacity_label);
2054 gtk_widget_hide (priv->opacity_slider);
2055 gtk_widget_hide (priv->opacity_entry);
2058 if (priv->has_palette == FALSE)
2060 gtk_widget_hide (priv->palette_frame);
2063 atk_obj = gtk_widget_get_accessible (priv->triangle_colorsel);
2064 if (GTK_IS_ACCESSIBLE (atk_obj))
2066 atk_object_set_name (atk_obj, _("Color Wheel"));
2067 atk_object_set_role (gtk_widget_get_accessible (GTK_WIDGET (colorsel)), ATK_ROLE_COLOR_CHOOSER);
2068 make_all_relations (atk_obj, priv);
2071 gtk_widget_pop_composite_child ();
2075 gtk_color_selection_destroy (GtkObject *object)
2077 GtkColorSelection *cselection = GTK_COLOR_SELECTION (object);
2078 ColorSelectionPrivate *priv = cselection->private_data;
2080 if (priv->dropper_grab_widget)
2082 gtk_widget_destroy (priv->dropper_grab_widget);
2083 priv->dropper_grab_widget = NULL;
2086 GTK_OBJECT_CLASS (gtk_color_selection_parent_class)->destroy (object);
2090 gtk_color_selection_finalize (GObject *object)
2092 G_OBJECT_CLASS (gtk_color_selection_parent_class)->finalize (object);
2096 gtk_color_selection_realize (GtkWidget *widget)
2098 GtkColorSelection *colorsel = GTK_COLOR_SELECTION (widget);
2099 ColorSelectionPrivate *priv = colorsel->private_data;
2100 GtkSettings *settings = gtk_widget_get_settings (widget);
2102 priv->settings_connection = g_signal_connect (settings,
2103 "notify::gtk-color-palette",
2104 G_CALLBACK (palette_change_notify_instance),
2106 update_palette (colorsel);
2108 GTK_WIDGET_CLASS (gtk_color_selection_parent_class)->realize (widget);
2112 gtk_color_selection_unrealize (GtkWidget *widget)
2114 GtkColorSelection *colorsel = GTK_COLOR_SELECTION (widget);
2115 ColorSelectionPrivate *priv = colorsel->private_data;
2116 GtkSettings *settings = gtk_widget_get_settings (widget);
2118 g_signal_handler_disconnect (settings, priv->settings_connection);
2120 GTK_WIDGET_CLASS (gtk_color_selection_parent_class)->unrealize (widget);
2123 /* We override show-all since we have internal widgets that
2124 * shouldn't be shown when you call show_all(), like the
2125 * palette and opacity sliders.
2128 gtk_color_selection_show_all (GtkWidget *widget)
2130 gtk_widget_show (widget);
2134 * gtk_color_selection_new:
2136 * Creates a new GtkColorSelection.
2138 * Return value: a new #GtkColorSelection
2141 gtk_color_selection_new (void)
2143 GtkColorSelection *colorsel;
2144 ColorSelectionPrivate *priv;
2151 colorsel = g_object_new (GTK_TYPE_COLOR_SELECTION, NULL);
2152 priv = colorsel->private_data;
2153 set_color_internal (colorsel, color);
2154 gtk_color_selection_set_has_opacity_control (colorsel, TRUE);
2156 /* We want to make sure that default_set is FALSE */
2157 /* This way the user can still set it */
2158 priv->default_set = FALSE;
2159 priv->default_alpha_set = FALSE;
2161 return GTK_WIDGET (colorsel);
2166 gtk_color_selection_set_update_policy (GtkColorSelection *colorsel,
2167 GtkUpdateType policy)
2169 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2173 * gtk_color_selection_get_has_opacity_control:
2174 * @colorsel: a #GtkColorSelection.
2176 * Determines whether the colorsel has an opacity control.
2178 * Return value: %TRUE if the @colorsel has an opacity control. %FALSE if it does't.
2181 gtk_color_selection_get_has_opacity_control (GtkColorSelection *colorsel)
2183 ColorSelectionPrivate *priv;
2185 g_return_val_if_fail (GTK_IS_COLOR_SELECTION (colorsel), FALSE);
2187 priv = colorsel->private_data;
2189 return priv->has_opacity;
2193 * gtk_color_selection_set_has_opacity_control:
2194 * @colorsel: a #GtkColorSelection.
2195 * @has_opacity: %TRUE if @colorsel can set the opacity, %FALSE otherwise.
2197 * Sets the @colorsel to use or not use opacity.
2201 gtk_color_selection_set_has_opacity_control (GtkColorSelection *colorsel,
2202 gboolean has_opacity)
2204 ColorSelectionPrivate *priv;
2206 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2208 priv = colorsel->private_data;
2209 has_opacity = has_opacity != FALSE;
2211 if (priv->has_opacity != has_opacity)
2213 priv->has_opacity = has_opacity;
2216 gtk_widget_show (priv->opacity_slider);
2217 gtk_widget_show (priv->opacity_label);
2218 gtk_widget_show (priv->opacity_entry);
2222 gtk_widget_hide (priv->opacity_slider);
2223 gtk_widget_hide (priv->opacity_label);
2224 gtk_widget_hide (priv->opacity_entry);
2226 color_sample_update_samples (colorsel);
2228 g_object_notify (G_OBJECT (colorsel), "has-opacity-control");
2233 * gtk_color_selection_get_has_palette:
2234 * @colorsel: a #GtkColorSelection.
2236 * Determines whether the color selector has a color palette.
2238 * Return value: %TRUE if the selector has a palette. %FALSE if it hasn't.
2241 gtk_color_selection_get_has_palette (GtkColorSelection *colorsel)
2243 ColorSelectionPrivate *priv;
2245 g_return_val_if_fail (GTK_IS_COLOR_SELECTION (colorsel), FALSE);
2247 priv = colorsel->private_data;
2249 return priv->has_palette;
2253 * gtk_color_selection_set_has_palette:
2254 * @colorsel: a #GtkColorSelection.
2255 * @has_palette: %TRUE if palette is to be visible, %FALSE otherwise.
2257 * Shows and hides the palette based upon the value of @has_palette.
2261 gtk_color_selection_set_has_palette (GtkColorSelection *colorsel,
2262 gboolean has_palette)
2264 ColorSelectionPrivate *priv;
2265 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2267 priv = colorsel->private_data;
2268 has_palette = has_palette != FALSE;
2270 if (priv->has_palette != has_palette)
2272 priv->has_palette = has_palette;
2274 gtk_widget_show (priv->palette_frame);
2276 gtk_widget_hide (priv->palette_frame);
2278 g_object_notify (G_OBJECT (colorsel), "has-palette");
2283 * gtk_color_selection_set_current_color:
2284 * @colorsel: a #GtkColorSelection.
2285 * @color: A #GdkColor to set the current color with.
2287 * Sets the current color to be @color. The first time this is called, it will
2288 * also set the original color to be @color too.
2291 gtk_color_selection_set_current_color (GtkColorSelection *colorsel,
2292 const GdkColor *color)
2294 ColorSelectionPrivate *priv;
2297 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2298 g_return_if_fail (color != NULL);
2300 priv = colorsel->private_data;
2301 priv->changing = TRUE;
2302 priv->color[COLORSEL_RED] = SCALE (color->red);
2303 priv->color[COLORSEL_GREEN] = SCALE (color->green);
2304 priv->color[COLORSEL_BLUE] = SCALE (color->blue);
2305 gtk_rgb_to_hsv (priv->color[COLORSEL_RED],
2306 priv->color[COLORSEL_GREEN],
2307 priv->color[COLORSEL_BLUE],
2308 &priv->color[COLORSEL_HUE],
2309 &priv->color[COLORSEL_SATURATION],
2310 &priv->color[COLORSEL_VALUE]);
2311 if (priv->default_set == FALSE)
2313 for (i = 0; i < COLORSEL_NUM_CHANNELS; i++)
2314 priv->old_color[i] = priv->color[i];
2316 priv->default_set = TRUE;
2317 update_color (colorsel);
2321 * gtk_color_selection_set_current_alpha:
2322 * @colorsel: a #GtkColorSelection.
2323 * @alpha: an integer between 0 and 65535.
2325 * Sets the current opacity to be @alpha. The first time this is called, it will
2326 * also set the original opacity to be @alpha too.
2329 gtk_color_selection_set_current_alpha (GtkColorSelection *colorsel,
2332 ColorSelectionPrivate *priv;
2335 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2337 priv = colorsel->private_data;
2338 priv->changing = TRUE;
2339 priv->color[COLORSEL_OPACITY] = SCALE (alpha);
2340 if (priv->default_alpha_set == FALSE)
2342 for (i = 0; i < COLORSEL_NUM_CHANNELS; i++)
2343 priv->old_color[i] = priv->color[i];
2345 priv->default_alpha_set = TRUE;
2346 update_color (colorsel);
2350 * gtk_color_selection_set_color:
2351 * @colorsel: a #GtkColorSelection.
2352 * @color: an array of 4 doubles specifying the red, green, blue and opacity
2353 * to set the current color to.
2355 * Sets the current color to be @color. The first time this is called, it will
2356 * also set the original color to be @color too.
2358 * Deprecated: Use gtk_color_selection_set_current_color() instead.
2361 gtk_color_selection_set_color (GtkColorSelection *colorsel,
2364 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2366 set_color_internal (colorsel, color);
2370 * gtk_color_selection_get_current_color:
2371 * @colorsel: a #GtkColorSelection.
2372 * @color: a #GdkColor to fill in with the current color.
2374 * Sets @color to be the current color in the GtkColorSelection widget.
2377 gtk_color_selection_get_current_color (GtkColorSelection *colorsel,
2380 ColorSelectionPrivate *priv;
2382 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2383 g_return_if_fail (color != NULL);
2385 priv = colorsel->private_data;
2386 color->red = UNSCALE (priv->color[COLORSEL_RED]);
2387 color->green = UNSCALE (priv->color[COLORSEL_GREEN]);
2388 color->blue = UNSCALE (priv->color[COLORSEL_BLUE]);
2392 * gtk_color_selection_get_current_alpha:
2393 * @colorsel: a #GtkColorSelection.
2395 * Returns the current alpha value.
2397 * Return value: an integer between 0 and 65535.
2400 gtk_color_selection_get_current_alpha (GtkColorSelection *colorsel)
2402 ColorSelectionPrivate *priv;
2404 g_return_val_if_fail (GTK_IS_COLOR_SELECTION (colorsel), 0);
2406 priv = colorsel->private_data;
2407 return priv->has_opacity ? UNSCALE (priv->color[COLORSEL_OPACITY]) : 65535;
2411 * gtk_color_selection_get_color:
2412 * @colorsel: a #GtkColorSelection.
2413 * @color: an array of 4 #gdouble to fill in with the current color.
2415 * Sets @color to be the current color in the GtkColorSelection widget.
2417 * This function is deprecated, use gtk_color_selection_get_current_color() instead.
2420 gtk_color_selection_get_color (GtkColorSelection *colorsel,
2423 ColorSelectionPrivate *priv;
2425 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2427 priv = colorsel->private_data;
2428 color[0] = priv->color[COLORSEL_RED];
2429 color[1] = priv->color[COLORSEL_GREEN];
2430 color[2] = priv->color[COLORSEL_BLUE];
2431 color[3] = priv->has_opacity ? priv->color[COLORSEL_OPACITY] : 65535;
2435 * gtk_color_selection_set_previous_color:
2436 * @colorsel: a #GtkColorSelection.
2437 * @color: a #GdkColor to set the previous color with.
2439 * Sets the 'previous' color to be @color. This function should be called with
2440 * some hesitations, as it might seem confusing to have that color change.
2441 * Calling gtk_color_selection_set_current_color() will also set this color the first
2442 * time it is called.
2445 gtk_color_selection_set_previous_color (GtkColorSelection *colorsel,
2446 const GdkColor *color)
2448 ColorSelectionPrivate *priv;
2450 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2451 g_return_if_fail (color != NULL);
2453 priv = colorsel->private_data;
2454 priv->changing = TRUE;
2455 priv->old_color[COLORSEL_RED] = SCALE (color->red);
2456 priv->old_color[COLORSEL_GREEN] = SCALE (color->green);
2457 priv->old_color[COLORSEL_BLUE] = SCALE (color->blue);
2458 gtk_rgb_to_hsv (priv->old_color[COLORSEL_RED],
2459 priv->old_color[COLORSEL_GREEN],
2460 priv->old_color[COLORSEL_BLUE],
2461 &priv->old_color[COLORSEL_HUE],
2462 &priv->old_color[COLORSEL_SATURATION],
2463 &priv->old_color[COLORSEL_VALUE]);
2464 color_sample_update_samples (colorsel);
2465 priv->default_set = TRUE;
2466 priv->changing = FALSE;
2470 * gtk_color_selection_set_previous_alpha:
2471 * @colorsel: a #GtkColorSelection.
2472 * @alpha: an integer between 0 and 65535.
2474 * Sets the 'previous' alpha to be @alpha. This function should be called with
2475 * some hesitations, as it might seem confusing to have that alpha change.
2478 gtk_color_selection_set_previous_alpha (GtkColorSelection *colorsel,
2481 ColorSelectionPrivate *priv;
2483 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2485 priv = colorsel->private_data;
2486 priv->changing = TRUE;
2487 priv->old_color[COLORSEL_OPACITY] = SCALE (alpha);
2488 color_sample_update_samples (colorsel);
2489 priv->default_alpha_set = TRUE;
2490 priv->changing = FALSE;
2495 * gtk_color_selection_get_previous_color:
2496 * @colorsel: a #GtkColorSelection.
2497 * @color: a #GdkColor to fill in with the original color value.
2499 * Fills @color in with the original color value.
2502 gtk_color_selection_get_previous_color (GtkColorSelection *colorsel,
2505 ColorSelectionPrivate *priv;
2507 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2508 g_return_if_fail (color != NULL);
2510 priv = colorsel->private_data;
2511 color->red = UNSCALE (priv->old_color[COLORSEL_RED]);
2512 color->green = UNSCALE (priv->old_color[COLORSEL_GREEN]);
2513 color->blue = UNSCALE (priv->old_color[COLORSEL_BLUE]);
2517 * gtk_color_selection_get_previous_alpha:
2518 * @colorsel: a #GtkColorSelection.
2520 * Returns the previous alpha value.
2522 * Return value: an integer between 0 and 65535.
2525 gtk_color_selection_get_previous_alpha (GtkColorSelection *colorsel)
2527 ColorSelectionPrivate *priv;
2529 g_return_val_if_fail (GTK_IS_COLOR_SELECTION (colorsel), 0);
2531 priv = colorsel->private_data;
2532 return priv->has_opacity ? UNSCALE (priv->old_color[COLORSEL_OPACITY]) : 65535;
2536 * gtk_color_selection_set_palette_color:
2537 * @colorsel: a #GtkColorSelection.
2538 * @index: the color index of the palette.
2539 * @color: A #GdkColor to set the palette with.
2541 * Sets the palette located at @index to have @color as its color.
2545 gtk_color_selection_set_palette_color (GtkColorSelection *colorsel,
2549 ColorSelectionPrivate *priv;
2553 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2554 g_return_if_fail (index >= 0 && index < GTK_CUSTOM_PALETTE_WIDTH*GTK_CUSTOM_PALETTE_HEIGHT);
2556 x = index % GTK_CUSTOM_PALETTE_WIDTH;
2557 y = index / GTK_CUSTOM_PALETTE_WIDTH;
2559 priv = colorsel->private_data;
2560 col[0] = SCALE (color->red);
2561 col[1] = SCALE (color->green);
2562 col[2] = SCALE (color->blue);
2564 palette_set_color (priv->custom_palette[x][y], colorsel, col);
2568 * gtk_color_selection_is_adjusting:
2569 * @colorsel: a #GtkColorSelection.
2571 * Gets the current state of the @colorsel.
2573 * Return value: %TRUE if the user is currently dragging a color around, and %FALSE
2574 * if the selection has stopped.
2577 gtk_color_selection_is_adjusting (GtkColorSelection *colorsel)
2579 ColorSelectionPrivate *priv;
2581 g_return_val_if_fail (GTK_IS_COLOR_SELECTION (colorsel), FALSE);
2583 priv = colorsel->private_data;
2585 return (gtk_hsv_is_adjusting (GTK_HSV (priv->triangle_colorsel)));
2589 gtk_color_selection_set_property (GObject *object,
2591 const GValue *value,
2594 GtkColorSelection *colorsel = GTK_COLOR_SELECTION (object);
2598 case PROP_HAS_OPACITY_CONTROL:
2599 gtk_color_selection_set_has_opacity_control (colorsel,
2600 g_value_get_boolean (value));
2602 case PROP_HAS_PALETTE:
2603 gtk_color_selection_set_has_palette (colorsel,
2604 g_value_get_boolean (value));
2606 case PROP_CURRENT_COLOR:
2607 gtk_color_selection_set_current_color (colorsel, g_value_get_boxed (value));
2609 case PROP_CURRENT_ALPHA:
2610 gtk_color_selection_set_current_alpha (colorsel, g_value_get_uint (value));
2613 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
2620 gtk_color_selection_get_property (GObject *object,
2625 GtkColorSelection *colorsel = GTK_COLOR_SELECTION (object);
2630 case PROP_HAS_OPACITY_CONTROL:
2631 g_value_set_boolean (value, gtk_color_selection_get_has_opacity_control (colorsel));
2633 case PROP_HAS_PALETTE:
2634 g_value_set_boolean (value, gtk_color_selection_get_has_palette (colorsel));
2636 case PROP_CURRENT_COLOR:
2637 gtk_color_selection_get_current_color (colorsel, &color);
2638 g_value_set_boxed (value, &color);
2640 case PROP_CURRENT_ALPHA:
2641 g_value_set_uint (value, gtk_color_selection_get_current_alpha (colorsel));
2644 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
2651 * gtk_color_selection_palette_from_string:
2652 * @str: a string encoding a color palette.
2653 * @colors: return location for allocated array of #GdkColor.
2654 * @n_colors: return location for length of array.
2656 * Parses a color palette string; the string is a colon-separated
2657 * list of color names readable by gdk_color_parse().
2659 * Return value: %TRUE if a palette was successfully parsed.
2662 gtk_color_selection_palette_from_string (const gchar *str,
2674 copy = g_strdup (str);
2680 if (*p == ':' || *p == '\0')
2682 gboolean done = TRUE;
2686 goto failed; /* empty entry */
2695 retval = g_renew (GdkColor, retval, count + 1);
2696 if (!gdk_color_parse (start, retval + count))
2737 * gtk_color_selection_palette_to_string:
2738 * @colors: an array of colors.
2739 * @n_colors: length of the array.
2741 * Encodes a palette as a string, useful for persistent storage.
2743 * Return value: allocated string encoding the palette.
2746 gtk_color_selection_palette_to_string (const GdkColor *colors,
2750 gchar **strs = NULL;
2754 return g_strdup ("");
2756 strs = g_new0 (gchar*, n_colors + 1);
2759 while (i < n_colors)
2764 g_strdup_printf ("#%2X%2X%2X",
2765 colors[i].red / 256,
2766 colors[i].green / 256,
2767 colors[i].blue / 256);
2769 for (ptr = strs[i]; *ptr; ptr++)
2776 retval = g_strjoinv (":", strs);
2784 * gtk_color_selection_set_change_palette_hook:
2785 * @func: a function to call when the custom palette needs saving.
2787 * Installs a global function to be called whenever the user tries to
2788 * modify the palette in a color selection. This function should save
2789 * the new palette contents, and update the GtkSettings property
2790 * "gtk-color-palette" so all GtkColorSelection widgets will be modified.
2792 * Return value: the previous change palette hook (that was replaced).
2794 * Deprecated: This function is deprecated in favor of
2795 * gtk_color_selection_set_change_palette_with_screen_hook(), and does
2796 * not work in multihead environments.
2799 GtkColorSelectionChangePaletteFunc
2800 gtk_color_selection_set_change_palette_hook (GtkColorSelectionChangePaletteFunc func)
2802 GtkColorSelectionChangePaletteFunc old;
2804 old = noscreen_change_palette_hook;
2806 noscreen_change_palette_hook = func;
2812 * gtk_color_selection_set_change_palette_with_screen_hook:
2813 * @func: a function to call when the custom palette needs saving.
2815 * Installs a global function to be called whenever the user tries to
2816 * modify the palette in a color selection. This function should save
2817 * the new palette contents, and update the GtkSettings property
2818 * "gtk-color-palette" so all GtkColorSelection widgets will be modified.
2820 * Return value: the previous change palette hook (that was replaced).
2824 GtkColorSelectionChangePaletteWithScreenFunc
2825 gtk_color_selection_set_change_palette_with_screen_hook (GtkColorSelectionChangePaletteWithScreenFunc func)
2827 GtkColorSelectionChangePaletteWithScreenFunc old;
2829 old = change_palette_hook;
2831 change_palette_hook = func;
2837 make_control_relations (AtkObject *atk_obj,
2842 obj = gtk_widget_get_accessible (widget);
2843 atk_object_add_relationship (atk_obj, ATK_RELATION_CONTROLLED_BY, obj);
2844 atk_object_add_relationship (obj, ATK_RELATION_CONTROLLER_FOR, atk_obj);
2848 make_all_relations (AtkObject *atk_obj,
2849 ColorSelectionPrivate *priv)
2851 make_control_relations (atk_obj, priv->hue_spinbutton);
2852 make_control_relations (atk_obj, priv->sat_spinbutton);
2853 make_control_relations (atk_obj, priv->val_spinbutton);
2854 make_control_relations (atk_obj, priv->red_spinbutton);
2855 make_control_relations (atk_obj, priv->green_spinbutton);
2856 make_control_relations (atk_obj, priv->blue_spinbutton);
2859 #define __GTK_COLOR_SELECTION_C__
2860 #include "gtkaliasdef.c"