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"
59 #include "gtkaccessible.h"
60 #include "gtkprivate.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;
112 gdouble color[COLORSEL_NUM_CHANNELS];
113 gdouble old_color[COLORSEL_NUM_CHANNELS];
115 GtkWidget *triangle_colorsel;
116 GtkWidget *hue_spinbutton;
117 GtkWidget *sat_spinbutton;
118 GtkWidget *val_spinbutton;
119 GtkWidget *red_spinbutton;
120 GtkWidget *green_spinbutton;
121 GtkWidget *blue_spinbutton;
122 GtkWidget *opacity_slider;
123 GtkWidget *opacity_label;
124 GtkWidget *opacity_entry;
125 GtkWidget *palette_frame;
126 GtkWidget *hex_entry;
128 /* The Palette code */
129 GtkWidget *custom_palette [GTK_CUSTOM_PALETTE_WIDTH][GTK_CUSTOM_PALETTE_HEIGHT];
131 /* The color_sample stuff */
132 GtkWidget *sample_area;
133 GtkWidget *old_sample;
134 GtkWidget *cur_sample;
138 GtkTooltips *tooltips;
140 /* Window for grabbing on */
141 GtkWidget *dropper_grab_widget;
144 /* Connection to settings */
145 gulong settings_connection;
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);
164 static gboolean gtk_color_selection_grab_broken (GtkWidget *widget,
165 GdkEventGrabBroken *event);
167 static void gtk_color_selection_set_palette_color (GtkColorSelection *colorsel,
170 static void set_focus_line_attributes (GtkWidget *drawing_area,
173 static void default_noscreen_change_palette_func (const GdkColor *colors,
175 static void default_change_palette_func (GdkScreen *screen,
176 const GdkColor *colors,
178 static void make_control_relations (AtkObject *atk_obj,
180 static void make_all_relations (AtkObject *atk_obj,
181 ColorSelectionPrivate *priv);
183 static guint color_selection_signals[LAST_SIGNAL] = { 0 };
185 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";
187 static GtkColorSelectionChangePaletteFunc noscreen_change_palette_hook = default_noscreen_change_palette_func;
188 static GtkColorSelectionChangePaletteWithScreenFunc change_palette_hook = default_change_palette_func;
190 /* The cursor for the dropper */
191 #define DROPPER_WIDTH 17
192 #define DROPPER_HEIGHT 17
193 #define DROPPER_X_HOT 2
194 #define DROPPER_Y_HOT 16
197 static const guchar dropper_bits[] = {
198 0xff, 0x8f, 0x01, 0xff, 0x77, 0x01, 0xff, 0xfb, 0x00, 0xff, 0xf8, 0x00,
199 0x7f, 0xff, 0x00, 0xff, 0x7e, 0x01, 0xff, 0x9d, 0x01, 0xff, 0xd8, 0x01,
200 0x7f, 0xd4, 0x01, 0x3f, 0xee, 0x01, 0x1f, 0xff, 0x01, 0x8f, 0xff, 0x01,
201 0xc7, 0xff, 0x01, 0xe3, 0xff, 0x01, 0xf3, 0xff, 0x01, 0xfd, 0xff, 0x01,
204 static const guchar dropper_mask[] = {
205 0x00, 0x70, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xfc, 0x01, 0x00, 0xff, 0x01,
206 0x80, 0xff, 0x01, 0x00, 0xff, 0x00, 0x00, 0x7f, 0x00, 0x80, 0x3f, 0x00,
207 0xc0, 0x3f, 0x00, 0xe0, 0x13, 0x00, 0xf0, 0x01, 0x00, 0xf8, 0x00, 0x00,
208 0x7c, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x0d, 0x00, 0x00,
217 #define SAMPLE_WIDTH 64
218 #define SAMPLE_HEIGHT 28
220 static void color_sample_draw_sample (GtkColorSelection *colorsel, int which);
221 static void color_sample_update_samples (GtkColorSelection *colorsel);
224 set_color_internal (GtkColorSelection *colorsel,
227 ColorSelectionPrivate *priv;
230 priv = colorsel->private_data;
231 priv->changing = TRUE;
232 priv->color[COLORSEL_RED] = color[0];
233 priv->color[COLORSEL_GREEN] = color[1];
234 priv->color[COLORSEL_BLUE] = color[2];
235 priv->color[COLORSEL_OPACITY] = color[3];
236 gtk_rgb_to_hsv (priv->color[COLORSEL_RED],
237 priv->color[COLORSEL_GREEN],
238 priv->color[COLORSEL_BLUE],
239 &priv->color[COLORSEL_HUE],
240 &priv->color[COLORSEL_SATURATION],
241 &priv->color[COLORSEL_VALUE]);
242 if (priv->default_set == FALSE)
244 for (i = 0; i < COLORSEL_NUM_CHANNELS; i++)
245 priv->old_color[i] = priv->color[i];
247 priv->default_set = TRUE;
248 priv->default_alpha_set = TRUE;
249 update_color (colorsel);
253 set_color_icon (GdkDragContext *context,
259 pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE,
262 pixel = (((UNSCALE (colors[COLORSEL_RED]) & 0xff00) << 16) |
263 ((UNSCALE (colors[COLORSEL_GREEN]) & 0xff00) << 8) |
264 ((UNSCALE (colors[COLORSEL_BLUE]) & 0xff00)));
266 gdk_pixbuf_fill (pixbuf, pixel);
268 gtk_drag_set_icon_pixbuf (context, pixbuf, -2, -2);
269 g_object_unref (pixbuf);
273 color_sample_drag_begin (GtkWidget *widget,
274 GdkDragContext *context,
277 GtkColorSelection *colorsel = data;
278 ColorSelectionPrivate *priv;
281 priv = colorsel->private_data;
283 if (widget == priv->old_sample)
284 colsrc = priv->old_color;
286 colsrc = priv->color;
288 set_color_icon (context, colsrc);
292 color_sample_drag_end (GtkWidget *widget,
293 GdkDragContext *context,
296 g_object_set_data (G_OBJECT (widget), I_("gtk-color-selection-drag-window"), NULL);
300 color_sample_drop_handle (GtkWidget *widget,
301 GdkDragContext *context,
304 GtkSelectionData *selection_data,
309 GtkColorSelection *colorsel = data;
310 ColorSelectionPrivate *priv;
313 priv = colorsel->private_data;
315 /* This is currently a guint16 array of the format:
322 if (selection_data->length < 0)
325 /* We accept drops with the wrong format, since the KDE color
326 * chooser incorrectly drops application/x-color with format 8.
328 if (selection_data->length != 8)
330 g_warning ("Received invalid color data\n");
334 vals = (guint16 *)selection_data->data;
336 if (widget == priv->cur_sample)
338 color[0] = (gdouble)vals[0] / 0xffff;
339 color[1] = (gdouble)vals[1] / 0xffff;
340 color[2] = (gdouble)vals[2] / 0xffff;
341 color[3] = (gdouble)vals[3] / 0xffff;
343 set_color_internal (colorsel, color);
348 color_sample_drag_handle (GtkWidget *widget,
349 GdkDragContext *context,
350 GtkSelectionData *selection_data,
355 GtkColorSelection *colorsel = data;
356 ColorSelectionPrivate *priv;
360 priv = colorsel->private_data;
362 if (widget == priv->old_sample)
363 colsrc = priv->old_color;
365 colsrc = priv->color;
367 vals[0] = colsrc[COLORSEL_RED] * 0xffff;
368 vals[1] = colsrc[COLORSEL_GREEN] * 0xffff;
369 vals[2] = colsrc[COLORSEL_BLUE] * 0xffff;
370 vals[3] = priv->has_opacity ? colsrc[COLORSEL_OPACITY] * 0xffff : 0xffff;
372 gtk_selection_data_set (selection_data,
373 gdk_atom_intern_static_string ("application/x-color"),
374 16, (guchar *)vals, 8);
377 /* which = 0 means draw old sample, which = 1 means draw new */
379 color_sample_draw_sample (GtkColorSelection *colorsel, int which)
382 gint x, y, wid, heig, goff;
383 ColorSelectionPrivate *priv;
386 g_return_if_fail (colorsel != NULL);
387 priv = colorsel->private_data;
389 g_return_if_fail (priv->sample_area != NULL);
390 if (!GTK_WIDGET_DRAWABLE (priv->sample_area))
395 da = priv->old_sample;
400 da = priv->cur_sample;
401 goff = priv->old_sample->allocation.width % 32;
404 cr = gdk_cairo_create (da->window);
406 wid = da->allocation.width;
407 heig = da->allocation.height;
409 /* Below needs tweaking for non-power-of-two */
410 #define CHECK_SIZE 16
412 if (priv->has_opacity)
414 /* Draw checks in background */
416 cairo_set_source_rgb (cr, 0.5, 0.5, 0.5);
417 cairo_rectangle (cr, 0, 0, wid, heig);
420 cairo_set_source_rgb (cr, 0.75, 0.75, 0.75);
421 for (x = goff & -CHECK_SIZE; x < goff + wid; x += CHECK_SIZE)
422 for (y = 0; y < heig; y += CHECK_SIZE)
423 if ((x / CHECK_SIZE + y / CHECK_SIZE) % 2 == 0)
424 cairo_rectangle (cr, x - goff, y, CHECK_SIZE, CHECK_SIZE);
430 cairo_set_source_rgba (cr,
431 priv->old_color[COLORSEL_RED],
432 priv->old_color[COLORSEL_GREEN],
433 priv->old_color[COLORSEL_BLUE],
435 priv->old_color[COLORSEL_OPACITY] : 1.0);
439 cairo_set_source_rgba (cr,
440 priv->color[COLORSEL_RED],
441 priv->color[COLORSEL_GREEN],
442 priv->color[COLORSEL_BLUE],
444 priv->color[COLORSEL_OPACITY] : 1.0);
447 cairo_rectangle (cr, 0, 0, wid, heig);
455 color_sample_update_samples (GtkColorSelection *colorsel)
457 ColorSelectionPrivate *priv = colorsel->private_data;
458 gtk_widget_queue_draw (priv->old_sample);
459 gtk_widget_queue_draw (priv->cur_sample);
463 color_old_sample_expose (GtkWidget *da,
464 GdkEventExpose *event,
465 GtkColorSelection *colorsel)
467 color_sample_draw_sample (colorsel, 0);
473 color_cur_sample_expose (GtkWidget *da,
474 GdkEventExpose *event,
475 GtkColorSelection *colorsel)
477 color_sample_draw_sample (colorsel, 1);
482 color_sample_setup_dnd (GtkColorSelection *colorsel, GtkWidget *sample)
484 static const GtkTargetEntry targets[] = {
485 { "application/x-color", 0 }
487 ColorSelectionPrivate *priv;
488 priv = colorsel->private_data;
490 gtk_drag_source_set (sample,
491 GDK_BUTTON1_MASK | GDK_BUTTON3_MASK,
493 GDK_ACTION_COPY | GDK_ACTION_MOVE);
495 g_signal_connect (sample,
497 G_CALLBACK (color_sample_drag_begin),
499 if (sample == priv->cur_sample)
502 gtk_drag_dest_set (sample,
503 GTK_DEST_DEFAULT_HIGHLIGHT |
504 GTK_DEST_DEFAULT_MOTION |
505 GTK_DEST_DEFAULT_DROP,
509 g_signal_connect (sample,
511 G_CALLBACK (color_sample_drag_end),
515 g_signal_connect (sample,
517 G_CALLBACK (color_sample_drag_handle),
519 g_signal_connect (sample,
520 "drag_data_received",
521 G_CALLBACK (color_sample_drop_handle),
528 color_sample_new (GtkColorSelection *colorsel)
530 ColorSelectionPrivate *priv;
532 priv = colorsel->private_data;
534 priv->sample_area = gtk_hbox_new (FALSE, 0);
535 priv->old_sample = gtk_drawing_area_new ();
536 priv->cur_sample = gtk_drawing_area_new ();
538 /* We need enter/leave to do tooltips */
539 gtk_widget_add_events (priv->old_sample,
540 GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK);
541 gtk_widget_add_events (priv->cur_sample,
542 GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK);
544 gtk_box_pack_start (GTK_BOX (priv->sample_area), priv->old_sample,
546 gtk_box_pack_start (GTK_BOX (priv->sample_area), priv->cur_sample,
549 g_signal_connect (priv->old_sample, "expose_event",
550 G_CALLBACK (color_old_sample_expose),
552 g_signal_connect (priv->cur_sample, "expose_event",
553 G_CALLBACK (color_cur_sample_expose),
556 color_sample_setup_dnd (colorsel, priv->old_sample);
557 color_sample_setup_dnd (colorsel, priv->cur_sample);
559 gtk_tooltips_set_tip (priv->tooltips,
561 _("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);
564 gtk_tooltips_set_tip (priv->tooltips,
566 _("The color you've chosen. You can drag this color to a palette entry to save it for use in the future."), NULL);
568 gtk_widget_show_all (priv->sample_area);
574 * The palette area code
577 #define CUSTOM_PALETTE_ENTRY_WIDTH 20
578 #define CUSTOM_PALETTE_ENTRY_HEIGHT 20
581 palette_get_color (GtkWidget *drawing_area, gdouble *color)
585 g_return_if_fail (color != NULL);
587 color_val = g_object_get_data (G_OBJECT (drawing_area), "color_val");
588 if (color_val == NULL)
590 /* Default to white for no good reason */
598 color[0] = color_val[0];
599 color[1] = color_val[1];
600 color[2] = color_val[2];
604 #define INTENSITY(r, g, b) ((r) * 0.30 + (g) * 0.59 + (b) * 0.11)
606 palette_paint (GtkWidget *drawing_area,
613 if (drawing_area->window == NULL)
616 cr = gdk_cairo_create (drawing_area->window);
618 gdk_cairo_set_source_color (cr, &drawing_area->style->bg[GTK_STATE_NORMAL]);
619 gdk_cairo_rectangle (cr, area);
622 if (GTK_WIDGET_HAS_FOCUS (drawing_area))
624 set_focus_line_attributes (drawing_area, cr, &focus_width);
627 focus_width / 2., focus_width / 2.,
628 drawing_area->allocation.width - focus_width,
629 drawing_area->allocation.height - focus_width);
637 set_focus_line_attributes (GtkWidget *drawing_area,
644 gtk_widget_style_get (drawing_area,
645 "focus-line-width", focus_width,
646 "focus-line-pattern", (gchar *)&dash_list,
649 palette_get_color (drawing_area, color);
651 if (INTENSITY (color[0], color[1], color[2]) > 0.5)
652 cairo_set_source_rgb (cr, 0., 0., 0.);
654 cairo_set_source_rgb (cr, 1., 1., 1.);
656 cairo_set_line_width (cr, *focus_width);
660 gint n_dashes = strlen (dash_list);
661 gdouble *dashes = g_new (gdouble, n_dashes);
662 gdouble total_length = 0;
666 for (i = 0; i < n_dashes; i++)
668 dashes[i] = dash_list[i];
669 total_length += dash_list[i];
672 /* The dash offset here aligns the pattern to integer pixels
673 * by starting the dash at the right side of the left border
674 * Negative dash offsets in cairo don't work
675 * (https://bugs.freedesktop.org/show_bug.cgi?id=2729)
677 dash_offset = - *focus_width / 2.;
678 while (dash_offset < 0)
679 dash_offset += total_length;
681 cairo_set_dash (cr, dashes, n_dashes, dash_offset);
689 palette_drag_begin (GtkWidget *widget,
690 GdkDragContext *context,
695 palette_get_color (widget, colors);
696 set_color_icon (context, colors);
700 palette_drag_handle (GtkWidget *widget,
701 GdkDragContext *context,
702 GtkSelectionData *selection_data,
710 palette_get_color (widget, colsrc);
712 vals[0] = colsrc[COLORSEL_RED] * 0xffff;
713 vals[1] = colsrc[COLORSEL_GREEN] * 0xffff;
714 vals[2] = colsrc[COLORSEL_BLUE] * 0xffff;
717 gtk_selection_data_set (selection_data,
718 gdk_atom_intern_static_string ("application/x-color"),
719 16, (guchar *)vals, 8);
723 palette_drag_end (GtkWidget *widget,
724 GdkDragContext *context,
727 g_object_set_data (G_OBJECT (widget), I_("gtk-color-selection-drag-window"), NULL);
731 get_current_colors (GtkColorSelection *colorsel)
733 GtkSettings *settings;
734 GdkColor *colors = NULL;
738 settings = gtk_widget_get_settings (GTK_WIDGET (colorsel));
739 g_object_get (settings,
740 "gtk-color-palette", &palette,
743 if (!gtk_color_selection_palette_from_string (palette, &colors, &n_colors))
745 gtk_color_selection_palette_from_string (default_colors, &colors, &n_colors);
749 /* If there are less colors provided than the number of slots in the
750 * color selection, we fill in the rest from the defaults.
752 if (n_colors < (GTK_CUSTOM_PALETTE_WIDTH * GTK_CUSTOM_PALETTE_HEIGHT))
754 GdkColor *tmp_colors = colors;
755 gint tmp_n_colors = n_colors;
757 gtk_color_selection_palette_from_string (default_colors, &colors, &n_colors);
758 memcpy (colors, tmp_colors, sizeof (GdkColor) * tmp_n_colors);
764 g_assert (n_colors >= GTK_CUSTOM_PALETTE_WIDTH * GTK_CUSTOM_PALETTE_HEIGHT);
770 /* Changes the model color */
772 palette_change_color (GtkWidget *drawing_area,
773 GtkColorSelection *colorsel,
777 ColorSelectionPrivate *priv;
779 GdkColor *current_colors;
782 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
783 g_return_if_fail (GTK_IS_DRAWING_AREA (drawing_area));
785 priv = colorsel->private_data;
787 gdk_color.red = UNSCALE (color[0]);
788 gdk_color.green = UNSCALE (color[1]);
789 gdk_color.blue = UNSCALE (color[2]);
793 y = 0; /* Quiet GCC */
794 while (x < GTK_CUSTOM_PALETTE_WIDTH)
797 while (y < GTK_CUSTOM_PALETTE_HEIGHT)
799 if (priv->custom_palette[x][y] == drawing_area)
810 g_assert (x < GTK_CUSTOM_PALETTE_WIDTH || y < GTK_CUSTOM_PALETTE_HEIGHT);
812 current_colors = get_current_colors (colorsel);
813 current_colors[y * GTK_CUSTOM_PALETTE_WIDTH + x] = gdk_color;
815 screen = gtk_widget_get_screen (GTK_WIDGET (colorsel));
816 if (change_palette_hook != default_change_palette_func)
817 (* change_palette_hook) (screen, current_colors,
818 GTK_CUSTOM_PALETTE_WIDTH * GTK_CUSTOM_PALETTE_HEIGHT);
819 else if (noscreen_change_palette_hook != default_noscreen_change_palette_func)
821 if (screen != gdk_screen_get_default ())
822 g_warning ("gtk_color_selection_set_change_palette_hook used by widget is not on the default screen.");
823 (* noscreen_change_palette_hook) (current_colors,
824 GTK_CUSTOM_PALETTE_WIDTH * GTK_CUSTOM_PALETTE_HEIGHT);
827 (* change_palette_hook) (screen, current_colors,
828 GTK_CUSTOM_PALETTE_WIDTH * GTK_CUSTOM_PALETTE_HEIGHT);
830 g_free (current_colors);
833 /* Changes the view color */
835 palette_set_color (GtkWidget *drawing_area,
836 GtkColorSelection *colorsel,
839 gdouble *new_color = g_new (double, 4);
842 gdk_color.red = UNSCALE (color[0]);
843 gdk_color.green = UNSCALE (color[1]);
844 gdk_color.blue = UNSCALE (color[2]);
846 gtk_widget_modify_bg (drawing_area, GTK_STATE_NORMAL, &gdk_color);
848 if (GPOINTER_TO_INT (g_object_get_data (G_OBJECT (drawing_area), "color_set")) == 0)
850 static const GtkTargetEntry targets[] = {
851 { "application/x-color", 0 }
853 gtk_drag_source_set (drawing_area,
854 GDK_BUTTON1_MASK | GDK_BUTTON3_MASK,
856 GDK_ACTION_COPY | GDK_ACTION_MOVE);
858 g_signal_connect (drawing_area,
860 G_CALLBACK (palette_drag_begin),
862 g_signal_connect (drawing_area,
864 G_CALLBACK (palette_drag_handle),
867 g_object_set_data (G_OBJECT (drawing_area), I_("color_set"),
868 GINT_TO_POINTER (1));
871 new_color[0] = color[0];
872 new_color[1] = color[1];
873 new_color[2] = color[2];
876 g_object_set_data_full (G_OBJECT (drawing_area), I_("color_val"), new_color, (GDestroyNotify)g_free);
880 palette_expose (GtkWidget *drawing_area,
881 GdkEventExpose *event,
884 if (drawing_area->window == NULL)
887 palette_paint (drawing_area, &(event->area), data);
893 popup_position_func (GtkMenu *menu,
904 widget = GTK_WIDGET (user_data);
906 g_return_if_fail (GTK_WIDGET_REALIZED (widget));
908 gdk_window_get_origin (widget->window, &root_x, &root_y);
910 gtk_widget_size_request (GTK_WIDGET (menu), &req);
912 /* Put corner of menu centered on color cell */
913 *x = root_x + widget->allocation.width / 2;
914 *y = root_y + widget->allocation.height / 2;
917 screen = gtk_widget_get_screen (widget);
918 *x = CLAMP (*x, 0, MAX (0, gdk_screen_get_width (screen) - req.width));
919 *y = CLAMP (*y, 0, MAX (0, gdk_screen_get_height (screen) - req.height));
923 save_color_selected (GtkWidget *menuitem,
926 GtkColorSelection *colorsel;
927 GtkWidget *drawing_area;
928 ColorSelectionPrivate *priv;
930 drawing_area = GTK_WIDGET (data);
932 colorsel = GTK_COLOR_SELECTION (g_object_get_data (G_OBJECT (drawing_area),
935 priv = colorsel->private_data;
937 palette_change_color (drawing_area, colorsel, priv->color);
941 do_popup (GtkColorSelection *colorsel,
942 GtkWidget *drawing_area,
948 g_object_set_data (G_OBJECT (drawing_area),
952 menu = gtk_menu_new ();
954 mi = gtk_menu_item_new_with_mnemonic (_("_Save color here"));
956 g_signal_connect (mi, "activate",
957 G_CALLBACK (save_color_selected),
960 gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
962 gtk_widget_show_all (mi);
964 gtk_menu_popup (GTK_MENU (menu), NULL, NULL,
965 popup_position_func, drawing_area,
971 palette_enter (GtkWidget *drawing_area,
972 GdkEventCrossing *event,
975 g_object_set_data (G_OBJECT (drawing_area),
976 I_("gtk-colorsel-have-pointer"),
977 GUINT_TO_POINTER (TRUE));
983 palette_leave (GtkWidget *drawing_area,
984 GdkEventCrossing *event,
987 g_object_set_data (G_OBJECT (drawing_area),
988 I_("gtk-colorsel-have-pointer"),
995 palette_press (GtkWidget *drawing_area,
996 GdkEventButton *event,
999 GtkColorSelection *colorsel = GTK_COLOR_SELECTION (data);
1001 gtk_widget_grab_focus (drawing_area);
1003 if (event->button == 3 &&
1004 event->type == GDK_BUTTON_PRESS)
1006 do_popup (colorsel, drawing_area, event->time);
1014 palette_release (GtkWidget *drawing_area,
1015 GdkEventButton *event,
1018 GtkColorSelection *colorsel = GTK_COLOR_SELECTION (data);
1020 gtk_widget_grab_focus (drawing_area);
1022 if (event->button == 1 &&
1023 g_object_get_data (G_OBJECT (drawing_area),
1024 "gtk-colorsel-have-pointer") != NULL)
1026 if (GPOINTER_TO_INT (g_object_get_data (G_OBJECT (drawing_area), "color_set")) != 0)
1029 palette_get_color (drawing_area, color);
1030 set_color_internal (colorsel, color);
1038 palette_drop_handle (GtkWidget *widget,
1039 GdkDragContext *context,
1042 GtkSelectionData *selection_data,
1047 GtkColorSelection *colorsel = GTK_COLOR_SELECTION (data);
1051 if (selection_data->length < 0)
1054 /* We accept drops with the wrong format, since the KDE color
1055 * chooser incorrectly drops application/x-color with format 8.
1057 if (selection_data->length != 8)
1059 g_warning ("Received invalid color data\n");
1063 vals = (guint16 *)selection_data->data;
1065 color[0] = (gdouble)vals[0] / 0xffff;
1066 color[1] = (gdouble)vals[1] / 0xffff;
1067 color[2] = (gdouble)vals[2] / 0xffff;
1068 color[3] = (gdouble)vals[3] / 0xffff;
1069 palette_change_color (widget, colorsel, color);
1070 set_color_internal (colorsel, color);
1074 palette_activate (GtkWidget *widget,
1078 /* should have a drawing area subclass with an activate signal */
1079 if ((event->keyval == GDK_space) ||
1080 (event->keyval == GDK_Return) ||
1081 (event->keyval == GDK_KP_Enter) ||
1082 (event->keyval == GDK_KP_Space))
1084 if (GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget), "color_set")) != 0)
1087 palette_get_color (widget, color);
1088 set_color_internal (GTK_COLOR_SELECTION (data), color);
1097 palette_popup (GtkWidget *widget,
1100 GtkColorSelection *colorsel = GTK_COLOR_SELECTION (data);
1102 do_popup (colorsel, widget, GDK_CURRENT_TIME);
1108 palette_new (GtkColorSelection *colorsel)
1111 ColorSelectionPrivate *priv;
1113 static const GtkTargetEntry targets[] = {
1114 { "application/x-color", 0 }
1117 priv = colorsel->private_data;
1119 retval = gtk_drawing_area_new ();
1121 GTK_WIDGET_SET_FLAGS (retval, GTK_CAN_FOCUS);
1123 g_object_set_data (G_OBJECT (retval), I_("color_set"), GINT_TO_POINTER (0));
1124 gtk_widget_set_events (retval, GDK_BUTTON_PRESS_MASK
1125 | GDK_BUTTON_RELEASE_MASK
1127 | GDK_ENTER_NOTIFY_MASK
1128 | GDK_LEAVE_NOTIFY_MASK);
1130 g_signal_connect (retval, "expose_event",
1131 G_CALLBACK (palette_expose), colorsel);
1132 g_signal_connect (retval, "button_press_event",
1133 G_CALLBACK (palette_press), colorsel);
1134 g_signal_connect (retval, "button_release_event",
1135 G_CALLBACK (palette_release), colorsel);
1136 g_signal_connect (retval, "enter_notify_event",
1137 G_CALLBACK (palette_enter), colorsel);
1138 g_signal_connect (retval, "leave_notify_event",
1139 G_CALLBACK (palette_leave), colorsel);
1140 g_signal_connect (retval, "key_press_event",
1141 G_CALLBACK (palette_activate), colorsel);
1142 g_signal_connect (retval, "popup_menu",
1143 G_CALLBACK (palette_popup), colorsel);
1145 gtk_drag_dest_set (retval,
1146 GTK_DEST_DEFAULT_HIGHLIGHT |
1147 GTK_DEST_DEFAULT_MOTION |
1148 GTK_DEST_DEFAULT_DROP,
1152 g_signal_connect (retval, "drag_end",
1153 G_CALLBACK (palette_drag_end), NULL);
1154 g_signal_connect (retval, "drag_data_received",
1155 G_CALLBACK (palette_drop_handle), colorsel);
1157 gtk_tooltips_set_tip (priv->tooltips,
1159 _("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.\""),
1167 * The actual GtkColorSelection widget
1172 make_picker_cursor (GdkScreen *screen)
1176 cursor = gdk_cursor_new_from_name (gdk_screen_get_display (screen),
1181 GdkColor bg = { 0, 0xffff, 0xffff, 0xffff };
1182 GdkColor fg = { 0, 0x0000, 0x0000, 0x0000 };
1184 GdkPixmap *pixmap, *mask;
1186 window = gdk_screen_get_root_window (screen);
1189 gdk_bitmap_create_from_data (window, (gchar *) dropper_bits,
1190 DROPPER_WIDTH, DROPPER_HEIGHT);
1193 gdk_bitmap_create_from_data (window, (gchar *) dropper_mask,
1194 DROPPER_WIDTH, DROPPER_HEIGHT);
1196 cursor = gdk_cursor_new_from_pixmap (pixmap, mask, &fg, &bg,
1197 DROPPER_X_HOT, DROPPER_Y_HOT);
1199 g_object_unref (pixmap);
1200 g_object_unref (mask);
1207 grab_color_at_mouse (GdkScreen *screen,
1214 GtkColorSelection *colorsel = data;
1215 ColorSelectionPrivate *priv;
1217 GdkColormap *colormap = gdk_screen_get_system_colormap (screen);
1218 GdkWindow *root_window = gdk_screen_get_root_window (screen);
1220 priv = colorsel->private_data;
1222 image = gdk_drawable_get_image (root_window, x_root, y_root, 1, 1);
1226 GdkDisplay *display = gdk_screen_get_display (screen);
1227 GdkWindow *window = gdk_display_get_window_at_pointer (display, &x, &y);
1230 image = gdk_drawable_get_image (window, x, y, 1, 1);
1234 pixel = gdk_image_get_pixel (image, 0, 0);
1235 g_object_unref (image);
1237 gdk_colormap_query_color (colormap, pixel, &color);
1239 priv->color[COLORSEL_RED] = SCALE (color.red);
1240 priv->color[COLORSEL_GREEN] = SCALE (color.green);
1241 priv->color[COLORSEL_BLUE] = SCALE (color.blue);
1243 gtk_rgb_to_hsv (priv->color[COLORSEL_RED],
1244 priv->color[COLORSEL_GREEN],
1245 priv->color[COLORSEL_BLUE],
1246 &priv->color[COLORSEL_HUE],
1247 &priv->color[COLORSEL_SATURATION],
1248 &priv->color[COLORSEL_VALUE]);
1250 update_color (colorsel);
1254 shutdown_eyedropper (GtkWidget *widget)
1256 GtkColorSelection *colorsel;
1257 ColorSelectionPrivate *priv;
1258 GdkDisplay *display = gtk_widget_get_display (widget);
1260 colorsel = GTK_COLOR_SELECTION (widget);
1261 priv = colorsel->private_data;
1265 gdk_display_keyboard_ungrab (display, priv->grab_time);
1266 gdk_display_pointer_ungrab (display, priv->grab_time);
1267 gtk_grab_remove (priv->dropper_grab_widget);
1269 priv->has_grab = FALSE;
1274 gtk_color_selection_grab_broken (GtkWidget *widget,
1275 GdkEventGrabBroken *event)
1277 shutdown_eyedropper (widget);
1283 mouse_motion (GtkWidget *invisible,
1284 GdkEventMotion *event,
1287 grab_color_at_mouse (gdk_event_get_screen ((GdkEvent *)event),
1288 event->x_root, event->y_root, data);
1292 mouse_release (GtkWidget *invisible,
1293 GdkEventButton *event,
1296 /* GtkColorSelection *colorsel = data; */
1298 if (event->button != 1)
1301 grab_color_at_mouse (gdk_event_get_screen ((GdkEvent *)event),
1302 event->x_root, event->y_root, data);
1304 shutdown_eyedropper (GTK_WIDGET (data));
1306 g_signal_handlers_disconnect_by_func (invisible,
1309 g_signal_handlers_disconnect_by_func (invisible,
1316 /* Helper Functions */
1318 static gboolean mouse_press (GtkWidget *invisible,
1319 GdkEventButton *event,
1325 key_press (GtkWidget *invisible,
1329 GdkDisplay *display = gtk_widget_get_display (invisible);
1330 GdkScreen *screen = gdk_event_get_screen ((GdkEvent *)event);
1331 guint state = event->state & gtk_accelerator_get_default_mod_mask ();
1335 gdk_display_get_pointer (display, NULL, &x, &y, NULL);
1340 switch (event->keyval)
1346 grab_color_at_mouse (screen, x, y, data);
1350 shutdown_eyedropper (data);
1352 g_signal_handlers_disconnect_by_func (invisible,
1355 g_signal_handlers_disconnect_by_func (invisible,
1361 #if defined GDK_WINDOWING_X11 || defined GDK_WINDOWING_WIN32
1364 dy = state == GDK_MOD1_MASK ? -BIG_STEP : -1;
1369 dy = state == GDK_MOD1_MASK ? BIG_STEP : 1;
1374 dx = state == GDK_MOD1_MASK ? -BIG_STEP : -1;
1379 dx = state == GDK_MOD1_MASK ? BIG_STEP : 1;
1387 gdk_display_warp_pointer (display, screen, x + dx, y + dy);
1394 mouse_press (GtkWidget *invisible,
1395 GdkEventButton *event,
1398 /* GtkColorSelection *colorsel = data; */
1400 if (event->type == GDK_BUTTON_PRESS &&
1403 g_signal_connect (invisible, "motion_notify_event",
1404 G_CALLBACK (mouse_motion),
1406 g_signal_connect (invisible, "button_release_event",
1407 G_CALLBACK (mouse_release),
1409 g_signal_handlers_disconnect_by_func (invisible,
1412 g_signal_handlers_disconnect_by_func (invisible,
1421 /* when the button is clicked */
1423 get_screen_color (GtkWidget *button)
1425 GtkColorSelection *colorsel = g_object_get_data (G_OBJECT (button), "COLORSEL");
1426 ColorSelectionPrivate *priv = colorsel->private_data;
1427 GdkScreen *screen = gtk_widget_get_screen (GTK_WIDGET (button));
1428 GdkCursor *picker_cursor;
1429 GdkGrabStatus grab_status;
1430 GtkWidget *grab_widget, *toplevel;
1432 guint32 time = gtk_get_current_event_time ();
1434 if (priv->dropper_grab_widget == NULL)
1436 grab_widget = gtk_window_new (GTK_WINDOW_POPUP);
1437 gtk_window_set_screen (GTK_WINDOW (grab_widget), screen);
1438 gtk_window_resize (GTK_WINDOW (grab_widget), 1, 1);
1439 gtk_window_move (GTK_WINDOW (grab_widget), -100, -100);
1440 gtk_widget_show (grab_widget);
1442 gtk_widget_add_events (grab_widget,
1443 GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_PRESS_MASK | GDK_POINTER_MOTION_MASK);
1445 toplevel = gtk_widget_get_toplevel (GTK_WIDGET (colorsel));
1447 if (GTK_IS_WINDOW (toplevel))
1449 if (GTK_WINDOW (toplevel)->group)
1450 gtk_window_group_add_window (GTK_WINDOW (toplevel)->group,
1451 GTK_WINDOW (grab_widget));
1454 priv->dropper_grab_widget = grab_widget;
1457 if (gdk_keyboard_grab (priv->dropper_grab_widget->window,
1458 FALSE, time) != GDK_GRAB_SUCCESS)
1461 picker_cursor = make_picker_cursor (screen);
1462 grab_status = gdk_pointer_grab (priv->dropper_grab_widget->window,
1464 GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_PRESS_MASK | GDK_POINTER_MOTION_MASK,
1468 gdk_cursor_unref (picker_cursor);
1470 if (grab_status != GDK_GRAB_SUCCESS)
1472 gdk_display_keyboard_ungrab (gtk_widget_get_display (button), time);
1476 gtk_grab_add (priv->dropper_grab_widget);
1477 priv->grab_time = time;
1478 priv->has_grab = TRUE;
1480 g_signal_connect (priv->dropper_grab_widget, "button_press_event",
1481 G_CALLBACK (mouse_press), colorsel);
1482 g_signal_connect (priv->dropper_grab_widget, "key_press_event",
1483 G_CALLBACK (key_press), colorsel);
1487 hex_changed (GtkWidget *hex_entry,
1490 GtkColorSelection *colorsel;
1491 ColorSelectionPrivate *priv;
1495 colorsel = GTK_COLOR_SELECTION (data);
1496 priv = colorsel->private_data;
1501 text = gtk_editable_get_chars (GTK_EDITABLE (priv->hex_entry), 0, -1);
1502 if (gdk_color_parse (text, &color))
1504 priv->color[COLORSEL_RED] = CLAMP (color.red/65535.0, 0.0, 1.0);
1505 priv->color[COLORSEL_GREEN] = CLAMP (color.green/65535.0, 0.0, 1.0);
1506 priv->color[COLORSEL_BLUE] = CLAMP (color.blue/65535.0, 0.0, 1.0);
1507 gtk_rgb_to_hsv (priv->color[COLORSEL_RED],
1508 priv->color[COLORSEL_GREEN],
1509 priv->color[COLORSEL_BLUE],
1510 &priv->color[COLORSEL_HUE],
1511 &priv->color[COLORSEL_SATURATION],
1512 &priv->color[COLORSEL_VALUE]);
1513 update_color (colorsel);
1519 hex_focus_out (GtkWidget *hex_entry,
1520 GdkEventFocus *event,
1523 hex_changed (hex_entry, data);
1529 hsv_changed (GtkWidget *hsv,
1532 GtkColorSelection *colorsel;
1533 ColorSelectionPrivate *priv;
1535 colorsel = GTK_COLOR_SELECTION (data);
1536 priv = colorsel->private_data;
1541 gtk_hsv_get_color (GTK_HSV (hsv),
1542 &priv->color[COLORSEL_HUE],
1543 &priv->color[COLORSEL_SATURATION],
1544 &priv->color[COLORSEL_VALUE]);
1545 gtk_hsv_to_rgb (priv->color[COLORSEL_HUE],
1546 priv->color[COLORSEL_SATURATION],
1547 priv->color[COLORSEL_VALUE],
1548 &priv->color[COLORSEL_RED],
1549 &priv->color[COLORSEL_GREEN],
1550 &priv->color[COLORSEL_BLUE]);
1551 update_color (colorsel);
1555 adjustment_changed (GtkAdjustment *adjustment,
1558 GtkColorSelection *colorsel;
1559 ColorSelectionPrivate *priv;
1561 colorsel = GTK_COLOR_SELECTION (g_object_get_data (G_OBJECT (adjustment), "COLORSEL"));
1562 priv = colorsel->private_data;
1567 switch (GPOINTER_TO_INT (data))
1569 case COLORSEL_SATURATION:
1570 case COLORSEL_VALUE:
1571 priv->color[GPOINTER_TO_INT (data)] = adjustment->value / 100;
1572 gtk_hsv_to_rgb (priv->color[COLORSEL_HUE],
1573 priv->color[COLORSEL_SATURATION],
1574 priv->color[COLORSEL_VALUE],
1575 &priv->color[COLORSEL_RED],
1576 &priv->color[COLORSEL_GREEN],
1577 &priv->color[COLORSEL_BLUE]);
1580 priv->color[GPOINTER_TO_INT (data)] = adjustment->value / 360;
1581 gtk_hsv_to_rgb (priv->color[COLORSEL_HUE],
1582 priv->color[COLORSEL_SATURATION],
1583 priv->color[COLORSEL_VALUE],
1584 &priv->color[COLORSEL_RED],
1585 &priv->color[COLORSEL_GREEN],
1586 &priv->color[COLORSEL_BLUE]);
1589 case COLORSEL_GREEN:
1591 priv->color[GPOINTER_TO_INT (data)] = adjustment->value / 255;
1593 gtk_rgb_to_hsv (priv->color[COLORSEL_RED],
1594 priv->color[COLORSEL_GREEN],
1595 priv->color[COLORSEL_BLUE],
1596 &priv->color[COLORSEL_HUE],
1597 &priv->color[COLORSEL_SATURATION],
1598 &priv->color[COLORSEL_VALUE]);
1601 priv->color[GPOINTER_TO_INT (data)] = adjustment->value / 255;
1604 update_color (colorsel);
1608 opacity_entry_changed (GtkWidget *opacity_entry,
1611 GtkColorSelection *colorsel;
1612 ColorSelectionPrivate *priv;
1616 colorsel = GTK_COLOR_SELECTION (data);
1617 priv = colorsel->private_data;
1622 text = gtk_editable_get_chars (GTK_EDITABLE (priv->opacity_entry), 0, -1);
1623 adj = gtk_range_get_adjustment (GTK_RANGE (priv->opacity_slider));
1624 gtk_adjustment_set_value (adj, g_strtod (text, NULL));
1626 update_color (colorsel);
1632 make_label_spinbutton (GtkColorSelection *colorsel,
1633 GtkWidget **spinbutton,
1639 const gchar *tooltip)
1642 GtkAdjustment *adjust;
1643 ColorSelectionPrivate *priv = colorsel->private_data;
1645 if (channel_type == COLORSEL_HUE)
1647 adjust = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 360.0, 1.0, 1.0, 1.0));
1649 else if (channel_type == COLORSEL_SATURATION ||
1650 channel_type == COLORSEL_VALUE)
1652 adjust = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 100.0, 1.0, 1.0, 1.0));
1656 adjust = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 255.0, 1.0, 1.0, 1.0));
1658 g_object_set_data (G_OBJECT (adjust), I_("COLORSEL"), colorsel);
1659 *spinbutton = gtk_spin_button_new (adjust, 10.0, 0);
1661 gtk_tooltips_set_tip (priv->tooltips, *spinbutton, tooltip, NULL);
1663 g_signal_connect (adjust, "value_changed",
1664 G_CALLBACK (adjustment_changed),
1665 GINT_TO_POINTER (channel_type));
1666 label = gtk_label_new_with_mnemonic (text);
1667 gtk_label_set_mnemonic_widget (GTK_LABEL (label), *spinbutton);
1669 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
1670 gtk_table_attach_defaults (GTK_TABLE (table), label, i, i+1, j, j+1);
1671 gtk_table_attach_defaults (GTK_TABLE (table), *spinbutton, i+1, i+2, j, j+1);
1675 make_palette_frame (GtkColorSelection *colorsel,
1681 ColorSelectionPrivate *priv;
1683 priv = colorsel->private_data;
1684 frame = gtk_frame_new (NULL);
1685 gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
1686 priv->custom_palette[i][j] = palette_new (colorsel);
1687 gtk_widget_set_size_request (priv->custom_palette[i][j], CUSTOM_PALETTE_ENTRY_WIDTH, CUSTOM_PALETTE_ENTRY_HEIGHT);
1688 gtk_container_add (GTK_CONTAINER (frame), priv->custom_palette[i][j]);
1689 gtk_table_attach_defaults (GTK_TABLE (table), frame, i, i+1, j, j+1);
1692 /* Set the palette entry [x][y] to be the currently selected one. */
1694 set_selected_palette (GtkColorSelection *colorsel, int x, int y)
1696 ColorSelectionPrivate *priv = colorsel->private_data;
1698 gtk_widget_grab_focus (priv->custom_palette[x][y]);
1702 scale_round (double val, double factor)
1704 val = floor (val * factor + 0.5);
1706 val = MIN (val, factor);
1711 update_color (GtkColorSelection *colorsel)
1713 ColorSelectionPrivate *priv = colorsel->private_data;
1715 gchar opacity_text[32];
1718 priv->changing = TRUE;
1719 color_sample_update_samples (colorsel);
1721 gtk_hsv_set_color (GTK_HSV (priv->triangle_colorsel),
1722 priv->color[COLORSEL_HUE],
1723 priv->color[COLORSEL_SATURATION],
1724 priv->color[COLORSEL_VALUE]);
1725 gtk_adjustment_set_value (gtk_spin_button_get_adjustment
1726 (GTK_SPIN_BUTTON (priv->hue_spinbutton)),
1727 scale_round (priv->color[COLORSEL_HUE], 360));
1728 gtk_adjustment_set_value (gtk_spin_button_get_adjustment
1729 (GTK_SPIN_BUTTON (priv->sat_spinbutton)),
1730 scale_round (priv->color[COLORSEL_SATURATION], 100));
1731 gtk_adjustment_set_value (gtk_spin_button_get_adjustment
1732 (GTK_SPIN_BUTTON (priv->val_spinbutton)),
1733 scale_round (priv->color[COLORSEL_VALUE], 100));
1734 gtk_adjustment_set_value (gtk_spin_button_get_adjustment
1735 (GTK_SPIN_BUTTON (priv->red_spinbutton)),
1736 scale_round (priv->color[COLORSEL_RED], 255));
1737 gtk_adjustment_set_value (gtk_spin_button_get_adjustment
1738 (GTK_SPIN_BUTTON (priv->green_spinbutton)),
1739 scale_round (priv->color[COLORSEL_GREEN], 255));
1740 gtk_adjustment_set_value (gtk_spin_button_get_adjustment
1741 (GTK_SPIN_BUTTON (priv->blue_spinbutton)),
1742 scale_round (priv->color[COLORSEL_BLUE], 255));
1743 gtk_adjustment_set_value (gtk_range_get_adjustment
1744 (GTK_RANGE (priv->opacity_slider)),
1745 scale_round (priv->color[COLORSEL_OPACITY], 255));
1747 g_snprintf (opacity_text, 32, "%.0f", scale_round (priv->color[COLORSEL_OPACITY], 255));
1748 gtk_entry_set_text (GTK_ENTRY (priv->opacity_entry), opacity_text);
1750 g_snprintf (entryval, 11, "#%2X%2X%2X",
1751 (guint) (scale_round (priv->color[COLORSEL_RED], 255)),
1752 (guint) (scale_round (priv->color[COLORSEL_GREEN], 255)),
1753 (guint) (scale_round (priv->color[COLORSEL_BLUE], 255)));
1755 for (ptr = entryval; *ptr; ptr++)
1758 gtk_entry_set_text (GTK_ENTRY (priv->hex_entry), entryval);
1759 priv->changing = FALSE;
1761 g_object_ref (colorsel);
1763 g_signal_emit (colorsel, color_selection_signals[COLOR_CHANGED], 0);
1765 g_object_freeze_notify (G_OBJECT (colorsel));
1766 g_object_notify (G_OBJECT (colorsel), "current-color");
1767 g_object_notify (G_OBJECT (colorsel), "current-alpha");
1768 g_object_thaw_notify (G_OBJECT (colorsel));
1770 g_object_unref (colorsel);
1774 update_palette (GtkColorSelection *colorsel)
1776 GdkColor *current_colors;
1779 current_colors = get_current_colors (colorsel);
1781 for (i = 0; i < GTK_CUSTOM_PALETTE_HEIGHT; i++)
1783 for (j = 0; j < GTK_CUSTOM_PALETTE_WIDTH; j++)
1787 index = i * GTK_CUSTOM_PALETTE_WIDTH + j;
1789 gtk_color_selection_set_palette_color (colorsel,
1791 ¤t_colors[index]);
1795 g_free (current_colors);
1799 palette_change_notify_instance (GObject *object,
1803 update_palette (GTK_COLOR_SELECTION (data));
1807 default_noscreen_change_palette_func (const GdkColor *colors,
1810 default_change_palette_func (gdk_screen_get_default (), colors, n_colors);
1814 default_change_palette_func (GdkScreen *screen,
1815 const GdkColor *colors,
1820 str = gtk_color_selection_palette_to_string (colors, n_colors);
1822 gtk_settings_set_string_property (gtk_settings_get_for_screen (screen),
1823 "gtk-color-palette",
1825 "gtk_color_selection_palette_to_string");
1830 G_DEFINE_TYPE (GtkColorSelection, gtk_color_selection, GTK_TYPE_VBOX)
1833 gtk_color_selection_class_init (GtkColorSelectionClass *klass)
1835 GObjectClass *gobject_class;
1836 GtkObjectClass *object_class;
1837 GtkWidgetClass *widget_class;
1839 gobject_class = G_OBJECT_CLASS (klass);
1840 object_class = GTK_OBJECT_CLASS (klass);
1841 widget_class = GTK_WIDGET_CLASS (klass);
1843 object_class->destroy = gtk_color_selection_destroy;
1844 gobject_class->finalize = gtk_color_selection_finalize;
1846 gobject_class->set_property = gtk_color_selection_set_property;
1847 gobject_class->get_property = gtk_color_selection_get_property;
1849 widget_class->realize = gtk_color_selection_realize;
1850 widget_class->unrealize = gtk_color_selection_unrealize;
1851 widget_class->show_all = gtk_color_selection_show_all;
1852 widget_class->grab_broken_event = gtk_color_selection_grab_broken;
1854 g_object_class_install_property (gobject_class,
1855 PROP_HAS_OPACITY_CONTROL,
1856 g_param_spec_boolean ("has-opacity-control",
1857 P_("Has Opacity Control"),
1858 P_("Whether the color selector should allow setting opacity"),
1860 GTK_PARAM_READWRITE));
1861 g_object_class_install_property (gobject_class,
1863 g_param_spec_boolean ("has-palette",
1865 P_("Whether a palette should be used"),
1867 GTK_PARAM_READWRITE));
1868 g_object_class_install_property (gobject_class,
1870 g_param_spec_boxed ("current-color",
1871 P_("Current Color"),
1872 P_("The current color"),
1874 GTK_PARAM_READWRITE));
1875 g_object_class_install_property (gobject_class,
1877 g_param_spec_uint ("current-alpha",
1878 P_("Current Alpha"),
1879 P_("The current opacity value (0 fully transparent, 65535 fully opaque)"),
1881 GTK_PARAM_READWRITE));
1883 color_selection_signals[COLOR_CHANGED] =
1884 g_signal_new (I_("color_changed"),
1885 G_OBJECT_CLASS_TYPE (object_class),
1887 G_STRUCT_OFFSET (GtkColorSelectionClass, color_changed),
1889 _gtk_marshal_VOID__VOID,
1892 gtk_settings_install_property (g_param_spec_string ("gtk-color-palette",
1893 P_("Custom palette"),
1894 P_("Palette to use in the color selector"),
1896 GTK_PARAM_READWRITE));
1898 g_type_class_add_private (gobject_class, sizeof (ColorSelectionPrivate));
1901 /* widget functions */
1904 gtk_color_selection_init (GtkColorSelection *colorsel)
1906 GtkWidget *top_hbox;
1907 GtkWidget *top_right_vbox;
1908 GtkWidget *table, *label, *hbox, *frame, *vbox, *button;
1909 GtkAdjustment *adjust;
1910 GtkWidget *picker_image;
1912 ColorSelectionPrivate *priv;
1914 GList *focus_chain = NULL;
1916 gtk_widget_push_composite_child ();
1918 priv = colorsel->private_data = G_TYPE_INSTANCE_GET_PRIVATE (colorsel, GTK_TYPE_COLOR_SELECTION, ColorSelectionPrivate);
1919 priv->changing = FALSE;
1920 priv->default_set = FALSE;
1921 priv->default_alpha_set = FALSE;
1923 priv->tooltips = gtk_tooltips_new ();
1924 g_object_ref_sink (priv->tooltips);
1926 top_hbox = gtk_hbox_new (FALSE, 12);
1927 gtk_box_pack_start (GTK_BOX (colorsel), top_hbox, FALSE, FALSE, 0);
1929 vbox = gtk_vbox_new (FALSE, 6);
1930 priv->triangle_colorsel = gtk_hsv_new ();
1931 g_signal_connect (priv->triangle_colorsel, "changed",
1932 G_CALLBACK (hsv_changed), colorsel);
1933 gtk_hsv_set_metrics (GTK_HSV (priv->triangle_colorsel), 174, 15);
1934 gtk_box_pack_start (GTK_BOX (top_hbox), vbox, FALSE, FALSE, 0);
1935 gtk_box_pack_start (GTK_BOX (vbox), priv->triangle_colorsel, FALSE, FALSE, 0);
1936 gtk_tooltips_set_tip (priv->tooltips, priv->triangle_colorsel,
1937 _("Select the color you want from the outer ring. Select the darkness or lightness of that color using the inner triangle."), NULL);
1939 hbox = gtk_hbox_new (FALSE, 6);
1940 gtk_box_pack_end (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
1942 frame = gtk_frame_new (NULL);
1943 gtk_widget_set_size_request (frame, -1, 30);
1944 gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
1945 color_sample_new (colorsel);
1946 gtk_container_add (GTK_CONTAINER (frame), priv->sample_area);
1947 gtk_box_pack_start (GTK_BOX (hbox), frame, TRUE, TRUE, 0);
1949 button = gtk_button_new ();
1951 gtk_widget_set_events (button, GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK);
1952 g_object_set_data (G_OBJECT (button), I_("COLORSEL"), colorsel);
1953 g_signal_connect (button, "clicked",
1954 G_CALLBACK (get_screen_color), NULL);
1955 picker_image = gtk_image_new_from_stock (GTK_STOCK_COLOR_PICKER, GTK_ICON_SIZE_BUTTON);
1956 gtk_container_add (GTK_CONTAINER (button), picker_image);
1957 gtk_widget_show (GTK_WIDGET (picker_image));
1958 gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
1960 gtk_tooltips_set_tip (priv->tooltips,
1962 _("Click the eyedropper, then click a color anywhere on your screen to select that color."), NULL);
1964 top_right_vbox = gtk_vbox_new (FALSE, 6);
1965 gtk_box_pack_start (GTK_BOX (top_hbox), top_right_vbox, FALSE, FALSE, 0);
1966 table = gtk_table_new (8, 6, FALSE);
1967 gtk_box_pack_start (GTK_BOX (top_right_vbox), table, FALSE, FALSE, 0);
1968 gtk_table_set_row_spacings (GTK_TABLE (table), 6);
1969 gtk_table_set_col_spacings (GTK_TABLE (table), 12);
1971 make_label_spinbutton (colorsel, &priv->hue_spinbutton, _("_Hue:"), table, 0, 0, COLORSEL_HUE,
1972 _("Position on the color wheel."));
1973 gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (priv->hue_spinbutton), TRUE);
1974 make_label_spinbutton (colorsel, &priv->sat_spinbutton, _("_Saturation:"), table, 0, 1, COLORSEL_SATURATION,
1975 _("\"Deepness\" of the color."));
1976 make_label_spinbutton (colorsel, &priv->val_spinbutton, _("_Value:"), table, 0, 2, COLORSEL_VALUE,
1977 _("Brightness of the color."));
1978 make_label_spinbutton (colorsel, &priv->red_spinbutton, _("_Red:"), table, 6, 0, COLORSEL_RED,
1979 _("Amount of red light in the color."));
1980 make_label_spinbutton (colorsel, &priv->green_spinbutton, _("_Green:"), table, 6, 1, COLORSEL_GREEN,
1981 _("Amount of green light in the color."));
1982 make_label_spinbutton (colorsel, &priv->blue_spinbutton, _("_Blue:"), table, 6, 2, COLORSEL_BLUE,
1983 _("Amount of blue light in the color."));
1984 gtk_table_attach_defaults (GTK_TABLE (table), gtk_hseparator_new (), 0, 8, 3, 4);
1986 priv->opacity_label = gtk_label_new_with_mnemonic (_("Op_acity:"));
1987 gtk_misc_set_alignment (GTK_MISC (priv->opacity_label), 0.0, 0.5);
1988 gtk_table_attach_defaults (GTK_TABLE (table), priv->opacity_label, 0, 1, 4, 5);
1989 adjust = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 255.0, 1.0, 1.0, 0.0));
1990 g_object_set_data (G_OBJECT (adjust), I_("COLORSEL"), colorsel);
1991 priv->opacity_slider = gtk_hscale_new (adjust);
1992 gtk_tooltips_set_tip (priv->tooltips,
1993 priv->opacity_slider,
1994 _("Transparency of the color."), NULL);
1995 gtk_label_set_mnemonic_widget (GTK_LABEL (priv->opacity_label),
1996 priv->opacity_slider);
1997 gtk_scale_set_draw_value (GTK_SCALE (priv->opacity_slider), FALSE);
1998 g_signal_connect (adjust, "value_changed",
1999 G_CALLBACK (adjustment_changed),
2000 GINT_TO_POINTER (COLORSEL_OPACITY));
2001 gtk_table_attach_defaults (GTK_TABLE (table), priv->opacity_slider, 1, 7, 4, 5);
2002 priv->opacity_entry = gtk_entry_new ();
2003 gtk_tooltips_set_tip (priv->tooltips,
2004 priv->opacity_entry,
2005 _("Transparency of the color."), NULL);
2006 gtk_widget_set_size_request (priv->opacity_entry, 40, -1);
2008 g_signal_connect (priv->opacity_entry, "activate",
2009 G_CALLBACK (opacity_entry_changed), colorsel);
2010 gtk_table_attach_defaults (GTK_TABLE (table), priv->opacity_entry, 7, 8, 4, 5);
2012 label = gtk_label_new_with_mnemonic (_("Color _name:"));
2013 gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 5, 6);
2014 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
2015 priv->hex_entry = gtk_entry_new ();
2017 gtk_label_set_mnemonic_widget (GTK_LABEL (label), priv->hex_entry);
2019 g_signal_connect (priv->hex_entry, "activate",
2020 G_CALLBACK (hex_changed), colorsel);
2022 g_signal_connect (priv->hex_entry, "focus_out_event",
2023 G_CALLBACK (hex_focus_out), colorsel);
2025 gtk_tooltips_set_tip (priv->tooltips,
2027 _("You can enter an HTML-style hexadecimal color value, or simply a color name such as 'orange' in this entry."), NULL);
2029 gtk_entry_set_width_chars (GTK_ENTRY (priv->hex_entry), 7);
2030 gtk_table_attach_defaults (GTK_TABLE (table), priv->hex_entry, 1, 5, 5, 6);
2032 focus_chain = g_list_append (focus_chain, priv->hue_spinbutton);
2033 focus_chain = g_list_append (focus_chain, priv->sat_spinbutton);
2034 focus_chain = g_list_append (focus_chain, priv->val_spinbutton);
2035 focus_chain = g_list_append (focus_chain, priv->red_spinbutton);
2036 focus_chain = g_list_append (focus_chain, priv->green_spinbutton);
2037 focus_chain = g_list_append (focus_chain, priv->blue_spinbutton);
2038 focus_chain = g_list_append (focus_chain, priv->opacity_slider);
2039 focus_chain = g_list_append (focus_chain, priv->opacity_entry);
2040 focus_chain = g_list_append (focus_chain, priv->hex_entry);
2041 gtk_container_set_focus_chain (GTK_CONTAINER (table), focus_chain);
2042 g_list_free (focus_chain);
2044 /* Set up the palette */
2045 table = gtk_table_new (GTK_CUSTOM_PALETTE_HEIGHT, GTK_CUSTOM_PALETTE_WIDTH, TRUE);
2046 gtk_table_set_row_spacings (GTK_TABLE (table), 1);
2047 gtk_table_set_col_spacings (GTK_TABLE (table), 1);
2048 for (i = 0; i < GTK_CUSTOM_PALETTE_WIDTH; i++)
2050 for (j = 0; j < GTK_CUSTOM_PALETTE_HEIGHT; j++)
2052 make_palette_frame (colorsel, table, i, j);
2055 set_selected_palette (colorsel, 0, 0);
2056 priv->palette_frame = gtk_vbox_new (FALSE, 6);
2057 label = gtk_label_new_with_mnemonic (_("_Palette:"));
2058 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
2059 gtk_box_pack_start (GTK_BOX (priv->palette_frame), label, FALSE, FALSE, 0);
2061 gtk_label_set_mnemonic_widget (GTK_LABEL (label),
2062 priv->custom_palette[0][0]);
2064 gtk_box_pack_end (GTK_BOX (top_right_vbox), priv->palette_frame, FALSE, FALSE, 0);
2065 gtk_box_pack_start (GTK_BOX (priv->palette_frame), table, FALSE, FALSE, 0);
2067 gtk_widget_show_all (top_hbox);
2069 /* hide unused stuff */
2071 if (priv->has_opacity == FALSE)
2073 gtk_widget_hide (priv->opacity_label);
2074 gtk_widget_hide (priv->opacity_slider);
2075 gtk_widget_hide (priv->opacity_entry);
2078 if (priv->has_palette == FALSE)
2080 gtk_widget_hide (priv->palette_frame);
2083 atk_obj = gtk_widget_get_accessible (priv->triangle_colorsel);
2084 if (GTK_IS_ACCESSIBLE (atk_obj))
2086 atk_object_set_name (atk_obj, _("Color Wheel"));
2087 atk_object_set_role (gtk_widget_get_accessible (GTK_WIDGET (colorsel)), ATK_ROLE_COLOR_CHOOSER);
2088 make_all_relations (atk_obj, priv);
2091 gtk_widget_pop_composite_child ();
2095 gtk_color_selection_destroy (GtkObject *object)
2097 GtkColorSelection *cselection = GTK_COLOR_SELECTION (object);
2098 ColorSelectionPrivate *priv = cselection->private_data;
2100 if (priv->dropper_grab_widget)
2102 gtk_widget_destroy (priv->dropper_grab_widget);
2103 priv->dropper_grab_widget = NULL;
2108 g_object_unref (priv->tooltips);
2109 priv->tooltips = NULL;
2112 GTK_OBJECT_CLASS (gtk_color_selection_parent_class)->destroy (object);
2116 gtk_color_selection_finalize (GObject *object)
2118 G_OBJECT_CLASS (gtk_color_selection_parent_class)->finalize (object);
2122 gtk_color_selection_realize (GtkWidget *widget)
2124 GtkColorSelection *colorsel = GTK_COLOR_SELECTION (widget);
2125 ColorSelectionPrivate *priv = colorsel->private_data;
2126 GtkSettings *settings = gtk_widget_get_settings (widget);
2128 priv->settings_connection = g_signal_connect (settings,
2129 "notify::gtk-color-palette",
2130 G_CALLBACK (palette_change_notify_instance),
2132 update_palette (colorsel);
2134 GTK_WIDGET_CLASS (gtk_color_selection_parent_class)->realize (widget);
2138 gtk_color_selection_unrealize (GtkWidget *widget)
2140 GtkColorSelection *colorsel = GTK_COLOR_SELECTION (widget);
2141 ColorSelectionPrivate *priv = colorsel->private_data;
2142 GtkSettings *settings = gtk_widget_get_settings (widget);
2144 g_signal_handler_disconnect (settings, priv->settings_connection);
2146 GTK_WIDGET_CLASS (gtk_color_selection_parent_class)->unrealize (widget);
2149 /* We override show-all since we have internal widgets that
2150 * shouldn't be shown when you call show_all(), like the
2151 * palette and opacity sliders.
2154 gtk_color_selection_show_all (GtkWidget *widget)
2156 gtk_widget_show (widget);
2160 * gtk_color_selection_new:
2162 * Creates a new GtkColorSelection.
2164 * Return value: a new #GtkColorSelection
2167 gtk_color_selection_new (void)
2169 GtkColorSelection *colorsel;
2170 ColorSelectionPrivate *priv;
2177 colorsel = g_object_new (GTK_TYPE_COLOR_SELECTION, NULL);
2178 priv = colorsel->private_data;
2179 set_color_internal (colorsel, color);
2180 gtk_color_selection_set_has_opacity_control (colorsel, TRUE);
2182 /* We want to make sure that default_set is FALSE */
2183 /* This way the user can still set it */
2184 priv->default_set = FALSE;
2185 priv->default_alpha_set = FALSE;
2187 return GTK_WIDGET (colorsel);
2192 gtk_color_selection_set_update_policy (GtkColorSelection *colorsel,
2193 GtkUpdateType policy)
2195 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2199 * gtk_color_selection_get_has_opacity_control:
2200 * @colorsel: a #GtkColorSelection.
2202 * Determines whether the colorsel has an opacity control.
2204 * Return value: %TRUE if the @colorsel has an opacity control. %FALSE if it does't.
2207 gtk_color_selection_get_has_opacity_control (GtkColorSelection *colorsel)
2209 ColorSelectionPrivate *priv;
2211 g_return_val_if_fail (GTK_IS_COLOR_SELECTION (colorsel), FALSE);
2213 priv = colorsel->private_data;
2215 return priv->has_opacity;
2219 * gtk_color_selection_set_has_opacity_control:
2220 * @colorsel: a #GtkColorSelection.
2221 * @has_opacity: %TRUE if @colorsel can set the opacity, %FALSE otherwise.
2223 * Sets the @colorsel to use or not use opacity.
2227 gtk_color_selection_set_has_opacity_control (GtkColorSelection *colorsel,
2228 gboolean has_opacity)
2230 ColorSelectionPrivate *priv;
2232 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2234 priv = colorsel->private_data;
2235 has_opacity = has_opacity != FALSE;
2237 if (priv->has_opacity != has_opacity)
2239 priv->has_opacity = has_opacity;
2242 gtk_widget_show (priv->opacity_slider);
2243 gtk_widget_show (priv->opacity_label);
2244 gtk_widget_show (priv->opacity_entry);
2248 gtk_widget_hide (priv->opacity_slider);
2249 gtk_widget_hide (priv->opacity_label);
2250 gtk_widget_hide (priv->opacity_entry);
2252 color_sample_update_samples (colorsel);
2254 g_object_notify (G_OBJECT (colorsel), "has-opacity-control");
2259 * gtk_color_selection_get_has_palette:
2260 * @colorsel: a #GtkColorSelection.
2262 * Determines whether the color selector has a color palette.
2264 * Return value: %TRUE if the selector has a palette. %FALSE if it hasn't.
2267 gtk_color_selection_get_has_palette (GtkColorSelection *colorsel)
2269 ColorSelectionPrivate *priv;
2271 g_return_val_if_fail (GTK_IS_COLOR_SELECTION (colorsel), FALSE);
2273 priv = colorsel->private_data;
2275 return priv->has_palette;
2279 * gtk_color_selection_set_has_palette:
2280 * @colorsel: a #GtkColorSelection.
2281 * @has_palette: %TRUE if palette is to be visible, %FALSE otherwise.
2283 * Shows and hides the palette based upon the value of @has_palette.
2287 gtk_color_selection_set_has_palette (GtkColorSelection *colorsel,
2288 gboolean has_palette)
2290 ColorSelectionPrivate *priv;
2291 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2293 priv = colorsel->private_data;
2294 has_palette = has_palette != FALSE;
2296 if (priv->has_palette != has_palette)
2298 priv->has_palette = has_palette;
2300 gtk_widget_show (priv->palette_frame);
2302 gtk_widget_hide (priv->palette_frame);
2304 g_object_notify (G_OBJECT (colorsel), "has-palette");
2309 * gtk_color_selection_set_current_color:
2310 * @colorsel: a #GtkColorSelection.
2311 * @color: A #GdkColor to set the current color with.
2313 * Sets the current color to be @color. The first time this is called, it will
2314 * also set the original color to be @color too.
2317 gtk_color_selection_set_current_color (GtkColorSelection *colorsel,
2318 const GdkColor *color)
2320 ColorSelectionPrivate *priv;
2323 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2324 g_return_if_fail (color != NULL);
2326 priv = colorsel->private_data;
2327 priv->changing = TRUE;
2328 priv->color[COLORSEL_RED] = SCALE (color->red);
2329 priv->color[COLORSEL_GREEN] = SCALE (color->green);
2330 priv->color[COLORSEL_BLUE] = SCALE (color->blue);
2331 gtk_rgb_to_hsv (priv->color[COLORSEL_RED],
2332 priv->color[COLORSEL_GREEN],
2333 priv->color[COLORSEL_BLUE],
2334 &priv->color[COLORSEL_HUE],
2335 &priv->color[COLORSEL_SATURATION],
2336 &priv->color[COLORSEL_VALUE]);
2337 if (priv->default_set == FALSE)
2339 for (i = 0; i < COLORSEL_NUM_CHANNELS; i++)
2340 priv->old_color[i] = priv->color[i];
2342 priv->default_set = TRUE;
2343 update_color (colorsel);
2347 * gtk_color_selection_set_current_alpha:
2348 * @colorsel: a #GtkColorSelection.
2349 * @alpha: an integer between 0 and 65535.
2351 * Sets the current opacity to be @alpha. The first time this is called, it will
2352 * also set the original opacity to be @alpha too.
2355 gtk_color_selection_set_current_alpha (GtkColorSelection *colorsel,
2358 ColorSelectionPrivate *priv;
2361 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2363 priv = colorsel->private_data;
2364 priv->changing = TRUE;
2365 priv->color[COLORSEL_OPACITY] = SCALE (alpha);
2366 if (priv->default_alpha_set == FALSE)
2368 for (i = 0; i < COLORSEL_NUM_CHANNELS; i++)
2369 priv->old_color[i] = priv->color[i];
2371 priv->default_alpha_set = TRUE;
2372 update_color (colorsel);
2376 * gtk_color_selection_set_color:
2377 * @colorsel: a #GtkColorSelection.
2378 * @color: an array of 4 doubles specifying the red, green, blue and opacity
2379 * to set the current color to.
2381 * Sets the current color to be @color. The first time this is called, it will
2382 * also set the original color to be @color too.
2384 * Deprecated: Use gtk_color_selection_set_current_color() instead.
2387 gtk_color_selection_set_color (GtkColorSelection *colorsel,
2390 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2392 set_color_internal (colorsel, color);
2396 * gtk_color_selection_get_current_color:
2397 * @colorsel: a #GtkColorSelection.
2398 * @color: a #GdkColor to fill in with the current color.
2400 * Sets @color to be the current color in the GtkColorSelection widget.
2403 gtk_color_selection_get_current_color (GtkColorSelection *colorsel,
2406 ColorSelectionPrivate *priv;
2408 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2409 g_return_if_fail (color != NULL);
2411 priv = colorsel->private_data;
2412 color->red = UNSCALE (priv->color[COLORSEL_RED]);
2413 color->green = UNSCALE (priv->color[COLORSEL_GREEN]);
2414 color->blue = UNSCALE (priv->color[COLORSEL_BLUE]);
2418 * gtk_color_selection_get_current_alpha:
2419 * @colorsel: a #GtkColorSelection.
2421 * Returns the current alpha value.
2423 * Return value: an integer between 0 and 65535.
2426 gtk_color_selection_get_current_alpha (GtkColorSelection *colorsel)
2428 ColorSelectionPrivate *priv;
2430 g_return_val_if_fail (GTK_IS_COLOR_SELECTION (colorsel), 0);
2432 priv = colorsel->private_data;
2433 return priv->has_opacity ? UNSCALE (priv->color[COLORSEL_OPACITY]) : 65535;
2437 * gtk_color_selection_get_color:
2438 * @colorsel: a #GtkColorSelection.
2439 * @color: an array of 4 #gdouble to fill in with the current color.
2441 * Sets @color to be the current color in the GtkColorSelection widget.
2443 * This function is deprecated, use gtk_color_selection_get_current_color() instead.
2446 gtk_color_selection_get_color (GtkColorSelection *colorsel,
2449 ColorSelectionPrivate *priv;
2451 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2453 priv = colorsel->private_data;
2454 color[0] = priv->color[COLORSEL_RED];
2455 color[1] = priv->color[COLORSEL_GREEN];
2456 color[2] = priv->color[COLORSEL_BLUE];
2457 color[3] = priv->has_opacity ? priv->color[COLORSEL_OPACITY] : 65535;
2461 * gtk_color_selection_set_previous_color:
2462 * @colorsel: a #GtkColorSelection.
2463 * @color: a #GdkColor to set the previous color with.
2465 * Sets the 'previous' color to be @color. This function should be called with
2466 * some hesitations, as it might seem confusing to have that color change.
2467 * Calling gtk_color_selection_set_current_color() will also set this color the first
2468 * time it is called.
2471 gtk_color_selection_set_previous_color (GtkColorSelection *colorsel,
2472 const GdkColor *color)
2474 ColorSelectionPrivate *priv;
2476 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2477 g_return_if_fail (color != NULL);
2479 priv = colorsel->private_data;
2480 priv->changing = TRUE;
2481 priv->old_color[COLORSEL_RED] = SCALE (color->red);
2482 priv->old_color[COLORSEL_GREEN] = SCALE (color->green);
2483 priv->old_color[COLORSEL_BLUE] = SCALE (color->blue);
2484 gtk_rgb_to_hsv (priv->old_color[COLORSEL_RED],
2485 priv->old_color[COLORSEL_GREEN],
2486 priv->old_color[COLORSEL_BLUE],
2487 &priv->old_color[COLORSEL_HUE],
2488 &priv->old_color[COLORSEL_SATURATION],
2489 &priv->old_color[COLORSEL_VALUE]);
2490 color_sample_update_samples (colorsel);
2491 priv->default_set = TRUE;
2492 priv->changing = FALSE;
2496 * gtk_color_selection_set_previous_alpha:
2497 * @colorsel: a #GtkColorSelection.
2498 * @alpha: an integer between 0 and 65535.
2500 * Sets the 'previous' alpha to be @alpha. This function should be called with
2501 * some hesitations, as it might seem confusing to have that alpha change.
2504 gtk_color_selection_set_previous_alpha (GtkColorSelection *colorsel,
2507 ColorSelectionPrivate *priv;
2509 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2511 priv = colorsel->private_data;
2512 priv->changing = TRUE;
2513 priv->old_color[COLORSEL_OPACITY] = SCALE (alpha);
2514 color_sample_update_samples (colorsel);
2515 priv->default_alpha_set = TRUE;
2516 priv->changing = FALSE;
2521 * gtk_color_selection_get_previous_color:
2522 * @colorsel: a #GtkColorSelection.
2523 * @color: a #GdkColor to fill in with the original color value.
2525 * Fills @color in with the original color value.
2528 gtk_color_selection_get_previous_color (GtkColorSelection *colorsel,
2531 ColorSelectionPrivate *priv;
2533 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2534 g_return_if_fail (color != NULL);
2536 priv = colorsel->private_data;
2537 color->red = UNSCALE (priv->old_color[COLORSEL_RED]);
2538 color->green = UNSCALE (priv->old_color[COLORSEL_GREEN]);
2539 color->blue = UNSCALE (priv->old_color[COLORSEL_BLUE]);
2543 * gtk_color_selection_get_previous_alpha:
2544 * @colorsel: a #GtkColorSelection.
2546 * Returns the previous alpha value.
2548 * Return value: an integer between 0 and 65535.
2551 gtk_color_selection_get_previous_alpha (GtkColorSelection *colorsel)
2553 ColorSelectionPrivate *priv;
2555 g_return_val_if_fail (GTK_IS_COLOR_SELECTION (colorsel), 0);
2557 priv = colorsel->private_data;
2558 return priv->has_opacity ? UNSCALE (priv->old_color[COLORSEL_OPACITY]) : 65535;
2562 * gtk_color_selection_set_palette_color:
2563 * @colorsel: a #GtkColorSelection.
2564 * @index: the color index of the palette.
2565 * @color: A #GdkColor to set the palette with.
2567 * Sets the palette located at @index to have @color as its color.
2571 gtk_color_selection_set_palette_color (GtkColorSelection *colorsel,
2575 ColorSelectionPrivate *priv;
2579 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2580 g_return_if_fail (index >= 0 && index < GTK_CUSTOM_PALETTE_WIDTH*GTK_CUSTOM_PALETTE_HEIGHT);
2582 x = index % GTK_CUSTOM_PALETTE_WIDTH;
2583 y = index / GTK_CUSTOM_PALETTE_WIDTH;
2585 priv = colorsel->private_data;
2586 col[0] = SCALE (color->red);
2587 col[1] = SCALE (color->green);
2588 col[2] = SCALE (color->blue);
2590 palette_set_color (priv->custom_palette[x][y], colorsel, col);
2594 * gtk_color_selection_is_adjusting:
2595 * @colorsel: a #GtkColorSelection.
2597 * Gets the current state of the @colorsel.
2599 * Return value: %TRUE if the user is currently dragging a color around, and %FALSE
2600 * if the selection has stopped.
2603 gtk_color_selection_is_adjusting (GtkColorSelection *colorsel)
2605 ColorSelectionPrivate *priv;
2607 g_return_val_if_fail (GTK_IS_COLOR_SELECTION (colorsel), FALSE);
2609 priv = colorsel->private_data;
2611 return (gtk_hsv_is_adjusting (GTK_HSV (priv->triangle_colorsel)));
2615 gtk_color_selection_set_property (GObject *object,
2617 const GValue *value,
2620 GtkColorSelection *colorsel = GTK_COLOR_SELECTION (object);
2624 case PROP_HAS_OPACITY_CONTROL:
2625 gtk_color_selection_set_has_opacity_control (colorsel,
2626 g_value_get_boolean (value));
2628 case PROP_HAS_PALETTE:
2629 gtk_color_selection_set_has_palette (colorsel,
2630 g_value_get_boolean (value));
2632 case PROP_CURRENT_COLOR:
2633 gtk_color_selection_set_current_color (colorsel, g_value_get_boxed (value));
2635 case PROP_CURRENT_ALPHA:
2636 gtk_color_selection_set_current_alpha (colorsel, g_value_get_uint (value));
2639 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
2646 gtk_color_selection_get_property (GObject *object,
2651 GtkColorSelection *colorsel = GTK_COLOR_SELECTION (object);
2656 case PROP_HAS_OPACITY_CONTROL:
2657 g_value_set_boolean (value, gtk_color_selection_get_has_opacity_control (colorsel));
2659 case PROP_HAS_PALETTE:
2660 g_value_set_boolean (value, gtk_color_selection_get_has_palette (colorsel));
2662 case PROP_CURRENT_COLOR:
2663 gtk_color_selection_get_current_color (colorsel, &color);
2664 g_value_set_boxed (value, &color);
2666 case PROP_CURRENT_ALPHA:
2667 g_value_set_uint (value, gtk_color_selection_get_current_alpha (colorsel));
2670 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
2677 * gtk_color_selection_palette_from_string:
2678 * @str: a string encoding a color palette.
2679 * @colors: return location for allocated array of #GdkColor.
2680 * @n_colors: return location for length of array.
2682 * Parses a color palette string; the string is a colon-separated
2683 * list of color names readable by gdk_color_parse().
2685 * Return value: %TRUE if a palette was successfully parsed.
2688 gtk_color_selection_palette_from_string (const gchar *str,
2700 copy = g_strdup (str);
2706 if (*p == ':' || *p == '\0')
2708 gboolean done = TRUE;
2712 goto failed; /* empty entry */
2721 retval = g_renew (GdkColor, retval, count + 1);
2722 if (!gdk_color_parse (start, retval + count))
2763 * gtk_color_selection_palette_to_string:
2764 * @colors: an array of colors.
2765 * @n_colors: length of the array.
2767 * Encodes a palette as a string, useful for persistent storage.
2769 * Return value: allocated string encoding the palette.
2772 gtk_color_selection_palette_to_string (const GdkColor *colors,
2776 gchar **strs = NULL;
2780 return g_strdup ("");
2782 strs = g_new0 (gchar*, n_colors + 1);
2785 while (i < n_colors)
2790 g_strdup_printf ("#%2X%2X%2X",
2791 colors[i].red / 256,
2792 colors[i].green / 256,
2793 colors[i].blue / 256);
2795 for (ptr = strs[i]; *ptr; ptr++)
2802 retval = g_strjoinv (":", strs);
2810 * gtk_color_selection_set_change_palette_hook:
2811 * @func: a function to call when the custom palette needs saving.
2813 * Installs a global function to be called whenever the user tries to
2814 * modify the palette in a color selection. This function should save
2815 * the new palette contents, and update the GtkSettings property
2816 * "gtk-color-palette" so all GtkColorSelection widgets will be modified.
2818 * Return value: the previous change palette hook (that was replaced).
2820 * Deprecated: This function is deprecated in favor of
2821 * gtk_color_selection_set_change_palette_with_screen_hook(), and does
2822 * not work in multihead environments.
2825 GtkColorSelectionChangePaletteFunc
2826 gtk_color_selection_set_change_palette_hook (GtkColorSelectionChangePaletteFunc func)
2828 GtkColorSelectionChangePaletteFunc old;
2830 old = noscreen_change_palette_hook;
2832 noscreen_change_palette_hook = func;
2838 * gtk_color_selection_set_change_palette_with_screen_hook:
2839 * @func: a function to call when the custom palette needs saving.
2841 * Installs a global function to be called whenever the user tries to
2842 * modify the palette in a color selection. This function should save
2843 * the new palette contents, and update the GtkSettings property
2844 * "gtk-color-palette" so all GtkColorSelection widgets will be modified.
2846 * Return value: the previous change palette hook (that was replaced).
2850 GtkColorSelectionChangePaletteWithScreenFunc
2851 gtk_color_selection_set_change_palette_with_screen_hook (GtkColorSelectionChangePaletteWithScreenFunc func)
2853 GtkColorSelectionChangePaletteWithScreenFunc old;
2855 old = change_palette_hook;
2857 change_palette_hook = func;
2863 make_control_relations (AtkObject *atk_obj,
2868 obj = gtk_widget_get_accessible (widget);
2869 atk_object_add_relationship (atk_obj, ATK_RELATION_CONTROLLED_BY, obj);
2870 atk_object_add_relationship (obj, ATK_RELATION_CONTROLLER_FOR, atk_obj);
2874 make_all_relations (AtkObject *atk_obj,
2875 ColorSelectionPrivate *priv)
2877 make_control_relations (atk_obj, priv->hue_spinbutton);
2878 make_control_relations (atk_obj, priv->sat_spinbutton);
2879 make_control_relations (atk_obj, priv->val_spinbutton);
2880 make_control_relations (atk_obj, priv->red_spinbutton);
2881 make_control_relations (atk_obj, priv->green_spinbutton);
2882 make_control_relations (atk_obj, priv->blue_spinbutton);
2885 #define __GTK_COLOR_SELECTION_C__
2886 #include "gtkaliasdef.c"