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/.
28 #include "gdkconfig.h"
31 #include "gdk/gdkkeysyms.h"
32 #include "gtkcolorsel.h"
34 #include "gtkwindow.h"
35 #include "gtkselection.h"
37 #include "gtkdrawingarea.h"
44 #include "gtkmarshalers.h"
46 #include "gtkspinbutton.h"
48 #include "gtkhscale.h"
50 #include "gtkbutton.h"
51 #include "gtkhseparator.h"
52 #include "gtktooltips.h"
53 #include "gtkinvisible.h"
54 #include "gtkmenuitem.h"
56 #include "gtksettings.h"
63 /* Number of elements in the custom palatte */
64 #define GTK_CUSTOM_PALETTE_WIDTH 10
65 #define GTK_CUSTOM_PALETTE_HEIGHT 2
67 /* Conversion between 0->1 double and and guint16. See
68 * scale_round() below for more general conversions
70 #define SCALE(i) (i / 65535.)
71 #define UNSCALE(d) ((guint16)(d * 65535 + 0.5))
82 PROP_HAS_OPACITY_CONTROL,
98 typedef struct _ColorSelectionPrivate ColorSelectionPrivate;
100 struct _ColorSelectionPrivate
102 guint has_opacity : 1;
103 guint has_palette : 1;
105 guint default_set : 1;
106 guint default_alpha_set : 1;
108 gdouble color[COLORSEL_NUM_CHANNELS];
109 gdouble old_color[COLORSEL_NUM_CHANNELS];
111 GtkWidget *triangle_colorsel;
112 GtkWidget *hue_spinbutton;
113 GtkWidget *sat_spinbutton;
114 GtkWidget *val_spinbutton;
115 GtkWidget *red_spinbutton;
116 GtkWidget *green_spinbutton;
117 GtkWidget *blue_spinbutton;
118 GtkWidget *opacity_slider;
119 GtkWidget *opacity_label;
120 GtkWidget *opacity_entry;
121 GtkWidget *palette_frame;
122 GtkWidget *hex_entry;
124 /* The Palette code */
125 GtkWidget *custom_palette [GTK_CUSTOM_PALETTE_WIDTH][GTK_CUSTOM_PALETTE_HEIGHT];
127 /* The color_sample stuff */
128 GtkWidget *sample_area;
129 GtkWidget *old_sample;
130 GtkWidget *cur_sample;
134 GtkTooltips *tooltips;
136 /* Window for grabbing on */
137 GtkWidget *dropper_grab_widget;
139 /* Connection to settings */
140 gulong settings_connection;
144 static void gtk_color_selection_init (GtkColorSelection *colorsel);
145 static void gtk_color_selection_class_init (GtkColorSelectionClass *klass);
146 static void gtk_color_selection_destroy (GtkObject *object);
147 static void gtk_color_selection_finalize (GObject *object);
148 static void update_color (GtkColorSelection *colorsel);
149 static void gtk_color_selection_set_property (GObject *object,
153 static void gtk_color_selection_get_property (GObject *object,
158 static void gtk_color_selection_realize (GtkWidget *widget);
159 static void gtk_color_selection_unrealize (GtkWidget *widget);
160 static void gtk_color_selection_show_all (GtkWidget *widget);
162 static void gtk_color_selection_set_palette_color (GtkColorSelection *colorsel,
165 static GdkGC *get_focus_gc (GtkWidget *drawing_area,
167 static void default_noscreen_change_palette_func (const GdkColor *colors,
169 static void default_change_palette_func (GdkScreen *screen,
170 const GdkColor *colors,
173 static gpointer parent_class = NULL;
174 static guint color_selection_signals[LAST_SIGNAL] = { 0 };
176 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";
178 static GtkColorSelectionChangePaletteFunc noscreen_change_palette_hook = default_noscreen_change_palette_func;
179 static GtkColorSelectionChangePaletteWithScreenFunc change_palette_hook = default_change_palette_func;
181 /* The cursor for the dropper */
182 #define DROPPER_WIDTH 17
183 #define DROPPER_HEIGHT 17
184 #define DROPPER_X_HOT 2
185 #define DROPPER_Y_HOT 16
188 static const guchar dropper_bits[] = {
189 0xff, 0x8f, 0x01, 0xff, 0x77, 0x01, 0xff, 0xfb, 0x00, 0xff, 0xf8, 0x00,
190 0x7f, 0xff, 0x00, 0xff, 0x7e, 0x01, 0xff, 0x9d, 0x01, 0xff, 0xd8, 0x01,
191 0x7f, 0xd4, 0x01, 0x3f, 0xee, 0x01, 0x1f, 0xff, 0x01, 0x8f, 0xff, 0x01,
192 0xc7, 0xff, 0x01, 0xe3, 0xff, 0x01, 0xf3, 0xff, 0x01, 0xfd, 0xff, 0x01,
195 static const guchar dropper_mask[] = {
196 0x00, 0x70, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xfc, 0x01, 0x00, 0xff, 0x01,
197 0x80, 0xff, 0x01, 0x00, 0xff, 0x00, 0x00, 0x7f, 0x00, 0x80, 0x3f, 0x00,
198 0xc0, 0x3f, 0x00, 0xe0, 0x13, 0x00, 0xf0, 0x01, 0x00, 0xf8, 0x00, 0x00,
199 0x7c, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x0d, 0x00, 0x00,
208 #define SAMPLE_WIDTH 64
209 #define SAMPLE_HEIGHT 28
211 static void color_sample_draw_sample (GtkColorSelection *colorsel, int which);
212 static void color_sample_draw_samples (GtkColorSelection *colorsel);
215 set_color_internal (GtkColorSelection *colorsel,
218 ColorSelectionPrivate *priv;
221 priv = colorsel->private_data;
222 priv->changing = TRUE;
223 priv->color[COLORSEL_RED] = color[0];
224 priv->color[COLORSEL_GREEN] = color[1];
225 priv->color[COLORSEL_BLUE] = color[2];
226 priv->color[COLORSEL_OPACITY] = color[3];
227 gtk_rgb_to_hsv (priv->color[COLORSEL_RED],
228 priv->color[COLORSEL_GREEN],
229 priv->color[COLORSEL_BLUE],
230 &priv->color[COLORSEL_HUE],
231 &priv->color[COLORSEL_SATURATION],
232 &priv->color[COLORSEL_VALUE]);
233 if (priv->default_set == FALSE)
235 for (i = 0; i < COLORSEL_NUM_CHANNELS; i++)
236 priv->old_color[i] = priv->color[i];
238 priv->default_set = TRUE;
239 priv->default_alpha_set = TRUE;
240 update_color (colorsel);
244 set_color_icon (GdkDragContext *context,
250 pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE,
253 pixel = (((UNSCALE (colors[COLORSEL_RED]) & 0xff00) << 16) |
254 ((UNSCALE (colors[COLORSEL_GREEN]) & 0xff00) << 8) |
255 ((UNSCALE (colors[COLORSEL_BLUE]) & 0xff00)));
257 gdk_pixbuf_fill (pixbuf, pixel);
259 gtk_drag_set_icon_pixbuf (context, pixbuf, -2, -2);
260 g_object_unref (pixbuf);
264 color_sample_drag_begin (GtkWidget *widget,
265 GdkDragContext *context,
268 GtkColorSelection *colorsel = data;
269 ColorSelectionPrivate *priv;
272 priv = colorsel->private_data;
274 if (widget == priv->old_sample)
275 colsrc = priv->old_color;
277 colsrc = priv->color;
279 set_color_icon (context, colsrc);
283 color_sample_drag_end (GtkWidget *widget,
284 GdkDragContext *context,
287 g_object_set_data (G_OBJECT (widget), "gtk-color-selection-drag-window", NULL);
291 color_sample_drop_handle (GtkWidget *widget,
292 GdkDragContext *context,
295 GtkSelectionData *selection_data,
300 GtkColorSelection *colorsel = data;
301 ColorSelectionPrivate *priv;
304 priv = colorsel->private_data;
306 /* This is currently a guint16 array of the format:
313 if (selection_data->length < 0)
316 if ((selection_data->format != 16) ||
317 (selection_data->length != 8))
319 g_warning ("Received invalid color data\n");
323 vals = (guint16 *)selection_data->data;
325 if (widget == priv->cur_sample)
327 color[0] = (gdouble)vals[0] / 0xffff;
328 color[1] = (gdouble)vals[1] / 0xffff;
329 color[2] = (gdouble)vals[2] / 0xffff;
330 color[3] = (gdouble)vals[3] / 0xffff;
332 set_color_internal (colorsel, color);
337 color_sample_drag_handle (GtkWidget *widget,
338 GdkDragContext *context,
339 GtkSelectionData *selection_data,
344 GtkColorSelection *colorsel = data;
345 ColorSelectionPrivate *priv;
349 priv = colorsel->private_data;
351 if (widget == priv->old_sample)
352 colsrc = priv->old_color;
354 colsrc = priv->color;
356 vals[0] = colsrc[COLORSEL_RED] * 0xffff;
357 vals[1] = colsrc[COLORSEL_GREEN] * 0xffff;
358 vals[2] = colsrc[COLORSEL_BLUE] * 0xffff;
359 vals[3] = priv->has_opacity ? colsrc[COLORSEL_OPACITY] * 0xffff : 0xffff;
361 gtk_selection_data_set (selection_data,
362 gdk_atom_intern ("application/x-color", FALSE),
363 16, (guchar *)vals, 8);
366 /* which = 0 means draw old sample, which = 1 means draw new */
368 color_sample_draw_sample (GtkColorSelection *colorsel, int which)
371 gint x, y, i, wid, heig, f, n, goff;
372 guchar c[3 * 2], cc[3 * 4], *cp = c;
375 ColorSelectionPrivate *priv;
377 g_return_if_fail (colorsel != NULL);
378 priv = colorsel->private_data;
380 g_return_if_fail (priv->sample_area != NULL);
381 if (!GTK_WIDGET_DRAWABLE (priv->sample_area))
386 da = priv->old_sample;
387 for (n = 0, i = COLORSEL_RED; n < 3; n++, i++)
388 c[n] = (guchar) (UNSCALE (priv->old_color[i]) >> 8);
393 da = priv->cur_sample;
394 for (n = 0, i = COLORSEL_RED; n < 3; n++, i++)
395 c[n] = (guchar) (UNSCALE (priv->color[i]) >> 8);
396 goff = priv->old_sample->allocation.width % 32;
399 wid = da->allocation.width;
400 heig = da->allocation.height;
402 buf = g_new (guchar, 3 * wid * heig);
406 for (n = 0; n < 3; n++)
408 c[n] = (guchar) (255.0 * priv->old_color[i]);
409 c[n + 3] = (guchar) (255.0 * priv->color[i++]);
413 if (priv->has_opacity)
415 o = (which) ? priv->color[COLORSEL_OPACITY] : priv->old_color[COLORSEL_OPACITY];
417 for (n = 0; n < 3; n++)
419 cc[n] = (guchar) ((1.0 - o) * 192 + (o * (gdouble) c[n]));
420 cc[n + 3] = (guchar) ((1.0 - o) * 128 + (o * (gdouble) c[n]));
426 for (y = 0; y < heig; y++)
428 for (x = 0; x < wid; x++)
430 if (priv->has_opacity)
431 f = 3 * ((((goff + x) % 32) < 16) ^ ((y % 32) < 16));
435 for (n = 0; n < 3; n++)
436 buf[i++] = cp[n + f];
440 gdk_draw_rgb_image (da->window,
444 GDK_RGB_DITHER_NORMAL,
454 color_sample_draw_samples (GtkColorSelection *colorsel)
456 color_sample_draw_sample (colorsel, 0);
457 color_sample_draw_sample (colorsel, 1);
461 color_old_sample_expose (GtkWidget *da,
462 GdkEventExpose *event,
463 GtkColorSelection *colorsel)
465 color_sample_draw_sample (colorsel, 0);
471 color_cur_sample_expose (GtkWidget *da,
472 GdkEventExpose *event,
473 GtkColorSelection *colorsel)
475 color_sample_draw_sample (colorsel, 1);
480 color_sample_setup_dnd (GtkColorSelection *colorsel, GtkWidget *sample)
482 static const GtkTargetEntry targets[] = {
483 { "application/x-color", 0 }
485 ColorSelectionPrivate *priv;
486 priv = colorsel->private_data;
488 gtk_drag_source_set (sample,
489 GDK_BUTTON1_MASK | GDK_BUTTON3_MASK,
491 GDK_ACTION_COPY | GDK_ACTION_MOVE);
493 g_signal_connect (sample,
495 G_CALLBACK (color_sample_drag_begin),
497 if (sample == priv->cur_sample)
500 gtk_drag_dest_set (sample,
501 GTK_DEST_DEFAULT_HIGHLIGHT |
502 GTK_DEST_DEFAULT_MOTION |
503 GTK_DEST_DEFAULT_DROP,
507 g_signal_connect (sample,
509 G_CALLBACK (color_sample_drag_end),
513 g_signal_connect (sample,
515 G_CALLBACK (color_sample_drag_handle),
517 g_signal_connect (sample,
518 "drag_data_received",
519 G_CALLBACK (color_sample_drop_handle),
526 color_sample_new (GtkColorSelection *colorsel)
528 ColorSelectionPrivate *priv;
530 priv = colorsel->private_data;
532 priv->sample_area = gtk_hbox_new (FALSE, 0);
533 priv->old_sample = gtk_drawing_area_new ();
534 priv->cur_sample = gtk_drawing_area_new ();
536 /* We need enter/leave to do tooltips */
537 gtk_widget_add_events (priv->old_sample,
538 GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK);
539 gtk_widget_add_events (priv->cur_sample,
540 GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK);
542 gtk_box_pack_start (GTK_BOX (priv->sample_area), priv->old_sample,
544 gtk_box_pack_start (GTK_BOX (priv->sample_area), priv->cur_sample,
547 g_signal_connect (priv->old_sample, "expose_event",
548 G_CALLBACK (color_old_sample_expose),
550 g_signal_connect (priv->cur_sample, "expose_event",
551 G_CALLBACK (color_cur_sample_expose),
554 color_sample_setup_dnd (colorsel, priv->old_sample);
555 color_sample_setup_dnd (colorsel, priv->cur_sample);
557 gtk_tooltips_set_tip (priv->tooltips,
559 _("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);
562 gtk_tooltips_set_tip (priv->tooltips,
564 _("The color you've chosen. You can drag this color to a palette entry to save it for use in the future."), NULL);
566 gtk_widget_show_all (priv->sample_area);
572 * The palette area code
575 #define CUSTOM_PALETTE_ENTRY_WIDTH 20
576 #define CUSTOM_PALETTE_ENTRY_HEIGHT 20
579 palette_get_color (GtkWidget *drawing_area, gdouble *color)
583 g_return_if_fail (color != NULL);
585 color_val = g_object_get_data (G_OBJECT (drawing_area), "color_val");
586 if (color_val == NULL)
588 /* Default to white for no good reason */
596 color[0] = color_val[0];
597 color[1] = color_val[1];
598 color[2] = color_val[2];
602 #define INTENSITY(r, g, b) ((r) * 0.30 + (g) * 0.59 + (b) * 0.11)
604 palette_paint (GtkWidget *drawing_area,
608 if (drawing_area->window == NULL)
611 gdk_draw_rectangle (drawing_area->window,
612 drawing_area->style->bg_gc[GTK_STATE_NORMAL],
614 area->x, area->y, area->width, area->height);
616 if (GTK_WIDGET_HAS_FOCUS (drawing_area))
619 GdkGC *gc = get_focus_gc (drawing_area, &focus_width);
620 gdk_draw_rectangle (drawing_area->window,
621 gc, FALSE, focus_width / 2, focus_width / 2,
622 drawing_area->allocation.width - focus_width,
623 drawing_area->allocation.height - focus_width);
629 get_focus_gc (GtkWidget *drawing_area,
632 GdkGC *gc = gdk_gc_new (drawing_area->window);
636 gtk_widget_style_get (drawing_area,
637 "focus-line-width", focus_width,
638 "focus-line-pattern", (gchar *)&dash_list,
641 palette_get_color (drawing_area, color);
643 if (INTENSITY (color[0], color[1], color[2]) > 0.5)
644 gdk_gc_copy (gc, drawing_area->style->black_gc);
646 gdk_gc_copy (gc, drawing_area->style->white_gc);
648 gdk_gc_set_line_attributes (gc, *focus_width,
649 dash_list[0] ? GDK_LINE_ON_OFF_DASH : GDK_LINE_SOLID,
650 GDK_CAP_BUTT, GDK_JOIN_MITER);
653 gdk_gc_set_dashes (gc, 0, dash_list, strlen ((char *)dash_list));
661 palette_drag_begin (GtkWidget *widget,
662 GdkDragContext *context,
667 palette_get_color (widget, colors);
668 set_color_icon (context, colors);
672 palette_drag_handle (GtkWidget *widget,
673 GdkDragContext *context,
674 GtkSelectionData *selection_data,
682 palette_get_color (widget, colsrc);
684 vals[0] = colsrc[COLORSEL_RED] * 0xffff;
685 vals[1] = colsrc[COLORSEL_GREEN] * 0xffff;
686 vals[2] = colsrc[COLORSEL_BLUE] * 0xffff;
689 gtk_selection_data_set (selection_data,
690 gdk_atom_intern ("application/x-color", FALSE),
691 16, (guchar *)vals, 8);
695 palette_drag_end (GtkWidget *widget,
696 GdkDragContext *context,
699 g_object_set_data (G_OBJECT (widget), "gtk-color-selection-drag-window", NULL);
703 get_current_colors (GtkColorSelection *colorsel)
705 GtkSettings *settings;
706 GdkColor *colors = NULL;
710 settings = gtk_widget_get_settings (GTK_WIDGET (colorsel));
711 g_object_get (settings,
712 "gtk-color-palette", &palette,
715 if (!gtk_color_selection_palette_from_string (palette, &colors, &n_colors))
717 gtk_color_selection_palette_from_string (default_colors, &colors, &n_colors);
721 /* If there are less colors provided than the number of slots in the
722 * color selection, we fill in the rest from the defaults.
724 if (n_colors < (GTK_CUSTOM_PALETTE_WIDTH * GTK_CUSTOM_PALETTE_HEIGHT))
726 GdkColor *tmp_colors = colors;
727 gint tmp_n_colors = n_colors;
729 gtk_color_selection_palette_from_string (default_colors, &colors, &n_colors);
730 memcpy (colors, tmp_colors, sizeof (GdkColor) * tmp_n_colors);
736 g_assert (n_colors >= GTK_CUSTOM_PALETTE_WIDTH * GTK_CUSTOM_PALETTE_HEIGHT);
742 /* Changes the model color */
744 palette_change_color (GtkWidget *drawing_area,
745 GtkColorSelection *colorsel,
749 ColorSelectionPrivate *priv;
751 GdkColor *current_colors;
754 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
755 g_return_if_fail (GTK_IS_DRAWING_AREA (drawing_area));
757 priv = colorsel->private_data;
759 gdk_color.red = UNSCALE (color[0]);
760 gdk_color.green = UNSCALE (color[1]);
761 gdk_color.blue = UNSCALE (color[2]);
764 y = 0; /* Quiet GCC */
765 while (x < GTK_CUSTOM_PALETTE_WIDTH)
768 while (y < GTK_CUSTOM_PALETTE_HEIGHT)
770 if (priv->custom_palette[x][y] == drawing_area)
781 g_assert (x < GTK_CUSTOM_PALETTE_WIDTH || y < GTK_CUSTOM_PALETTE_HEIGHT);
783 current_colors = get_current_colors (colorsel);
784 current_colors[y * GTK_CUSTOM_PALETTE_WIDTH + x] = gdk_color;
786 screen = gtk_widget_get_screen (GTK_WIDGET (colorsel));
787 if (change_palette_hook != default_change_palette_func)
788 (* change_palette_hook) (screen, current_colors,
789 GTK_CUSTOM_PALETTE_WIDTH * GTK_CUSTOM_PALETTE_HEIGHT);
790 else if (noscreen_change_palette_hook != default_noscreen_change_palette_func)
792 if (screen != gdk_screen_get_default ())
793 g_warning ("gtk_color_selection_set_change_palette_hook used by widget is not on the default screen.");
794 (* noscreen_change_palette_hook) (current_colors,
795 GTK_CUSTOM_PALETTE_WIDTH * GTK_CUSTOM_PALETTE_HEIGHT);
798 (* change_palette_hook) (screen, current_colors,
799 GTK_CUSTOM_PALETTE_WIDTH * GTK_CUSTOM_PALETTE_HEIGHT);
801 g_free (current_colors);
804 /* Changes the view color */
806 palette_set_color (GtkWidget *drawing_area,
807 GtkColorSelection *colorsel,
810 gdouble *new_color = g_new (double, 4);
813 gdk_color.red = UNSCALE (color[0]);
814 gdk_color.green = UNSCALE (color[1]);
815 gdk_color.blue = UNSCALE (color[2]);
817 gtk_widget_modify_bg (drawing_area, GTK_STATE_NORMAL, &gdk_color);
819 if (GPOINTER_TO_INT (g_object_get_data (G_OBJECT (drawing_area), "color_set")) == 0)
821 static const GtkTargetEntry targets[] = {
822 { "application/x-color", 0 }
824 gtk_drag_source_set (drawing_area,
825 GDK_BUTTON1_MASK | GDK_BUTTON3_MASK,
827 GDK_ACTION_COPY | GDK_ACTION_MOVE);
829 g_signal_connect (drawing_area,
831 G_CALLBACK (palette_drag_begin),
833 g_signal_connect (drawing_area,
835 G_CALLBACK (palette_drag_handle),
838 g_object_set_data (G_OBJECT (drawing_area), "color_set",
839 GINT_TO_POINTER (1));
842 new_color[0] = color[0];
843 new_color[1] = color[1];
844 new_color[2] = color[2];
847 g_object_set_data_full (G_OBJECT (drawing_area), "color_val", new_color, (GDestroyNotify)g_free);
851 palette_expose (GtkWidget *drawing_area,
852 GdkEventExpose *event,
855 if (drawing_area->window == NULL)
858 palette_paint (drawing_area, &(event->area), data);
864 popup_position_func (GtkMenu *menu,
875 widget = GTK_WIDGET (user_data);
877 g_return_if_fail (GTK_WIDGET_REALIZED (widget));
879 gdk_window_get_origin (widget->window, &root_x, &root_y);
881 gtk_widget_size_request (GTK_WIDGET (menu), &req);
883 /* Put corner of menu centered on color cell */
884 *x = root_x + widget->allocation.width / 2;
885 *y = root_y + widget->allocation.height / 2;
888 screen = gtk_widget_get_screen (widget);
889 *x = CLAMP (*x, 0, MAX (0, gdk_screen_get_width (screen) - req.width));
890 *y = CLAMP (*y, 0, MAX (0, gdk_screen_get_height (screen) - req.height));
894 save_color_selected (GtkWidget *menuitem,
897 GtkColorSelection *colorsel;
898 GtkWidget *drawing_area;
899 ColorSelectionPrivate *priv;
901 drawing_area = GTK_WIDGET (data);
903 colorsel = GTK_COLOR_SELECTION (g_object_get_data (G_OBJECT (drawing_area),
906 priv = colorsel->private_data;
908 palette_change_color (drawing_area, colorsel, priv->color);
912 do_popup (GtkColorSelection *colorsel,
913 GtkWidget *drawing_area,
919 g_object_set_data (G_OBJECT (drawing_area),
923 menu = gtk_menu_new ();
925 mi = gtk_menu_item_new_with_mnemonic (_("_Save color here"));
927 g_signal_connect (mi, "activate",
928 G_CALLBACK (save_color_selected),
931 gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
933 gtk_widget_show_all (mi);
935 gtk_menu_popup (GTK_MENU (menu), NULL, NULL,
936 popup_position_func, drawing_area,
942 palette_enter (GtkWidget *drawing_area,
943 GdkEventCrossing *event,
946 g_object_set_data (G_OBJECT (drawing_area),
947 "gtk-colorsel-have-pointer",
948 GUINT_TO_POINTER (TRUE));
954 palette_leave (GtkWidget *drawing_area,
955 GdkEventCrossing *event,
958 g_object_set_data (G_OBJECT (drawing_area),
959 "gtk-colorsel-have-pointer",
966 palette_press (GtkWidget *drawing_area,
967 GdkEventButton *event,
970 GtkColorSelection *colorsel = GTK_COLOR_SELECTION (data);
972 gtk_widget_grab_focus (drawing_area);
974 if (event->button == 3 &&
975 event->type == GDK_BUTTON_PRESS)
977 do_popup (colorsel, drawing_area, event->time);
985 palette_release (GtkWidget *drawing_area,
986 GdkEventButton *event,
989 GtkColorSelection *colorsel = GTK_COLOR_SELECTION (data);
991 gtk_widget_grab_focus (drawing_area);
993 if (event->button == 1 &&
994 g_object_get_data (G_OBJECT (drawing_area),
995 "gtk-colorsel-have-pointer") != NULL)
997 if (GPOINTER_TO_INT (g_object_get_data (G_OBJECT (drawing_area), "color_set")) != 0)
1000 palette_get_color (drawing_area, color);
1001 set_color_internal (colorsel, color);
1009 palette_drop_handle (GtkWidget *widget,
1010 GdkDragContext *context,
1013 GtkSelectionData *selection_data,
1018 GtkColorSelection *colorsel = GTK_COLOR_SELECTION (data);
1022 if (selection_data->length < 0)
1025 if ((selection_data->format != 16) ||
1026 (selection_data->length != 8))
1028 g_warning ("Received invalid color data\n");
1032 vals = (guint16 *)selection_data->data;
1034 color[0] = (gdouble)vals[0] / 0xffff;
1035 color[1] = (gdouble)vals[1] / 0xffff;
1036 color[2] = (gdouble)vals[2] / 0xffff;
1037 color[3] = (gdouble)vals[3] / 0xffff;
1038 palette_change_color (widget, colorsel, color);
1039 set_color_internal (colorsel, color);
1043 palette_activate (GtkWidget *widget,
1047 /* should have a drawing area subclass with an activate signal */
1048 if ((event->keyval == GDK_space) ||
1049 (event->keyval == GDK_Return) ||
1050 (event->keyval == GDK_KP_Enter) ||
1051 (event->keyval == GDK_KP_Space))
1053 if (GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget), "color_set")) != 0)
1056 palette_get_color (widget, color);
1057 set_color_internal (GTK_COLOR_SELECTION (data), color);
1066 palette_popup (GtkWidget *widget,
1069 GtkColorSelection *colorsel = GTK_COLOR_SELECTION (data);
1071 do_popup (colorsel, widget, GDK_CURRENT_TIME);
1077 palette_new (GtkColorSelection *colorsel)
1080 ColorSelectionPrivate *priv;
1082 static const GtkTargetEntry targets[] = {
1083 { "application/x-color", 0 }
1086 priv = colorsel->private_data;
1088 retval = gtk_drawing_area_new ();
1090 GTK_WIDGET_SET_FLAGS (retval, GTK_CAN_FOCUS);
1092 g_object_set_data (G_OBJECT (retval), "color_set", GINT_TO_POINTER (0));
1093 gtk_widget_set_events (retval, GDK_BUTTON_PRESS_MASK
1094 | GDK_BUTTON_RELEASE_MASK
1096 | GDK_ENTER_NOTIFY_MASK
1097 | GDK_LEAVE_NOTIFY_MASK);
1099 g_signal_connect (retval, "expose_event",
1100 G_CALLBACK (palette_expose), colorsel);
1101 g_signal_connect (retval, "button_press_event",
1102 G_CALLBACK (palette_press), colorsel);
1103 g_signal_connect (retval, "button_release_event",
1104 G_CALLBACK (palette_release), colorsel);
1105 g_signal_connect (retval, "enter_notify_event",
1106 G_CALLBACK (palette_enter), colorsel);
1107 g_signal_connect (retval, "leave_notify_event",
1108 G_CALLBACK (palette_leave), colorsel);
1109 g_signal_connect (retval, "key_press_event",
1110 G_CALLBACK (palette_activate), colorsel);
1111 g_signal_connect (retval, "popup_menu",
1112 G_CALLBACK (palette_popup), colorsel);
1114 gtk_drag_dest_set (retval,
1115 GTK_DEST_DEFAULT_HIGHLIGHT |
1116 GTK_DEST_DEFAULT_MOTION |
1117 GTK_DEST_DEFAULT_DROP,
1121 g_signal_connect (retval, "drag_end",
1122 G_CALLBACK (palette_drag_end), NULL);
1123 g_signal_connect (retval, "drag_data_received",
1124 G_CALLBACK (palette_drop_handle), colorsel);
1126 gtk_tooltips_set_tip (priv->tooltips,
1128 _("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.\""),
1136 * The actual GtkColorSelection widget
1141 make_picker_cursor (GdkScreen *screen)
1144 GdkColor bg = { 0, 0xffff, 0xffff, 0xffff };
1145 GdkColor fg = { 0, 0x0000, 0x0000, 0x0000 };
1146 GdkWindow *window = gdk_screen_get_root_window (screen);
1149 gdk_bitmap_create_from_data (window, (gchar *) dropper_bits,
1150 DROPPER_WIDTH, DROPPER_HEIGHT);
1153 gdk_bitmap_create_from_data (window, (gchar *) dropper_mask,
1154 DROPPER_WIDTH, DROPPER_HEIGHT);
1156 cursor = gdk_cursor_new_from_pixmap (pixmap, mask, &fg, &bg,
1157 DROPPER_X_HOT, DROPPER_Y_HOT);
1159 g_object_unref (pixmap);
1160 g_object_unref (mask);
1166 grab_color_at_mouse (GdkScreen *screen,
1173 GtkColorSelection *colorsel = data;
1174 ColorSelectionPrivate *priv;
1176 GdkColormap *colormap = gdk_screen_get_system_colormap (screen);
1177 GdkWindow *root_window = gdk_screen_get_root_window (screen);
1179 priv = colorsel->private_data;
1181 image = gdk_drawable_get_image (root_window, x_root, y_root, 1, 1);
1182 pixel = gdk_image_get_pixel (image, 0, 0);
1183 g_object_unref (image);
1185 gdk_colormap_query_color (colormap, pixel, &color);
1187 priv->color[COLORSEL_RED] = SCALE (color.red);
1188 priv->color[COLORSEL_GREEN] = SCALE (color.green);
1189 priv->color[COLORSEL_BLUE] = SCALE (color.blue);
1191 gtk_rgb_to_hsv (priv->color[COLORSEL_RED],
1192 priv->color[COLORSEL_GREEN],
1193 priv->color[COLORSEL_BLUE],
1194 &priv->color[COLORSEL_HUE],
1195 &priv->color[COLORSEL_SATURATION],
1196 &priv->color[COLORSEL_VALUE]);
1198 update_color (colorsel);
1202 shutdown_eyedropper (GtkWidget *widget)
1204 GtkColorSelection *colorsel;
1205 ColorSelectionPrivate *priv;
1206 GdkDisplay *display = gtk_widget_get_display (widget);
1207 guint32 time = gtk_get_current_event_time ();
1209 colorsel = GTK_COLOR_SELECTION (widget);
1210 priv = colorsel->private_data;
1212 gdk_display_keyboard_ungrab (display, time);
1213 gdk_display_pointer_ungrab (display, time);
1214 gtk_grab_remove (priv->dropper_grab_widget);
1218 mouse_motion (GtkWidget *invisible,
1219 GdkEventMotion *event,
1222 grab_color_at_mouse (gdk_event_get_screen ((GdkEvent *)event),
1223 event->x_root, event->y_root, data);
1227 mouse_release (GtkWidget *invisible,
1228 GdkEventButton *event,
1231 GtkColorSelection *colorsel = data;
1232 ColorSelectionPrivate *priv;
1233 priv = colorsel->private_data;
1235 if (event->button != 1)
1238 grab_color_at_mouse (gdk_event_get_screen ((GdkEvent *)event),
1239 event->x_root, event->y_root, data);
1241 shutdown_eyedropper (GTK_WIDGET (data));
1243 g_signal_handlers_disconnect_by_func (invisible,
1246 g_signal_handlers_disconnect_by_func (invisible,
1253 /* Helper Functions */
1255 static gboolean mouse_press (GtkWidget *invisible,
1256 GdkEventButton *event,
1260 key_press (GtkWidget *invisible,
1264 if (event->keyval == GDK_Escape)
1266 shutdown_eyedropper (data);
1268 g_signal_handlers_disconnect_by_func (invisible,
1271 g_signal_handlers_disconnect_by_func (invisible,
1282 mouse_press (GtkWidget *invisible,
1283 GdkEventButton *event,
1286 GtkColorSelection *colorsel = data;
1287 ColorSelectionPrivate *priv;
1288 priv = colorsel->private_data;
1290 if (event->type == GDK_BUTTON_PRESS &&
1293 g_signal_connect (invisible, "motion_notify_event",
1294 G_CALLBACK (mouse_motion),
1296 g_signal_connect (invisible, "button_release_event",
1297 G_CALLBACK (mouse_release),
1299 g_signal_handlers_disconnect_by_func (invisible,
1302 g_signal_handlers_disconnect_by_func (invisible,
1311 /* when the button is clicked */
1313 get_screen_color (GtkWidget *button)
1315 GtkColorSelection *colorsel = g_object_get_data (G_OBJECT (button), "COLORSEL");
1316 ColorSelectionPrivate *priv = colorsel->private_data;
1317 GdkScreen *screen = gtk_widget_get_screen (GTK_WIDGET (button));
1318 GdkCursor *picker_cursor;
1319 GdkGrabStatus grab_status;
1321 if (priv->dropper_grab_widget == NULL)
1323 priv->dropper_grab_widget = gtk_invisible_new_for_screen (screen);
1325 gtk_widget_add_events (priv->dropper_grab_widget,
1326 GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_PRESS_MASK | GDK_POINTER_MOTION_MASK);
1328 gtk_widget_show (priv->dropper_grab_widget);
1331 if (gdk_keyboard_grab (priv->dropper_grab_widget->window,
1333 gtk_get_current_event_time ()) != GDK_GRAB_SUCCESS)
1336 picker_cursor = make_picker_cursor (screen);
1337 grab_status = gdk_pointer_grab (priv->dropper_grab_widget->window,
1339 GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_PRESS_MASK | GDK_POINTER_MOTION_MASK,
1342 gtk_get_current_event_time ());
1343 gdk_cursor_unref (picker_cursor);
1345 if (grab_status != GDK_GRAB_SUCCESS)
1347 gdk_display_keyboard_ungrab (gtk_widget_get_display (button), GDK_CURRENT_TIME);
1351 gtk_grab_add (priv->dropper_grab_widget);
1353 g_signal_connect (priv->dropper_grab_widget, "button_press_event",
1354 G_CALLBACK (mouse_press), colorsel);
1355 g_signal_connect (priv->dropper_grab_widget, "key_press_event",
1356 G_CALLBACK (key_press), colorsel);
1360 hex_changed (GtkWidget *hex_entry,
1363 GtkColorSelection *colorsel;
1364 ColorSelectionPrivate *priv;
1368 colorsel = GTK_COLOR_SELECTION (data);
1369 priv = colorsel->private_data;
1374 text = gtk_editable_get_chars (GTK_EDITABLE (priv->hex_entry), 0, -1);
1375 if (gdk_color_parse (text, &color))
1377 priv->color[COLORSEL_RED] = CLAMP (color.red/65535.0, 0.0, 1.0);
1378 priv->color[COLORSEL_GREEN] = CLAMP (color.green/65535.0, 0.0, 1.0);
1379 priv->color[COLORSEL_BLUE] = CLAMP (color.blue/65535.0, 0.0, 1.0);
1380 gtk_rgb_to_hsv (priv->color[COLORSEL_RED],
1381 priv->color[COLORSEL_GREEN],
1382 priv->color[COLORSEL_BLUE],
1383 &priv->color[COLORSEL_HUE],
1384 &priv->color[COLORSEL_SATURATION],
1385 &priv->color[COLORSEL_VALUE]);
1386 update_color (colorsel);
1392 hex_focus_out (GtkWidget *hex_entry,
1393 GdkEventFocus *event,
1396 hex_changed (hex_entry, data);
1402 hsv_changed (GtkWidget *hsv,
1405 GtkColorSelection *colorsel;
1406 ColorSelectionPrivate *priv;
1408 colorsel = GTK_COLOR_SELECTION (data);
1409 priv = colorsel->private_data;
1414 gtk_hsv_get_color (GTK_HSV (hsv),
1415 &priv->color[COLORSEL_HUE],
1416 &priv->color[COLORSEL_SATURATION],
1417 &priv->color[COLORSEL_VALUE]);
1418 gtk_hsv_to_rgb (priv->color[COLORSEL_HUE],
1419 priv->color[COLORSEL_SATURATION],
1420 priv->color[COLORSEL_VALUE],
1421 &priv->color[COLORSEL_RED],
1422 &priv->color[COLORSEL_GREEN],
1423 &priv->color[COLORSEL_BLUE]);
1424 update_color (colorsel);
1428 adjustment_changed (GtkAdjustment *adjustment,
1431 GtkColorSelection *colorsel;
1432 ColorSelectionPrivate *priv;
1434 colorsel = GTK_COLOR_SELECTION (g_object_get_data (G_OBJECT (adjustment), "COLORSEL"));
1435 priv = colorsel->private_data;
1440 switch (GPOINTER_TO_INT (data))
1442 case COLORSEL_SATURATION:
1443 case COLORSEL_VALUE:
1444 priv->color[GPOINTER_TO_INT (data)] = adjustment->value / 255;
1445 gtk_hsv_to_rgb (priv->color[COLORSEL_HUE],
1446 priv->color[COLORSEL_SATURATION],
1447 priv->color[COLORSEL_VALUE],
1448 &priv->color[COLORSEL_RED],
1449 &priv->color[COLORSEL_GREEN],
1450 &priv->color[COLORSEL_BLUE]);
1453 priv->color[GPOINTER_TO_INT (data)] = adjustment->value / 360;
1454 gtk_hsv_to_rgb (priv->color[COLORSEL_HUE],
1455 priv->color[COLORSEL_SATURATION],
1456 priv->color[COLORSEL_VALUE],
1457 &priv->color[COLORSEL_RED],
1458 &priv->color[COLORSEL_GREEN],
1459 &priv->color[COLORSEL_BLUE]);
1462 case COLORSEL_GREEN:
1464 priv->color[GPOINTER_TO_INT (data)] = adjustment->value / 255;
1466 gtk_rgb_to_hsv (priv->color[COLORSEL_RED],
1467 priv->color[COLORSEL_GREEN],
1468 priv->color[COLORSEL_BLUE],
1469 &priv->color[COLORSEL_HUE],
1470 &priv->color[COLORSEL_SATURATION],
1471 &priv->color[COLORSEL_VALUE]);
1474 priv->color[GPOINTER_TO_INT (data)] = adjustment->value / 255;
1477 update_color (colorsel);
1481 opacity_entry_changed (GtkWidget *opacity_entry,
1484 GtkColorSelection *colorsel;
1485 ColorSelectionPrivate *priv;
1489 colorsel = GTK_COLOR_SELECTION (data);
1490 priv = colorsel->private_data;
1495 text = gtk_editable_get_chars (GTK_EDITABLE (priv->opacity_entry), 0, -1);
1496 adj = gtk_range_get_adjustment (GTK_RANGE (priv->opacity_slider));
1497 gtk_adjustment_set_value (adj, g_strtod (text, NULL));
1499 update_color (colorsel);
1505 make_label_spinbutton (GtkColorSelection *colorsel,
1506 GtkWidget **spinbutton,
1512 const gchar *tooltip)
1515 GtkAdjustment *adjust;
1516 ColorSelectionPrivate *priv = colorsel->private_data;
1518 if (channel_type == COLORSEL_HUE)
1520 adjust = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 360.0, 1.0, 1.0, 1.0));
1524 adjust = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 255.0, 1.0, 1.0, 1.0));
1526 g_object_set_data (G_OBJECT (adjust), "COLORSEL", colorsel);
1527 *spinbutton = gtk_spin_button_new (adjust, 10.0, 0);
1529 gtk_tooltips_set_tip (priv->tooltips, *spinbutton, tooltip, NULL);
1531 g_signal_connect (adjust, "value_changed",
1532 G_CALLBACK (adjustment_changed),
1533 GINT_TO_POINTER (channel_type));
1534 label = gtk_label_new_with_mnemonic (text);
1535 gtk_label_set_mnemonic_widget (GTK_LABEL (label), *spinbutton);
1537 gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5);
1538 gtk_table_attach_defaults (GTK_TABLE (table), label, i, i+1, j, j+1);
1539 gtk_table_attach_defaults (GTK_TABLE (table), *spinbutton, i+1, i+2, j, j+1);
1543 make_palette_frame (GtkColorSelection *colorsel,
1549 ColorSelectionPrivate *priv;
1551 priv = colorsel->private_data;
1552 frame = gtk_frame_new (NULL);
1553 gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
1554 priv->custom_palette[i][j] = palette_new (colorsel);
1555 gtk_widget_set_size_request (priv->custom_palette[i][j], CUSTOM_PALETTE_ENTRY_WIDTH, CUSTOM_PALETTE_ENTRY_HEIGHT);
1556 gtk_container_add (GTK_CONTAINER (frame), priv->custom_palette[i][j]);
1557 gtk_table_attach_defaults (GTK_TABLE (table), frame, i, i+1, j, j+1);
1560 /* Set the palette entry [x][y] to be the currently selected one. */
1562 set_selected_palette (GtkColorSelection *colorsel, int x, int y)
1564 ColorSelectionPrivate *priv = colorsel->private_data;
1566 gtk_widget_grab_focus (priv->custom_palette[x][y]);
1570 scale_round (double val, double factor)
1572 val = floor (val * factor + 0.5);
1574 val = MIN (val, factor);
1579 update_color (GtkColorSelection *colorsel)
1581 ColorSelectionPrivate *priv = colorsel->private_data;
1583 gchar opacity_text[32];
1586 priv->changing = TRUE;
1587 color_sample_draw_samples (colorsel);
1589 gtk_hsv_set_color (GTK_HSV (priv->triangle_colorsel),
1590 priv->color[COLORSEL_HUE],
1591 priv->color[COLORSEL_SATURATION],
1592 priv->color[COLORSEL_VALUE]);
1593 gtk_adjustment_set_value (gtk_spin_button_get_adjustment
1594 (GTK_SPIN_BUTTON (priv->hue_spinbutton)),
1595 scale_round (priv->color[COLORSEL_HUE], 360));
1596 gtk_adjustment_set_value (gtk_spin_button_get_adjustment
1597 (GTK_SPIN_BUTTON (priv->sat_spinbutton)),
1598 scale_round (priv->color[COLORSEL_SATURATION], 255));
1599 gtk_adjustment_set_value (gtk_spin_button_get_adjustment
1600 (GTK_SPIN_BUTTON (priv->val_spinbutton)),
1601 scale_round (priv->color[COLORSEL_VALUE], 255));
1602 gtk_adjustment_set_value (gtk_spin_button_get_adjustment
1603 (GTK_SPIN_BUTTON (priv->red_spinbutton)),
1604 scale_round (priv->color[COLORSEL_RED], 255));
1605 gtk_adjustment_set_value (gtk_spin_button_get_adjustment
1606 (GTK_SPIN_BUTTON (priv->green_spinbutton)),
1607 scale_round (priv->color[COLORSEL_GREEN], 255));
1608 gtk_adjustment_set_value (gtk_spin_button_get_adjustment
1609 (GTK_SPIN_BUTTON (priv->blue_spinbutton)),
1610 scale_round (priv->color[COLORSEL_BLUE], 255));
1611 gtk_adjustment_set_value (gtk_range_get_adjustment
1612 (GTK_RANGE (priv->opacity_slider)),
1613 scale_round (priv->color[COLORSEL_OPACITY], 255));
1615 g_snprintf (opacity_text, 32, "%.0f", scale_round (priv->color[COLORSEL_OPACITY], 255));
1616 gtk_entry_set_text (GTK_ENTRY (priv->opacity_entry), opacity_text);
1618 g_snprintf (entryval, 11, "#%2X%2X%2X",
1619 (guint) (scale_round (priv->color[COLORSEL_RED], 255)),
1620 (guint) (scale_round (priv->color[COLORSEL_GREEN], 255)),
1621 (guint) (scale_round (priv->color[COLORSEL_BLUE], 255)));
1623 for (ptr = entryval; *ptr; ptr++)
1626 gtk_entry_set_text (GTK_ENTRY (priv->hex_entry), entryval);
1627 priv->changing = FALSE;
1629 g_object_ref (colorsel);
1631 g_signal_emit (colorsel, color_selection_signals[COLOR_CHANGED], 0);
1633 g_object_freeze_notify (G_OBJECT (colorsel));
1634 g_object_notify (G_OBJECT (colorsel), "current_color");
1635 g_object_notify (G_OBJECT (colorsel), "current_alpha");
1636 g_object_thaw_notify (G_OBJECT (colorsel));
1638 g_object_unref (colorsel);
1642 update_palette (GtkColorSelection *colorsel)
1644 GdkColor *current_colors;
1647 current_colors = get_current_colors (colorsel);
1649 for (i = 0; i < GTK_CUSTOM_PALETTE_HEIGHT; i++)
1651 for (j = 0; j < GTK_CUSTOM_PALETTE_WIDTH; j++)
1655 index = i * GTK_CUSTOM_PALETTE_WIDTH + j;
1657 gtk_color_selection_set_palette_color (colorsel,
1659 ¤t_colors[index]);
1663 g_free (current_colors);
1667 palette_change_notify_instance (GObject *object,
1671 update_palette (GTK_COLOR_SELECTION (data));
1675 default_noscreen_change_palette_func (const GdkColor *colors,
1678 default_change_palette_func (gdk_screen_get_default (), colors, n_colors);
1682 default_change_palette_func (GdkScreen *screen,
1683 const GdkColor *colors,
1688 str = gtk_color_selection_palette_to_string (colors, n_colors);
1690 gtk_settings_set_string_property (gtk_settings_get_for_screen (screen),
1691 "gtk-color-palette",
1693 "gtk_color_selection_palette_to_string");
1699 gtk_color_selection_get_type (void)
1701 static GType color_selection_type = 0;
1703 if (!color_selection_type)
1705 static const GTypeInfo color_selection_info =
1707 sizeof (GtkColorSelectionClass),
1708 NULL, /* base_init */
1709 NULL, /* base_finalize */
1710 (GClassInitFunc) gtk_color_selection_class_init,
1711 NULL, /* class_finalize */
1712 NULL, /* class_data */
1713 sizeof (GtkColorSelection),
1714 0, /* n_preallocs */
1715 (GInstanceInitFunc) gtk_color_selection_init,
1718 color_selection_type =
1719 g_type_register_static (GTK_TYPE_VBOX, "GtkColorSelection",
1720 &color_selection_info, 0);
1723 return color_selection_type;
1727 gtk_color_selection_class_init (GtkColorSelectionClass *klass)
1729 GObjectClass *gobject_class;
1730 GtkObjectClass *object_class;
1731 GtkWidgetClass *widget_class;
1733 gobject_class = G_OBJECT_CLASS (klass);
1734 object_class = GTK_OBJECT_CLASS (klass);
1735 widget_class = GTK_WIDGET_CLASS (klass);
1737 parent_class = g_type_class_peek_parent (klass);
1739 object_class->destroy = gtk_color_selection_destroy;
1740 gobject_class->finalize = gtk_color_selection_finalize;
1742 gobject_class->set_property = gtk_color_selection_set_property;
1743 gobject_class->get_property = gtk_color_selection_get_property;
1745 widget_class->realize = gtk_color_selection_realize;
1746 widget_class->unrealize = gtk_color_selection_unrealize;
1747 widget_class->show_all = gtk_color_selection_show_all;
1749 g_object_class_install_property (gobject_class,
1750 PROP_HAS_OPACITY_CONTROL,
1751 g_param_spec_boolean ("has_opacity_control",
1752 _("Has Opacity Control"),
1753 _("Whether the color selector should allow setting opacity"),
1755 G_PARAM_READABLE | G_PARAM_WRITABLE));
1756 g_object_class_install_property (gobject_class,
1758 g_param_spec_boolean ("has_palette",
1760 _("Whether a palette should be used"),
1762 G_PARAM_READABLE | G_PARAM_WRITABLE));
1763 g_object_class_install_property (gobject_class,
1765 g_param_spec_boxed ("current_color",
1767 _("The current color"),
1769 G_PARAM_READABLE | G_PARAM_WRITABLE));
1770 g_object_class_install_property (gobject_class,
1772 g_param_spec_uint ("current_alpha",
1774 _("The current opacity value (0 fully transparent, 65535 fully opaque)"),
1776 G_PARAM_READABLE | G_PARAM_WRITABLE));
1778 color_selection_signals[COLOR_CHANGED] =
1779 g_signal_new ("color_changed",
1780 G_OBJECT_CLASS_TYPE (object_class),
1782 G_STRUCT_OFFSET (GtkColorSelectionClass, color_changed),
1784 _gtk_marshal_VOID__VOID,
1787 gtk_settings_install_property (g_param_spec_string ("gtk-color-palette",
1788 _("Custom palette"),
1789 _("Palette to use in the color selector"),
1791 G_PARAM_READWRITE));
1794 /* widget functions */
1797 gtk_color_selection_init (GtkColorSelection *colorsel)
1799 GtkWidget *top_hbox;
1800 GtkWidget *top_right_vbox;
1801 GtkWidget *table, *label, *hbox, *frame, *vbox, *button;
1802 GtkAdjustment *adjust;
1803 GtkWidget *picker_image;
1805 ColorSelectionPrivate *priv;
1807 gtk_widget_push_composite_child ();
1809 priv = colorsel->private_data = g_new0 (ColorSelectionPrivate, 1);
1810 priv->changing = FALSE;
1811 priv->default_set = FALSE;
1812 priv->default_alpha_set = FALSE;
1814 priv->tooltips = gtk_tooltips_new ();
1815 g_object_ref (priv->tooltips);
1816 gtk_object_sink (GTK_OBJECT (priv->tooltips));
1818 gtk_box_set_spacing (GTK_BOX (colorsel), 4);
1819 top_hbox = gtk_hbox_new (FALSE, 8);
1820 gtk_box_pack_start (GTK_BOX (colorsel), top_hbox, FALSE, FALSE, 0);
1822 vbox = gtk_vbox_new (FALSE, 4);
1823 priv->triangle_colorsel = gtk_hsv_new ();
1824 g_signal_connect (priv->triangle_colorsel, "changed",
1825 G_CALLBACK (hsv_changed), colorsel);
1826 gtk_hsv_set_metrics (GTK_HSV (priv->triangle_colorsel), 174, 15);
1827 gtk_box_pack_start (GTK_BOX (top_hbox), vbox, FALSE, FALSE, 0);
1828 gtk_box_pack_start (GTK_BOX (vbox), priv->triangle_colorsel, FALSE, FALSE, 0);
1829 gtk_tooltips_set_tip (priv->tooltips, priv->triangle_colorsel,
1830 _("Select the color you want from the outer ring. Select the darkness or lightness of that color using the inner triangle."), NULL);
1832 hbox = gtk_hbox_new (FALSE, 4);
1833 gtk_box_pack_end (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
1835 frame = gtk_frame_new (NULL);
1836 gtk_widget_set_size_request (frame, -1, 30);
1837 gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
1838 color_sample_new (colorsel);
1839 gtk_container_add (GTK_CONTAINER (frame), priv->sample_area);
1840 gtk_box_pack_start (GTK_BOX (hbox), frame, TRUE, TRUE, 0);
1842 button = gtk_button_new ();
1844 gtk_widget_set_events (button, GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK);
1845 g_object_set_data (G_OBJECT (button), "COLORSEL", colorsel);
1846 g_signal_connect (button, "clicked",
1847 G_CALLBACK (get_screen_color), NULL);
1848 picker_image = gtk_image_new_from_stock (GTK_STOCK_COLOR_PICKER, GTK_ICON_SIZE_BUTTON);
1849 gtk_container_add (GTK_CONTAINER (button), picker_image);
1850 gtk_widget_show (GTK_WIDGET (picker_image));
1851 gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
1853 gtk_tooltips_set_tip (priv->tooltips,
1855 _("Click the eyedropper, then click a color anywhere on your screen to select that color."), NULL);
1857 top_right_vbox = gtk_vbox_new (FALSE, 4);
1858 gtk_box_pack_start (GTK_BOX (top_hbox), top_right_vbox, FALSE, FALSE, 0);
1859 table = gtk_table_new (8, 6, FALSE);
1860 gtk_box_pack_start (GTK_BOX (top_right_vbox), table, FALSE, FALSE, 0);
1861 gtk_table_set_row_spacings (GTK_TABLE (table), 4);
1862 gtk_table_set_col_spacings (GTK_TABLE (table), 4);
1864 make_label_spinbutton (colorsel, &priv->hue_spinbutton, _("_Hue:"), table, 0, 0, COLORSEL_HUE,
1865 _("Position on the color wheel."));
1866 make_label_spinbutton (colorsel, &priv->sat_spinbutton, _("_Saturation:"), table, 0, 1, COLORSEL_SATURATION,
1867 _("\"Deepness\" of the color."));
1868 make_label_spinbutton (colorsel, &priv->val_spinbutton, _("_Value:"), table, 0, 2, COLORSEL_VALUE,
1869 _("Brightness of the color."));
1870 make_label_spinbutton (colorsel, &priv->red_spinbutton, _("_Red:"), table, 6, 0, COLORSEL_RED,
1871 _("Amount of red light in the color."));
1872 make_label_spinbutton (colorsel, &priv->green_spinbutton, _("_Green:"), table, 6, 1, COLORSEL_GREEN,
1873 _("Amount of green light in the color."));
1874 make_label_spinbutton (colorsel, &priv->blue_spinbutton, _("_Blue:"), table, 6, 2, COLORSEL_BLUE,
1875 _("Amount of blue light in the color."));
1876 gtk_table_attach_defaults (GTK_TABLE (table), gtk_hseparator_new (), 0, 8, 3, 4);
1878 priv->opacity_label = gtk_label_new_with_mnemonic (_("_Opacity:"));
1879 gtk_misc_set_alignment (GTK_MISC (priv->opacity_label), 1.0, 0.5);
1880 gtk_table_attach_defaults (GTK_TABLE (table), priv->opacity_label, 0, 1, 4, 5);
1881 adjust = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 255.0, 1.0, 1.0, 0.0));
1882 g_object_set_data (G_OBJECT (adjust), "COLORSEL", colorsel);
1883 priv->opacity_slider = gtk_hscale_new (adjust);
1884 gtk_tooltips_set_tip (priv->tooltips,
1885 priv->opacity_slider,
1886 _("Transparency of the currently-selected color."), NULL);
1887 gtk_label_set_mnemonic_widget (GTK_LABEL (priv->opacity_label),
1888 priv->opacity_slider);
1889 gtk_scale_set_draw_value (GTK_SCALE (priv->opacity_slider), FALSE);
1890 g_signal_connect (adjust, "value_changed",
1891 G_CALLBACK (adjustment_changed),
1892 GINT_TO_POINTER (COLORSEL_OPACITY));
1893 gtk_table_attach_defaults (GTK_TABLE (table), priv->opacity_slider, 1, 7, 4, 5);
1894 priv->opacity_entry = gtk_entry_new ();
1895 gtk_widget_set_size_request (priv->opacity_entry, 40, -1);
1897 g_signal_connect (priv->opacity_entry, "activate",
1898 G_CALLBACK (opacity_entry_changed), colorsel);
1899 gtk_table_attach_defaults (GTK_TABLE (table), priv->opacity_entry, 7, 8, 4, 5);
1901 label = gtk_label_new_with_mnemonic (_("Color _Name:"));
1902 gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 5, 6);
1903 gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5);
1904 priv->hex_entry = gtk_entry_new ();
1906 gtk_label_set_mnemonic_widget (GTK_LABEL (label), priv->hex_entry);
1908 g_signal_connect (priv->hex_entry, "activate",
1909 G_CALLBACK (hex_changed), colorsel);
1911 g_signal_connect (priv->hex_entry, "focus_out_event",
1912 G_CALLBACK (hex_focus_out), colorsel);
1914 gtk_tooltips_set_tip (priv->tooltips,
1916 _("You can enter an HTML-style hexadecimal color value, or simply a color name such as 'orange' in this entry."), NULL);
1918 gtk_widget_set_size_request (priv->hex_entry, 75, -1);
1919 gtk_table_set_col_spacing (GTK_TABLE (table), 3, 15);
1920 gtk_table_attach_defaults (GTK_TABLE (table), priv->hex_entry, 1, 5, 5, 6);
1922 /* Set up the palette */
1923 table = gtk_table_new (GTK_CUSTOM_PALETTE_HEIGHT, GTK_CUSTOM_PALETTE_WIDTH, TRUE);
1924 gtk_table_set_row_spacings (GTK_TABLE (table), 1);
1925 gtk_table_set_col_spacings (GTK_TABLE (table), 1);
1926 for (i = 0; i < GTK_CUSTOM_PALETTE_WIDTH; i++)
1928 for (j = 0; j < GTK_CUSTOM_PALETTE_HEIGHT; j++)
1930 make_palette_frame (colorsel, table, i, j);
1933 set_selected_palette (colorsel, 0, 0);
1934 priv->palette_frame = gtk_frame_new (NULL);
1935 label = gtk_label_new_with_mnemonic (_("_Palette"));
1936 gtk_frame_set_label_widget (GTK_FRAME (priv->palette_frame), label);
1938 gtk_label_set_mnemonic_widget (GTK_LABEL (label),
1939 priv->custom_palette[0][0]);
1941 gtk_box_pack_end (GTK_BOX (top_right_vbox), priv->palette_frame, FALSE, FALSE, 0);
1942 vbox = gtk_vbox_new (FALSE, 4);
1943 gtk_container_add (GTK_CONTAINER (priv->palette_frame), vbox);
1944 gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0);
1946 gtk_container_set_border_width (GTK_CONTAINER (vbox), 4);
1948 gtk_widget_show_all (top_hbox);
1950 /* hide unused stuff */
1952 if (priv->has_opacity == FALSE)
1954 gtk_widget_hide (priv->opacity_label);
1955 gtk_widget_hide (priv->opacity_slider);
1956 gtk_widget_hide (priv->opacity_entry);
1959 if (priv->has_palette == FALSE)
1961 gtk_widget_hide (priv->palette_frame);
1964 gtk_widget_pop_composite_child ();
1968 gtk_color_selection_destroy (GtkObject *object)
1970 GtkColorSelection *cselection = GTK_COLOR_SELECTION (object);
1971 ColorSelectionPrivate *priv = cselection->private_data;
1973 if (priv->dropper_grab_widget)
1975 gtk_widget_destroy (priv->dropper_grab_widget);
1976 priv->dropper_grab_widget = NULL;
1981 g_object_unref (priv->tooltips);
1982 priv->tooltips = NULL;
1985 GTK_OBJECT_CLASS (parent_class)->destroy (object);
1989 gtk_color_selection_finalize (GObject *object)
1991 GtkColorSelection *cselection = GTK_COLOR_SELECTION (object);
1993 if (cselection->private_data)
1995 g_free (cselection->private_data);
1996 cselection->private_data = NULL;
1999 G_OBJECT_CLASS (parent_class)->finalize (object);
2003 gtk_color_selection_realize (GtkWidget *widget)
2005 GtkColorSelection *colorsel = GTK_COLOR_SELECTION (widget);
2006 ColorSelectionPrivate *priv = colorsel->private_data;
2007 GtkSettings *settings = gtk_widget_get_settings (widget);
2009 priv->settings_connection = g_signal_connect (settings,
2010 "notify::gtk-color-palette",
2011 G_CALLBACK (palette_change_notify_instance),
2013 update_palette (colorsel);
2015 GTK_WIDGET_CLASS (parent_class)->realize (widget);
2019 gtk_color_selection_unrealize (GtkWidget *widget)
2021 GtkColorSelection *colorsel = GTK_COLOR_SELECTION (widget);
2022 ColorSelectionPrivate *priv = colorsel->private_data;
2023 GtkSettings *settings = gtk_widget_get_settings (widget);
2025 g_signal_handler_disconnect (settings, priv->settings_connection);
2027 GTK_WIDGET_CLASS (parent_class)->unrealize (widget);
2030 /* We override show-all since we have internal widgets that
2031 * shouldn't be shown when you call show_all(), like the
2032 * palette and opacity sliders.
2035 gtk_color_selection_show_all (GtkWidget *widget)
2037 gtk_widget_show (widget);
2041 * gtk_color_selection_new:
2043 * Creates a new GtkColorSelection.
2045 * Return value: a new #GtkColorSelection
2048 gtk_color_selection_new (void)
2050 GtkColorSelection *colorsel;
2051 ColorSelectionPrivate *priv;
2058 colorsel = g_object_new (GTK_TYPE_COLOR_SELECTION, NULL);
2059 priv = colorsel->private_data;
2060 set_color_internal (colorsel, color);
2061 gtk_color_selection_set_has_opacity_control (colorsel, TRUE);
2063 /* We want to make sure that default_set is FALSE */
2064 /* This way the user can still set it */
2065 priv->default_set = FALSE;
2066 priv->default_alpha_set = FALSE;
2068 return GTK_WIDGET (colorsel);
2073 gtk_color_selection_set_update_policy (GtkColorSelection *colorsel,
2074 GtkUpdateType policy)
2076 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2080 * gtk_color_selection_get_has_opacity_control:
2081 * @colorsel: a #GtkColorSelection.
2083 * Determines whether the colorsel has an opacity control.
2085 * Return value: %TRUE if the @colorsel has an opacity control. %FALSE if it does't.
2088 gtk_color_selection_get_has_opacity_control (GtkColorSelection *colorsel)
2090 ColorSelectionPrivate *priv;
2092 g_return_val_if_fail (GTK_IS_COLOR_SELECTION (colorsel), FALSE);
2094 priv = colorsel->private_data;
2096 return priv->has_opacity;
2100 * gtk_color_selection_set_has_opacity_control:
2101 * @colorsel: a #GtkColorSelection.
2102 * @has_opacity: %TRUE if @colorsel can set the opacity, %FALSE otherwise.
2104 * Sets the @colorsel to use or not use opacity.
2108 gtk_color_selection_set_has_opacity_control (GtkColorSelection *colorsel,
2109 gboolean has_opacity)
2111 ColorSelectionPrivate *priv;
2113 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2115 priv = colorsel->private_data;
2116 has_opacity = has_opacity != FALSE;
2118 if (priv->has_opacity != has_opacity)
2120 priv->has_opacity = has_opacity;
2123 gtk_widget_show (priv->opacity_slider);
2124 gtk_widget_show (priv->opacity_label);
2125 gtk_widget_show (priv->opacity_entry);
2129 gtk_widget_hide (priv->opacity_slider);
2130 gtk_widget_hide (priv->opacity_label);
2131 gtk_widget_hide (priv->opacity_entry);
2133 color_sample_draw_samples (colorsel);
2135 g_object_notify (G_OBJECT (colorsel), "has_opacity_control");
2140 * gtk_color_selection_get_has_palette:
2141 * @colorsel: a #GtkColorSelection.
2143 * Determines whether the color selector has a color palette.
2145 * Return value: %TRUE if the selector has a palette. %FALSE if it hasn't.
2148 gtk_color_selection_get_has_palette (GtkColorSelection *colorsel)
2150 ColorSelectionPrivate *priv;
2152 g_return_val_if_fail (GTK_IS_COLOR_SELECTION (colorsel), FALSE);
2154 priv = colorsel->private_data;
2156 return priv->has_palette;
2160 * gtk_color_selection_set_has_palette:
2161 * @colorsel: a #GtkColorSelection.
2162 * @has_palette: %TRUE if palette is to be visible, %FALSE otherwise.
2164 * Shows and hides the palette based upon the value of @has_palette.
2168 gtk_color_selection_set_has_palette (GtkColorSelection *colorsel,
2169 gboolean has_palette)
2171 ColorSelectionPrivate *priv;
2172 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2174 priv = colorsel->private_data;
2175 has_palette = has_palette != FALSE;
2177 if (priv->has_palette != has_palette)
2179 priv->has_palette = has_palette;
2181 gtk_widget_show (priv->palette_frame);
2183 gtk_widget_hide (priv->palette_frame);
2185 g_object_notify (G_OBJECT (colorsel), "has_palette");
2190 * gtk_color_selection_set_current_color:
2191 * @colorsel: a #GtkColorSelection.
2192 * @color: A #GdkColor to set the current color with.
2194 * Sets the current color to be @color. The first time this is called, it will
2195 * also set the original color to be @color too.
2198 gtk_color_selection_set_current_color (GtkColorSelection *colorsel,
2201 ColorSelectionPrivate *priv;
2203 gboolean previous_changed;
2205 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2207 priv = colorsel->private_data;
2208 priv->changing = TRUE;
2209 priv->color[COLORSEL_RED] = SCALE (color->red);
2210 priv->color[COLORSEL_GREEN] = SCALE (color->green);
2211 priv->color[COLORSEL_BLUE] = SCALE (color->blue);
2212 gtk_rgb_to_hsv (priv->color[COLORSEL_RED],
2213 priv->color[COLORSEL_GREEN],
2214 priv->color[COLORSEL_BLUE],
2215 &priv->color[COLORSEL_HUE],
2216 &priv->color[COLORSEL_SATURATION],
2217 &priv->color[COLORSEL_VALUE]);
2218 if (priv->default_set == FALSE)
2220 previous_changed = TRUE;
2221 for (i = 0; i < COLORSEL_NUM_CHANNELS; i++)
2222 priv->old_color[i] = priv->color[i];
2224 priv->default_set = TRUE;
2225 update_color (colorsel);
2229 * gtk_color_selection_set_current_alpha:
2230 * @colorsel: a #GtkColorSelection.
2231 * @alpha: an integer between 0 and 65535.
2233 * Sets the current opacity to be @alpha. The first time this is called, it will
2234 * also set the original opacity to be @alpha too.
2237 gtk_color_selection_set_current_alpha (GtkColorSelection *colorsel,
2240 ColorSelectionPrivate *priv;
2243 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2245 priv = colorsel->private_data;
2246 priv->changing = TRUE;
2247 priv->color[COLORSEL_OPACITY] = SCALE (alpha);
2248 if (priv->default_alpha_set == FALSE)
2250 for (i = 0; i < COLORSEL_NUM_CHANNELS; i++)
2251 priv->old_color[i] = priv->color[i];
2253 priv->default_alpha_set = TRUE;
2254 update_color (colorsel);
2258 * gtk_color_selection_set_color:
2259 * @colorsel: a #GtkColorSelection.
2260 * @color: an array of 4 doubles specifying the red, green, blue and opacity
2261 * to set the current color to.
2263 * Sets the current color to be @color. The first time this is called, it will
2264 * also set the original color to be @color too.
2266 * Deprecated: Use gtk_color_selection_set_current_color() instead.
2269 gtk_color_selection_set_color (GtkColorSelection *colorsel,
2272 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2274 set_color_internal (colorsel, color);
2278 * gtk_color_selection_get_current_color:
2279 * @colorsel: a #GtkColorSelection.
2280 * @color: a #GdkColor to fill in with the current color.
2282 * Sets @color to be the current color in the GtkColorSelection widget.
2285 gtk_color_selection_get_current_color (GtkColorSelection *colorsel,
2288 ColorSelectionPrivate *priv;
2290 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2292 priv = colorsel->private_data;
2293 color->red = UNSCALE (priv->color[COLORSEL_RED]);
2294 color->green = UNSCALE (priv->color[COLORSEL_GREEN]);
2295 color->blue = UNSCALE (priv->color[COLORSEL_BLUE]);
2299 * gtk_color_selection_get_current_alpha:
2300 * @colorsel: a #GtkColorSelection.
2302 * Returns the current alpha value.
2304 * Return value: an integer between 0 and 65535.
2307 gtk_color_selection_get_current_alpha (GtkColorSelection *colorsel)
2309 ColorSelectionPrivate *priv;
2311 g_return_val_if_fail (GTK_IS_COLOR_SELECTION (colorsel), 0);
2313 priv = colorsel->private_data;
2314 return priv->has_opacity ? UNSCALE (priv->color[COLORSEL_OPACITY]) : 65535;
2318 * gtk_color_selection_get_color:
2319 * @colorsel: a #GtkColorSelection.
2320 * @color: an array of 4 #gdouble to fill in with the current color.
2322 * Sets @color to be the current color in the GtkColorSelection widget.
2324 * This function is deprecated, use gtk_color_selection_get_current_color() instead.
2327 gtk_color_selection_get_color (GtkColorSelection *colorsel,
2330 ColorSelectionPrivate *priv;
2332 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2334 priv = colorsel->private_data;
2335 color[0] = priv->color[COLORSEL_RED];
2336 color[1] = priv->color[COLORSEL_GREEN];
2337 color[2] = priv->color[COLORSEL_BLUE];
2338 color[3] = priv->has_opacity ? priv->color[COLORSEL_OPACITY] : 65535;
2342 * gtk_color_selection_set_previous_color:
2343 * @colorsel: a #GtkColorSelection.
2344 * @color: a #GdkColor to set the previous color with.
2346 * Sets the 'previous' color to be @color. This function should be called with
2347 * some hesitations, as it might seem confusing to have that color change.
2348 * Calling gtk_color_selection_set_current_color() will also set this color the first
2349 * time it is called.
2352 gtk_color_selection_set_previous_color (GtkColorSelection *colorsel,
2355 ColorSelectionPrivate *priv;
2357 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2359 priv = colorsel->private_data;
2360 priv->changing = TRUE;
2361 priv->old_color[COLORSEL_RED] = SCALE (color->red);
2362 priv->old_color[COLORSEL_GREEN] = SCALE (color->green);
2363 priv->old_color[COLORSEL_BLUE] = SCALE (color->blue);
2364 gtk_rgb_to_hsv (priv->old_color[COLORSEL_RED],
2365 priv->old_color[COLORSEL_GREEN],
2366 priv->old_color[COLORSEL_BLUE],
2367 &priv->old_color[COLORSEL_HUE],
2368 &priv->old_color[COLORSEL_SATURATION],
2369 &priv->old_color[COLORSEL_VALUE]);
2370 color_sample_draw_samples (colorsel);
2371 priv->default_set = TRUE;
2372 priv->changing = FALSE;
2376 * gtk_color_selection_set_previous_alpha:
2377 * @colorsel: a #GtkColorSelection.
2378 * @alpha: an integer between 0 and 65535.
2380 * Sets the 'previous' alpha to be @alpha. This function should be called with
2381 * some hesitations, as it might seem confusing to have that alpha change.
2384 gtk_color_selection_set_previous_alpha (GtkColorSelection *colorsel,
2387 ColorSelectionPrivate *priv;
2389 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2391 priv = colorsel->private_data;
2392 priv->changing = TRUE;
2393 priv->old_color[COLORSEL_OPACITY] = SCALE (alpha);
2394 color_sample_draw_samples (colorsel);
2395 priv->default_alpha_set = TRUE;
2396 priv->changing = FALSE;
2401 * gtk_color_selection_get_previous_color:
2402 * @colorsel: a #GtkColorSelection.
2403 * @color: a #GdkColor to fill in with the original color value.
2405 * Fills @color in with the original color value.
2408 gtk_color_selection_get_previous_color (GtkColorSelection *colorsel,
2411 ColorSelectionPrivate *priv;
2413 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2415 priv = colorsel->private_data;
2416 color->red = UNSCALE (priv->old_color[COLORSEL_RED]);
2417 color->green = UNSCALE (priv->old_color[COLORSEL_GREEN]);
2418 color->blue = UNSCALE (priv->old_color[COLORSEL_BLUE]);
2422 * gtk_color_selection_get_previous_alpha:
2423 * @colorsel: a #GtkColorSelection.
2425 * Returns the previous alpha value.
2427 * Return value: an integer between 0 and 65535.
2430 gtk_color_selection_get_previous_alpha (GtkColorSelection *colorsel)
2432 ColorSelectionPrivate *priv;
2434 g_return_val_if_fail (GTK_IS_COLOR_SELECTION (colorsel), 0);
2436 priv = colorsel->private_data;
2437 return priv->has_opacity ? UNSCALE (priv->old_color[COLORSEL_OPACITY]) : 65535;
2441 * gtk_color_selection_set_palette_color:
2442 * @colorsel: a #GtkColorSelection.
2443 * @index: the color index of the palette.
2444 * @color: A #GdkColor to set the palette with.
2446 * Sets the palette located at @index to have @color as its color.
2450 gtk_color_selection_set_palette_color (GtkColorSelection *colorsel,
2454 ColorSelectionPrivate *priv;
2458 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2459 g_return_if_fail (index >= 0 && index < GTK_CUSTOM_PALETTE_WIDTH*GTK_CUSTOM_PALETTE_HEIGHT);
2461 x = index % GTK_CUSTOM_PALETTE_WIDTH;
2462 y = index / GTK_CUSTOM_PALETTE_WIDTH;
2464 priv = colorsel->private_data;
2465 col[0] = SCALE (color->red);
2466 col[1] = SCALE (color->green);
2467 col[2] = SCALE (color->blue);
2469 palette_set_color (priv->custom_palette[x][y], colorsel, col);
2473 * gtk_color_selection_is_adjusting:
2474 * @colorsel: a #GtkColorSelection.
2476 * Gets the current state of the @colorsel.
2478 * Return value: %TRUE if the user is currently dragging a color around, and %FALSE
2479 * if the selection has stopped.
2482 gtk_color_selection_is_adjusting (GtkColorSelection *colorsel)
2484 ColorSelectionPrivate *priv;
2486 g_return_val_if_fail (GTK_IS_COLOR_SELECTION (colorsel), FALSE);
2488 priv = colorsel->private_data;
2490 return (gtk_hsv_is_adjusting (GTK_HSV (priv->triangle_colorsel)));
2494 gtk_color_selection_set_property (GObject *object,
2496 const GValue *value,
2499 GtkColorSelection *colorsel = GTK_COLOR_SELECTION (object);
2503 case PROP_HAS_OPACITY_CONTROL:
2504 gtk_color_selection_set_has_opacity_control (colorsel,
2505 g_value_get_boolean (value));
2507 case PROP_HAS_PALETTE:
2508 gtk_color_selection_set_has_palette (colorsel,
2509 g_value_get_boolean (value));
2511 case PROP_CURRENT_COLOR:
2512 gtk_color_selection_set_current_color (colorsel, g_value_get_boxed (value));
2514 case PROP_CURRENT_ALPHA:
2515 gtk_color_selection_set_current_alpha (colorsel, g_value_get_uint (value));
2518 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
2525 gtk_color_selection_get_property (GObject *object,
2530 GtkColorSelection *colorsel = GTK_COLOR_SELECTION (object);
2535 case PROP_HAS_OPACITY_CONTROL:
2536 g_value_set_boolean (value, gtk_color_selection_get_has_opacity_control (colorsel));
2538 case PROP_HAS_PALETTE:
2539 g_value_set_boolean (value, gtk_color_selection_get_has_palette (colorsel));
2541 case PROP_CURRENT_COLOR:
2542 gtk_color_selection_get_current_color (colorsel, &color);
2543 g_value_set_boxed (value, &color);
2545 case PROP_CURRENT_ALPHA:
2546 g_value_set_uint (value, gtk_color_selection_get_current_alpha (colorsel));
2549 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
2556 * gtk_color_selection_palette_from_string:
2557 * @str: a string encoding a color palette.
2558 * @colors: return location for allocated array of #GdkColor.
2559 * @n_colors: return location for length of array.
2561 * Parses a color palette string; the string is a colon-separated
2562 * list of color names readable by gdk_color_parse().
2564 * Return value: %TRUE if a palette was successfully parsed.
2567 gtk_color_selection_palette_from_string (const gchar *str,
2579 copy = g_strdup (str);
2585 if (*p == ':' || *p == '\0')
2587 gboolean done = TRUE;
2591 goto failed; /* empty entry */
2600 retval = g_renew (GdkColor, retval, count + 1);
2601 if (!gdk_color_parse (start, retval + count))
2642 * gtk_color_selection_palette_to_string:
2643 * @colors: an array of colors.
2644 * @n_colors: length of the array.
2646 * Encodes a palette as a string, useful for persistent storage.
2648 * Return value: allocated string encoding the palette.
2651 gtk_color_selection_palette_to_string (const GdkColor *colors,
2655 gchar **strs = NULL;
2659 return g_strdup ("");
2661 strs = g_new0 (gchar*, n_colors + 1);
2664 while (i < n_colors)
2669 g_strdup_printf ("#%2X%2X%2X",
2670 colors[i].red / 256,
2671 colors[i].green / 256,
2672 colors[i].blue / 256);
2674 for (ptr = strs[i]; *ptr; ptr++)
2681 retval = g_strjoinv (":", strs);
2689 * gtk_color_selection_set_change_palette_hook:
2690 * @func: a function to call when the custom palette needs saving.
2692 * Installs a global function to be called whenever the user tries to
2693 * modify the palette in a color selection. This function should save
2694 * the new palette contents, and update the GtkSettings property
2695 * "gtk-color-palette" so all GtkColorSelection widgets will be modified.
2697 * Return value: the previous change palette hook (that was replaced).
2699 * Deprecated: This function is deprecated in favor of
2700 * gtk_color_selection_set_change_palette_with_screen_hook(), and does
2701 * not work in multihead environments.
2704 GtkColorSelectionChangePaletteFunc
2705 gtk_color_selection_set_change_palette_hook (GtkColorSelectionChangePaletteFunc func)
2707 GtkColorSelectionChangePaletteFunc old;
2709 old = noscreen_change_palette_hook;
2711 noscreen_change_palette_hook = func;
2717 * gtk_color_selection_set_change_palette_with_screen_hook:
2718 * @func: a function to call when the custom palette needs saving.
2720 * Installs a global function to be called whenever the user tries to
2721 * modify the palette in a color selection. This function should save
2722 * the new palette contents, and update the GtkSettings property
2723 * "gtk-color-palette" so all GtkColorSelection widgets will be modified.
2725 * Return value: the previous change palette hook (that was replaced).
2729 GtkColorSelectionChangePaletteWithScreenFunc
2730 gtk_color_selection_set_change_palette_with_screen_hook (GtkColorSelectionChangePaletteWithScreenFunc func)
2732 GtkColorSelectionChangePaletteWithScreenFunc old;
2734 old = change_palette_hook;
2736 change_palette_hook = func;