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/.
32 #include "gdkconfig.h"
33 #include "gdk/gdkkeysyms.h"
34 #include "gtkcolorsel.h"
36 #include "gtkwindow.h"
37 #include "gtkselection.h"
39 #include "gtkdrawingarea.h"
46 #include "gtkmarshalers.h"
48 #include "gtkspinbutton.h"
50 #include "gtkhscale.h"
52 #include "gtkbutton.h"
53 #include "gtkhseparator.h"
54 #include "gtkinvisible.h"
55 #include "gtkmenuitem.h"
57 #include "gtksettings.h"
59 #include "gtkaccessible.h"
60 #include "gtkprivate.h"
64 /* Number of elements in the custom palatte */
65 #define GTK_CUSTOM_PALETTE_WIDTH 10
66 #define GTK_CUSTOM_PALETTE_HEIGHT 2
68 #define CUSTOM_PALETTE_ENTRY_WIDTH 20
69 #define CUSTOM_PALETTE_ENTRY_HEIGHT 20
71 /* The cursor for the dropper */
72 #define DROPPER_WIDTH 17
73 #define DROPPER_HEIGHT 17
74 #define DROPPER_X_HOT 2
75 #define DROPPER_Y_HOT 16
77 #define SAMPLE_WIDTH 64
78 #define SAMPLE_HEIGHT 28
82 /* Conversion between 0->1 double and and guint16. See
83 * scale_round() below for more general conversions
85 #define SCALE(i) (i / 65535.)
86 #define UNSCALE(d) ((guint16)(d * 65535 + 0.5))
87 #define INTENSITY(r, g, b) ((r) * 0.30 + (g) * 0.59 + (b) * 0.11)
97 PROP_HAS_OPACITY_CONTROL,
106 COLORSEL_OPACITY = 3,
110 COLORSEL_NUM_CHANNELS
113 typedef struct _ColorSelectionPrivate ColorSelectionPrivate;
115 struct _ColorSelectionPrivate
117 guint has_opacity : 1;
118 guint has_palette : 1;
120 guint default_set : 1;
121 guint default_alpha_set : 1;
124 gdouble color[COLORSEL_NUM_CHANNELS];
125 gdouble old_color[COLORSEL_NUM_CHANNELS];
127 GtkWidget *triangle_colorsel;
128 GtkWidget *hue_spinbutton;
129 GtkWidget *sat_spinbutton;
130 GtkWidget *val_spinbutton;
131 GtkWidget *red_spinbutton;
132 GtkWidget *green_spinbutton;
133 GtkWidget *blue_spinbutton;
134 GtkWidget *opacity_slider;
135 GtkWidget *opacity_label;
136 GtkWidget *opacity_entry;
137 GtkWidget *palette_frame;
138 GtkWidget *hex_entry;
140 /* The Palette code */
141 GtkWidget *custom_palette [GTK_CUSTOM_PALETTE_WIDTH][GTK_CUSTOM_PALETTE_HEIGHT];
143 /* The color_sample stuff */
144 GtkWidget *sample_area;
145 GtkWidget *old_sample;
146 GtkWidget *cur_sample;
149 /* Window for grabbing on */
150 GtkWidget *dropper_grab_widget;
153 /* Connection to settings */
154 gulong settings_connection;
158 static void gtk_color_selection_destroy (GtkObject *object);
159 static void gtk_color_selection_finalize (GObject *object);
160 static void update_color (GtkColorSelection *colorsel);
161 static void gtk_color_selection_set_property (GObject *object,
165 static void gtk_color_selection_get_property (GObject *object,
170 static void gtk_color_selection_realize (GtkWidget *widget);
171 static void gtk_color_selection_unrealize (GtkWidget *widget);
172 static void gtk_color_selection_show_all (GtkWidget *widget);
173 static gboolean gtk_color_selection_grab_broken (GtkWidget *widget,
174 GdkEventGrabBroken *event);
176 static void gtk_color_selection_set_palette_color (GtkColorSelection *colorsel,
179 static void set_focus_line_attributes (GtkWidget *drawing_area,
182 static void default_noscreen_change_palette_func (const GdkColor *colors,
184 static void default_change_palette_func (GdkScreen *screen,
185 const GdkColor *colors,
187 static void make_control_relations (AtkObject *atk_obj,
189 static void make_all_relations (AtkObject *atk_obj,
190 ColorSelectionPrivate *priv);
192 static void hsv_changed (GtkWidget *hsv,
194 static void get_screen_color (GtkWidget *button);
195 static void adjustment_changed (GtkAdjustment *adjustment,
197 static void opacity_entry_changed (GtkWidget *opacity_entry,
199 static void hex_changed (GtkWidget *hex_entry,
201 static gboolean hex_focus_out (GtkWidget *hex_entry,
202 GdkEventFocus *event,
204 static void color_sample_new (GtkColorSelection *colorsel);
205 static void make_label_spinbutton (GtkColorSelection *colorsel,
206 GtkWidget **spinbutton,
212 const gchar *tooltip);
213 static void make_palette_frame (GtkColorSelection *colorsel,
217 static void set_selected_palette (GtkColorSelection *colorsel,
220 static void set_focus_line_attributes (GtkWidget *drawing_area,
223 static gboolean mouse_press (GtkWidget *invisible,
224 GdkEventButton *event,
226 static void palette_change_notify_instance (GObject *object,
229 static void update_palette (GtkColorSelection *colorsel);
230 static void shutdown_eyedropper (GtkWidget *widget);
232 static guint color_selection_signals[LAST_SIGNAL] = { 0 };
234 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";
236 static GtkColorSelectionChangePaletteFunc noscreen_change_palette_hook = default_noscreen_change_palette_func;
237 static GtkColorSelectionChangePaletteWithScreenFunc change_palette_hook = default_change_palette_func;
239 static const guchar dropper_bits[] = {
240 0xff, 0x8f, 0x01, 0xff, 0x77, 0x01, 0xff, 0xfb, 0x00, 0xff, 0xf8, 0x00,
241 0x7f, 0xff, 0x00, 0xff, 0x7e, 0x01, 0xff, 0x9d, 0x01, 0xff, 0xd8, 0x01,
242 0x7f, 0xd4, 0x01, 0x3f, 0xee, 0x01, 0x1f, 0xff, 0x01, 0x8f, 0xff, 0x01,
243 0xc7, 0xff, 0x01, 0xe3, 0xff, 0x01, 0xf3, 0xff, 0x01, 0xfd, 0xff, 0x01,
246 static const guchar dropper_mask[] = {
247 0x00, 0x70, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xfc, 0x01, 0x00, 0xff, 0x01,
248 0x80, 0xff, 0x01, 0x00, 0xff, 0x00, 0x00, 0x7f, 0x00, 0x80, 0x3f, 0x00,
249 0xc0, 0x3f, 0x00, 0xe0, 0x13, 0x00, 0xf0, 0x01, 0x00, 0xf8, 0x00, 0x00,
250 0x7c, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x0d, 0x00, 0x00,
253 G_DEFINE_TYPE (GtkColorSelection, gtk_color_selection, GTK_TYPE_VBOX)
256 gtk_color_selection_class_init (GtkColorSelectionClass *klass)
258 GObjectClass *gobject_class;
259 GtkObjectClass *object_class;
260 GtkWidgetClass *widget_class;
262 gobject_class = G_OBJECT_CLASS (klass);
263 gobject_class->finalize = gtk_color_selection_finalize;
264 gobject_class->set_property = gtk_color_selection_set_property;
265 gobject_class->get_property = gtk_color_selection_get_property;
267 object_class = GTK_OBJECT_CLASS (klass);
268 object_class->destroy = gtk_color_selection_destroy;
270 widget_class = GTK_WIDGET_CLASS (klass);
271 widget_class->realize = gtk_color_selection_realize;
272 widget_class->unrealize = gtk_color_selection_unrealize;
273 widget_class->show_all = gtk_color_selection_show_all;
274 widget_class->grab_broken_event = gtk_color_selection_grab_broken;
276 g_object_class_install_property (gobject_class,
277 PROP_HAS_OPACITY_CONTROL,
278 g_param_spec_boolean ("has-opacity-control",
279 P_("Has Opacity Control"),
280 P_("Whether the color selector should allow setting opacity"),
282 GTK_PARAM_READWRITE));
283 g_object_class_install_property (gobject_class,
285 g_param_spec_boolean ("has-palette",
287 P_("Whether a palette should be used"),
289 GTK_PARAM_READWRITE));
290 g_object_class_install_property (gobject_class,
292 g_param_spec_boxed ("current-color",
294 P_("The current color"),
296 GTK_PARAM_READWRITE));
297 g_object_class_install_property (gobject_class,
299 g_param_spec_uint ("current-alpha",
301 P_("The current opacity value (0 fully transparent, 65535 fully opaque)"),
303 GTK_PARAM_READWRITE));
305 color_selection_signals[COLOR_CHANGED] =
306 g_signal_new (I_("color_changed"),
307 G_OBJECT_CLASS_TYPE (object_class),
309 G_STRUCT_OFFSET (GtkColorSelectionClass, color_changed),
311 _gtk_marshal_VOID__VOID,
314 gtk_settings_install_property (g_param_spec_string ("gtk-color-palette",
315 P_("Custom palette"),
316 P_("Palette to use in the color selector"),
318 GTK_PARAM_READWRITE));
320 g_type_class_add_private (gobject_class, sizeof (ColorSelectionPrivate));
324 gtk_color_selection_init (GtkColorSelection *colorsel)
327 GtkWidget *top_right_vbox;
328 GtkWidget *table, *label, *hbox, *frame, *vbox, *button;
329 GtkAdjustment *adjust;
330 GtkWidget *picker_image;
332 ColorSelectionPrivate *priv;
334 GList *focus_chain = NULL;
336 gtk_widget_push_composite_child ();
338 priv = colorsel->private_data = G_TYPE_INSTANCE_GET_PRIVATE (colorsel, GTK_TYPE_COLOR_SELECTION, ColorSelectionPrivate);
339 priv->changing = FALSE;
340 priv->default_set = FALSE;
341 priv->default_alpha_set = FALSE;
343 top_hbox = gtk_hbox_new (FALSE, 12);
344 gtk_box_pack_start (GTK_BOX (colorsel), top_hbox, FALSE, FALSE, 0);
346 vbox = gtk_vbox_new (FALSE, 6);
347 priv->triangle_colorsel = gtk_hsv_new ();
348 g_signal_connect (priv->triangle_colorsel, "changed",
349 G_CALLBACK (hsv_changed), colorsel);
350 gtk_hsv_set_metrics (GTK_HSV (priv->triangle_colorsel), 174, 15);
351 gtk_box_pack_start (GTK_BOX (top_hbox), vbox, FALSE, FALSE, 0);
352 gtk_box_pack_start (GTK_BOX (vbox), priv->triangle_colorsel, FALSE, FALSE, 0);
353 gtk_widget_set_tooltip_text (priv->triangle_colorsel,
354 _("Select the color you want from the outer ring. Select the darkness or lightness of that color using the inner triangle."));
356 hbox = gtk_hbox_new (FALSE, 6);
357 gtk_box_pack_end (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
359 frame = gtk_frame_new (NULL);
360 gtk_widget_set_size_request (frame, -1, 30);
361 gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
362 color_sample_new (colorsel);
363 gtk_container_add (GTK_CONTAINER (frame), priv->sample_area);
364 gtk_box_pack_start (GTK_BOX (hbox), frame, TRUE, TRUE, 0);
366 button = gtk_button_new ();
368 gtk_widget_set_events (button, GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK);
369 g_object_set_data (G_OBJECT (button), I_("COLORSEL"), colorsel);
370 g_signal_connect (button, "clicked",
371 G_CALLBACK (get_screen_color), NULL);
372 picker_image = gtk_image_new_from_stock (GTK_STOCK_COLOR_PICKER, GTK_ICON_SIZE_BUTTON);
373 gtk_container_add (GTK_CONTAINER (button), picker_image);
374 gtk_widget_show (GTK_WIDGET (picker_image));
375 gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
377 gtk_widget_set_tooltip_text (button,
378 _("Click the eyedropper, then click a color anywhere on your screen to select that color."));
380 top_right_vbox = gtk_vbox_new (FALSE, 6);
381 gtk_box_pack_start (GTK_BOX (top_hbox), top_right_vbox, FALSE, FALSE, 0);
382 table = gtk_table_new (8, 6, FALSE);
383 gtk_box_pack_start (GTK_BOX (top_right_vbox), table, FALSE, FALSE, 0);
384 gtk_table_set_row_spacings (GTK_TABLE (table), 6);
385 gtk_table_set_col_spacings (GTK_TABLE (table), 12);
387 make_label_spinbutton (colorsel, &priv->hue_spinbutton, _("_Hue:"), table, 0, 0, COLORSEL_HUE,
388 _("Position on the color wheel."));
389 gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (priv->hue_spinbutton), TRUE);
390 make_label_spinbutton (colorsel, &priv->sat_spinbutton, _("_Saturation:"), table, 0, 1, COLORSEL_SATURATION,
391 _("\"Deepness\" of the color."));
392 make_label_spinbutton (colorsel, &priv->val_spinbutton, _("_Value:"), table, 0, 2, COLORSEL_VALUE,
393 _("Brightness of the color."));
394 make_label_spinbutton (colorsel, &priv->red_spinbutton, _("_Red:"), table, 6, 0, COLORSEL_RED,
395 _("Amount of red light in the color."));
396 make_label_spinbutton (colorsel, &priv->green_spinbutton, _("_Green:"), table, 6, 1, COLORSEL_GREEN,
397 _("Amount of green light in the color."));
398 make_label_spinbutton (colorsel, &priv->blue_spinbutton, _("_Blue:"), table, 6, 2, COLORSEL_BLUE,
399 _("Amount of blue light in the color."));
400 gtk_table_attach_defaults (GTK_TABLE (table), gtk_hseparator_new (), 0, 8, 3, 4);
402 priv->opacity_label = gtk_label_new_with_mnemonic (_("Op_acity:"));
403 gtk_misc_set_alignment (GTK_MISC (priv->opacity_label), 0.0, 0.5);
404 gtk_table_attach_defaults (GTK_TABLE (table), priv->opacity_label, 0, 1, 4, 5);
405 adjust = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 255.0, 1.0, 1.0, 0.0));
406 g_object_set_data (G_OBJECT (adjust), I_("COLORSEL"), colorsel);
407 priv->opacity_slider = gtk_hscale_new (adjust);
408 gtk_widget_set_tooltip_text (priv->opacity_slider,
409 _("Transparency of the color."));
410 gtk_label_set_mnemonic_widget (GTK_LABEL (priv->opacity_label),
411 priv->opacity_slider);
412 gtk_scale_set_draw_value (GTK_SCALE (priv->opacity_slider), FALSE);
413 g_signal_connect (adjust, "value_changed",
414 G_CALLBACK (adjustment_changed),
415 GINT_TO_POINTER (COLORSEL_OPACITY));
416 gtk_table_attach_defaults (GTK_TABLE (table), priv->opacity_slider, 1, 7, 4, 5);
417 priv->opacity_entry = gtk_entry_new ();
418 gtk_widget_set_tooltip_text (priv->opacity_entry,
419 _("Transparency of the color."));
420 gtk_widget_set_size_request (priv->opacity_entry, 40, -1);
422 g_signal_connect (priv->opacity_entry, "activate",
423 G_CALLBACK (opacity_entry_changed), colorsel);
424 gtk_table_attach_defaults (GTK_TABLE (table), priv->opacity_entry, 7, 8, 4, 5);
426 label = gtk_label_new_with_mnemonic (_("Color _name:"));
427 gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 5, 6);
428 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
429 priv->hex_entry = gtk_entry_new ();
431 gtk_label_set_mnemonic_widget (GTK_LABEL (label), priv->hex_entry);
433 g_signal_connect (priv->hex_entry, "activate",
434 G_CALLBACK (hex_changed), colorsel);
436 g_signal_connect (priv->hex_entry, "focus_out_event",
437 G_CALLBACK (hex_focus_out), colorsel);
439 gtk_widget_set_tooltip_text (priv->hex_entry,
440 _("You can enter an HTML-style hexadecimal color value, or simply a color name such as 'orange' in this entry."));
442 gtk_entry_set_width_chars (GTK_ENTRY (priv->hex_entry), 7);
443 gtk_table_attach_defaults (GTK_TABLE (table), priv->hex_entry, 1, 5, 5, 6);
445 focus_chain = g_list_append (focus_chain, priv->hue_spinbutton);
446 focus_chain = g_list_append (focus_chain, priv->sat_spinbutton);
447 focus_chain = g_list_append (focus_chain, priv->val_spinbutton);
448 focus_chain = g_list_append (focus_chain, priv->red_spinbutton);
449 focus_chain = g_list_append (focus_chain, priv->green_spinbutton);
450 focus_chain = g_list_append (focus_chain, priv->blue_spinbutton);
451 focus_chain = g_list_append (focus_chain, priv->opacity_slider);
452 focus_chain = g_list_append (focus_chain, priv->opacity_entry);
453 focus_chain = g_list_append (focus_chain, priv->hex_entry);
454 gtk_container_set_focus_chain (GTK_CONTAINER (table), focus_chain);
455 g_list_free (focus_chain);
457 /* Set up the palette */
458 table = gtk_table_new (GTK_CUSTOM_PALETTE_HEIGHT, GTK_CUSTOM_PALETTE_WIDTH, TRUE);
459 gtk_table_set_row_spacings (GTK_TABLE (table), 1);
460 gtk_table_set_col_spacings (GTK_TABLE (table), 1);
461 for (i = 0; i < GTK_CUSTOM_PALETTE_WIDTH; i++)
463 for (j = 0; j < GTK_CUSTOM_PALETTE_HEIGHT; j++)
465 make_palette_frame (colorsel, table, i, j);
468 set_selected_palette (colorsel, 0, 0);
469 priv->palette_frame = gtk_vbox_new (FALSE, 6);
470 label = gtk_label_new_with_mnemonic (_("_Palette:"));
471 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
472 gtk_box_pack_start (GTK_BOX (priv->palette_frame), label, FALSE, FALSE, 0);
474 gtk_label_set_mnemonic_widget (GTK_LABEL (label),
475 priv->custom_palette[0][0]);
477 gtk_box_pack_end (GTK_BOX (top_right_vbox), priv->palette_frame, FALSE, FALSE, 0);
478 gtk_box_pack_start (GTK_BOX (priv->palette_frame), table, FALSE, FALSE, 0);
480 gtk_widget_show_all (top_hbox);
482 /* hide unused stuff */
484 if (priv->has_opacity == FALSE)
486 gtk_widget_hide (priv->opacity_label);
487 gtk_widget_hide (priv->opacity_slider);
488 gtk_widget_hide (priv->opacity_entry);
491 if (priv->has_palette == FALSE)
493 gtk_widget_hide (priv->palette_frame);
496 atk_obj = gtk_widget_get_accessible (priv->triangle_colorsel);
497 if (GTK_IS_ACCESSIBLE (atk_obj))
499 atk_object_set_name (atk_obj, _("Color Wheel"));
500 atk_object_set_role (gtk_widget_get_accessible (GTK_WIDGET (colorsel)), ATK_ROLE_COLOR_CHOOSER);
501 make_all_relations (atk_obj, priv);
504 gtk_widget_pop_composite_child ();
507 /* GObject methods */
509 gtk_color_selection_finalize (GObject *object)
511 G_OBJECT_CLASS (gtk_color_selection_parent_class)->finalize (object);
515 gtk_color_selection_set_property (GObject *object,
520 GtkColorSelection *colorsel = GTK_COLOR_SELECTION (object);
524 case PROP_HAS_OPACITY_CONTROL:
525 gtk_color_selection_set_has_opacity_control (colorsel,
526 g_value_get_boolean (value));
528 case PROP_HAS_PALETTE:
529 gtk_color_selection_set_has_palette (colorsel,
530 g_value_get_boolean (value));
532 case PROP_CURRENT_COLOR:
533 gtk_color_selection_set_current_color (colorsel, g_value_get_boxed (value));
535 case PROP_CURRENT_ALPHA:
536 gtk_color_selection_set_current_alpha (colorsel, g_value_get_uint (value));
539 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
546 gtk_color_selection_get_property (GObject *object,
551 GtkColorSelection *colorsel = GTK_COLOR_SELECTION (object);
556 case PROP_HAS_OPACITY_CONTROL:
557 g_value_set_boolean (value, gtk_color_selection_get_has_opacity_control (colorsel));
559 case PROP_HAS_PALETTE:
560 g_value_set_boolean (value, gtk_color_selection_get_has_palette (colorsel));
562 case PROP_CURRENT_COLOR:
563 gtk_color_selection_get_current_color (colorsel, &color);
564 g_value_set_boxed (value, &color);
566 case PROP_CURRENT_ALPHA:
567 g_value_set_uint (value, gtk_color_selection_get_current_alpha (colorsel));
570 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
575 /* GtkObject methods */
578 gtk_color_selection_destroy (GtkObject *object)
580 GtkColorSelection *cselection = GTK_COLOR_SELECTION (object);
581 ColorSelectionPrivate *priv = cselection->private_data;
583 if (priv->dropper_grab_widget)
585 gtk_widget_destroy (priv->dropper_grab_widget);
586 priv->dropper_grab_widget = NULL;
589 GTK_OBJECT_CLASS (gtk_color_selection_parent_class)->destroy (object);
592 /* GtkWidget methods */
595 gtk_color_selection_realize (GtkWidget *widget)
597 GtkColorSelection *colorsel = GTK_COLOR_SELECTION (widget);
598 ColorSelectionPrivate *priv = colorsel->private_data;
599 GtkSettings *settings = gtk_widget_get_settings (widget);
601 priv->settings_connection = g_signal_connect (settings,
602 "notify::gtk-color-palette",
603 G_CALLBACK (palette_change_notify_instance),
605 update_palette (colorsel);
607 GTK_WIDGET_CLASS (gtk_color_selection_parent_class)->realize (widget);
611 gtk_color_selection_unrealize (GtkWidget *widget)
613 GtkColorSelection *colorsel = GTK_COLOR_SELECTION (widget);
614 ColorSelectionPrivate *priv = colorsel->private_data;
615 GtkSettings *settings = gtk_widget_get_settings (widget);
617 g_signal_handler_disconnect (settings, priv->settings_connection);
619 GTK_WIDGET_CLASS (gtk_color_selection_parent_class)->unrealize (widget);
622 /* We override show-all since we have internal widgets that
623 * shouldn't be shown when you call show_all(), like the
624 * palette and opacity sliders.
627 gtk_color_selection_show_all (GtkWidget *widget)
629 gtk_widget_show (widget);
633 gtk_color_selection_grab_broken (GtkWidget *widget,
634 GdkEventGrabBroken *event)
636 shutdown_eyedropper (widget);
647 static void color_sample_draw_sample (GtkColorSelection *colorsel, int which);
648 static void color_sample_update_samples (GtkColorSelection *colorsel);
651 set_color_internal (GtkColorSelection *colorsel,
654 ColorSelectionPrivate *priv;
657 priv = colorsel->private_data;
658 priv->changing = TRUE;
659 priv->color[COLORSEL_RED] = color[0];
660 priv->color[COLORSEL_GREEN] = color[1];
661 priv->color[COLORSEL_BLUE] = color[2];
662 priv->color[COLORSEL_OPACITY] = color[3];
663 gtk_rgb_to_hsv (priv->color[COLORSEL_RED],
664 priv->color[COLORSEL_GREEN],
665 priv->color[COLORSEL_BLUE],
666 &priv->color[COLORSEL_HUE],
667 &priv->color[COLORSEL_SATURATION],
668 &priv->color[COLORSEL_VALUE]);
669 if (priv->default_set == FALSE)
671 for (i = 0; i < COLORSEL_NUM_CHANNELS; i++)
672 priv->old_color[i] = priv->color[i];
674 priv->default_set = TRUE;
675 priv->default_alpha_set = TRUE;
676 update_color (colorsel);
680 set_color_icon (GdkDragContext *context,
686 pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE,
689 pixel = (((UNSCALE (colors[COLORSEL_RED]) & 0xff00) << 16) |
690 ((UNSCALE (colors[COLORSEL_GREEN]) & 0xff00) << 8) |
691 ((UNSCALE (colors[COLORSEL_BLUE]) & 0xff00)));
693 gdk_pixbuf_fill (pixbuf, pixel);
695 gtk_drag_set_icon_pixbuf (context, pixbuf, -2, -2);
696 g_object_unref (pixbuf);
700 color_sample_drag_begin (GtkWidget *widget,
701 GdkDragContext *context,
704 GtkColorSelection *colorsel = data;
705 ColorSelectionPrivate *priv;
708 priv = colorsel->private_data;
710 if (widget == priv->old_sample)
711 colsrc = priv->old_color;
713 colsrc = priv->color;
715 set_color_icon (context, colsrc);
719 color_sample_drag_end (GtkWidget *widget,
720 GdkDragContext *context,
723 g_object_set_data (G_OBJECT (widget), I_("gtk-color-selection-drag-window"), NULL);
727 color_sample_drop_handle (GtkWidget *widget,
728 GdkDragContext *context,
731 GtkSelectionData *selection_data,
736 GtkColorSelection *colorsel = data;
737 ColorSelectionPrivate *priv;
740 priv = colorsel->private_data;
742 /* This is currently a guint16 array of the format:
749 if (selection_data->length < 0)
752 /* We accept drops with the wrong format, since the KDE color
753 * chooser incorrectly drops application/x-color with format 8.
755 if (selection_data->length != 8)
757 g_warning ("Received invalid color data\n");
761 vals = (guint16 *)selection_data->data;
763 if (widget == priv->cur_sample)
765 color[0] = (gdouble)vals[0] / 0xffff;
766 color[1] = (gdouble)vals[1] / 0xffff;
767 color[2] = (gdouble)vals[2] / 0xffff;
768 color[3] = (gdouble)vals[3] / 0xffff;
770 set_color_internal (colorsel, color);
775 color_sample_drag_handle (GtkWidget *widget,
776 GdkDragContext *context,
777 GtkSelectionData *selection_data,
782 GtkColorSelection *colorsel = data;
783 ColorSelectionPrivate *priv;
787 priv = colorsel->private_data;
789 if (widget == priv->old_sample)
790 colsrc = priv->old_color;
792 colsrc = priv->color;
794 vals[0] = colsrc[COLORSEL_RED] * 0xffff;
795 vals[1] = colsrc[COLORSEL_GREEN] * 0xffff;
796 vals[2] = colsrc[COLORSEL_BLUE] * 0xffff;
797 vals[3] = priv->has_opacity ? colsrc[COLORSEL_OPACITY] * 0xffff : 0xffff;
799 gtk_selection_data_set (selection_data,
800 gdk_atom_intern_static_string ("application/x-color"),
801 16, (guchar *)vals, 8);
804 /* which = 0 means draw old sample, which = 1 means draw new */
806 color_sample_draw_sample (GtkColorSelection *colorsel, int which)
809 gint x, y, wid, heig, goff;
810 ColorSelectionPrivate *priv;
813 g_return_if_fail (colorsel != NULL);
814 priv = colorsel->private_data;
816 g_return_if_fail (priv->sample_area != NULL);
817 if (!GTK_WIDGET_DRAWABLE (priv->sample_area))
822 da = priv->old_sample;
827 da = priv->cur_sample;
828 goff = priv->old_sample->allocation.width % 32;
831 cr = gdk_cairo_create (da->window);
833 wid = da->allocation.width;
834 heig = da->allocation.height;
836 /* Below needs tweaking for non-power-of-two */
838 if (priv->has_opacity)
840 /* Draw checks in background */
842 cairo_set_source_rgb (cr, 0.5, 0.5, 0.5);
843 cairo_rectangle (cr, 0, 0, wid, heig);
846 cairo_set_source_rgb (cr, 0.75, 0.75, 0.75);
847 for (x = goff & -CHECK_SIZE; x < goff + wid; x += CHECK_SIZE)
848 for (y = 0; y < heig; y += CHECK_SIZE)
849 if ((x / CHECK_SIZE + y / CHECK_SIZE) % 2 == 0)
850 cairo_rectangle (cr, x - goff, y, CHECK_SIZE, CHECK_SIZE);
856 cairo_set_source_rgba (cr,
857 priv->old_color[COLORSEL_RED],
858 priv->old_color[COLORSEL_GREEN],
859 priv->old_color[COLORSEL_BLUE],
861 priv->old_color[COLORSEL_OPACITY] : 1.0);
865 cairo_set_source_rgba (cr,
866 priv->color[COLORSEL_RED],
867 priv->color[COLORSEL_GREEN],
868 priv->color[COLORSEL_BLUE],
870 priv->color[COLORSEL_OPACITY] : 1.0);
873 cairo_rectangle (cr, 0, 0, wid, heig);
881 color_sample_update_samples (GtkColorSelection *colorsel)
883 ColorSelectionPrivate *priv = colorsel->private_data;
884 gtk_widget_queue_draw (priv->old_sample);
885 gtk_widget_queue_draw (priv->cur_sample);
889 color_old_sample_expose (GtkWidget *da,
890 GdkEventExpose *event,
891 GtkColorSelection *colorsel)
893 color_sample_draw_sample (colorsel, 0);
899 color_cur_sample_expose (GtkWidget *da,
900 GdkEventExpose *event,
901 GtkColorSelection *colorsel)
903 color_sample_draw_sample (colorsel, 1);
908 color_sample_setup_dnd (GtkColorSelection *colorsel, GtkWidget *sample)
910 static const GtkTargetEntry targets[] = {
911 { "application/x-color", 0 }
913 ColorSelectionPrivate *priv;
914 priv = colorsel->private_data;
916 gtk_drag_source_set (sample,
917 GDK_BUTTON1_MASK | GDK_BUTTON3_MASK,
919 GDK_ACTION_COPY | GDK_ACTION_MOVE);
921 g_signal_connect (sample,
923 G_CALLBACK (color_sample_drag_begin),
925 if (sample == priv->cur_sample)
928 gtk_drag_dest_set (sample,
929 GTK_DEST_DEFAULT_HIGHLIGHT |
930 GTK_DEST_DEFAULT_MOTION |
931 GTK_DEST_DEFAULT_DROP,
935 g_signal_connect (sample,
937 G_CALLBACK (color_sample_drag_end),
941 g_signal_connect (sample,
943 G_CALLBACK (color_sample_drag_handle),
945 g_signal_connect (sample,
946 "drag_data_received",
947 G_CALLBACK (color_sample_drop_handle),
954 color_sample_new (GtkColorSelection *colorsel)
956 ColorSelectionPrivate *priv;
958 priv = colorsel->private_data;
960 priv->sample_area = gtk_hbox_new (FALSE, 0);
961 priv->old_sample = gtk_drawing_area_new ();
962 priv->cur_sample = gtk_drawing_area_new ();
964 gtk_box_pack_start (GTK_BOX (priv->sample_area), priv->old_sample,
966 gtk_box_pack_start (GTK_BOX (priv->sample_area), priv->cur_sample,
969 g_signal_connect (priv->old_sample, "expose_event",
970 G_CALLBACK (color_old_sample_expose),
972 g_signal_connect (priv->cur_sample, "expose_event",
973 G_CALLBACK (color_cur_sample_expose),
976 color_sample_setup_dnd (colorsel, priv->old_sample);
977 color_sample_setup_dnd (colorsel, priv->cur_sample);
979 gtk_widget_set_tooltip_text (priv->old_sample,
980 _("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."));
983 gtk_widget_set_tooltip_text (priv->cur_sample,
984 _("The color you've chosen. You can drag this color to a palette entry to save it for use in the future."));
986 gtk_widget_show_all (priv->sample_area);
992 * The palette area code
997 palette_get_color (GtkWidget *drawing_area, gdouble *color)
1001 g_return_if_fail (color != NULL);
1003 color_val = g_object_get_data (G_OBJECT (drawing_area), "color_val");
1004 if (color_val == NULL)
1006 /* Default to white for no good reason */
1014 color[0] = color_val[0];
1015 color[1] = color_val[1];
1016 color[2] = color_val[2];
1021 palette_paint (GtkWidget *drawing_area,
1028 if (drawing_area->window == NULL)
1031 cr = gdk_cairo_create (drawing_area->window);
1033 gdk_cairo_set_source_color (cr, &drawing_area->style->bg[GTK_STATE_NORMAL]);
1034 gdk_cairo_rectangle (cr, area);
1037 if (GTK_WIDGET_HAS_FOCUS (drawing_area))
1039 set_focus_line_attributes (drawing_area, cr, &focus_width);
1041 cairo_rectangle (cr,
1042 focus_width / 2., focus_width / 2.,
1043 drawing_area->allocation.width - focus_width,
1044 drawing_area->allocation.height - focus_width);
1052 set_focus_line_attributes (GtkWidget *drawing_area,
1059 gtk_widget_style_get (drawing_area,
1060 "focus-line-width", focus_width,
1061 "focus-line-pattern", (gchar *)&dash_list,
1064 palette_get_color (drawing_area, color);
1066 if (INTENSITY (color[0], color[1], color[2]) > 0.5)
1067 cairo_set_source_rgb (cr, 0., 0., 0.);
1069 cairo_set_source_rgb (cr, 1., 1., 1.);
1071 cairo_set_line_width (cr, *focus_width);
1075 gint n_dashes = strlen (dash_list);
1076 gdouble *dashes = g_new (gdouble, n_dashes);
1077 gdouble total_length = 0;
1078 gdouble dash_offset;
1081 for (i = 0; i < n_dashes; i++)
1083 dashes[i] = dash_list[i];
1084 total_length += dash_list[i];
1087 /* The dash offset here aligns the pattern to integer pixels
1088 * by starting the dash at the right side of the left border
1089 * Negative dash offsets in cairo don't work
1090 * (https://bugs.freedesktop.org/show_bug.cgi?id=2729)
1092 dash_offset = - *focus_width / 2.;
1093 while (dash_offset < 0)
1094 dash_offset += total_length;
1096 cairo_set_dash (cr, dashes, n_dashes, dash_offset);
1104 palette_drag_begin (GtkWidget *widget,
1105 GdkDragContext *context,
1110 palette_get_color (widget, colors);
1111 set_color_icon (context, colors);
1115 palette_drag_handle (GtkWidget *widget,
1116 GdkDragContext *context,
1117 GtkSelectionData *selection_data,
1125 palette_get_color (widget, colsrc);
1127 vals[0] = colsrc[COLORSEL_RED] * 0xffff;
1128 vals[1] = colsrc[COLORSEL_GREEN] * 0xffff;
1129 vals[2] = colsrc[COLORSEL_BLUE] * 0xffff;
1132 gtk_selection_data_set (selection_data,
1133 gdk_atom_intern_static_string ("application/x-color"),
1134 16, (guchar *)vals, 8);
1138 palette_drag_end (GtkWidget *widget,
1139 GdkDragContext *context,
1142 g_object_set_data (G_OBJECT (widget), I_("gtk-color-selection-drag-window"), NULL);
1146 get_current_colors (GtkColorSelection *colorsel)
1148 GtkSettings *settings;
1149 GdkColor *colors = NULL;
1153 settings = gtk_widget_get_settings (GTK_WIDGET (colorsel));
1154 g_object_get (settings,
1155 "gtk-color-palette", &palette,
1158 if (!gtk_color_selection_palette_from_string (palette, &colors, &n_colors))
1160 gtk_color_selection_palette_from_string (default_colors, &colors, &n_colors);
1164 /* If there are less colors provided than the number of slots in the
1165 * color selection, we fill in the rest from the defaults.
1167 if (n_colors < (GTK_CUSTOM_PALETTE_WIDTH * GTK_CUSTOM_PALETTE_HEIGHT))
1169 GdkColor *tmp_colors = colors;
1170 gint tmp_n_colors = n_colors;
1172 gtk_color_selection_palette_from_string (default_colors, &colors, &n_colors);
1173 memcpy (colors, tmp_colors, sizeof (GdkColor) * tmp_n_colors);
1175 g_free (tmp_colors);
1179 g_assert (n_colors >= GTK_CUSTOM_PALETTE_WIDTH * GTK_CUSTOM_PALETTE_HEIGHT);
1185 /* Changes the model color */
1187 palette_change_color (GtkWidget *drawing_area,
1188 GtkColorSelection *colorsel,
1192 ColorSelectionPrivate *priv;
1194 GdkColor *current_colors;
1197 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
1198 g_return_if_fail (GTK_IS_DRAWING_AREA (drawing_area));
1200 priv = colorsel->private_data;
1202 gdk_color.red = UNSCALE (color[0]);
1203 gdk_color.green = UNSCALE (color[1]);
1204 gdk_color.blue = UNSCALE (color[2]);
1205 gdk_color.pixel = 0;
1208 y = 0; /* Quiet GCC */
1209 while (x < GTK_CUSTOM_PALETTE_WIDTH)
1212 while (y < GTK_CUSTOM_PALETTE_HEIGHT)
1214 if (priv->custom_palette[x][y] == drawing_area)
1225 g_assert (x < GTK_CUSTOM_PALETTE_WIDTH || y < GTK_CUSTOM_PALETTE_HEIGHT);
1227 current_colors = get_current_colors (colorsel);
1228 current_colors[y * GTK_CUSTOM_PALETTE_WIDTH + x] = gdk_color;
1230 screen = gtk_widget_get_screen (GTK_WIDGET (colorsel));
1231 if (change_palette_hook != default_change_palette_func)
1232 (* change_palette_hook) (screen, current_colors,
1233 GTK_CUSTOM_PALETTE_WIDTH * GTK_CUSTOM_PALETTE_HEIGHT);
1234 else if (noscreen_change_palette_hook != default_noscreen_change_palette_func)
1236 if (screen != gdk_screen_get_default ())
1237 g_warning ("gtk_color_selection_set_change_palette_hook used by widget is not on the default screen.");
1238 (* noscreen_change_palette_hook) (current_colors,
1239 GTK_CUSTOM_PALETTE_WIDTH * GTK_CUSTOM_PALETTE_HEIGHT);
1242 (* change_palette_hook) (screen, current_colors,
1243 GTK_CUSTOM_PALETTE_WIDTH * GTK_CUSTOM_PALETTE_HEIGHT);
1245 g_free (current_colors);
1248 /* Changes the view color */
1250 palette_set_color (GtkWidget *drawing_area,
1251 GtkColorSelection *colorsel,
1254 gdouble *new_color = g_new (double, 4);
1257 gdk_color.red = UNSCALE (color[0]);
1258 gdk_color.green = UNSCALE (color[1]);
1259 gdk_color.blue = UNSCALE (color[2]);
1261 gtk_widget_modify_bg (drawing_area, GTK_STATE_NORMAL, &gdk_color);
1263 if (GPOINTER_TO_INT (g_object_get_data (G_OBJECT (drawing_area), "color_set")) == 0)
1265 static const GtkTargetEntry targets[] = {
1266 { "application/x-color", 0 }
1268 gtk_drag_source_set (drawing_area,
1269 GDK_BUTTON1_MASK | GDK_BUTTON3_MASK,
1271 GDK_ACTION_COPY | GDK_ACTION_MOVE);
1273 g_signal_connect (drawing_area,
1275 G_CALLBACK (palette_drag_begin),
1277 g_signal_connect (drawing_area,
1279 G_CALLBACK (palette_drag_handle),
1282 g_object_set_data (G_OBJECT (drawing_area), I_("color_set"),
1283 GINT_TO_POINTER (1));
1286 new_color[0] = color[0];
1287 new_color[1] = color[1];
1288 new_color[2] = color[2];
1291 g_object_set_data_full (G_OBJECT (drawing_area), I_("color_val"), new_color, (GDestroyNotify)g_free);
1295 palette_expose (GtkWidget *drawing_area,
1296 GdkEventExpose *event,
1299 if (drawing_area->window == NULL)
1302 palette_paint (drawing_area, &(event->area), data);
1308 popup_position_func (GtkMenu *menu,
1316 gint root_x, root_y;
1319 widget = GTK_WIDGET (user_data);
1321 g_return_if_fail (GTK_WIDGET_REALIZED (widget));
1323 gdk_window_get_origin (widget->window, &root_x, &root_y);
1325 gtk_widget_size_request (GTK_WIDGET (menu), &req);
1327 /* Put corner of menu centered on color cell */
1328 *x = root_x + widget->allocation.width / 2;
1329 *y = root_y + widget->allocation.height / 2;
1332 screen = gtk_widget_get_screen (widget);
1333 *x = CLAMP (*x, 0, MAX (0, gdk_screen_get_width (screen) - req.width));
1334 *y = CLAMP (*y, 0, MAX (0, gdk_screen_get_height (screen) - req.height));
1338 save_color_selected (GtkWidget *menuitem,
1341 GtkColorSelection *colorsel;
1342 GtkWidget *drawing_area;
1343 ColorSelectionPrivate *priv;
1345 drawing_area = GTK_WIDGET (data);
1347 colorsel = GTK_COLOR_SELECTION (g_object_get_data (G_OBJECT (drawing_area),
1350 priv = colorsel->private_data;
1352 palette_change_color (drawing_area, colorsel, priv->color);
1356 do_popup (GtkColorSelection *colorsel,
1357 GtkWidget *drawing_area,
1363 g_object_set_data (G_OBJECT (drawing_area),
1364 I_("gtk-color-sel"),
1367 menu = gtk_menu_new ();
1369 mi = gtk_menu_item_new_with_mnemonic (_("_Save color here"));
1371 g_signal_connect (mi, "activate",
1372 G_CALLBACK (save_color_selected),
1375 gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
1377 gtk_widget_show_all (mi);
1379 gtk_menu_popup (GTK_MENU (menu), NULL, NULL,
1380 popup_position_func, drawing_area,
1386 palette_enter (GtkWidget *drawing_area,
1387 GdkEventCrossing *event,
1390 g_object_set_data (G_OBJECT (drawing_area),
1391 I_("gtk-colorsel-have-pointer"),
1392 GUINT_TO_POINTER (TRUE));
1398 palette_leave (GtkWidget *drawing_area,
1399 GdkEventCrossing *event,
1402 g_object_set_data (G_OBJECT (drawing_area),
1403 I_("gtk-colorsel-have-pointer"),
1410 palette_press (GtkWidget *drawing_area,
1411 GdkEventButton *event,
1414 GtkColorSelection *colorsel = GTK_COLOR_SELECTION (data);
1416 gtk_widget_grab_focus (drawing_area);
1418 if (event->button == 3 &&
1419 event->type == GDK_BUTTON_PRESS)
1421 do_popup (colorsel, drawing_area, event->time);
1429 palette_release (GtkWidget *drawing_area,
1430 GdkEventButton *event,
1433 GtkColorSelection *colorsel = GTK_COLOR_SELECTION (data);
1435 gtk_widget_grab_focus (drawing_area);
1437 if (event->button == 1 &&
1438 g_object_get_data (G_OBJECT (drawing_area),
1439 "gtk-colorsel-have-pointer") != NULL)
1441 if (GPOINTER_TO_INT (g_object_get_data (G_OBJECT (drawing_area), "color_set")) != 0)
1444 palette_get_color (drawing_area, color);
1445 set_color_internal (colorsel, color);
1453 palette_drop_handle (GtkWidget *widget,
1454 GdkDragContext *context,
1457 GtkSelectionData *selection_data,
1462 GtkColorSelection *colorsel = GTK_COLOR_SELECTION (data);
1466 if (selection_data->length < 0)
1469 /* We accept drops with the wrong format, since the KDE color
1470 * chooser incorrectly drops application/x-color with format 8.
1472 if (selection_data->length != 8)
1474 g_warning ("Received invalid color data\n");
1478 vals = (guint16 *)selection_data->data;
1480 color[0] = (gdouble)vals[0] / 0xffff;
1481 color[1] = (gdouble)vals[1] / 0xffff;
1482 color[2] = (gdouble)vals[2] / 0xffff;
1483 color[3] = (gdouble)vals[3] / 0xffff;
1484 palette_change_color (widget, colorsel, color);
1485 set_color_internal (colorsel, color);
1489 palette_activate (GtkWidget *widget,
1493 /* should have a drawing area subclass with an activate signal */
1494 if ((event->keyval == GDK_space) ||
1495 (event->keyval == GDK_Return) ||
1496 (event->keyval == GDK_ISO_Enter) ||
1497 (event->keyval == GDK_KP_Enter) ||
1498 (event->keyval == GDK_KP_Space))
1500 if (GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget), "color_set")) != 0)
1503 palette_get_color (widget, color);
1504 set_color_internal (GTK_COLOR_SELECTION (data), color);
1513 palette_popup (GtkWidget *widget,
1516 GtkColorSelection *colorsel = GTK_COLOR_SELECTION (data);
1518 do_popup (colorsel, widget, GDK_CURRENT_TIME);
1524 palette_new (GtkColorSelection *colorsel)
1527 ColorSelectionPrivate *priv;
1529 static const GtkTargetEntry targets[] = {
1530 { "application/x-color", 0 }
1533 priv = colorsel->private_data;
1535 retval = gtk_drawing_area_new ();
1537 GTK_WIDGET_SET_FLAGS (retval, GTK_CAN_FOCUS);
1539 g_object_set_data (G_OBJECT (retval), I_("color_set"), GINT_TO_POINTER (0));
1540 gtk_widget_set_events (retval, GDK_BUTTON_PRESS_MASK
1541 | GDK_BUTTON_RELEASE_MASK
1543 | GDK_ENTER_NOTIFY_MASK
1544 | GDK_LEAVE_NOTIFY_MASK);
1546 g_signal_connect (retval, "expose_event",
1547 G_CALLBACK (palette_expose), colorsel);
1548 g_signal_connect (retval, "button_press_event",
1549 G_CALLBACK (palette_press), colorsel);
1550 g_signal_connect (retval, "button_release_event",
1551 G_CALLBACK (palette_release), colorsel);
1552 g_signal_connect (retval, "enter_notify_event",
1553 G_CALLBACK (palette_enter), colorsel);
1554 g_signal_connect (retval, "leave_notify_event",
1555 G_CALLBACK (palette_leave), colorsel);
1556 g_signal_connect (retval, "key_press_event",
1557 G_CALLBACK (palette_activate), colorsel);
1558 g_signal_connect (retval, "popup_menu",
1559 G_CALLBACK (palette_popup), colorsel);
1561 gtk_drag_dest_set (retval,
1562 GTK_DEST_DEFAULT_HIGHLIGHT |
1563 GTK_DEST_DEFAULT_MOTION |
1564 GTK_DEST_DEFAULT_DROP,
1568 g_signal_connect (retval, "drag_end",
1569 G_CALLBACK (palette_drag_end), NULL);
1570 g_signal_connect (retval, "drag_data_received",
1571 G_CALLBACK (palette_drop_handle), colorsel);
1573 gtk_widget_set_tooltip_text (retval,
1574 _("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.\""));
1581 * The actual GtkColorSelection widget
1586 make_picker_cursor (GdkScreen *screen)
1590 cursor = gdk_cursor_new_from_name (gdk_screen_get_display (screen),
1595 GdkColor bg = { 0, 0xffff, 0xffff, 0xffff };
1596 GdkColor fg = { 0, 0x0000, 0x0000, 0x0000 };
1598 GdkPixmap *pixmap, *mask;
1600 window = gdk_screen_get_root_window (screen);
1603 gdk_bitmap_create_from_data (window, (gchar *) dropper_bits,
1604 DROPPER_WIDTH, DROPPER_HEIGHT);
1607 gdk_bitmap_create_from_data (window, (gchar *) dropper_mask,
1608 DROPPER_WIDTH, DROPPER_HEIGHT);
1610 cursor = gdk_cursor_new_from_pixmap (pixmap, mask, &fg, &bg,
1611 DROPPER_X_HOT, DROPPER_Y_HOT);
1613 g_object_unref (pixmap);
1614 g_object_unref (mask);
1621 grab_color_at_mouse (GdkScreen *screen,
1628 GtkColorSelection *colorsel = data;
1629 ColorSelectionPrivate *priv;
1631 GdkColormap *colormap = gdk_screen_get_system_colormap (screen);
1632 GdkWindow *root_window = gdk_screen_get_root_window (screen);
1634 priv = colorsel->private_data;
1636 image = gdk_drawable_get_image (root_window, x_root, y_root, 1, 1);
1640 GdkDisplay *display = gdk_screen_get_display (screen);
1641 GdkWindow *window = gdk_display_get_window_at_pointer (display, &x, &y);
1644 image = gdk_drawable_get_image (window, x, y, 1, 1);
1648 pixel = gdk_image_get_pixel (image, 0, 0);
1649 g_object_unref (image);
1651 gdk_colormap_query_color (colormap, pixel, &color);
1653 priv->color[COLORSEL_RED] = SCALE (color.red);
1654 priv->color[COLORSEL_GREEN] = SCALE (color.green);
1655 priv->color[COLORSEL_BLUE] = SCALE (color.blue);
1657 gtk_rgb_to_hsv (priv->color[COLORSEL_RED],
1658 priv->color[COLORSEL_GREEN],
1659 priv->color[COLORSEL_BLUE],
1660 &priv->color[COLORSEL_HUE],
1661 &priv->color[COLORSEL_SATURATION],
1662 &priv->color[COLORSEL_VALUE]);
1664 update_color (colorsel);
1668 shutdown_eyedropper (GtkWidget *widget)
1670 GtkColorSelection *colorsel;
1671 ColorSelectionPrivate *priv;
1672 GdkDisplay *display = gtk_widget_get_display (widget);
1674 colorsel = GTK_COLOR_SELECTION (widget);
1675 priv = colorsel->private_data;
1679 gdk_display_keyboard_ungrab (display, priv->grab_time);
1680 gdk_display_pointer_ungrab (display, priv->grab_time);
1681 gtk_grab_remove (priv->dropper_grab_widget);
1683 priv->has_grab = FALSE;
1688 mouse_motion (GtkWidget *invisible,
1689 GdkEventMotion *event,
1692 grab_color_at_mouse (gdk_event_get_screen ((GdkEvent *)event),
1693 event->x_root, event->y_root, data);
1697 mouse_release (GtkWidget *invisible,
1698 GdkEventButton *event,
1701 /* GtkColorSelection *colorsel = data; */
1703 if (event->button != 1)
1706 grab_color_at_mouse (gdk_event_get_screen ((GdkEvent *)event),
1707 event->x_root, event->y_root, data);
1709 shutdown_eyedropper (GTK_WIDGET (data));
1711 g_signal_handlers_disconnect_by_func (invisible,
1714 g_signal_handlers_disconnect_by_func (invisible,
1721 /* Helper Functions */
1724 key_press (GtkWidget *invisible,
1728 GdkDisplay *display = gtk_widget_get_display (invisible);
1729 GdkScreen *screen = gdk_event_get_screen ((GdkEvent *)event);
1730 guint state = event->state & gtk_accelerator_get_default_mod_mask ();
1734 gdk_display_get_pointer (display, NULL, &x, &y, NULL);
1739 switch (event->keyval)
1746 grab_color_at_mouse (screen, x, y, data);
1750 shutdown_eyedropper (data);
1752 g_signal_handlers_disconnect_by_func (invisible,
1755 g_signal_handlers_disconnect_by_func (invisible,
1761 #if defined GDK_WINDOWING_X11 || defined GDK_WINDOWING_WIN32
1764 dy = state == GDK_MOD1_MASK ? -BIG_STEP : -1;
1769 dy = state == GDK_MOD1_MASK ? BIG_STEP : 1;
1774 dx = state == GDK_MOD1_MASK ? -BIG_STEP : -1;
1779 dx = state == GDK_MOD1_MASK ? BIG_STEP : 1;
1787 gdk_display_warp_pointer (display, screen, x + dx, y + dy);
1794 mouse_press (GtkWidget *invisible,
1795 GdkEventButton *event,
1798 /* GtkColorSelection *colorsel = data; */
1800 if (event->type == GDK_BUTTON_PRESS &&
1803 g_signal_connect (invisible, "motion_notify_event",
1804 G_CALLBACK (mouse_motion),
1806 g_signal_connect (invisible, "button_release_event",
1807 G_CALLBACK (mouse_release),
1809 g_signal_handlers_disconnect_by_func (invisible,
1812 g_signal_handlers_disconnect_by_func (invisible,
1821 /* when the button is clicked */
1823 get_screen_color (GtkWidget *button)
1825 GtkColorSelection *colorsel = g_object_get_data (G_OBJECT (button), "COLORSEL");
1826 ColorSelectionPrivate *priv = colorsel->private_data;
1827 GdkScreen *screen = gtk_widget_get_screen (GTK_WIDGET (button));
1828 GdkCursor *picker_cursor;
1829 GdkGrabStatus grab_status;
1830 GtkWidget *grab_widget, *toplevel;
1832 guint32 time = gtk_get_current_event_time ();
1834 if (priv->dropper_grab_widget == NULL)
1836 grab_widget = gtk_window_new (GTK_WINDOW_POPUP);
1837 gtk_window_set_screen (GTK_WINDOW (grab_widget), screen);
1838 gtk_window_resize (GTK_WINDOW (grab_widget), 1, 1);
1839 gtk_window_move (GTK_WINDOW (grab_widget), -100, -100);
1840 gtk_widget_show (grab_widget);
1842 gtk_widget_add_events (grab_widget,
1843 GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_PRESS_MASK | GDK_POINTER_MOTION_MASK);
1845 toplevel = gtk_widget_get_toplevel (GTK_WIDGET (colorsel));
1847 if (GTK_IS_WINDOW (toplevel))
1849 if (GTK_WINDOW (toplevel)->group)
1850 gtk_window_group_add_window (GTK_WINDOW (toplevel)->group,
1851 GTK_WINDOW (grab_widget));
1854 priv->dropper_grab_widget = grab_widget;
1857 if (gdk_keyboard_grab (priv->dropper_grab_widget->window,
1858 FALSE, time) != GDK_GRAB_SUCCESS)
1861 picker_cursor = make_picker_cursor (screen);
1862 grab_status = gdk_pointer_grab (priv->dropper_grab_widget->window,
1864 GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_PRESS_MASK | GDK_POINTER_MOTION_MASK,
1868 gdk_cursor_unref (picker_cursor);
1870 if (grab_status != GDK_GRAB_SUCCESS)
1872 gdk_display_keyboard_ungrab (gtk_widget_get_display (button), time);
1876 gtk_grab_add (priv->dropper_grab_widget);
1877 priv->grab_time = time;
1878 priv->has_grab = TRUE;
1880 g_signal_connect (priv->dropper_grab_widget, "button_press_event",
1881 G_CALLBACK (mouse_press), colorsel);
1882 g_signal_connect (priv->dropper_grab_widget, "key_press_event",
1883 G_CALLBACK (key_press), colorsel);
1887 hex_changed (GtkWidget *hex_entry,
1890 GtkColorSelection *colorsel;
1891 ColorSelectionPrivate *priv;
1895 colorsel = GTK_COLOR_SELECTION (data);
1896 priv = colorsel->private_data;
1901 text = gtk_editable_get_chars (GTK_EDITABLE (priv->hex_entry), 0, -1);
1902 if (gdk_color_parse (text, &color))
1904 priv->color[COLORSEL_RED] = CLAMP (color.red/65535.0, 0.0, 1.0);
1905 priv->color[COLORSEL_GREEN] = CLAMP (color.green/65535.0, 0.0, 1.0);
1906 priv->color[COLORSEL_BLUE] = CLAMP (color.blue/65535.0, 0.0, 1.0);
1907 gtk_rgb_to_hsv (priv->color[COLORSEL_RED],
1908 priv->color[COLORSEL_GREEN],
1909 priv->color[COLORSEL_BLUE],
1910 &priv->color[COLORSEL_HUE],
1911 &priv->color[COLORSEL_SATURATION],
1912 &priv->color[COLORSEL_VALUE]);
1913 update_color (colorsel);
1919 hex_focus_out (GtkWidget *hex_entry,
1920 GdkEventFocus *event,
1923 hex_changed (hex_entry, data);
1929 hsv_changed (GtkWidget *hsv,
1932 GtkColorSelection *colorsel;
1933 ColorSelectionPrivate *priv;
1935 colorsel = GTK_COLOR_SELECTION (data);
1936 priv = colorsel->private_data;
1941 gtk_hsv_get_color (GTK_HSV (hsv),
1942 &priv->color[COLORSEL_HUE],
1943 &priv->color[COLORSEL_SATURATION],
1944 &priv->color[COLORSEL_VALUE]);
1945 gtk_hsv_to_rgb (priv->color[COLORSEL_HUE],
1946 priv->color[COLORSEL_SATURATION],
1947 priv->color[COLORSEL_VALUE],
1948 &priv->color[COLORSEL_RED],
1949 &priv->color[COLORSEL_GREEN],
1950 &priv->color[COLORSEL_BLUE]);
1951 update_color (colorsel);
1955 adjustment_changed (GtkAdjustment *adjustment,
1958 GtkColorSelection *colorsel;
1959 ColorSelectionPrivate *priv;
1961 colorsel = GTK_COLOR_SELECTION (g_object_get_data (G_OBJECT (adjustment), "COLORSEL"));
1962 priv = colorsel->private_data;
1967 switch (GPOINTER_TO_INT (data))
1969 case COLORSEL_SATURATION:
1970 case COLORSEL_VALUE:
1971 priv->color[GPOINTER_TO_INT (data)] = adjustment->value / 100;
1972 gtk_hsv_to_rgb (priv->color[COLORSEL_HUE],
1973 priv->color[COLORSEL_SATURATION],
1974 priv->color[COLORSEL_VALUE],
1975 &priv->color[COLORSEL_RED],
1976 &priv->color[COLORSEL_GREEN],
1977 &priv->color[COLORSEL_BLUE]);
1980 priv->color[GPOINTER_TO_INT (data)] = adjustment->value / 360;
1981 gtk_hsv_to_rgb (priv->color[COLORSEL_HUE],
1982 priv->color[COLORSEL_SATURATION],
1983 priv->color[COLORSEL_VALUE],
1984 &priv->color[COLORSEL_RED],
1985 &priv->color[COLORSEL_GREEN],
1986 &priv->color[COLORSEL_BLUE]);
1989 case COLORSEL_GREEN:
1991 priv->color[GPOINTER_TO_INT (data)] = adjustment->value / 255;
1993 gtk_rgb_to_hsv (priv->color[COLORSEL_RED],
1994 priv->color[COLORSEL_GREEN],
1995 priv->color[COLORSEL_BLUE],
1996 &priv->color[COLORSEL_HUE],
1997 &priv->color[COLORSEL_SATURATION],
1998 &priv->color[COLORSEL_VALUE]);
2001 priv->color[GPOINTER_TO_INT (data)] = adjustment->value / 255;
2004 update_color (colorsel);
2008 opacity_entry_changed (GtkWidget *opacity_entry,
2011 GtkColorSelection *colorsel;
2012 ColorSelectionPrivate *priv;
2016 colorsel = GTK_COLOR_SELECTION (data);
2017 priv = colorsel->private_data;
2022 text = gtk_editable_get_chars (GTK_EDITABLE (priv->opacity_entry), 0, -1);
2023 adj = gtk_range_get_adjustment (GTK_RANGE (priv->opacity_slider));
2024 gtk_adjustment_set_value (adj, g_strtod (text, NULL));
2026 update_color (colorsel);
2032 make_label_spinbutton (GtkColorSelection *colorsel,
2033 GtkWidget **spinbutton,
2039 const gchar *tooltip)
2042 GtkAdjustment *adjust;
2044 if (channel_type == COLORSEL_HUE)
2046 adjust = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 360.0, 1.0, 1.0, 1.0));
2048 else if (channel_type == COLORSEL_SATURATION ||
2049 channel_type == COLORSEL_VALUE)
2051 adjust = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 100.0, 1.0, 1.0, 1.0));
2055 adjust = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 255.0, 1.0, 1.0, 1.0));
2057 g_object_set_data (G_OBJECT (adjust), I_("COLORSEL"), colorsel);
2058 *spinbutton = gtk_spin_button_new (adjust, 10.0, 0);
2060 gtk_widget_set_tooltip_text (*spinbutton, tooltip);
2062 g_signal_connect (adjust, "value_changed",
2063 G_CALLBACK (adjustment_changed),
2064 GINT_TO_POINTER (channel_type));
2065 label = gtk_label_new_with_mnemonic (text);
2066 gtk_label_set_mnemonic_widget (GTK_LABEL (label), *spinbutton);
2068 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
2069 gtk_table_attach_defaults (GTK_TABLE (table), label, i, i+1, j, j+1);
2070 gtk_table_attach_defaults (GTK_TABLE (table), *spinbutton, i+1, i+2, j, j+1);
2074 make_palette_frame (GtkColorSelection *colorsel,
2080 ColorSelectionPrivate *priv;
2082 priv = colorsel->private_data;
2083 frame = gtk_frame_new (NULL);
2084 gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
2085 priv->custom_palette[i][j] = palette_new (colorsel);
2086 gtk_widget_set_size_request (priv->custom_palette[i][j], CUSTOM_PALETTE_ENTRY_WIDTH, CUSTOM_PALETTE_ENTRY_HEIGHT);
2087 gtk_container_add (GTK_CONTAINER (frame), priv->custom_palette[i][j]);
2088 gtk_table_attach_defaults (GTK_TABLE (table), frame, i, i+1, j, j+1);
2091 /* Set the palette entry [x][y] to be the currently selected one. */
2093 set_selected_palette (GtkColorSelection *colorsel, int x, int y)
2095 ColorSelectionPrivate *priv = colorsel->private_data;
2097 gtk_widget_grab_focus (priv->custom_palette[x][y]);
2101 scale_round (double val, double factor)
2103 val = floor (val * factor + 0.5);
2105 val = MIN (val, factor);
2110 update_color (GtkColorSelection *colorsel)
2112 ColorSelectionPrivate *priv = colorsel->private_data;
2114 gchar opacity_text[32];
2117 priv->changing = TRUE;
2118 color_sample_update_samples (colorsel);
2120 gtk_hsv_set_color (GTK_HSV (priv->triangle_colorsel),
2121 priv->color[COLORSEL_HUE],
2122 priv->color[COLORSEL_SATURATION],
2123 priv->color[COLORSEL_VALUE]);
2124 gtk_adjustment_set_value (gtk_spin_button_get_adjustment
2125 (GTK_SPIN_BUTTON (priv->hue_spinbutton)),
2126 scale_round (priv->color[COLORSEL_HUE], 360));
2127 gtk_adjustment_set_value (gtk_spin_button_get_adjustment
2128 (GTK_SPIN_BUTTON (priv->sat_spinbutton)),
2129 scale_round (priv->color[COLORSEL_SATURATION], 100));
2130 gtk_adjustment_set_value (gtk_spin_button_get_adjustment
2131 (GTK_SPIN_BUTTON (priv->val_spinbutton)),
2132 scale_round (priv->color[COLORSEL_VALUE], 100));
2133 gtk_adjustment_set_value (gtk_spin_button_get_adjustment
2134 (GTK_SPIN_BUTTON (priv->red_spinbutton)),
2135 scale_round (priv->color[COLORSEL_RED], 255));
2136 gtk_adjustment_set_value (gtk_spin_button_get_adjustment
2137 (GTK_SPIN_BUTTON (priv->green_spinbutton)),
2138 scale_round (priv->color[COLORSEL_GREEN], 255));
2139 gtk_adjustment_set_value (gtk_spin_button_get_adjustment
2140 (GTK_SPIN_BUTTON (priv->blue_spinbutton)),
2141 scale_round (priv->color[COLORSEL_BLUE], 255));
2142 gtk_adjustment_set_value (gtk_range_get_adjustment
2143 (GTK_RANGE (priv->opacity_slider)),
2144 scale_round (priv->color[COLORSEL_OPACITY], 255));
2146 g_snprintf (opacity_text, 32, "%.0f", scale_round (priv->color[COLORSEL_OPACITY], 255));
2147 gtk_entry_set_text (GTK_ENTRY (priv->opacity_entry), opacity_text);
2149 g_snprintf (entryval, 11, "#%2X%2X%2X",
2150 (guint) (scale_round (priv->color[COLORSEL_RED], 255)),
2151 (guint) (scale_round (priv->color[COLORSEL_GREEN], 255)),
2152 (guint) (scale_round (priv->color[COLORSEL_BLUE], 255)));
2154 for (ptr = entryval; *ptr; ptr++)
2157 gtk_entry_set_text (GTK_ENTRY (priv->hex_entry), entryval);
2158 priv->changing = FALSE;
2160 g_object_ref (colorsel);
2162 g_signal_emit (colorsel, color_selection_signals[COLOR_CHANGED], 0);
2164 g_object_freeze_notify (G_OBJECT (colorsel));
2165 g_object_notify (G_OBJECT (colorsel), "current-color");
2166 g_object_notify (G_OBJECT (colorsel), "current-alpha");
2167 g_object_thaw_notify (G_OBJECT (colorsel));
2169 g_object_unref (colorsel);
2173 update_palette (GtkColorSelection *colorsel)
2175 GdkColor *current_colors;
2178 current_colors = get_current_colors (colorsel);
2180 for (i = 0; i < GTK_CUSTOM_PALETTE_HEIGHT; i++)
2182 for (j = 0; j < GTK_CUSTOM_PALETTE_WIDTH; j++)
2186 index = i * GTK_CUSTOM_PALETTE_WIDTH + j;
2188 gtk_color_selection_set_palette_color (colorsel,
2190 ¤t_colors[index]);
2194 g_free (current_colors);
2198 palette_change_notify_instance (GObject *object,
2202 update_palette (GTK_COLOR_SELECTION (data));
2206 default_noscreen_change_palette_func (const GdkColor *colors,
2209 default_change_palette_func (gdk_screen_get_default (), colors, n_colors);
2213 default_change_palette_func (GdkScreen *screen,
2214 const GdkColor *colors,
2219 str = gtk_color_selection_palette_to_string (colors, n_colors);
2221 gtk_settings_set_string_property (gtk_settings_get_for_screen (screen),
2222 "gtk-color-palette",
2224 "gtk_color_selection_palette_to_string");
2230 * gtk_color_selection_new:
2232 * Creates a new GtkColorSelection.
2234 * Return value: a new #GtkColorSelection
2237 gtk_color_selection_new (void)
2239 GtkColorSelection *colorsel;
2240 ColorSelectionPrivate *priv;
2247 colorsel = g_object_new (GTK_TYPE_COLOR_SELECTION, NULL);
2248 priv = colorsel->private_data;
2249 set_color_internal (colorsel, color);
2250 gtk_color_selection_set_has_opacity_control (colorsel, TRUE);
2252 /* We want to make sure that default_set is FALSE */
2253 /* This way the user can still set it */
2254 priv->default_set = FALSE;
2255 priv->default_alpha_set = FALSE;
2257 return GTK_WIDGET (colorsel);
2262 gtk_color_selection_set_update_policy (GtkColorSelection *colorsel,
2263 GtkUpdateType policy)
2265 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2269 * gtk_color_selection_get_has_opacity_control:
2270 * @colorsel: a #GtkColorSelection.
2272 * Determines whether the colorsel has an opacity control.
2274 * Return value: %TRUE if the @colorsel has an opacity control. %FALSE if it does't.
2277 gtk_color_selection_get_has_opacity_control (GtkColorSelection *colorsel)
2279 ColorSelectionPrivate *priv;
2281 g_return_val_if_fail (GTK_IS_COLOR_SELECTION (colorsel), FALSE);
2283 priv = colorsel->private_data;
2285 return priv->has_opacity;
2289 * gtk_color_selection_set_has_opacity_control:
2290 * @colorsel: a #GtkColorSelection.
2291 * @has_opacity: %TRUE if @colorsel can set the opacity, %FALSE otherwise.
2293 * Sets the @colorsel to use or not use opacity.
2297 gtk_color_selection_set_has_opacity_control (GtkColorSelection *colorsel,
2298 gboolean has_opacity)
2300 ColorSelectionPrivate *priv;
2302 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2304 priv = colorsel->private_data;
2305 has_opacity = has_opacity != FALSE;
2307 if (priv->has_opacity != has_opacity)
2309 priv->has_opacity = has_opacity;
2312 gtk_widget_show (priv->opacity_slider);
2313 gtk_widget_show (priv->opacity_label);
2314 gtk_widget_show (priv->opacity_entry);
2318 gtk_widget_hide (priv->opacity_slider);
2319 gtk_widget_hide (priv->opacity_label);
2320 gtk_widget_hide (priv->opacity_entry);
2322 color_sample_update_samples (colorsel);
2324 g_object_notify (G_OBJECT (colorsel), "has-opacity-control");
2329 * gtk_color_selection_get_has_palette:
2330 * @colorsel: a #GtkColorSelection.
2332 * Determines whether the color selector has a color palette.
2334 * Return value: %TRUE if the selector has a palette. %FALSE if it hasn't.
2337 gtk_color_selection_get_has_palette (GtkColorSelection *colorsel)
2339 ColorSelectionPrivate *priv;
2341 g_return_val_if_fail (GTK_IS_COLOR_SELECTION (colorsel), FALSE);
2343 priv = colorsel->private_data;
2345 return priv->has_palette;
2349 * gtk_color_selection_set_has_palette:
2350 * @colorsel: a #GtkColorSelection.
2351 * @has_palette: %TRUE if palette is to be visible, %FALSE otherwise.
2353 * Shows and hides the palette based upon the value of @has_palette.
2357 gtk_color_selection_set_has_palette (GtkColorSelection *colorsel,
2358 gboolean has_palette)
2360 ColorSelectionPrivate *priv;
2361 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2363 priv = colorsel->private_data;
2364 has_palette = has_palette != FALSE;
2366 if (priv->has_palette != has_palette)
2368 priv->has_palette = has_palette;
2370 gtk_widget_show (priv->palette_frame);
2372 gtk_widget_hide (priv->palette_frame);
2374 g_object_notify (G_OBJECT (colorsel), "has-palette");
2379 * gtk_color_selection_set_current_color:
2380 * @colorsel: a #GtkColorSelection.
2381 * @color: A #GdkColor to set the current color with.
2383 * Sets the current color to be @color. The first time this is called, it will
2384 * also set the original color to be @color too.
2387 gtk_color_selection_set_current_color (GtkColorSelection *colorsel,
2388 const GdkColor *color)
2390 ColorSelectionPrivate *priv;
2393 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2394 g_return_if_fail (color != NULL);
2396 priv = colorsel->private_data;
2397 priv->changing = TRUE;
2398 priv->color[COLORSEL_RED] = SCALE (color->red);
2399 priv->color[COLORSEL_GREEN] = SCALE (color->green);
2400 priv->color[COLORSEL_BLUE] = SCALE (color->blue);
2401 gtk_rgb_to_hsv (priv->color[COLORSEL_RED],
2402 priv->color[COLORSEL_GREEN],
2403 priv->color[COLORSEL_BLUE],
2404 &priv->color[COLORSEL_HUE],
2405 &priv->color[COLORSEL_SATURATION],
2406 &priv->color[COLORSEL_VALUE]);
2407 if (priv->default_set == FALSE)
2409 for (i = 0; i < COLORSEL_NUM_CHANNELS; i++)
2410 priv->old_color[i] = priv->color[i];
2412 priv->default_set = TRUE;
2413 update_color (colorsel);
2417 * gtk_color_selection_set_current_alpha:
2418 * @colorsel: a #GtkColorSelection.
2419 * @alpha: an integer between 0 and 65535.
2421 * Sets the current opacity to be @alpha. The first time this is called, it will
2422 * also set the original opacity to be @alpha too.
2425 gtk_color_selection_set_current_alpha (GtkColorSelection *colorsel,
2428 ColorSelectionPrivate *priv;
2431 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2433 priv = colorsel->private_data;
2434 priv->changing = TRUE;
2435 priv->color[COLORSEL_OPACITY] = SCALE (alpha);
2436 if (priv->default_alpha_set == FALSE)
2438 for (i = 0; i < COLORSEL_NUM_CHANNELS; i++)
2439 priv->old_color[i] = priv->color[i];
2441 priv->default_alpha_set = TRUE;
2442 update_color (colorsel);
2446 * gtk_color_selection_set_color:
2447 * @colorsel: a #GtkColorSelection.
2448 * @color: an array of 4 doubles specifying the red, green, blue and opacity
2449 * to set the current color to.
2451 * Sets the current color to be @color. The first time this is called, it will
2452 * also set the original color to be @color too.
2454 * Deprecated: 2.0: Use gtk_color_selection_set_current_color() instead.
2457 gtk_color_selection_set_color (GtkColorSelection *colorsel,
2460 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2462 set_color_internal (colorsel, color);
2466 * gtk_color_selection_get_current_color:
2467 * @colorsel: a #GtkColorSelection.
2468 * @color: a #GdkColor to fill in with the current color.
2470 * Sets @color to be the current color in the GtkColorSelection widget.
2473 gtk_color_selection_get_current_color (GtkColorSelection *colorsel,
2476 ColorSelectionPrivate *priv;
2478 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2479 g_return_if_fail (color != NULL);
2481 priv = colorsel->private_data;
2482 color->red = UNSCALE (priv->color[COLORSEL_RED]);
2483 color->green = UNSCALE (priv->color[COLORSEL_GREEN]);
2484 color->blue = UNSCALE (priv->color[COLORSEL_BLUE]);
2488 * gtk_color_selection_get_current_alpha:
2489 * @colorsel: a #GtkColorSelection.
2491 * Returns the current alpha value.
2493 * Return value: an integer between 0 and 65535.
2496 gtk_color_selection_get_current_alpha (GtkColorSelection *colorsel)
2498 ColorSelectionPrivate *priv;
2500 g_return_val_if_fail (GTK_IS_COLOR_SELECTION (colorsel), 0);
2502 priv = colorsel->private_data;
2503 return priv->has_opacity ? UNSCALE (priv->color[COLORSEL_OPACITY]) : 65535;
2507 * gtk_color_selection_get_color:
2508 * @colorsel: a #GtkColorSelection.
2509 * @color: an array of 4 #gdouble to fill in with the current color.
2511 * Sets @color to be the current color in the GtkColorSelection widget.
2513 * This function is deprecated, use gtk_color_selection_get_current_color() instead.
2516 gtk_color_selection_get_color (GtkColorSelection *colorsel,
2519 ColorSelectionPrivate *priv;
2521 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2523 priv = colorsel->private_data;
2524 color[0] = priv->color[COLORSEL_RED];
2525 color[1] = priv->color[COLORSEL_GREEN];
2526 color[2] = priv->color[COLORSEL_BLUE];
2527 color[3] = priv->has_opacity ? priv->color[COLORSEL_OPACITY] : 65535;
2531 * gtk_color_selection_set_previous_color:
2532 * @colorsel: a #GtkColorSelection.
2533 * @color: a #GdkColor to set the previous color with.
2535 * Sets the 'previous' color to be @color. This function should be called with
2536 * some hesitations, as it might seem confusing to have that color change.
2537 * Calling gtk_color_selection_set_current_color() will also set this color the first
2538 * time it is called.
2541 gtk_color_selection_set_previous_color (GtkColorSelection *colorsel,
2542 const GdkColor *color)
2544 ColorSelectionPrivate *priv;
2546 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2547 g_return_if_fail (color != NULL);
2549 priv = colorsel->private_data;
2550 priv->changing = TRUE;
2551 priv->old_color[COLORSEL_RED] = SCALE (color->red);
2552 priv->old_color[COLORSEL_GREEN] = SCALE (color->green);
2553 priv->old_color[COLORSEL_BLUE] = SCALE (color->blue);
2554 gtk_rgb_to_hsv (priv->old_color[COLORSEL_RED],
2555 priv->old_color[COLORSEL_GREEN],
2556 priv->old_color[COLORSEL_BLUE],
2557 &priv->old_color[COLORSEL_HUE],
2558 &priv->old_color[COLORSEL_SATURATION],
2559 &priv->old_color[COLORSEL_VALUE]);
2560 color_sample_update_samples (colorsel);
2561 priv->default_set = TRUE;
2562 priv->changing = FALSE;
2566 * gtk_color_selection_set_previous_alpha:
2567 * @colorsel: a #GtkColorSelection.
2568 * @alpha: an integer between 0 and 65535.
2570 * Sets the 'previous' alpha to be @alpha. This function should be called with
2571 * some hesitations, as it might seem confusing to have that alpha change.
2574 gtk_color_selection_set_previous_alpha (GtkColorSelection *colorsel,
2577 ColorSelectionPrivate *priv;
2579 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2581 priv = colorsel->private_data;
2582 priv->changing = TRUE;
2583 priv->old_color[COLORSEL_OPACITY] = SCALE (alpha);
2584 color_sample_update_samples (colorsel);
2585 priv->default_alpha_set = TRUE;
2586 priv->changing = FALSE;
2591 * gtk_color_selection_get_previous_color:
2592 * @colorsel: a #GtkColorSelection.
2593 * @color: a #GdkColor to fill in with the original color value.
2595 * Fills @color in with the original color value.
2598 gtk_color_selection_get_previous_color (GtkColorSelection *colorsel,
2601 ColorSelectionPrivate *priv;
2603 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2604 g_return_if_fail (color != NULL);
2606 priv = colorsel->private_data;
2607 color->red = UNSCALE (priv->old_color[COLORSEL_RED]);
2608 color->green = UNSCALE (priv->old_color[COLORSEL_GREEN]);
2609 color->blue = UNSCALE (priv->old_color[COLORSEL_BLUE]);
2613 * gtk_color_selection_get_previous_alpha:
2614 * @colorsel: a #GtkColorSelection.
2616 * Returns the previous alpha value.
2618 * Return value: an integer between 0 and 65535.
2621 gtk_color_selection_get_previous_alpha (GtkColorSelection *colorsel)
2623 ColorSelectionPrivate *priv;
2625 g_return_val_if_fail (GTK_IS_COLOR_SELECTION (colorsel), 0);
2627 priv = colorsel->private_data;
2628 return priv->has_opacity ? UNSCALE (priv->old_color[COLORSEL_OPACITY]) : 65535;
2632 * gtk_color_selection_set_palette_color:
2633 * @colorsel: a #GtkColorSelection.
2634 * @index: the color index of the palette.
2635 * @color: A #GdkColor to set the palette with.
2637 * Sets the palette located at @index to have @color as its color.
2641 gtk_color_selection_set_palette_color (GtkColorSelection *colorsel,
2645 ColorSelectionPrivate *priv;
2649 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2650 g_return_if_fail (index >= 0 && index < GTK_CUSTOM_PALETTE_WIDTH*GTK_CUSTOM_PALETTE_HEIGHT);
2652 x = index % GTK_CUSTOM_PALETTE_WIDTH;
2653 y = index / GTK_CUSTOM_PALETTE_WIDTH;
2655 priv = colorsel->private_data;
2656 col[0] = SCALE (color->red);
2657 col[1] = SCALE (color->green);
2658 col[2] = SCALE (color->blue);
2660 palette_set_color (priv->custom_palette[x][y], colorsel, col);
2664 * gtk_color_selection_is_adjusting:
2665 * @colorsel: a #GtkColorSelection.
2667 * Gets the current state of the @colorsel.
2669 * Return value: %TRUE if the user is currently dragging a color around, and %FALSE
2670 * if the selection has stopped.
2673 gtk_color_selection_is_adjusting (GtkColorSelection *colorsel)
2675 ColorSelectionPrivate *priv;
2677 g_return_val_if_fail (GTK_IS_COLOR_SELECTION (colorsel), FALSE);
2679 priv = colorsel->private_data;
2681 return (gtk_hsv_is_adjusting (GTK_HSV (priv->triangle_colorsel)));
2686 * gtk_color_selection_palette_from_string:
2687 * @str: a string encoding a color palette.
2688 * @colors: return location for allocated array of #GdkColor.
2689 * @n_colors: return location for length of array.
2691 * Parses a color palette string; the string is a colon-separated
2692 * list of color names readable by gdk_color_parse().
2694 * Return value: %TRUE if a palette was successfully parsed.
2697 gtk_color_selection_palette_from_string (const gchar *str,
2709 copy = g_strdup (str);
2715 if (*p == ':' || *p == '\0')
2717 gboolean done = TRUE;
2721 goto failed; /* empty entry */
2730 retval = g_renew (GdkColor, retval, count + 1);
2731 if (!gdk_color_parse (start, retval + count))
2772 * gtk_color_selection_palette_to_string:
2773 * @colors: an array of colors.
2774 * @n_colors: length of the array.
2776 * Encodes a palette as a string, useful for persistent storage.
2778 * Return value: allocated string encoding the palette.
2781 gtk_color_selection_palette_to_string (const GdkColor *colors,
2785 gchar **strs = NULL;
2789 return g_strdup ("");
2791 strs = g_new0 (gchar*, n_colors + 1);
2794 while (i < n_colors)
2799 g_strdup_printf ("#%2X%2X%2X",
2800 colors[i].red / 256,
2801 colors[i].green / 256,
2802 colors[i].blue / 256);
2804 for (ptr = strs[i]; *ptr; ptr++)
2811 retval = g_strjoinv (":", strs);
2819 * gtk_color_selection_set_change_palette_hook:
2820 * @func: a function to call when the custom palette needs saving.
2822 * Installs a global function to be called whenever the user tries to
2823 * modify the palette in a color selection. This function should save
2824 * the new palette contents, and update the GtkSettings property
2825 * "gtk-color-palette" so all GtkColorSelection widgets will be modified.
2827 * Return value: the previous change palette hook (that was replaced).
2829 * Deprecated: 2.4: This function is deprecated in favor of
2830 * gtk_color_selection_set_change_palette_with_screen_hook(), and does
2831 * not work in multihead environments.
2834 GtkColorSelectionChangePaletteFunc
2835 gtk_color_selection_set_change_palette_hook (GtkColorSelectionChangePaletteFunc func)
2837 GtkColorSelectionChangePaletteFunc old;
2839 old = noscreen_change_palette_hook;
2841 noscreen_change_palette_hook = func;
2847 * gtk_color_selection_set_change_palette_with_screen_hook:
2848 * @func: a function to call when the custom palette needs saving.
2850 * Installs a global function to be called whenever the user tries to
2851 * modify the palette in a color selection. This function should save
2852 * the new palette contents, and update the GtkSettings property
2853 * "gtk-color-palette" so all GtkColorSelection widgets will be modified.
2855 * Return value: the previous change palette hook (that was replaced).
2859 GtkColorSelectionChangePaletteWithScreenFunc
2860 gtk_color_selection_set_change_palette_with_screen_hook (GtkColorSelectionChangePaletteWithScreenFunc func)
2862 GtkColorSelectionChangePaletteWithScreenFunc old;
2864 old = change_palette_hook;
2866 change_palette_hook = func;
2872 make_control_relations (AtkObject *atk_obj,
2877 obj = gtk_widget_get_accessible (widget);
2878 atk_object_add_relationship (atk_obj, ATK_RELATION_CONTROLLED_BY, obj);
2879 atk_object_add_relationship (obj, ATK_RELATION_CONTROLLER_FOR, atk_obj);
2883 make_all_relations (AtkObject *atk_obj,
2884 ColorSelectionPrivate *priv)
2886 make_control_relations (atk_obj, priv->hue_spinbutton);
2887 make_control_relations (atk_obj, priv->sat_spinbutton);
2888 make_control_relations (atk_obj, priv->val_spinbutton);
2889 make_control_relations (atk_obj, priv->red_spinbutton);
2890 make_control_relations (atk_obj, priv->green_spinbutton);
2891 make_control_relations (atk_obj, priv->blue_spinbutton);
2894 #define __GTK_COLOR_SELECTION_C__
2895 #include "gtkaliasdef.c"