1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 2000 Red Hat, Inc.
3 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
22 * Modified by the GTK+ Team and others 1997-2001. See the AUTHORS
23 * file for a list of people on the GTK+ Team. See the ChangeLog
24 * files for a list of changes. These files are distributed with
25 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
29 #include "gdkconfig.h"
32 #include "gdk/gdkkeysyms.h"
33 #include "gtkcolorsel.h"
35 #include "gtkwindow.h"
36 #include "gtkselection.h"
38 #include "gtkdrawingarea.h"
45 #include "gtkmarshalers.h"
47 #include "gtkspinbutton.h"
49 #include "gtkhscale.h"
51 #include "gtkbutton.h"
52 #include "gtkhseparator.h"
53 #include "gtktooltips.h"
54 #include "gtkinvisible.h"
55 #include "gtkmenuitem.h"
57 #include "gtksettings.h"
60 #include "gtkaccessible.h"
61 #include "gtkprivate.h"
67 /* Number of elements in the custom palatte */
68 #define GTK_CUSTOM_PALETTE_WIDTH 10
69 #define GTK_CUSTOM_PALETTE_HEIGHT 2
71 /* Conversion between 0->1 double and and guint16. See
72 * scale_round() below for more general conversions
74 #define SCALE(i) (i / 65535.)
75 #define UNSCALE(d) ((guint16)(d * 65535 + 0.5))
86 PROP_HAS_OPACITY_CONTROL,
102 typedef struct _ColorSelectionPrivate ColorSelectionPrivate;
104 struct _ColorSelectionPrivate
106 guint has_opacity : 1;
107 guint has_palette : 1;
109 guint default_set : 1;
110 guint default_alpha_set : 1;
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;
145 /* Connection to settings */
146 gulong settings_connection;
150 static void gtk_color_selection_init (GtkColorSelection *colorsel);
151 static void gtk_color_selection_class_init (GtkColorSelectionClass *klass);
152 static void gtk_color_selection_destroy (GtkObject *object);
153 static void gtk_color_selection_finalize (GObject *object);
154 static void update_color (GtkColorSelection *colorsel);
155 static void gtk_color_selection_set_property (GObject *object,
159 static void gtk_color_selection_get_property (GObject *object,
164 static void gtk_color_selection_realize (GtkWidget *widget);
165 static void gtk_color_selection_unrealize (GtkWidget *widget);
166 static void gtk_color_selection_show_all (GtkWidget *widget);
167 static gboolean gtk_color_selection_grab_broken (GtkWidget *widget,
168 GdkEventGrabBroken *event);
170 static void gtk_color_selection_set_palette_color (GtkColorSelection *colorsel,
173 static void set_focus_line_attributes (GtkWidget *drawing_area,
176 static void default_noscreen_change_palette_func (const GdkColor *colors,
178 static void default_change_palette_func (GdkScreen *screen,
179 const GdkColor *colors,
181 static void make_control_relations (AtkObject *atk_obj,
183 static void make_all_relations (AtkObject *atk_obj,
184 ColorSelectionPrivate *priv);
186 static gpointer parent_class = NULL;
187 static guint color_selection_signals[LAST_SIGNAL] = { 0 };
189 static const gchar default_colors[] = "black:white:gray50:red:purple:blue:light blue:green:yellow:orange:lavender:brown:goldenrod4:dodger blue:pink:light green:gray10:gray30:gray75:gray90";
191 static GtkColorSelectionChangePaletteFunc noscreen_change_palette_hook = default_noscreen_change_palette_func;
192 static GtkColorSelectionChangePaletteWithScreenFunc change_palette_hook = default_change_palette_func;
194 /* The cursor for the dropper */
195 #define DROPPER_WIDTH 17
196 #define DROPPER_HEIGHT 17
197 #define DROPPER_X_HOT 2
198 #define DROPPER_Y_HOT 16
201 static const guchar dropper_bits[] = {
202 0xff, 0x8f, 0x01, 0xff, 0x77, 0x01, 0xff, 0xfb, 0x00, 0xff, 0xf8, 0x00,
203 0x7f, 0xff, 0x00, 0xff, 0x7e, 0x01, 0xff, 0x9d, 0x01, 0xff, 0xd8, 0x01,
204 0x7f, 0xd4, 0x01, 0x3f, 0xee, 0x01, 0x1f, 0xff, 0x01, 0x8f, 0xff, 0x01,
205 0xc7, 0xff, 0x01, 0xe3, 0xff, 0x01, 0xf3, 0xff, 0x01, 0xfd, 0xff, 0x01,
208 static const guchar dropper_mask[] = {
209 0x00, 0x70, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xfc, 0x01, 0x00, 0xff, 0x01,
210 0x80, 0xff, 0x01, 0x00, 0xff, 0x00, 0x00, 0x7f, 0x00, 0x80, 0x3f, 0x00,
211 0xc0, 0x3f, 0x00, 0xe0, 0x13, 0x00, 0xf0, 0x01, 0x00, 0xf8, 0x00, 0x00,
212 0x7c, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x0d, 0x00, 0x00,
221 #define SAMPLE_WIDTH 64
222 #define SAMPLE_HEIGHT 28
224 static void color_sample_draw_sample (GtkColorSelection *colorsel, int which);
225 static void color_sample_update_samples (GtkColorSelection *colorsel);
228 set_color_internal (GtkColorSelection *colorsel,
231 ColorSelectionPrivate *priv;
234 priv = colorsel->private_data;
235 priv->changing = TRUE;
236 priv->color[COLORSEL_RED] = color[0];
237 priv->color[COLORSEL_GREEN] = color[1];
238 priv->color[COLORSEL_BLUE] = color[2];
239 priv->color[COLORSEL_OPACITY] = color[3];
240 gtk_rgb_to_hsv (priv->color[COLORSEL_RED],
241 priv->color[COLORSEL_GREEN],
242 priv->color[COLORSEL_BLUE],
243 &priv->color[COLORSEL_HUE],
244 &priv->color[COLORSEL_SATURATION],
245 &priv->color[COLORSEL_VALUE]);
246 if (priv->default_set == FALSE)
248 for (i = 0; i < COLORSEL_NUM_CHANNELS; i++)
249 priv->old_color[i] = priv->color[i];
251 priv->default_set = TRUE;
252 priv->default_alpha_set = TRUE;
253 update_color (colorsel);
257 set_color_icon (GdkDragContext *context,
263 pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE,
266 pixel = (((UNSCALE (colors[COLORSEL_RED]) & 0xff00) << 16) |
267 ((UNSCALE (colors[COLORSEL_GREEN]) & 0xff00) << 8) |
268 ((UNSCALE (colors[COLORSEL_BLUE]) & 0xff00)));
270 gdk_pixbuf_fill (pixbuf, pixel);
272 gtk_drag_set_icon_pixbuf (context, pixbuf, -2, -2);
273 g_object_unref (pixbuf);
277 color_sample_drag_begin (GtkWidget *widget,
278 GdkDragContext *context,
281 GtkColorSelection *colorsel = data;
282 ColorSelectionPrivate *priv;
285 priv = colorsel->private_data;
287 if (widget == priv->old_sample)
288 colsrc = priv->old_color;
290 colsrc = priv->color;
292 set_color_icon (context, colsrc);
296 color_sample_drag_end (GtkWidget *widget,
297 GdkDragContext *context,
300 g_object_set_data (G_OBJECT (widget), I_("gtk-color-selection-drag-window"), NULL);
304 color_sample_drop_handle (GtkWidget *widget,
305 GdkDragContext *context,
308 GtkSelectionData *selection_data,
313 GtkColorSelection *colorsel = data;
314 ColorSelectionPrivate *priv;
317 priv = colorsel->private_data;
319 /* This is currently a guint16 array of the format:
326 if (selection_data->length < 0)
329 /* We accept drops with the wrong format, since the KDE color
330 * chooser incorrectly drops application/x-color with format 8.
332 if (selection_data->length != 8)
334 g_warning ("Received invalid color data\n");
338 vals = (guint16 *)selection_data->data;
340 if (widget == priv->cur_sample)
342 color[0] = (gdouble)vals[0] / 0xffff;
343 color[1] = (gdouble)vals[1] / 0xffff;
344 color[2] = (gdouble)vals[2] / 0xffff;
345 color[3] = (gdouble)vals[3] / 0xffff;
347 set_color_internal (colorsel, color);
352 color_sample_drag_handle (GtkWidget *widget,
353 GdkDragContext *context,
354 GtkSelectionData *selection_data,
359 GtkColorSelection *colorsel = data;
360 ColorSelectionPrivate *priv;
364 priv = colorsel->private_data;
366 if (widget == priv->old_sample)
367 colsrc = priv->old_color;
369 colsrc = priv->color;
371 vals[0] = colsrc[COLORSEL_RED] * 0xffff;
372 vals[1] = colsrc[COLORSEL_GREEN] * 0xffff;
373 vals[2] = colsrc[COLORSEL_BLUE] * 0xffff;
374 vals[3] = priv->has_opacity ? colsrc[COLORSEL_OPACITY] * 0xffff : 0xffff;
376 gtk_selection_data_set (selection_data,
377 gdk_atom_intern_static_string ("application/x-color"),
378 16, (guchar *)vals, 8);
381 /* which = 0 means draw old sample, which = 1 means draw new */
383 color_sample_draw_sample (GtkColorSelection *colorsel, int which)
386 gint x, y, wid, heig, goff;
387 ColorSelectionPrivate *priv;
390 g_return_if_fail (colorsel != NULL);
391 priv = colorsel->private_data;
393 g_return_if_fail (priv->sample_area != NULL);
394 if (!GTK_WIDGET_DRAWABLE (priv->sample_area))
399 da = priv->old_sample;
404 da = priv->cur_sample;
405 goff = priv->old_sample->allocation.width % 32;
408 cr = gdk_cairo_create (da->window);
410 wid = da->allocation.width;
411 heig = da->allocation.height;
413 /* Below needs tweaking for non-power-of-two */
414 #define CHECK_SIZE 16
416 if (priv->has_opacity)
418 /* Draw checks in background */
420 cairo_set_source_rgb (cr, 0.5, 0.5, 0.5);
421 cairo_rectangle (cr, 0, 0, wid, heig);
424 cairo_set_source_rgb (cr, 0.75, 0.75, 0.75);
425 for (x = goff & -CHECK_SIZE; x < goff + wid; x += CHECK_SIZE)
426 for (y = 0; y < heig; y += CHECK_SIZE)
427 if ((x / CHECK_SIZE + y / CHECK_SIZE) % 2 == 0)
428 cairo_rectangle (cr, x - goff, y, CHECK_SIZE, CHECK_SIZE);
434 cairo_set_source_rgba (cr,
435 priv->old_color[COLORSEL_RED],
436 priv->old_color[COLORSEL_GREEN],
437 priv->old_color[COLORSEL_BLUE],
439 priv->old_color[COLORSEL_OPACITY] : 1.0);
443 cairo_set_source_rgba (cr,
444 priv->color[COLORSEL_RED],
445 priv->color[COLORSEL_GREEN],
446 priv->color[COLORSEL_BLUE],
448 priv->color[COLORSEL_OPACITY] : 1.0);
451 cairo_rectangle (cr, 0, 0, wid, heig);
459 color_sample_update_samples (GtkColorSelection *colorsel)
461 ColorSelectionPrivate *priv = colorsel->private_data;
462 gtk_widget_queue_draw (priv->old_sample);
463 gtk_widget_queue_draw (priv->cur_sample);
467 color_old_sample_expose (GtkWidget *da,
468 GdkEventExpose *event,
469 GtkColorSelection *colorsel)
471 color_sample_draw_sample (colorsel, 0);
477 color_cur_sample_expose (GtkWidget *da,
478 GdkEventExpose *event,
479 GtkColorSelection *colorsel)
481 color_sample_draw_sample (colorsel, 1);
486 color_sample_setup_dnd (GtkColorSelection *colorsel, GtkWidget *sample)
488 static const GtkTargetEntry targets[] = {
489 { "application/x-color", 0 }
491 ColorSelectionPrivate *priv;
492 priv = colorsel->private_data;
494 gtk_drag_source_set (sample,
495 GDK_BUTTON1_MASK | GDK_BUTTON3_MASK,
497 GDK_ACTION_COPY | GDK_ACTION_MOVE);
499 g_signal_connect (sample,
501 G_CALLBACK (color_sample_drag_begin),
503 if (sample == priv->cur_sample)
506 gtk_drag_dest_set (sample,
507 GTK_DEST_DEFAULT_HIGHLIGHT |
508 GTK_DEST_DEFAULT_MOTION |
509 GTK_DEST_DEFAULT_DROP,
513 g_signal_connect (sample,
515 G_CALLBACK (color_sample_drag_end),
519 g_signal_connect (sample,
521 G_CALLBACK (color_sample_drag_handle),
523 g_signal_connect (sample,
524 "drag_data_received",
525 G_CALLBACK (color_sample_drop_handle),
532 color_sample_new (GtkColorSelection *colorsel)
534 ColorSelectionPrivate *priv;
536 priv = colorsel->private_data;
538 priv->sample_area = gtk_hbox_new (FALSE, 0);
539 priv->old_sample = gtk_drawing_area_new ();
540 priv->cur_sample = gtk_drawing_area_new ();
542 /* We need enter/leave to do tooltips */
543 gtk_widget_add_events (priv->old_sample,
544 GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK);
545 gtk_widget_add_events (priv->cur_sample,
546 GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK);
548 gtk_box_pack_start (GTK_BOX (priv->sample_area), priv->old_sample,
550 gtk_box_pack_start (GTK_BOX (priv->sample_area), priv->cur_sample,
553 g_signal_connect (priv->old_sample, "expose_event",
554 G_CALLBACK (color_old_sample_expose),
556 g_signal_connect (priv->cur_sample, "expose_event",
557 G_CALLBACK (color_cur_sample_expose),
560 color_sample_setup_dnd (colorsel, priv->old_sample);
561 color_sample_setup_dnd (colorsel, priv->cur_sample);
563 gtk_tooltips_set_tip (priv->tooltips,
565 _("The previously-selected color, for comparison to the color you're selecting now. You can drag this color to a palette entry, or select this color as current by dragging it to the other color swatch alongside."), NULL);
568 gtk_tooltips_set_tip (priv->tooltips,
570 _("The color you've chosen. You can drag this color to a palette entry to save it for use in the future."), NULL);
572 gtk_widget_show_all (priv->sample_area);
578 * The palette area code
581 #define CUSTOM_PALETTE_ENTRY_WIDTH 20
582 #define CUSTOM_PALETTE_ENTRY_HEIGHT 20
585 palette_get_color (GtkWidget *drawing_area, gdouble *color)
589 g_return_if_fail (color != NULL);
591 color_val = g_object_get_data (G_OBJECT (drawing_area), "color_val");
592 if (color_val == NULL)
594 /* Default to white for no good reason */
602 color[0] = color_val[0];
603 color[1] = color_val[1];
604 color[2] = color_val[2];
608 #define INTENSITY(r, g, b) ((r) * 0.30 + (g) * 0.59 + (b) * 0.11)
610 palette_paint (GtkWidget *drawing_area,
617 if (drawing_area->window == NULL)
620 cr = gdk_cairo_create (drawing_area->window);
622 gdk_cairo_set_source_color (cr, &drawing_area->style->bg[GTK_STATE_NORMAL]);
623 gdk_cairo_rectangle (cr, area);
626 if (GTK_WIDGET_HAS_FOCUS (drawing_area))
628 set_focus_line_attributes (drawing_area, cr, &focus_width);
629 g_print ("%g %g %g %g\n",
630 focus_width / 2., focus_width / 2.,
631 (double)drawing_area->allocation.width - focus_width,
632 (double)drawing_area->allocation.height - focus_width);
635 focus_width / 2., focus_width / 2.,
636 drawing_area->allocation.width - focus_width,
637 drawing_area->allocation.height - focus_width);
645 set_focus_line_attributes (GtkWidget *drawing_area,
652 gtk_widget_style_get (drawing_area,
653 "focus-line-width", focus_width,
654 "focus-line-pattern", (gchar *)&dash_list,
657 palette_get_color (drawing_area, color);
659 if (INTENSITY (color[0], color[1], color[2]) > 0.5)
660 cairo_set_source_rgb (cr, 0., 0., 0.);
662 cairo_set_source_rgb (cr, 1., 1., 1.);
664 cairo_set_line_width (cr, *focus_width);
668 gint n_dashes = strlen (dash_list);
669 gdouble *dashes = g_new (gdouble, n_dashes);
670 gdouble total_length = 0;
674 for (i = 0; i < n_dashes; i++)
676 dashes[i] = dash_list[i];
677 total_length += dash_list[i];
680 /* The dash offset here aligns the pattern to integer pixels
681 * by starting the dash at the right side of the left border
682 * Negative dash offsets in cairo don't work
683 * (https://bugs.freedesktop.org/show_bug.cgi?id=2729)
685 dash_offset = - *focus_width / 2.;
686 while (dash_offset < 0)
687 dash_offset += total_length;
689 cairo_set_dash (cr, dashes, n_dashes, dash_offset);
697 palette_drag_begin (GtkWidget *widget,
698 GdkDragContext *context,
703 palette_get_color (widget, colors);
704 set_color_icon (context, colors);
708 palette_drag_handle (GtkWidget *widget,
709 GdkDragContext *context,
710 GtkSelectionData *selection_data,
718 palette_get_color (widget, colsrc);
720 vals[0] = colsrc[COLORSEL_RED] * 0xffff;
721 vals[1] = colsrc[COLORSEL_GREEN] * 0xffff;
722 vals[2] = colsrc[COLORSEL_BLUE] * 0xffff;
725 gtk_selection_data_set (selection_data,
726 gdk_atom_intern_static_string ("application/x-color"),
727 16, (guchar *)vals, 8);
731 palette_drag_end (GtkWidget *widget,
732 GdkDragContext *context,
735 g_object_set_data (G_OBJECT (widget), I_("gtk-color-selection-drag-window"), NULL);
739 get_current_colors (GtkColorSelection *colorsel)
741 GtkSettings *settings;
742 GdkColor *colors = NULL;
746 settings = gtk_widget_get_settings (GTK_WIDGET (colorsel));
747 g_object_get (settings,
748 "gtk-color-palette", &palette,
751 if (!gtk_color_selection_palette_from_string (palette, &colors, &n_colors))
753 gtk_color_selection_palette_from_string (default_colors, &colors, &n_colors);
757 /* If there are less colors provided than the number of slots in the
758 * color selection, we fill in the rest from the defaults.
760 if (n_colors < (GTK_CUSTOM_PALETTE_WIDTH * GTK_CUSTOM_PALETTE_HEIGHT))
762 GdkColor *tmp_colors = colors;
763 gint tmp_n_colors = n_colors;
765 gtk_color_selection_palette_from_string (default_colors, &colors, &n_colors);
766 memcpy (colors, tmp_colors, sizeof (GdkColor) * tmp_n_colors);
772 g_assert (n_colors >= GTK_CUSTOM_PALETTE_WIDTH * GTK_CUSTOM_PALETTE_HEIGHT);
778 /* Changes the model color */
780 palette_change_color (GtkWidget *drawing_area,
781 GtkColorSelection *colorsel,
785 ColorSelectionPrivate *priv;
787 GdkColor *current_colors;
790 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
791 g_return_if_fail (GTK_IS_DRAWING_AREA (drawing_area));
793 priv = colorsel->private_data;
795 gdk_color.red = UNSCALE (color[0]);
796 gdk_color.green = UNSCALE (color[1]);
797 gdk_color.blue = UNSCALE (color[2]);
800 y = 0; /* Quiet GCC */
801 while (x < GTK_CUSTOM_PALETTE_WIDTH)
804 while (y < GTK_CUSTOM_PALETTE_HEIGHT)
806 if (priv->custom_palette[x][y] == drawing_area)
817 g_assert (x < GTK_CUSTOM_PALETTE_WIDTH || y < GTK_CUSTOM_PALETTE_HEIGHT);
819 current_colors = get_current_colors (colorsel);
820 current_colors[y * GTK_CUSTOM_PALETTE_WIDTH + x] = gdk_color;
822 screen = gtk_widget_get_screen (GTK_WIDGET (colorsel));
823 if (change_palette_hook != default_change_palette_func)
824 (* change_palette_hook) (screen, current_colors,
825 GTK_CUSTOM_PALETTE_WIDTH * GTK_CUSTOM_PALETTE_HEIGHT);
826 else if (noscreen_change_palette_hook != default_noscreen_change_palette_func)
828 if (screen != gdk_screen_get_default ())
829 g_warning ("gtk_color_selection_set_change_palette_hook used by widget is not on the default screen.");
830 (* noscreen_change_palette_hook) (current_colors,
831 GTK_CUSTOM_PALETTE_WIDTH * GTK_CUSTOM_PALETTE_HEIGHT);
834 (* change_palette_hook) (screen, current_colors,
835 GTK_CUSTOM_PALETTE_WIDTH * GTK_CUSTOM_PALETTE_HEIGHT);
837 g_free (current_colors);
840 /* Changes the view color */
842 palette_set_color (GtkWidget *drawing_area,
843 GtkColorSelection *colorsel,
846 gdouble *new_color = g_new (double, 4);
849 gdk_color.red = UNSCALE (color[0]);
850 gdk_color.green = UNSCALE (color[1]);
851 gdk_color.blue = UNSCALE (color[2]);
853 gtk_widget_modify_bg (drawing_area, GTK_STATE_NORMAL, &gdk_color);
855 if (GPOINTER_TO_INT (g_object_get_data (G_OBJECT (drawing_area), "color_set")) == 0)
857 static const GtkTargetEntry targets[] = {
858 { "application/x-color", 0 }
860 gtk_drag_source_set (drawing_area,
861 GDK_BUTTON1_MASK | GDK_BUTTON3_MASK,
863 GDK_ACTION_COPY | GDK_ACTION_MOVE);
865 g_signal_connect (drawing_area,
867 G_CALLBACK (palette_drag_begin),
869 g_signal_connect (drawing_area,
871 G_CALLBACK (palette_drag_handle),
874 g_object_set_data (G_OBJECT (drawing_area), I_("color_set"),
875 GINT_TO_POINTER (1));
878 new_color[0] = color[0];
879 new_color[1] = color[1];
880 new_color[2] = color[2];
883 g_object_set_data_full (G_OBJECT (drawing_area), I_("color_val"), new_color, (GDestroyNotify)g_free);
887 palette_expose (GtkWidget *drawing_area,
888 GdkEventExpose *event,
891 if (drawing_area->window == NULL)
894 palette_paint (drawing_area, &(event->area), data);
900 popup_position_func (GtkMenu *menu,
911 widget = GTK_WIDGET (user_data);
913 g_return_if_fail (GTK_WIDGET_REALIZED (widget));
915 gdk_window_get_origin (widget->window, &root_x, &root_y);
917 gtk_widget_size_request (GTK_WIDGET (menu), &req);
919 /* Put corner of menu centered on color cell */
920 *x = root_x + widget->allocation.width / 2;
921 *y = root_y + widget->allocation.height / 2;
924 screen = gtk_widget_get_screen (widget);
925 *x = CLAMP (*x, 0, MAX (0, gdk_screen_get_width (screen) - req.width));
926 *y = CLAMP (*y, 0, MAX (0, gdk_screen_get_height (screen) - req.height));
930 save_color_selected (GtkWidget *menuitem,
933 GtkColorSelection *colorsel;
934 GtkWidget *drawing_area;
935 ColorSelectionPrivate *priv;
937 drawing_area = GTK_WIDGET (data);
939 colorsel = GTK_COLOR_SELECTION (g_object_get_data (G_OBJECT (drawing_area),
942 priv = colorsel->private_data;
944 palette_change_color (drawing_area, colorsel, priv->color);
948 do_popup (GtkColorSelection *colorsel,
949 GtkWidget *drawing_area,
955 g_object_set_data (G_OBJECT (drawing_area),
959 menu = gtk_menu_new ();
961 mi = gtk_menu_item_new_with_mnemonic (_("_Save color here"));
963 g_signal_connect (mi, "activate",
964 G_CALLBACK (save_color_selected),
967 gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
969 gtk_widget_show_all (mi);
971 gtk_menu_popup (GTK_MENU (menu), NULL, NULL,
972 popup_position_func, drawing_area,
978 palette_enter (GtkWidget *drawing_area,
979 GdkEventCrossing *event,
982 g_object_set_data (G_OBJECT (drawing_area),
983 I_("gtk-colorsel-have-pointer"),
984 GUINT_TO_POINTER (TRUE));
990 palette_leave (GtkWidget *drawing_area,
991 GdkEventCrossing *event,
994 g_object_set_data (G_OBJECT (drawing_area),
995 I_("gtk-colorsel-have-pointer"),
1002 palette_press (GtkWidget *drawing_area,
1003 GdkEventButton *event,
1006 GtkColorSelection *colorsel = GTK_COLOR_SELECTION (data);
1008 gtk_widget_grab_focus (drawing_area);
1010 if (event->button == 3 &&
1011 event->type == GDK_BUTTON_PRESS)
1013 do_popup (colorsel, drawing_area, event->time);
1021 palette_release (GtkWidget *drawing_area,
1022 GdkEventButton *event,
1025 GtkColorSelection *colorsel = GTK_COLOR_SELECTION (data);
1027 gtk_widget_grab_focus (drawing_area);
1029 if (event->button == 1 &&
1030 g_object_get_data (G_OBJECT (drawing_area),
1031 "gtk-colorsel-have-pointer") != NULL)
1033 if (GPOINTER_TO_INT (g_object_get_data (G_OBJECT (drawing_area), "color_set")) != 0)
1036 palette_get_color (drawing_area, color);
1037 set_color_internal (colorsel, color);
1045 palette_drop_handle (GtkWidget *widget,
1046 GdkDragContext *context,
1049 GtkSelectionData *selection_data,
1054 GtkColorSelection *colorsel = GTK_COLOR_SELECTION (data);
1058 if (selection_data->length < 0)
1061 /* We accept drops with the wrong format, since the KDE color
1062 * chooser incorrectly drops application/x-color with format 8.
1064 if (selection_data->length != 8)
1066 g_warning ("Received invalid color data\n");
1070 vals = (guint16 *)selection_data->data;
1072 color[0] = (gdouble)vals[0] / 0xffff;
1073 color[1] = (gdouble)vals[1] / 0xffff;
1074 color[2] = (gdouble)vals[2] / 0xffff;
1075 color[3] = (gdouble)vals[3] / 0xffff;
1076 palette_change_color (widget, colorsel, color);
1077 set_color_internal (colorsel, color);
1081 palette_activate (GtkWidget *widget,
1085 /* should have a drawing area subclass with an activate signal */
1086 if ((event->keyval == GDK_space) ||
1087 (event->keyval == GDK_Return) ||
1088 (event->keyval == GDK_KP_Enter) ||
1089 (event->keyval == GDK_KP_Space))
1091 if (GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget), "color_set")) != 0)
1094 palette_get_color (widget, color);
1095 set_color_internal (GTK_COLOR_SELECTION (data), color);
1104 palette_popup (GtkWidget *widget,
1107 GtkColorSelection *colorsel = GTK_COLOR_SELECTION (data);
1109 do_popup (colorsel, widget, GDK_CURRENT_TIME);
1115 palette_new (GtkColorSelection *colorsel)
1118 ColorSelectionPrivate *priv;
1120 static const GtkTargetEntry targets[] = {
1121 { "application/x-color", 0 }
1124 priv = colorsel->private_data;
1126 retval = gtk_drawing_area_new ();
1128 GTK_WIDGET_SET_FLAGS (retval, GTK_CAN_FOCUS);
1130 g_object_set_data (G_OBJECT (retval), I_("color_set"), GINT_TO_POINTER (0));
1131 gtk_widget_set_events (retval, GDK_BUTTON_PRESS_MASK
1132 | GDK_BUTTON_RELEASE_MASK
1134 | GDK_ENTER_NOTIFY_MASK
1135 | GDK_LEAVE_NOTIFY_MASK);
1137 g_signal_connect (retval, "expose_event",
1138 G_CALLBACK (palette_expose), colorsel);
1139 g_signal_connect (retval, "button_press_event",
1140 G_CALLBACK (palette_press), colorsel);
1141 g_signal_connect (retval, "button_release_event",
1142 G_CALLBACK (palette_release), colorsel);
1143 g_signal_connect (retval, "enter_notify_event",
1144 G_CALLBACK (palette_enter), colorsel);
1145 g_signal_connect (retval, "leave_notify_event",
1146 G_CALLBACK (palette_leave), colorsel);
1147 g_signal_connect (retval, "key_press_event",
1148 G_CALLBACK (palette_activate), colorsel);
1149 g_signal_connect (retval, "popup_menu",
1150 G_CALLBACK (palette_popup), colorsel);
1152 gtk_drag_dest_set (retval,
1153 GTK_DEST_DEFAULT_HIGHLIGHT |
1154 GTK_DEST_DEFAULT_MOTION |
1155 GTK_DEST_DEFAULT_DROP,
1159 g_signal_connect (retval, "drag_end",
1160 G_CALLBACK (palette_drag_end), NULL);
1161 g_signal_connect (retval, "drag_data_received",
1162 G_CALLBACK (palette_drop_handle), colorsel);
1164 gtk_tooltips_set_tip (priv->tooltips,
1166 _("Click this palette entry to make it the current color. To change this entry, drag a color swatch here or right-click it and select \"Save color here.\""),
1174 * The actual GtkColorSelection widget
1179 make_picker_cursor (GdkScreen *screen)
1183 cursor = gdk_cursor_new_from_name (gdk_screen_get_display (screen),
1188 GdkColor bg = { 0, 0xffff, 0xffff, 0xffff };
1189 GdkColor fg = { 0, 0x0000, 0x0000, 0x0000 };
1191 GdkPixmap *pixmap, *mask;
1193 window = gdk_screen_get_root_window (screen);
1196 gdk_bitmap_create_from_data (window, (gchar *) dropper_bits,
1197 DROPPER_WIDTH, DROPPER_HEIGHT);
1200 gdk_bitmap_create_from_data (window, (gchar *) dropper_mask,
1201 DROPPER_WIDTH, DROPPER_HEIGHT);
1203 cursor = gdk_cursor_new_from_pixmap (pixmap, mask, &fg, &bg,
1204 DROPPER_X_HOT, DROPPER_Y_HOT);
1206 g_object_unref (pixmap);
1207 g_object_unref (mask);
1214 grab_color_at_mouse (GdkScreen *screen,
1221 GtkColorSelection *colorsel = data;
1222 ColorSelectionPrivate *priv;
1224 GdkColormap *colormap = gdk_screen_get_system_colormap (screen);
1225 GdkWindow *root_window = gdk_screen_get_root_window (screen);
1227 priv = colorsel->private_data;
1229 image = gdk_drawable_get_image (root_window, x_root, y_root, 1, 1);
1230 pixel = gdk_image_get_pixel (image, 0, 0);
1231 g_object_unref (image);
1233 gdk_colormap_query_color (colormap, pixel, &color);
1235 priv->color[COLORSEL_RED] = SCALE (color.red);
1236 priv->color[COLORSEL_GREEN] = SCALE (color.green);
1237 priv->color[COLORSEL_BLUE] = SCALE (color.blue);
1239 gtk_rgb_to_hsv (priv->color[COLORSEL_RED],
1240 priv->color[COLORSEL_GREEN],
1241 priv->color[COLORSEL_BLUE],
1242 &priv->color[COLORSEL_HUE],
1243 &priv->color[COLORSEL_SATURATION],
1244 &priv->color[COLORSEL_VALUE]);
1246 update_color (colorsel);
1250 shutdown_eyedropper (GtkWidget *widget)
1252 GtkColorSelection *colorsel;
1253 ColorSelectionPrivate *priv;
1254 GdkDisplay *display = gtk_widget_get_display (widget);
1256 colorsel = GTK_COLOR_SELECTION (widget);
1257 priv = colorsel->private_data;
1261 gdk_display_keyboard_ungrab (display, priv->grab_time);
1262 gdk_display_pointer_ungrab (display, priv->grab_time);
1263 gtk_grab_remove (priv->dropper_grab_widget);
1265 priv->has_grab = FALSE;
1270 gtk_color_selection_grab_broken (GtkWidget *widget,
1271 GdkEventGrabBroken *event)
1273 shutdown_eyedropper (widget);
1279 mouse_motion (GtkWidget *invisible,
1280 GdkEventMotion *event,
1283 grab_color_at_mouse (gdk_event_get_screen ((GdkEvent *)event),
1284 event->x_root, event->y_root, data);
1288 mouse_release (GtkWidget *invisible,
1289 GdkEventButton *event,
1292 GtkColorSelection *colorsel = data;
1293 ColorSelectionPrivate *priv;
1294 priv = colorsel->private_data;
1296 if (event->button != 1)
1299 grab_color_at_mouse (gdk_event_get_screen ((GdkEvent *)event),
1300 event->x_root, event->y_root, data);
1302 shutdown_eyedropper (GTK_WIDGET (data));
1304 g_signal_handlers_disconnect_by_func (invisible,
1307 g_signal_handlers_disconnect_by_func (invisible,
1314 /* Helper Functions */
1316 static gboolean mouse_press (GtkWidget *invisible,
1317 GdkEventButton *event,
1323 key_press (GtkWidget *invisible,
1327 GdkDisplay *display = gtk_widget_get_display (invisible);
1328 GdkScreen *screen = gdk_event_get_screen ((GdkEvent *)event);
1329 guint state = event->state & gtk_accelerator_get_default_mod_mask ();
1333 gdk_display_get_pointer (display, NULL, &x, &y, NULL);
1338 switch (event->keyval)
1344 grab_color_at_mouse (screen, x, y, data);
1348 shutdown_eyedropper (data);
1350 g_signal_handlers_disconnect_by_func (invisible,
1353 g_signal_handlers_disconnect_by_func (invisible,
1359 #if defined GDK_WINDOWING_X11 || defined GDK_WINDOWING_WIN32
1362 dy = state == GDK_MOD1_MASK ? -BIG_STEP : -1;
1367 dy = state == GDK_MOD1_MASK ? BIG_STEP : 1;
1372 dx = state == GDK_MOD1_MASK ? -BIG_STEP : -1;
1377 dx = state == GDK_MOD1_MASK ? BIG_STEP : 1;
1385 gdk_display_warp_pointer (display, screen, x + dx, y + dy);
1392 mouse_press (GtkWidget *invisible,
1393 GdkEventButton *event,
1396 GtkColorSelection *colorsel = data;
1397 ColorSelectionPrivate *priv;
1398 priv = colorsel->private_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 guint32 time = gtk_get_current_event_time ();
1432 if (priv->dropper_grab_widget == NULL)
1434 priv->dropper_grab_widget = gtk_invisible_new_for_screen (screen);
1436 gtk_widget_add_events (priv->dropper_grab_widget,
1437 GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_PRESS_MASK | GDK_POINTER_MOTION_MASK);
1439 gtk_widget_show (priv->dropper_grab_widget);
1441 gdk_window_set_user_data (priv->dropper_grab_widget->window, colorsel);
1442 gdk_window_reparent (priv->dropper_grab_widget->window,
1443 GTK_WIDGET (colorsel)->window, 0, 0);
1446 if (gdk_keyboard_grab (priv->dropper_grab_widget->window,
1447 FALSE, time) != GDK_GRAB_SUCCESS)
1450 picker_cursor = make_picker_cursor (screen);
1451 grab_status = gdk_pointer_grab (priv->dropper_grab_widget->window,
1453 GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_PRESS_MASK | GDK_POINTER_MOTION_MASK,
1457 gdk_cursor_unref (picker_cursor);
1459 if (grab_status != GDK_GRAB_SUCCESS)
1461 gdk_display_keyboard_ungrab (gtk_widget_get_display (button), time);
1465 gtk_grab_add (priv->dropper_grab_widget);
1466 priv->grab_time = time;
1467 priv->has_grab = TRUE;
1469 g_signal_connect (priv->dropper_grab_widget, "button_press_event",
1470 G_CALLBACK (mouse_press), colorsel);
1471 g_signal_connect (priv->dropper_grab_widget, "key_press_event",
1472 G_CALLBACK (key_press), colorsel);
1476 hex_changed (GtkWidget *hex_entry,
1479 GtkColorSelection *colorsel;
1480 ColorSelectionPrivate *priv;
1484 colorsel = GTK_COLOR_SELECTION (data);
1485 priv = colorsel->private_data;
1490 text = gtk_editable_get_chars (GTK_EDITABLE (priv->hex_entry), 0, -1);
1491 if (gdk_color_parse (text, &color))
1493 priv->color[COLORSEL_RED] = CLAMP (color.red/65535.0, 0.0, 1.0);
1494 priv->color[COLORSEL_GREEN] = CLAMP (color.green/65535.0, 0.0, 1.0);
1495 priv->color[COLORSEL_BLUE] = CLAMP (color.blue/65535.0, 0.0, 1.0);
1496 gtk_rgb_to_hsv (priv->color[COLORSEL_RED],
1497 priv->color[COLORSEL_GREEN],
1498 priv->color[COLORSEL_BLUE],
1499 &priv->color[COLORSEL_HUE],
1500 &priv->color[COLORSEL_SATURATION],
1501 &priv->color[COLORSEL_VALUE]);
1502 update_color (colorsel);
1508 hex_focus_out (GtkWidget *hex_entry,
1509 GdkEventFocus *event,
1512 hex_changed (hex_entry, data);
1518 hsv_changed (GtkWidget *hsv,
1521 GtkColorSelection *colorsel;
1522 ColorSelectionPrivate *priv;
1524 colorsel = GTK_COLOR_SELECTION (data);
1525 priv = colorsel->private_data;
1530 gtk_hsv_get_color (GTK_HSV (hsv),
1531 &priv->color[COLORSEL_HUE],
1532 &priv->color[COLORSEL_SATURATION],
1533 &priv->color[COLORSEL_VALUE]);
1534 gtk_hsv_to_rgb (priv->color[COLORSEL_HUE],
1535 priv->color[COLORSEL_SATURATION],
1536 priv->color[COLORSEL_VALUE],
1537 &priv->color[COLORSEL_RED],
1538 &priv->color[COLORSEL_GREEN],
1539 &priv->color[COLORSEL_BLUE]);
1540 update_color (colorsel);
1544 adjustment_changed (GtkAdjustment *adjustment,
1547 GtkColorSelection *colorsel;
1548 ColorSelectionPrivate *priv;
1550 colorsel = GTK_COLOR_SELECTION (g_object_get_data (G_OBJECT (adjustment), "COLORSEL"));
1551 priv = colorsel->private_data;
1556 switch (GPOINTER_TO_INT (data))
1558 case COLORSEL_SATURATION:
1559 case COLORSEL_VALUE:
1560 priv->color[GPOINTER_TO_INT (data)] = adjustment->value / 100;
1561 gtk_hsv_to_rgb (priv->color[COLORSEL_HUE],
1562 priv->color[COLORSEL_SATURATION],
1563 priv->color[COLORSEL_VALUE],
1564 &priv->color[COLORSEL_RED],
1565 &priv->color[COLORSEL_GREEN],
1566 &priv->color[COLORSEL_BLUE]);
1569 priv->color[GPOINTER_TO_INT (data)] = adjustment->value / 360;
1570 gtk_hsv_to_rgb (priv->color[COLORSEL_HUE],
1571 priv->color[COLORSEL_SATURATION],
1572 priv->color[COLORSEL_VALUE],
1573 &priv->color[COLORSEL_RED],
1574 &priv->color[COLORSEL_GREEN],
1575 &priv->color[COLORSEL_BLUE]);
1578 case COLORSEL_GREEN:
1580 priv->color[GPOINTER_TO_INT (data)] = adjustment->value / 255;
1582 gtk_rgb_to_hsv (priv->color[COLORSEL_RED],
1583 priv->color[COLORSEL_GREEN],
1584 priv->color[COLORSEL_BLUE],
1585 &priv->color[COLORSEL_HUE],
1586 &priv->color[COLORSEL_SATURATION],
1587 &priv->color[COLORSEL_VALUE]);
1590 priv->color[GPOINTER_TO_INT (data)] = adjustment->value / 255;
1593 update_color (colorsel);
1597 opacity_entry_changed (GtkWidget *opacity_entry,
1600 GtkColorSelection *colorsel;
1601 ColorSelectionPrivate *priv;
1605 colorsel = GTK_COLOR_SELECTION (data);
1606 priv = colorsel->private_data;
1611 text = gtk_editable_get_chars (GTK_EDITABLE (priv->opacity_entry), 0, -1);
1612 adj = gtk_range_get_adjustment (GTK_RANGE (priv->opacity_slider));
1613 gtk_adjustment_set_value (adj, g_strtod (text, NULL));
1615 update_color (colorsel);
1621 make_label_spinbutton (GtkColorSelection *colorsel,
1622 GtkWidget **spinbutton,
1628 const gchar *tooltip)
1631 GtkAdjustment *adjust;
1632 ColorSelectionPrivate *priv = colorsel->private_data;
1634 if (channel_type == COLORSEL_HUE)
1636 adjust = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 360.0, 1.0, 1.0, 1.0));
1638 else if (channel_type == COLORSEL_SATURATION ||
1639 channel_type == COLORSEL_VALUE)
1641 adjust = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 100.0, 1.0, 1.0, 1.0));
1645 adjust = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 255.0, 1.0, 1.0, 1.0));
1647 g_object_set_data (G_OBJECT (adjust), I_("COLORSEL"), colorsel);
1648 *spinbutton = gtk_spin_button_new (adjust, 10.0, 0);
1650 gtk_tooltips_set_tip (priv->tooltips, *spinbutton, tooltip, NULL);
1652 g_signal_connect (adjust, "value_changed",
1653 G_CALLBACK (adjustment_changed),
1654 GINT_TO_POINTER (channel_type));
1655 label = gtk_label_new_with_mnemonic (text);
1656 gtk_label_set_mnemonic_widget (GTK_LABEL (label), *spinbutton);
1658 gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5);
1659 gtk_table_attach_defaults (GTK_TABLE (table), label, i, i+1, j, j+1);
1660 gtk_table_attach_defaults (GTK_TABLE (table), *spinbutton, i+1, i+2, j, j+1);
1664 make_palette_frame (GtkColorSelection *colorsel,
1670 ColorSelectionPrivate *priv;
1672 priv = colorsel->private_data;
1673 frame = gtk_frame_new (NULL);
1674 gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
1675 priv->custom_palette[i][j] = palette_new (colorsel);
1676 gtk_widget_set_size_request (priv->custom_palette[i][j], CUSTOM_PALETTE_ENTRY_WIDTH, CUSTOM_PALETTE_ENTRY_HEIGHT);
1677 gtk_container_add (GTK_CONTAINER (frame), priv->custom_palette[i][j]);
1678 gtk_table_attach_defaults (GTK_TABLE (table), frame, i, i+1, j, j+1);
1681 /* Set the palette entry [x][y] to be the currently selected one. */
1683 set_selected_palette (GtkColorSelection *colorsel, int x, int y)
1685 ColorSelectionPrivate *priv = colorsel->private_data;
1687 gtk_widget_grab_focus (priv->custom_palette[x][y]);
1691 scale_round (double val, double factor)
1693 val = floor (val * factor + 0.5);
1695 val = MIN (val, factor);
1700 update_color (GtkColorSelection *colorsel)
1702 ColorSelectionPrivate *priv = colorsel->private_data;
1704 gchar opacity_text[32];
1707 priv->changing = TRUE;
1708 color_sample_update_samples (colorsel);
1710 gtk_hsv_set_color (GTK_HSV (priv->triangle_colorsel),
1711 priv->color[COLORSEL_HUE],
1712 priv->color[COLORSEL_SATURATION],
1713 priv->color[COLORSEL_VALUE]);
1714 gtk_adjustment_set_value (gtk_spin_button_get_adjustment
1715 (GTK_SPIN_BUTTON (priv->hue_spinbutton)),
1716 scale_round (priv->color[COLORSEL_HUE], 360));
1717 gtk_adjustment_set_value (gtk_spin_button_get_adjustment
1718 (GTK_SPIN_BUTTON (priv->sat_spinbutton)),
1719 scale_round (priv->color[COLORSEL_SATURATION], 100));
1720 gtk_adjustment_set_value (gtk_spin_button_get_adjustment
1721 (GTK_SPIN_BUTTON (priv->val_spinbutton)),
1722 scale_round (priv->color[COLORSEL_VALUE], 100));
1723 gtk_adjustment_set_value (gtk_spin_button_get_adjustment
1724 (GTK_SPIN_BUTTON (priv->red_spinbutton)),
1725 scale_round (priv->color[COLORSEL_RED], 255));
1726 gtk_adjustment_set_value (gtk_spin_button_get_adjustment
1727 (GTK_SPIN_BUTTON (priv->green_spinbutton)),
1728 scale_round (priv->color[COLORSEL_GREEN], 255));
1729 gtk_adjustment_set_value (gtk_spin_button_get_adjustment
1730 (GTK_SPIN_BUTTON (priv->blue_spinbutton)),
1731 scale_round (priv->color[COLORSEL_BLUE], 255));
1732 gtk_adjustment_set_value (gtk_range_get_adjustment
1733 (GTK_RANGE (priv->opacity_slider)),
1734 scale_round (priv->color[COLORSEL_OPACITY], 255));
1736 g_snprintf (opacity_text, 32, "%.0f", scale_round (priv->color[COLORSEL_OPACITY], 255));
1737 gtk_entry_set_text (GTK_ENTRY (priv->opacity_entry), opacity_text);
1739 g_snprintf (entryval, 11, "#%2X%2X%2X",
1740 (guint) (scale_round (priv->color[COLORSEL_RED], 255)),
1741 (guint) (scale_round (priv->color[COLORSEL_GREEN], 255)),
1742 (guint) (scale_round (priv->color[COLORSEL_BLUE], 255)));
1744 for (ptr = entryval; *ptr; ptr++)
1747 gtk_entry_set_text (GTK_ENTRY (priv->hex_entry), entryval);
1748 priv->changing = FALSE;
1750 g_object_ref (colorsel);
1752 g_signal_emit (colorsel, color_selection_signals[COLOR_CHANGED], 0);
1754 g_object_freeze_notify (G_OBJECT (colorsel));
1755 g_object_notify (G_OBJECT (colorsel), "current-color");
1756 g_object_notify (G_OBJECT (colorsel), "current-alpha");
1757 g_object_thaw_notify (G_OBJECT (colorsel));
1759 g_object_unref (colorsel);
1763 update_palette (GtkColorSelection *colorsel)
1765 GdkColor *current_colors;
1768 current_colors = get_current_colors (colorsel);
1770 for (i = 0; i < GTK_CUSTOM_PALETTE_HEIGHT; i++)
1772 for (j = 0; j < GTK_CUSTOM_PALETTE_WIDTH; j++)
1776 index = i * GTK_CUSTOM_PALETTE_WIDTH + j;
1778 gtk_color_selection_set_palette_color (colorsel,
1780 ¤t_colors[index]);
1784 g_free (current_colors);
1788 palette_change_notify_instance (GObject *object,
1792 update_palette (GTK_COLOR_SELECTION (data));
1796 default_noscreen_change_palette_func (const GdkColor *colors,
1799 default_change_palette_func (gdk_screen_get_default (), colors, n_colors);
1803 default_change_palette_func (GdkScreen *screen,
1804 const GdkColor *colors,
1809 str = gtk_color_selection_palette_to_string (colors, n_colors);
1811 gtk_settings_set_string_property (gtk_settings_get_for_screen (screen),
1812 "gtk-color-palette",
1814 "gtk_color_selection_palette_to_string");
1820 gtk_color_selection_get_type (void)
1822 static GType color_selection_type = 0;
1824 if (!color_selection_type)
1826 static const GTypeInfo color_selection_info =
1828 sizeof (GtkColorSelectionClass),
1829 NULL, /* base_init */
1830 NULL, /* base_finalize */
1831 (GClassInitFunc) gtk_color_selection_class_init,
1832 NULL, /* class_finalize */
1833 NULL, /* class_data */
1834 sizeof (GtkColorSelection),
1835 0, /* n_preallocs */
1836 (GInstanceInitFunc) gtk_color_selection_init,
1839 color_selection_type =
1840 g_type_register_static (GTK_TYPE_VBOX, I_("GtkColorSelection"),
1841 &color_selection_info, 0);
1844 return color_selection_type;
1848 gtk_color_selection_class_init (GtkColorSelectionClass *klass)
1850 GObjectClass *gobject_class;
1851 GtkObjectClass *object_class;
1852 GtkWidgetClass *widget_class;
1854 gobject_class = G_OBJECT_CLASS (klass);
1855 object_class = GTK_OBJECT_CLASS (klass);
1856 widget_class = GTK_WIDGET_CLASS (klass);
1858 parent_class = g_type_class_peek_parent (klass);
1860 object_class->destroy = gtk_color_selection_destroy;
1861 gobject_class->finalize = gtk_color_selection_finalize;
1863 gobject_class->set_property = gtk_color_selection_set_property;
1864 gobject_class->get_property = gtk_color_selection_get_property;
1866 widget_class->realize = gtk_color_selection_realize;
1867 widget_class->unrealize = gtk_color_selection_unrealize;
1868 widget_class->show_all = gtk_color_selection_show_all;
1869 widget_class->grab_broken_event = gtk_color_selection_grab_broken;
1871 g_object_class_install_property (gobject_class,
1872 PROP_HAS_OPACITY_CONTROL,
1873 g_param_spec_boolean ("has-opacity-control",
1874 P_("Has Opacity Control"),
1875 P_("Whether the color selector should allow setting opacity"),
1877 GTK_PARAM_READWRITE));
1878 g_object_class_install_property (gobject_class,
1880 g_param_spec_boolean ("has-palette",
1882 P_("Whether a palette should be used"),
1884 GTK_PARAM_READWRITE));
1885 g_object_class_install_property (gobject_class,
1887 g_param_spec_boxed ("current-color",
1888 P_("Current Color"),
1889 P_("The current color"),
1891 GTK_PARAM_READWRITE));
1892 g_object_class_install_property (gobject_class,
1894 g_param_spec_uint ("current-alpha",
1895 P_("Current Alpha"),
1896 P_("The current opacity value (0 fully transparent, 65535 fully opaque)"),
1898 GTK_PARAM_READWRITE));
1900 color_selection_signals[COLOR_CHANGED] =
1901 g_signal_new (I_("color_changed"),
1902 G_OBJECT_CLASS_TYPE (object_class),
1904 G_STRUCT_OFFSET (GtkColorSelectionClass, color_changed),
1906 _gtk_marshal_VOID__VOID,
1909 gtk_settings_install_property (g_param_spec_string ("gtk-color-palette",
1910 P_("Custom palette"),
1911 P_("Palette to use in the color selector"),
1913 GTK_PARAM_READWRITE));
1916 /* widget functions */
1919 gtk_color_selection_init (GtkColorSelection *colorsel)
1921 GtkWidget *top_hbox;
1922 GtkWidget *top_right_vbox;
1923 GtkWidget *table, *label, *hbox, *frame, *vbox, *button;
1924 GtkAdjustment *adjust;
1925 GtkWidget *picker_image;
1927 ColorSelectionPrivate *priv;
1930 gtk_widget_push_composite_child ();
1932 priv = colorsel->private_data = g_new0 (ColorSelectionPrivate, 1);
1933 priv->changing = FALSE;
1934 priv->default_set = FALSE;
1935 priv->default_alpha_set = FALSE;
1937 priv->tooltips = gtk_tooltips_new ();
1938 g_object_ref (priv->tooltips);
1939 gtk_object_sink (GTK_OBJECT (priv->tooltips));
1941 gtk_box_set_spacing (GTK_BOX (colorsel), 4);
1942 top_hbox = gtk_hbox_new (FALSE, 8);
1943 gtk_box_pack_start (GTK_BOX (colorsel), top_hbox, FALSE, FALSE, 0);
1945 vbox = gtk_vbox_new (FALSE, 4);
1946 priv->triangle_colorsel = gtk_hsv_new ();
1947 g_signal_connect (priv->triangle_colorsel, "changed",
1948 G_CALLBACK (hsv_changed), colorsel);
1949 gtk_hsv_set_metrics (GTK_HSV (priv->triangle_colorsel), 174, 15);
1950 gtk_box_pack_start (GTK_BOX (top_hbox), vbox, FALSE, FALSE, 0);
1951 gtk_box_pack_start (GTK_BOX (vbox), priv->triangle_colorsel, FALSE, FALSE, 0);
1952 gtk_tooltips_set_tip (priv->tooltips, priv->triangle_colorsel,
1953 _("Select the color you want from the outer ring. Select the darkness or lightness of that color using the inner triangle."), NULL);
1955 hbox = gtk_hbox_new (FALSE, 4);
1956 gtk_box_pack_end (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
1958 frame = gtk_frame_new (NULL);
1959 gtk_widget_set_size_request (frame, -1, 30);
1960 gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
1961 color_sample_new (colorsel);
1962 gtk_container_add (GTK_CONTAINER (frame), priv->sample_area);
1963 gtk_box_pack_start (GTK_BOX (hbox), frame, TRUE, TRUE, 0);
1965 button = gtk_button_new ();
1967 gtk_widget_set_events (button, GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK);
1968 g_object_set_data (G_OBJECT (button), I_("COLORSEL"), colorsel);
1969 g_signal_connect (button, "clicked",
1970 G_CALLBACK (get_screen_color), NULL);
1971 picker_image = gtk_image_new_from_stock (GTK_STOCK_COLOR_PICKER, GTK_ICON_SIZE_BUTTON);
1972 gtk_container_add (GTK_CONTAINER (button), picker_image);
1973 gtk_widget_show (GTK_WIDGET (picker_image));
1974 gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
1976 gtk_tooltips_set_tip (priv->tooltips,
1978 _("Click the eyedropper, then click a color anywhere on your screen to select that color."), NULL);
1980 top_right_vbox = gtk_vbox_new (FALSE, 4);
1981 gtk_box_pack_start (GTK_BOX (top_hbox), top_right_vbox, FALSE, FALSE, 0);
1982 table = gtk_table_new (8, 6, FALSE);
1983 gtk_box_pack_start (GTK_BOX (top_right_vbox), table, FALSE, FALSE, 0);
1984 gtk_table_set_row_spacings (GTK_TABLE (table), 4);
1985 gtk_table_set_col_spacings (GTK_TABLE (table), 4);
1987 make_label_spinbutton (colorsel, &priv->hue_spinbutton, _("_Hue:"), table, 0, 0, COLORSEL_HUE,
1988 _("Position on the color wheel."));
1989 gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (priv->hue_spinbutton), TRUE);
1990 make_label_spinbutton (colorsel, &priv->sat_spinbutton, _("_Saturation:"), table, 0, 1, COLORSEL_SATURATION,
1991 _("\"Deepness\" of the color."));
1992 make_label_spinbutton (colorsel, &priv->val_spinbutton, _("_Value:"), table, 0, 2, COLORSEL_VALUE,
1993 _("Brightness of the color."));
1994 make_label_spinbutton (colorsel, &priv->red_spinbutton, _("_Red:"), table, 6, 0, COLORSEL_RED,
1995 _("Amount of red light in the color."));
1996 make_label_spinbutton (colorsel, &priv->green_spinbutton, _("_Green:"), table, 6, 1, COLORSEL_GREEN,
1997 _("Amount of green light in the color."));
1998 make_label_spinbutton (colorsel, &priv->blue_spinbutton, _("_Blue:"), table, 6, 2, COLORSEL_BLUE,
1999 _("Amount of blue light in the color."));
2000 gtk_table_attach_defaults (GTK_TABLE (table), gtk_hseparator_new (), 0, 8, 3, 4);
2002 priv->opacity_label = gtk_label_new_with_mnemonic (_("_Opacity:"));
2003 gtk_misc_set_alignment (GTK_MISC (priv->opacity_label), 1.0, 0.5);
2004 gtk_table_attach_defaults (GTK_TABLE (table), priv->opacity_label, 0, 1, 4, 5);
2005 adjust = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 255.0, 1.0, 1.0, 0.0));
2006 g_object_set_data (G_OBJECT (adjust), I_("COLORSEL"), colorsel);
2007 priv->opacity_slider = gtk_hscale_new (adjust);
2008 gtk_tooltips_set_tip (priv->tooltips,
2009 priv->opacity_slider,
2010 _("Transparency of the color."), NULL);
2011 gtk_label_set_mnemonic_widget (GTK_LABEL (priv->opacity_label),
2012 priv->opacity_slider);
2013 gtk_scale_set_draw_value (GTK_SCALE (priv->opacity_slider), FALSE);
2014 g_signal_connect (adjust, "value_changed",
2015 G_CALLBACK (adjustment_changed),
2016 GINT_TO_POINTER (COLORSEL_OPACITY));
2017 gtk_table_attach_defaults (GTK_TABLE (table), priv->opacity_slider, 1, 7, 4, 5);
2018 priv->opacity_entry = gtk_entry_new ();
2019 gtk_tooltips_set_tip (priv->tooltips,
2020 priv->opacity_entry,
2021 _("Transparency of the color."), NULL);
2022 gtk_widget_set_size_request (priv->opacity_entry, 40, -1);
2024 g_signal_connect (priv->opacity_entry, "activate",
2025 G_CALLBACK (opacity_entry_changed), colorsel);
2026 gtk_table_attach_defaults (GTK_TABLE (table), priv->opacity_entry, 7, 8, 4, 5);
2028 label = gtk_label_new_with_mnemonic (_("Color _Name:"));
2029 gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 5, 6);
2030 gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5);
2031 priv->hex_entry = gtk_entry_new ();
2033 gtk_label_set_mnemonic_widget (GTK_LABEL (label), priv->hex_entry);
2035 g_signal_connect (priv->hex_entry, "activate",
2036 G_CALLBACK (hex_changed), colorsel);
2038 g_signal_connect (priv->hex_entry, "focus_out_event",
2039 G_CALLBACK (hex_focus_out), colorsel);
2041 gtk_tooltips_set_tip (priv->tooltips,
2043 _("You can enter an HTML-style hexadecimal color value, or simply a color name such as 'orange' in this entry."), NULL);
2045 gtk_entry_set_width_chars (GTK_ENTRY (priv->hex_entry), 7);
2046 gtk_table_set_col_spacing (GTK_TABLE (table), 3, 15);
2047 gtk_table_attach_defaults (GTK_TABLE (table), priv->hex_entry, 1, 5, 5, 6);
2049 /* Set up the palette */
2050 table = gtk_table_new (GTK_CUSTOM_PALETTE_HEIGHT, GTK_CUSTOM_PALETTE_WIDTH, TRUE);
2051 gtk_table_set_row_spacings (GTK_TABLE (table), 1);
2052 gtk_table_set_col_spacings (GTK_TABLE (table), 1);
2053 for (i = 0; i < GTK_CUSTOM_PALETTE_WIDTH; i++)
2055 for (j = 0; j < GTK_CUSTOM_PALETTE_HEIGHT; j++)
2057 make_palette_frame (colorsel, table, i, j);
2060 set_selected_palette (colorsel, 0, 0);
2061 priv->palette_frame = gtk_frame_new (NULL);
2062 label = gtk_label_new_with_mnemonic (_("_Palette"));
2063 gtk_frame_set_label_widget (GTK_FRAME (priv->palette_frame), label);
2065 gtk_label_set_mnemonic_widget (GTK_LABEL (label),
2066 priv->custom_palette[0][0]);
2068 gtk_box_pack_end (GTK_BOX (top_right_vbox), priv->palette_frame, FALSE, FALSE, 0);
2069 vbox = gtk_vbox_new (FALSE, 4);
2070 gtk_container_add (GTK_CONTAINER (priv->palette_frame), vbox);
2071 gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0);
2073 gtk_container_set_border_width (GTK_CONTAINER (vbox), 4);
2075 gtk_widget_show_all (top_hbox);
2077 /* hide unused stuff */
2079 if (priv->has_opacity == FALSE)
2081 gtk_widget_hide (priv->opacity_label);
2082 gtk_widget_hide (priv->opacity_slider);
2083 gtk_widget_hide (priv->opacity_entry);
2086 if (priv->has_palette == FALSE)
2088 gtk_widget_hide (priv->palette_frame);
2091 atk_obj = gtk_widget_get_accessible (priv->triangle_colorsel);
2092 if (GTK_IS_ACCESSIBLE (atk_obj))
2094 atk_object_set_name (atk_obj, _("Color Wheel"));
2095 atk_object_set_role (gtk_widget_get_accessible (GTK_WIDGET (colorsel)), ATK_ROLE_COLOR_CHOOSER);
2096 make_all_relations (atk_obj, priv);
2099 gtk_widget_pop_composite_child ();
2103 gtk_color_selection_destroy (GtkObject *object)
2105 GtkColorSelection *cselection = GTK_COLOR_SELECTION (object);
2106 ColorSelectionPrivate *priv = cselection->private_data;
2108 if (priv->dropper_grab_widget)
2110 gtk_widget_destroy (priv->dropper_grab_widget);
2111 priv->dropper_grab_widget = NULL;
2116 g_object_unref (priv->tooltips);
2117 priv->tooltips = NULL;
2120 GTK_OBJECT_CLASS (parent_class)->destroy (object);
2124 gtk_color_selection_finalize (GObject *object)
2126 GtkColorSelection *cselection = GTK_COLOR_SELECTION (object);
2128 if (cselection->private_data)
2130 g_free (cselection->private_data);
2131 cselection->private_data = NULL;
2134 G_OBJECT_CLASS (parent_class)->finalize (object);
2138 gtk_color_selection_realize (GtkWidget *widget)
2140 GtkColorSelection *colorsel = GTK_COLOR_SELECTION (widget);
2141 ColorSelectionPrivate *priv = colorsel->private_data;
2142 GtkSettings *settings = gtk_widget_get_settings (widget);
2144 priv->settings_connection = g_signal_connect (settings,
2145 "notify::gtk-color-palette",
2146 G_CALLBACK (palette_change_notify_instance),
2148 update_palette (colorsel);
2150 GTK_WIDGET_CLASS (parent_class)->realize (widget);
2154 gtk_color_selection_unrealize (GtkWidget *widget)
2156 GtkColorSelection *colorsel = GTK_COLOR_SELECTION (widget);
2157 ColorSelectionPrivate *priv = colorsel->private_data;
2158 GtkSettings *settings = gtk_widget_get_settings (widget);
2160 g_signal_handler_disconnect (settings, priv->settings_connection);
2162 GTK_WIDGET_CLASS (parent_class)->unrealize (widget);
2165 /* We override show-all since we have internal widgets that
2166 * shouldn't be shown when you call show_all(), like the
2167 * palette and opacity sliders.
2170 gtk_color_selection_show_all (GtkWidget *widget)
2172 gtk_widget_show (widget);
2176 * gtk_color_selection_new:
2178 * Creates a new GtkColorSelection.
2180 * Return value: a new #GtkColorSelection
2183 gtk_color_selection_new (void)
2185 GtkColorSelection *colorsel;
2186 ColorSelectionPrivate *priv;
2193 colorsel = g_object_new (GTK_TYPE_COLOR_SELECTION, NULL);
2194 priv = colorsel->private_data;
2195 set_color_internal (colorsel, color);
2196 gtk_color_selection_set_has_opacity_control (colorsel, TRUE);
2198 /* We want to make sure that default_set is FALSE */
2199 /* This way the user can still set it */
2200 priv->default_set = FALSE;
2201 priv->default_alpha_set = FALSE;
2203 return GTK_WIDGET (colorsel);
2208 gtk_color_selection_set_update_policy (GtkColorSelection *colorsel,
2209 GtkUpdateType policy)
2211 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2215 * gtk_color_selection_get_has_opacity_control:
2216 * @colorsel: a #GtkColorSelection.
2218 * Determines whether the colorsel has an opacity control.
2220 * Return value: %TRUE if the @colorsel has an opacity control. %FALSE if it does't.
2223 gtk_color_selection_get_has_opacity_control (GtkColorSelection *colorsel)
2225 ColorSelectionPrivate *priv;
2227 g_return_val_if_fail (GTK_IS_COLOR_SELECTION (colorsel), FALSE);
2229 priv = colorsel->private_data;
2231 return priv->has_opacity;
2235 * gtk_color_selection_set_has_opacity_control:
2236 * @colorsel: a #GtkColorSelection.
2237 * @has_opacity: %TRUE if @colorsel can set the opacity, %FALSE otherwise.
2239 * Sets the @colorsel to use or not use opacity.
2243 gtk_color_selection_set_has_opacity_control (GtkColorSelection *colorsel,
2244 gboolean has_opacity)
2246 ColorSelectionPrivate *priv;
2248 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2250 priv = colorsel->private_data;
2251 has_opacity = has_opacity != FALSE;
2253 if (priv->has_opacity != has_opacity)
2255 priv->has_opacity = has_opacity;
2258 gtk_widget_show (priv->opacity_slider);
2259 gtk_widget_show (priv->opacity_label);
2260 gtk_widget_show (priv->opacity_entry);
2264 gtk_widget_hide (priv->opacity_slider);
2265 gtk_widget_hide (priv->opacity_label);
2266 gtk_widget_hide (priv->opacity_entry);
2268 color_sample_update_samples (colorsel);
2270 g_object_notify (G_OBJECT (colorsel), "has-opacity-control");
2275 * gtk_color_selection_get_has_palette:
2276 * @colorsel: a #GtkColorSelection.
2278 * Determines whether the color selector has a color palette.
2280 * Return value: %TRUE if the selector has a palette. %FALSE if it hasn't.
2283 gtk_color_selection_get_has_palette (GtkColorSelection *colorsel)
2285 ColorSelectionPrivate *priv;
2287 g_return_val_if_fail (GTK_IS_COLOR_SELECTION (colorsel), FALSE);
2289 priv = colorsel->private_data;
2291 return priv->has_palette;
2295 * gtk_color_selection_set_has_palette:
2296 * @colorsel: a #GtkColorSelection.
2297 * @has_palette: %TRUE if palette is to be visible, %FALSE otherwise.
2299 * Shows and hides the palette based upon the value of @has_palette.
2303 gtk_color_selection_set_has_palette (GtkColorSelection *colorsel,
2304 gboolean has_palette)
2306 ColorSelectionPrivate *priv;
2307 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2309 priv = colorsel->private_data;
2310 has_palette = has_palette != FALSE;
2312 if (priv->has_palette != has_palette)
2314 priv->has_palette = has_palette;
2316 gtk_widget_show (priv->palette_frame);
2318 gtk_widget_hide (priv->palette_frame);
2320 g_object_notify (G_OBJECT (colorsel), "has-palette");
2325 * gtk_color_selection_set_current_color:
2326 * @colorsel: a #GtkColorSelection.
2327 * @color: A #GdkColor to set the current color with.
2329 * Sets the current color to be @color. The first time this is called, it will
2330 * also set the original color to be @color too.
2333 gtk_color_selection_set_current_color (GtkColorSelection *colorsel,
2334 const GdkColor *color)
2336 ColorSelectionPrivate *priv;
2338 gboolean previous_changed;
2340 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2341 g_return_if_fail (color != NULL);
2343 priv = colorsel->private_data;
2344 priv->changing = TRUE;
2345 priv->color[COLORSEL_RED] = SCALE (color->red);
2346 priv->color[COLORSEL_GREEN] = SCALE (color->green);
2347 priv->color[COLORSEL_BLUE] = SCALE (color->blue);
2348 gtk_rgb_to_hsv (priv->color[COLORSEL_RED],
2349 priv->color[COLORSEL_GREEN],
2350 priv->color[COLORSEL_BLUE],
2351 &priv->color[COLORSEL_HUE],
2352 &priv->color[COLORSEL_SATURATION],
2353 &priv->color[COLORSEL_VALUE]);
2354 if (priv->default_set == FALSE)
2356 previous_changed = TRUE;
2357 for (i = 0; i < COLORSEL_NUM_CHANNELS; i++)
2358 priv->old_color[i] = priv->color[i];
2360 priv->default_set = TRUE;
2361 update_color (colorsel);
2365 * gtk_color_selection_set_current_alpha:
2366 * @colorsel: a #GtkColorSelection.
2367 * @alpha: an integer between 0 and 65535.
2369 * Sets the current opacity to be @alpha. The first time this is called, it will
2370 * also set the original opacity to be @alpha too.
2373 gtk_color_selection_set_current_alpha (GtkColorSelection *colorsel,
2376 ColorSelectionPrivate *priv;
2379 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2381 priv = colorsel->private_data;
2382 priv->changing = TRUE;
2383 priv->color[COLORSEL_OPACITY] = SCALE (alpha);
2384 if (priv->default_alpha_set == FALSE)
2386 for (i = 0; i < COLORSEL_NUM_CHANNELS; i++)
2387 priv->old_color[i] = priv->color[i];
2389 priv->default_alpha_set = TRUE;
2390 update_color (colorsel);
2394 * gtk_color_selection_set_color:
2395 * @colorsel: a #GtkColorSelection.
2396 * @color: an array of 4 doubles specifying the red, green, blue and opacity
2397 * to set the current color to.
2399 * Sets the current color to be @color. The first time this is called, it will
2400 * also set the original color to be @color too.
2402 * Deprecated: Use gtk_color_selection_set_current_color() instead.
2405 gtk_color_selection_set_color (GtkColorSelection *colorsel,
2408 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2410 set_color_internal (colorsel, color);
2414 * gtk_color_selection_get_current_color:
2415 * @colorsel: a #GtkColorSelection.
2416 * @color: a #GdkColor to fill in with the current color.
2418 * Sets @color to be the current color in the GtkColorSelection widget.
2421 gtk_color_selection_get_current_color (GtkColorSelection *colorsel,
2424 ColorSelectionPrivate *priv;
2426 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2427 g_return_if_fail (color != NULL);
2429 priv = colorsel->private_data;
2430 color->red = UNSCALE (priv->color[COLORSEL_RED]);
2431 color->green = UNSCALE (priv->color[COLORSEL_GREEN]);
2432 color->blue = UNSCALE (priv->color[COLORSEL_BLUE]);
2436 * gtk_color_selection_get_current_alpha:
2437 * @colorsel: a #GtkColorSelection.
2439 * Returns the current alpha value.
2441 * Return value: an integer between 0 and 65535.
2444 gtk_color_selection_get_current_alpha (GtkColorSelection *colorsel)
2446 ColorSelectionPrivate *priv;
2448 g_return_val_if_fail (GTK_IS_COLOR_SELECTION (colorsel), 0);
2450 priv = colorsel->private_data;
2451 return priv->has_opacity ? UNSCALE (priv->color[COLORSEL_OPACITY]) : 65535;
2455 * gtk_color_selection_get_color:
2456 * @colorsel: a #GtkColorSelection.
2457 * @color: an array of 4 #gdouble to fill in with the current color.
2459 * Sets @color to be the current color in the GtkColorSelection widget.
2461 * This function is deprecated, use gtk_color_selection_get_current_color() instead.
2464 gtk_color_selection_get_color (GtkColorSelection *colorsel,
2467 ColorSelectionPrivate *priv;
2469 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2471 priv = colorsel->private_data;
2472 color[0] = priv->color[COLORSEL_RED];
2473 color[1] = priv->color[COLORSEL_GREEN];
2474 color[2] = priv->color[COLORSEL_BLUE];
2475 color[3] = priv->has_opacity ? priv->color[COLORSEL_OPACITY] : 65535;
2479 * gtk_color_selection_set_previous_color:
2480 * @colorsel: a #GtkColorSelection.
2481 * @color: a #GdkColor to set the previous color with.
2483 * Sets the 'previous' color to be @color. This function should be called with
2484 * some hesitations, as it might seem confusing to have that color change.
2485 * Calling gtk_color_selection_set_current_color() will also set this color the first
2486 * time it is called.
2489 gtk_color_selection_set_previous_color (GtkColorSelection *colorsel,
2490 const GdkColor *color)
2492 ColorSelectionPrivate *priv;
2494 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2495 g_return_if_fail (color != NULL);
2497 priv = colorsel->private_data;
2498 priv->changing = TRUE;
2499 priv->old_color[COLORSEL_RED] = SCALE (color->red);
2500 priv->old_color[COLORSEL_GREEN] = SCALE (color->green);
2501 priv->old_color[COLORSEL_BLUE] = SCALE (color->blue);
2502 gtk_rgb_to_hsv (priv->old_color[COLORSEL_RED],
2503 priv->old_color[COLORSEL_GREEN],
2504 priv->old_color[COLORSEL_BLUE],
2505 &priv->old_color[COLORSEL_HUE],
2506 &priv->old_color[COLORSEL_SATURATION],
2507 &priv->old_color[COLORSEL_VALUE]);
2508 color_sample_update_samples (colorsel);
2509 priv->default_set = TRUE;
2510 priv->changing = FALSE;
2514 * gtk_color_selection_set_previous_alpha:
2515 * @colorsel: a #GtkColorSelection.
2516 * @alpha: an integer between 0 and 65535.
2518 * Sets the 'previous' alpha to be @alpha. This function should be called with
2519 * some hesitations, as it might seem confusing to have that alpha change.
2522 gtk_color_selection_set_previous_alpha (GtkColorSelection *colorsel,
2525 ColorSelectionPrivate *priv;
2527 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2529 priv = colorsel->private_data;
2530 priv->changing = TRUE;
2531 priv->old_color[COLORSEL_OPACITY] = SCALE (alpha);
2532 color_sample_update_samples (colorsel);
2533 priv->default_alpha_set = TRUE;
2534 priv->changing = FALSE;
2539 * gtk_color_selection_get_previous_color:
2540 * @colorsel: a #GtkColorSelection.
2541 * @color: a #GdkColor to fill in with the original color value.
2543 * Fills @color in with the original color value.
2546 gtk_color_selection_get_previous_color (GtkColorSelection *colorsel,
2549 ColorSelectionPrivate *priv;
2551 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2552 g_return_if_fail (color != NULL);
2554 priv = colorsel->private_data;
2555 color->red = UNSCALE (priv->old_color[COLORSEL_RED]);
2556 color->green = UNSCALE (priv->old_color[COLORSEL_GREEN]);
2557 color->blue = UNSCALE (priv->old_color[COLORSEL_BLUE]);
2561 * gtk_color_selection_get_previous_alpha:
2562 * @colorsel: a #GtkColorSelection.
2564 * Returns the previous alpha value.
2566 * Return value: an integer between 0 and 65535.
2569 gtk_color_selection_get_previous_alpha (GtkColorSelection *colorsel)
2571 ColorSelectionPrivate *priv;
2573 g_return_val_if_fail (GTK_IS_COLOR_SELECTION (colorsel), 0);
2575 priv = colorsel->private_data;
2576 return priv->has_opacity ? UNSCALE (priv->old_color[COLORSEL_OPACITY]) : 65535;
2580 * gtk_color_selection_set_palette_color:
2581 * @colorsel: a #GtkColorSelection.
2582 * @index: the color index of the palette.
2583 * @color: A #GdkColor to set the palette with.
2585 * Sets the palette located at @index to have @color as its color.
2589 gtk_color_selection_set_palette_color (GtkColorSelection *colorsel,
2593 ColorSelectionPrivate *priv;
2597 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2598 g_return_if_fail (index >= 0 && index < GTK_CUSTOM_PALETTE_WIDTH*GTK_CUSTOM_PALETTE_HEIGHT);
2600 x = index % GTK_CUSTOM_PALETTE_WIDTH;
2601 y = index / GTK_CUSTOM_PALETTE_WIDTH;
2603 priv = colorsel->private_data;
2604 col[0] = SCALE (color->red);
2605 col[1] = SCALE (color->green);
2606 col[2] = SCALE (color->blue);
2608 palette_set_color (priv->custom_palette[x][y], colorsel, col);
2612 * gtk_color_selection_is_adjusting:
2613 * @colorsel: a #GtkColorSelection.
2615 * Gets the current state of the @colorsel.
2617 * Return value: %TRUE if the user is currently dragging a color around, and %FALSE
2618 * if the selection has stopped.
2621 gtk_color_selection_is_adjusting (GtkColorSelection *colorsel)
2623 ColorSelectionPrivate *priv;
2625 g_return_val_if_fail (GTK_IS_COLOR_SELECTION (colorsel), FALSE);
2627 priv = colorsel->private_data;
2629 return (gtk_hsv_is_adjusting (GTK_HSV (priv->triangle_colorsel)));
2633 gtk_color_selection_set_property (GObject *object,
2635 const GValue *value,
2638 GtkColorSelection *colorsel = GTK_COLOR_SELECTION (object);
2642 case PROP_HAS_OPACITY_CONTROL:
2643 gtk_color_selection_set_has_opacity_control (colorsel,
2644 g_value_get_boolean (value));
2646 case PROP_HAS_PALETTE:
2647 gtk_color_selection_set_has_palette (colorsel,
2648 g_value_get_boolean (value));
2650 case PROP_CURRENT_COLOR:
2651 gtk_color_selection_set_current_color (colorsel, g_value_get_boxed (value));
2653 case PROP_CURRENT_ALPHA:
2654 gtk_color_selection_set_current_alpha (colorsel, g_value_get_uint (value));
2657 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
2664 gtk_color_selection_get_property (GObject *object,
2669 GtkColorSelection *colorsel = GTK_COLOR_SELECTION (object);
2674 case PROP_HAS_OPACITY_CONTROL:
2675 g_value_set_boolean (value, gtk_color_selection_get_has_opacity_control (colorsel));
2677 case PROP_HAS_PALETTE:
2678 g_value_set_boolean (value, gtk_color_selection_get_has_palette (colorsel));
2680 case PROP_CURRENT_COLOR:
2681 gtk_color_selection_get_current_color (colorsel, &color);
2682 g_value_set_boxed (value, &color);
2684 case PROP_CURRENT_ALPHA:
2685 g_value_set_uint (value, gtk_color_selection_get_current_alpha (colorsel));
2688 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
2695 * gtk_color_selection_palette_from_string:
2696 * @str: a string encoding a color palette.
2697 * @colors: return location for allocated array of #GdkColor.
2698 * @n_colors: return location for length of array.
2700 * Parses a color palette string; the string is a colon-separated
2701 * list of color names readable by gdk_color_parse().
2703 * Return value: %TRUE if a palette was successfully parsed.
2706 gtk_color_selection_palette_from_string (const gchar *str,
2718 copy = g_strdup (str);
2724 if (*p == ':' || *p == '\0')
2726 gboolean done = TRUE;
2730 goto failed; /* empty entry */
2739 retval = g_renew (GdkColor, retval, count + 1);
2740 if (!gdk_color_parse (start, retval + count))
2781 * gtk_color_selection_palette_to_string:
2782 * @colors: an array of colors.
2783 * @n_colors: length of the array.
2785 * Encodes a palette as a string, useful for persistent storage.
2787 * Return value: allocated string encoding the palette.
2790 gtk_color_selection_palette_to_string (const GdkColor *colors,
2794 gchar **strs = NULL;
2798 return g_strdup ("");
2800 strs = g_new0 (gchar*, n_colors + 1);
2803 while (i < n_colors)
2808 g_strdup_printf ("#%2X%2X%2X",
2809 colors[i].red / 256,
2810 colors[i].green / 256,
2811 colors[i].blue / 256);
2813 for (ptr = strs[i]; *ptr; ptr++)
2820 retval = g_strjoinv (":", strs);
2828 * gtk_color_selection_set_change_palette_hook:
2829 * @func: a function to call when the custom palette needs saving.
2831 * Installs a global function to be called whenever the user tries to
2832 * modify the palette in a color selection. This function should save
2833 * the new palette contents, and update the GtkSettings property
2834 * "gtk-color-palette" so all GtkColorSelection widgets will be modified.
2836 * Return value: the previous change palette hook (that was replaced).
2838 * Deprecated: This function is deprecated in favor of
2839 * gtk_color_selection_set_change_palette_with_screen_hook(), and does
2840 * not work in multihead environments.
2843 GtkColorSelectionChangePaletteFunc
2844 gtk_color_selection_set_change_palette_hook (GtkColorSelectionChangePaletteFunc func)
2846 GtkColorSelectionChangePaletteFunc old;
2848 old = noscreen_change_palette_hook;
2850 noscreen_change_palette_hook = func;
2856 * gtk_color_selection_set_change_palette_with_screen_hook:
2857 * @func: a function to call when the custom palette needs saving.
2859 * Installs a global function to be called whenever the user tries to
2860 * modify the palette in a color selection. This function should save
2861 * the new palette contents, and update the GtkSettings property
2862 * "gtk-color-palette" so all GtkColorSelection widgets will be modified.
2864 * Return value: the previous change palette hook (that was replaced).
2868 GtkColorSelectionChangePaletteWithScreenFunc
2869 gtk_color_selection_set_change_palette_with_screen_hook (GtkColorSelectionChangePaletteWithScreenFunc func)
2871 GtkColorSelectionChangePaletteWithScreenFunc old;
2873 old = change_palette_hook;
2875 change_palette_hook = func;
2881 make_control_relations (AtkObject *atk_obj,
2886 obj = gtk_widget_get_accessible (widget);
2887 atk_object_add_relationship (atk_obj, ATK_RELATION_CONTROLLED_BY, obj);
2888 atk_object_add_relationship (obj, ATK_RELATION_CONTROLLER_FOR, atk_obj);
2892 make_all_relations (AtkObject *atk_obj,
2893 ColorSelectionPrivate *priv)
2895 make_control_relations (atk_obj, priv->hue_spinbutton);
2896 make_control_relations (atk_obj, priv->sat_spinbutton);
2897 make_control_relations (atk_obj, priv->val_spinbutton);
2898 make_control_relations (atk_obj, priv->red_spinbutton);
2899 make_control_relations (atk_obj, priv->green_spinbutton);
2900 make_control_relations (atk_obj, priv->blue_spinbutton);
2903 #define __GTK_COLOR_SELECTION_C__
2904 #include "gtkaliasdef.c"