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;
152 GdkDevice *keyboard_device;
153 GdkDevice *pointer_device;
155 /* Connection to settings */
156 gulong settings_connection;
160 static void gtk_color_selection_destroy (GtkObject *object);
161 static void gtk_color_selection_finalize (GObject *object);
162 static void update_color (GtkColorSelection *colorsel);
163 static void gtk_color_selection_set_property (GObject *object,
167 static void gtk_color_selection_get_property (GObject *object,
172 static void gtk_color_selection_realize (GtkWidget *widget);
173 static void gtk_color_selection_unrealize (GtkWidget *widget);
174 static void gtk_color_selection_show_all (GtkWidget *widget);
175 static gboolean gtk_color_selection_grab_broken (GtkWidget *widget,
176 GdkEventGrabBroken *event);
178 static void gtk_color_selection_set_palette_color (GtkColorSelection *colorsel,
181 static void set_focus_line_attributes (GtkWidget *drawing_area,
184 static void default_noscreen_change_palette_func (const GdkColor *colors,
186 static void default_change_palette_func (GdkScreen *screen,
187 const GdkColor *colors,
189 static void make_control_relations (AtkObject *atk_obj,
191 static void make_all_relations (AtkObject *atk_obj,
192 ColorSelectionPrivate *priv);
194 static void hsv_changed (GtkWidget *hsv,
196 static void get_screen_color (GtkWidget *button);
197 static void adjustment_changed (GtkAdjustment *adjustment,
199 static void opacity_entry_changed (GtkWidget *opacity_entry,
201 static void hex_changed (GtkWidget *hex_entry,
203 static gboolean hex_focus_out (GtkWidget *hex_entry,
204 GdkEventFocus *event,
206 static void color_sample_new (GtkColorSelection *colorsel);
207 static void make_label_spinbutton (GtkColorSelection *colorsel,
208 GtkWidget **spinbutton,
214 const gchar *tooltip);
215 static void make_palette_frame (GtkColorSelection *colorsel,
219 static void set_selected_palette (GtkColorSelection *colorsel,
222 static void set_focus_line_attributes (GtkWidget *drawing_area,
225 static gboolean mouse_press (GtkWidget *invisible,
226 GdkEventButton *event,
228 static void palette_change_notify_instance (GObject *object,
231 static void update_palette (GtkColorSelection *colorsel);
232 static void shutdown_eyedropper (GtkWidget *widget);
234 static guint color_selection_signals[LAST_SIGNAL] = { 0 };
236 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";
238 static GtkColorSelectionChangePaletteFunc noscreen_change_palette_hook = default_noscreen_change_palette_func;
239 static GtkColorSelectionChangePaletteWithScreenFunc change_palette_hook = default_change_palette_func;
241 static const guchar dropper_bits[] = {
242 0xff, 0x8f, 0x01, 0xff, 0x77, 0x01, 0xff, 0xfb, 0x00, 0xff, 0xf8, 0x00,
243 0x7f, 0xff, 0x00, 0xff, 0x7e, 0x01, 0xff, 0x9d, 0x01, 0xff, 0xd8, 0x01,
244 0x7f, 0xd4, 0x01, 0x3f, 0xee, 0x01, 0x1f, 0xff, 0x01, 0x8f, 0xff, 0x01,
245 0xc7, 0xff, 0x01, 0xe3, 0xff, 0x01, 0xf3, 0xff, 0x01, 0xfd, 0xff, 0x01,
248 static const guchar dropper_mask[] = {
249 0x00, 0x70, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xfc, 0x01, 0x00, 0xff, 0x01,
250 0x80, 0xff, 0x01, 0x00, 0xff, 0x00, 0x00, 0x7f, 0x00, 0x80, 0x3f, 0x00,
251 0xc0, 0x3f, 0x00, 0xe0, 0x13, 0x00, 0xf0, 0x01, 0x00, 0xf8, 0x00, 0x00,
252 0x7c, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x0d, 0x00, 0x00,
255 G_DEFINE_TYPE (GtkColorSelection, gtk_color_selection, GTK_TYPE_VBOX)
258 gtk_color_selection_class_init (GtkColorSelectionClass *klass)
260 GObjectClass *gobject_class;
261 GtkObjectClass *object_class;
262 GtkWidgetClass *widget_class;
264 gobject_class = G_OBJECT_CLASS (klass);
265 gobject_class->finalize = gtk_color_selection_finalize;
266 gobject_class->set_property = gtk_color_selection_set_property;
267 gobject_class->get_property = gtk_color_selection_get_property;
269 object_class = GTK_OBJECT_CLASS (klass);
270 object_class->destroy = gtk_color_selection_destroy;
272 widget_class = GTK_WIDGET_CLASS (klass);
273 widget_class->realize = gtk_color_selection_realize;
274 widget_class->unrealize = gtk_color_selection_unrealize;
275 widget_class->show_all = gtk_color_selection_show_all;
276 widget_class->grab_broken_event = gtk_color_selection_grab_broken;
278 g_object_class_install_property (gobject_class,
279 PROP_HAS_OPACITY_CONTROL,
280 g_param_spec_boolean ("has-opacity-control",
281 P_("Has Opacity Control"),
282 P_("Whether the color selector should allow setting opacity"),
284 GTK_PARAM_READWRITE));
285 g_object_class_install_property (gobject_class,
287 g_param_spec_boolean ("has-palette",
289 P_("Whether a palette should be used"),
291 GTK_PARAM_READWRITE));
292 g_object_class_install_property (gobject_class,
294 g_param_spec_boxed ("current-color",
296 P_("The current color"),
298 GTK_PARAM_READWRITE));
299 g_object_class_install_property (gobject_class,
301 g_param_spec_uint ("current-alpha",
303 P_("The current opacity value (0 fully transparent, 65535 fully opaque)"),
305 GTK_PARAM_READWRITE));
307 color_selection_signals[COLOR_CHANGED] =
308 g_signal_new (I_("color-changed"),
309 G_OBJECT_CLASS_TYPE (object_class),
311 G_STRUCT_OFFSET (GtkColorSelectionClass, color_changed),
313 _gtk_marshal_VOID__VOID,
316 gtk_settings_install_property (g_param_spec_string ("gtk-color-palette",
317 P_("Custom palette"),
318 P_("Palette to use in the color selector"),
320 GTK_PARAM_READWRITE));
322 g_type_class_add_private (gobject_class, sizeof (ColorSelectionPrivate));
326 gtk_color_selection_init (GtkColorSelection *colorsel)
329 GtkWidget *top_right_vbox;
330 GtkWidget *table, *label, *hbox, *frame, *vbox, *button;
331 GtkAdjustment *adjust;
332 GtkWidget *picker_image;
334 ColorSelectionPrivate *priv;
336 GList *focus_chain = NULL;
338 gtk_widget_push_composite_child ();
340 priv = colorsel->private_data = G_TYPE_INSTANCE_GET_PRIVATE (colorsel, GTK_TYPE_COLOR_SELECTION, ColorSelectionPrivate);
341 priv->changing = FALSE;
342 priv->default_set = FALSE;
343 priv->default_alpha_set = FALSE;
345 top_hbox = gtk_hbox_new (FALSE, 12);
346 gtk_box_pack_start (GTK_BOX (colorsel), top_hbox, FALSE, FALSE, 0);
348 vbox = gtk_vbox_new (FALSE, 6);
349 priv->triangle_colorsel = gtk_hsv_new ();
350 g_signal_connect (priv->triangle_colorsel, "changed",
351 G_CALLBACK (hsv_changed), colorsel);
352 gtk_hsv_set_metrics (GTK_HSV (priv->triangle_colorsel), 174, 15);
353 gtk_box_pack_start (GTK_BOX (top_hbox), vbox, FALSE, FALSE, 0);
354 gtk_box_pack_start (GTK_BOX (vbox), priv->triangle_colorsel, FALSE, FALSE, 0);
355 gtk_widget_set_tooltip_text (priv->triangle_colorsel,
356 _("Select the color you want from the outer ring. Select the darkness or lightness of that color using the inner triangle."));
358 hbox = gtk_hbox_new (FALSE, 6);
359 gtk_box_pack_end (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
361 frame = gtk_frame_new (NULL);
362 gtk_widget_set_size_request (frame, -1, 30);
363 gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
364 color_sample_new (colorsel);
365 gtk_container_add (GTK_CONTAINER (frame), priv->sample_area);
366 gtk_box_pack_start (GTK_BOX (hbox), frame, TRUE, TRUE, 0);
368 button = gtk_button_new ();
370 gtk_widget_set_events (button, GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK);
371 g_object_set_data (G_OBJECT (button), I_("COLORSEL"), colorsel);
372 g_signal_connect (button, "clicked",
373 G_CALLBACK (get_screen_color), NULL);
374 picker_image = gtk_image_new_from_stock (GTK_STOCK_COLOR_PICKER, GTK_ICON_SIZE_BUTTON);
375 gtk_container_add (GTK_CONTAINER (button), picker_image);
376 gtk_widget_show (GTK_WIDGET (picker_image));
377 gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
379 gtk_widget_set_tooltip_text (button,
380 _("Click the eyedropper, then click a color anywhere on your screen to select that color."));
382 top_right_vbox = gtk_vbox_new (FALSE, 6);
383 gtk_box_pack_start (GTK_BOX (top_hbox), top_right_vbox, FALSE, FALSE, 0);
384 table = gtk_table_new (8, 6, FALSE);
385 gtk_box_pack_start (GTK_BOX (top_right_vbox), table, FALSE, FALSE, 0);
386 gtk_table_set_row_spacings (GTK_TABLE (table), 6);
387 gtk_table_set_col_spacings (GTK_TABLE (table), 12);
389 make_label_spinbutton (colorsel, &priv->hue_spinbutton, _("_Hue:"), table, 0, 0, COLORSEL_HUE,
390 _("Position on the color wheel."));
391 gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (priv->hue_spinbutton), TRUE);
392 make_label_spinbutton (colorsel, &priv->sat_spinbutton, _("_Saturation:"), table, 0, 1, COLORSEL_SATURATION,
393 _("Intensity of the color."));
394 make_label_spinbutton (colorsel, &priv->val_spinbutton, _("_Value:"), table, 0, 2, COLORSEL_VALUE,
395 _("Brightness of the color."));
396 make_label_spinbutton (colorsel, &priv->red_spinbutton, _("_Red:"), table, 6, 0, COLORSEL_RED,
397 _("Amount of red light in the color."));
398 make_label_spinbutton (colorsel, &priv->green_spinbutton, _("_Green:"), table, 6, 1, COLORSEL_GREEN,
399 _("Amount of green light in the color."));
400 make_label_spinbutton (colorsel, &priv->blue_spinbutton, _("_Blue:"), table, 6, 2, COLORSEL_BLUE,
401 _("Amount of blue light in the color."));
402 gtk_table_attach_defaults (GTK_TABLE (table), gtk_hseparator_new (), 0, 8, 3, 4);
404 priv->opacity_label = gtk_label_new_with_mnemonic (_("Op_acity:"));
405 gtk_misc_set_alignment (GTK_MISC (priv->opacity_label), 0.0, 0.5);
406 gtk_table_attach_defaults (GTK_TABLE (table), priv->opacity_label, 0, 1, 4, 5);
407 adjust = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 255.0, 1.0, 1.0, 0.0));
408 g_object_set_data (G_OBJECT (adjust), I_("COLORSEL"), colorsel);
409 priv->opacity_slider = gtk_hscale_new (adjust);
410 gtk_widget_set_tooltip_text (priv->opacity_slider,
411 _("Transparency of the color."));
412 gtk_label_set_mnemonic_widget (GTK_LABEL (priv->opacity_label),
413 priv->opacity_slider);
414 gtk_scale_set_draw_value (GTK_SCALE (priv->opacity_slider), FALSE);
415 g_signal_connect (adjust, "value-changed",
416 G_CALLBACK (adjustment_changed),
417 GINT_TO_POINTER (COLORSEL_OPACITY));
418 gtk_table_attach_defaults (GTK_TABLE (table), priv->opacity_slider, 1, 7, 4, 5);
419 priv->opacity_entry = gtk_entry_new ();
420 gtk_widget_set_tooltip_text (priv->opacity_entry,
421 _("Transparency of the color."));
422 gtk_widget_set_size_request (priv->opacity_entry, 40, -1);
424 g_signal_connect (priv->opacity_entry, "activate",
425 G_CALLBACK (opacity_entry_changed), colorsel);
426 gtk_table_attach_defaults (GTK_TABLE (table), priv->opacity_entry, 7, 8, 4, 5);
428 label = gtk_label_new_with_mnemonic (_("Color _name:"));
429 gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 5, 6);
430 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
431 priv->hex_entry = gtk_entry_new ();
433 gtk_label_set_mnemonic_widget (GTK_LABEL (label), priv->hex_entry);
435 g_signal_connect (priv->hex_entry, "activate",
436 G_CALLBACK (hex_changed), colorsel);
438 g_signal_connect (priv->hex_entry, "focus-out-event",
439 G_CALLBACK (hex_focus_out), colorsel);
441 gtk_widget_set_tooltip_text (priv->hex_entry,
442 _("You can enter an HTML-style hexadecimal color value, or simply a color name such as 'orange' in this entry."));
444 gtk_entry_set_width_chars (GTK_ENTRY (priv->hex_entry), 7);
445 gtk_table_attach_defaults (GTK_TABLE (table), priv->hex_entry, 1, 5, 5, 6);
447 focus_chain = g_list_append (focus_chain, priv->hue_spinbutton);
448 focus_chain = g_list_append (focus_chain, priv->sat_spinbutton);
449 focus_chain = g_list_append (focus_chain, priv->val_spinbutton);
450 focus_chain = g_list_append (focus_chain, priv->red_spinbutton);
451 focus_chain = g_list_append (focus_chain, priv->green_spinbutton);
452 focus_chain = g_list_append (focus_chain, priv->blue_spinbutton);
453 focus_chain = g_list_append (focus_chain, priv->opacity_slider);
454 focus_chain = g_list_append (focus_chain, priv->opacity_entry);
455 focus_chain = g_list_append (focus_chain, priv->hex_entry);
456 gtk_container_set_focus_chain (GTK_CONTAINER (table), focus_chain);
457 g_list_free (focus_chain);
459 /* Set up the palette */
460 table = gtk_table_new (GTK_CUSTOM_PALETTE_HEIGHT, GTK_CUSTOM_PALETTE_WIDTH, TRUE);
461 gtk_table_set_row_spacings (GTK_TABLE (table), 1);
462 gtk_table_set_col_spacings (GTK_TABLE (table), 1);
463 for (i = 0; i < GTK_CUSTOM_PALETTE_WIDTH; i++)
465 for (j = 0; j < GTK_CUSTOM_PALETTE_HEIGHT; j++)
467 make_palette_frame (colorsel, table, i, j);
470 set_selected_palette (colorsel, 0, 0);
471 priv->palette_frame = gtk_vbox_new (FALSE, 6);
472 label = gtk_label_new_with_mnemonic (_("_Palette:"));
473 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
474 gtk_box_pack_start (GTK_BOX (priv->palette_frame), label, FALSE, FALSE, 0);
476 gtk_label_set_mnemonic_widget (GTK_LABEL (label),
477 priv->custom_palette[0][0]);
479 gtk_box_pack_end (GTK_BOX (top_right_vbox), priv->palette_frame, FALSE, FALSE, 0);
480 gtk_box_pack_start (GTK_BOX (priv->palette_frame), table, FALSE, FALSE, 0);
482 gtk_widget_show_all (top_hbox);
484 /* hide unused stuff */
486 if (priv->has_opacity == FALSE)
488 gtk_widget_hide (priv->opacity_label);
489 gtk_widget_hide (priv->opacity_slider);
490 gtk_widget_hide (priv->opacity_entry);
493 if (priv->has_palette == FALSE)
495 gtk_widget_hide (priv->palette_frame);
498 atk_obj = gtk_widget_get_accessible (priv->triangle_colorsel);
499 if (GTK_IS_ACCESSIBLE (atk_obj))
501 atk_object_set_name (atk_obj, _("Color Wheel"));
502 atk_object_set_role (gtk_widget_get_accessible (GTK_WIDGET (colorsel)), ATK_ROLE_COLOR_CHOOSER);
503 make_all_relations (atk_obj, priv);
506 gtk_widget_pop_composite_child ();
509 /* GObject methods */
511 gtk_color_selection_finalize (GObject *object)
513 G_OBJECT_CLASS (gtk_color_selection_parent_class)->finalize (object);
517 gtk_color_selection_set_property (GObject *object,
522 GtkColorSelection *colorsel = GTK_COLOR_SELECTION (object);
526 case PROP_HAS_OPACITY_CONTROL:
527 gtk_color_selection_set_has_opacity_control (colorsel,
528 g_value_get_boolean (value));
530 case PROP_HAS_PALETTE:
531 gtk_color_selection_set_has_palette (colorsel,
532 g_value_get_boolean (value));
534 case PROP_CURRENT_COLOR:
535 gtk_color_selection_set_current_color (colorsel, g_value_get_boxed (value));
537 case PROP_CURRENT_ALPHA:
538 gtk_color_selection_set_current_alpha (colorsel, g_value_get_uint (value));
541 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
548 gtk_color_selection_get_property (GObject *object,
553 GtkColorSelection *colorsel = GTK_COLOR_SELECTION (object);
558 case PROP_HAS_OPACITY_CONTROL:
559 g_value_set_boolean (value, gtk_color_selection_get_has_opacity_control (colorsel));
561 case PROP_HAS_PALETTE:
562 g_value_set_boolean (value, gtk_color_selection_get_has_palette (colorsel));
564 case PROP_CURRENT_COLOR:
565 gtk_color_selection_get_current_color (colorsel, &color);
566 g_value_set_boxed (value, &color);
568 case PROP_CURRENT_ALPHA:
569 g_value_set_uint (value, gtk_color_selection_get_current_alpha (colorsel));
572 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
577 /* GtkObject methods */
580 gtk_color_selection_destroy (GtkObject *object)
582 GtkColorSelection *cselection = GTK_COLOR_SELECTION (object);
583 ColorSelectionPrivate *priv = cselection->private_data;
585 if (priv->dropper_grab_widget)
587 gtk_widget_destroy (priv->dropper_grab_widget);
588 priv->dropper_grab_widget = NULL;
591 GTK_OBJECT_CLASS (gtk_color_selection_parent_class)->destroy (object);
594 /* GtkWidget methods */
597 gtk_color_selection_realize (GtkWidget *widget)
599 GtkColorSelection *colorsel = GTK_COLOR_SELECTION (widget);
600 ColorSelectionPrivate *priv = colorsel->private_data;
601 GtkSettings *settings = gtk_widget_get_settings (widget);
603 priv->settings_connection = g_signal_connect (settings,
604 "notify::gtk-color-palette",
605 G_CALLBACK (palette_change_notify_instance),
607 update_palette (colorsel);
609 GTK_WIDGET_CLASS (gtk_color_selection_parent_class)->realize (widget);
613 gtk_color_selection_unrealize (GtkWidget *widget)
615 GtkColorSelection *colorsel = GTK_COLOR_SELECTION (widget);
616 ColorSelectionPrivate *priv = colorsel->private_data;
617 GtkSettings *settings = gtk_widget_get_settings (widget);
619 g_signal_handler_disconnect (settings, priv->settings_connection);
621 GTK_WIDGET_CLASS (gtk_color_selection_parent_class)->unrealize (widget);
624 /* We override show-all since we have internal widgets that
625 * shouldn't be shown when you call show_all(), like the
626 * palette and opacity sliders.
629 gtk_color_selection_show_all (GtkWidget *widget)
631 gtk_widget_show (widget);
635 gtk_color_selection_grab_broken (GtkWidget *widget,
636 GdkEventGrabBroken *event)
638 shutdown_eyedropper (widget);
649 static void color_sample_draw_sample (GtkColorSelection *colorsel, int which);
650 static void color_sample_update_samples (GtkColorSelection *colorsel);
653 set_color_internal (GtkColorSelection *colorsel,
656 ColorSelectionPrivate *priv;
659 priv = colorsel->private_data;
660 priv->changing = TRUE;
661 priv->color[COLORSEL_RED] = color[0];
662 priv->color[COLORSEL_GREEN] = color[1];
663 priv->color[COLORSEL_BLUE] = color[2];
664 priv->color[COLORSEL_OPACITY] = color[3];
665 gtk_rgb_to_hsv (priv->color[COLORSEL_RED],
666 priv->color[COLORSEL_GREEN],
667 priv->color[COLORSEL_BLUE],
668 &priv->color[COLORSEL_HUE],
669 &priv->color[COLORSEL_SATURATION],
670 &priv->color[COLORSEL_VALUE]);
671 if (priv->default_set == FALSE)
673 for (i = 0; i < COLORSEL_NUM_CHANNELS; i++)
674 priv->old_color[i] = priv->color[i];
676 priv->default_set = TRUE;
677 priv->default_alpha_set = TRUE;
678 update_color (colorsel);
682 set_color_icon (GdkDragContext *context,
688 pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE,
691 pixel = (((UNSCALE (colors[COLORSEL_RED]) & 0xff00) << 16) |
692 ((UNSCALE (colors[COLORSEL_GREEN]) & 0xff00) << 8) |
693 ((UNSCALE (colors[COLORSEL_BLUE]) & 0xff00)));
695 gdk_pixbuf_fill (pixbuf, pixel);
697 gtk_drag_set_icon_pixbuf (context, pixbuf, -2, -2);
698 g_object_unref (pixbuf);
702 color_sample_drag_begin (GtkWidget *widget,
703 GdkDragContext *context,
706 GtkColorSelection *colorsel = data;
707 ColorSelectionPrivate *priv;
710 priv = colorsel->private_data;
712 if (widget == priv->old_sample)
713 colsrc = priv->old_color;
715 colsrc = priv->color;
717 set_color_icon (context, colsrc);
721 color_sample_drag_end (GtkWidget *widget,
722 GdkDragContext *context,
725 g_object_set_data (G_OBJECT (widget), I_("gtk-color-selection-drag-window"), NULL);
729 color_sample_drop_handle (GtkWidget *widget,
730 GdkDragContext *context,
733 GtkSelectionData *selection_data,
738 GtkColorSelection *colorsel = data;
739 ColorSelectionPrivate *priv;
742 priv = colorsel->private_data;
744 /* This is currently a guint16 array of the format:
751 if (selection_data->length < 0)
754 /* We accept drops with the wrong format, since the KDE color
755 * chooser incorrectly drops application/x-color with format 8.
757 if (selection_data->length != 8)
759 g_warning ("Received invalid color data\n");
763 vals = (guint16 *)selection_data->data;
765 if (widget == priv->cur_sample)
767 color[0] = (gdouble)vals[0] / 0xffff;
768 color[1] = (gdouble)vals[1] / 0xffff;
769 color[2] = (gdouble)vals[2] / 0xffff;
770 color[3] = (gdouble)vals[3] / 0xffff;
772 set_color_internal (colorsel, color);
777 color_sample_drag_handle (GtkWidget *widget,
778 GdkDragContext *context,
779 GtkSelectionData *selection_data,
784 GtkColorSelection *colorsel = data;
785 ColorSelectionPrivate *priv;
789 priv = colorsel->private_data;
791 if (widget == priv->old_sample)
792 colsrc = priv->old_color;
794 colsrc = priv->color;
796 vals[0] = colsrc[COLORSEL_RED] * 0xffff;
797 vals[1] = colsrc[COLORSEL_GREEN] * 0xffff;
798 vals[2] = colsrc[COLORSEL_BLUE] * 0xffff;
799 vals[3] = priv->has_opacity ? colsrc[COLORSEL_OPACITY] * 0xffff : 0xffff;
801 gtk_selection_data_set (selection_data,
802 gdk_atom_intern_static_string ("application/x-color"),
803 16, (guchar *)vals, 8);
806 /* which = 0 means draw old sample, which = 1 means draw new */
808 color_sample_draw_sample (GtkColorSelection *colorsel, int which)
811 gint x, y, wid, heig, goff;
812 ColorSelectionPrivate *priv;
815 g_return_if_fail (colorsel != NULL);
816 priv = colorsel->private_data;
818 g_return_if_fail (priv->sample_area != NULL);
819 if (!gtk_widget_is_drawable (priv->sample_area))
824 da = priv->old_sample;
829 da = priv->cur_sample;
830 goff = priv->old_sample->allocation.width % 32;
833 cr = gdk_cairo_create (da->window);
835 wid = da->allocation.width;
836 heig = da->allocation.height;
838 /* Below needs tweaking for non-power-of-two */
840 if (priv->has_opacity)
842 /* Draw checks in background */
844 cairo_set_source_rgb (cr, 0.5, 0.5, 0.5);
845 cairo_rectangle (cr, 0, 0, wid, heig);
848 cairo_set_source_rgb (cr, 0.75, 0.75, 0.75);
849 for (x = goff & -CHECK_SIZE; x < goff + wid; x += CHECK_SIZE)
850 for (y = 0; y < heig; y += CHECK_SIZE)
851 if ((x / CHECK_SIZE + y / CHECK_SIZE) % 2 == 0)
852 cairo_rectangle (cr, x - goff, y, CHECK_SIZE, CHECK_SIZE);
858 cairo_set_source_rgba (cr,
859 priv->old_color[COLORSEL_RED],
860 priv->old_color[COLORSEL_GREEN],
861 priv->old_color[COLORSEL_BLUE],
863 priv->old_color[COLORSEL_OPACITY] : 1.0);
867 cairo_set_source_rgba (cr,
868 priv->color[COLORSEL_RED],
869 priv->color[COLORSEL_GREEN],
870 priv->color[COLORSEL_BLUE],
872 priv->color[COLORSEL_OPACITY] : 1.0);
875 cairo_rectangle (cr, 0, 0, wid, heig);
883 color_sample_update_samples (GtkColorSelection *colorsel)
885 ColorSelectionPrivate *priv = colorsel->private_data;
886 gtk_widget_queue_draw (priv->old_sample);
887 gtk_widget_queue_draw (priv->cur_sample);
891 color_old_sample_expose (GtkWidget *da,
892 GdkEventExpose *event,
893 GtkColorSelection *colorsel)
895 color_sample_draw_sample (colorsel, 0);
901 color_cur_sample_expose (GtkWidget *da,
902 GdkEventExpose *event,
903 GtkColorSelection *colorsel)
905 color_sample_draw_sample (colorsel, 1);
910 color_sample_setup_dnd (GtkColorSelection *colorsel, GtkWidget *sample)
912 static const GtkTargetEntry targets[] = {
913 { "application/x-color", 0 }
915 ColorSelectionPrivate *priv;
916 priv = colorsel->private_data;
918 gtk_drag_source_set (sample,
919 GDK_BUTTON1_MASK | GDK_BUTTON3_MASK,
921 GDK_ACTION_COPY | GDK_ACTION_MOVE);
923 g_signal_connect (sample, "drag-begin",
924 G_CALLBACK (color_sample_drag_begin),
926 if (sample == priv->cur_sample)
929 gtk_drag_dest_set (sample,
930 GTK_DEST_DEFAULT_HIGHLIGHT |
931 GTK_DEST_DEFAULT_MOTION |
932 GTK_DEST_DEFAULT_DROP,
936 g_signal_connect (sample, "drag-end",
937 G_CALLBACK (color_sample_drag_end),
941 g_signal_connect (sample, "drag-data-get",
942 G_CALLBACK (color_sample_drag_handle),
944 g_signal_connect (sample, "drag-data-received",
945 G_CALLBACK (color_sample_drop_handle),
951 update_tooltips (GtkColorSelection *colorsel)
953 ColorSelectionPrivate *priv;
955 priv = colorsel->private_data;
957 if (priv->has_palette == TRUE)
959 gtk_widget_set_tooltip_text (priv->old_sample,
960 _("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."));
962 gtk_widget_set_tooltip_text (priv->cur_sample,
963 _("The color you've chosen. You can drag this color to a palette entry to save it for use in the future."));
967 gtk_widget_set_tooltip_text (priv->old_sample,
968 _("The previously-selected color, for comparison to the color you're selecting now."));
970 gtk_widget_set_tooltip_text (priv->cur_sample,
971 _("The color you've chosen."));
976 color_sample_new (GtkColorSelection *colorsel)
978 ColorSelectionPrivate *priv;
980 priv = colorsel->private_data;
982 priv->sample_area = gtk_hbox_new (FALSE, 0);
983 priv->old_sample = gtk_drawing_area_new ();
984 priv->cur_sample = gtk_drawing_area_new ();
986 gtk_box_pack_start (GTK_BOX (priv->sample_area), priv->old_sample,
988 gtk_box_pack_start (GTK_BOX (priv->sample_area), priv->cur_sample,
991 g_signal_connect (priv->old_sample, "expose-event",
992 G_CALLBACK (color_old_sample_expose),
994 g_signal_connect (priv->cur_sample, "expose-event",
995 G_CALLBACK (color_cur_sample_expose),
998 color_sample_setup_dnd (colorsel, priv->old_sample);
999 color_sample_setup_dnd (colorsel, priv->cur_sample);
1001 update_tooltips (colorsel);
1003 gtk_widget_show_all (priv->sample_area);
1009 * The palette area code
1014 palette_get_color (GtkWidget *drawing_area, gdouble *color)
1018 g_return_if_fail (color != NULL);
1020 color_val = g_object_get_data (G_OBJECT (drawing_area), "color_val");
1021 if (color_val == NULL)
1023 /* Default to white for no good reason */
1031 color[0] = color_val[0];
1032 color[1] = color_val[1];
1033 color[2] = color_val[2];
1038 palette_paint (GtkWidget *drawing_area,
1045 if (drawing_area->window == NULL)
1048 cr = gdk_cairo_create (drawing_area->window);
1050 gdk_cairo_set_source_color (cr, &drawing_area->style->bg[GTK_STATE_NORMAL]);
1051 gdk_cairo_rectangle (cr, area);
1054 if (gtk_widget_has_focus (drawing_area))
1056 set_focus_line_attributes (drawing_area, cr, &focus_width);
1058 cairo_rectangle (cr,
1059 focus_width / 2., focus_width / 2.,
1060 drawing_area->allocation.width - focus_width,
1061 drawing_area->allocation.height - focus_width);
1069 set_focus_line_attributes (GtkWidget *drawing_area,
1076 gtk_widget_style_get (drawing_area,
1077 "focus-line-width", focus_width,
1078 "focus-line-pattern", (gchar *)&dash_list,
1081 palette_get_color (drawing_area, color);
1083 if (INTENSITY (color[0], color[1], color[2]) > 0.5)
1084 cairo_set_source_rgb (cr, 0., 0., 0.);
1086 cairo_set_source_rgb (cr, 1., 1., 1.);
1088 cairo_set_line_width (cr, *focus_width);
1092 gint n_dashes = strlen ((gchar *)dash_list);
1093 gdouble *dashes = g_new (gdouble, n_dashes);
1094 gdouble total_length = 0;
1095 gdouble dash_offset;
1098 for (i = 0; i < n_dashes; i++)
1100 dashes[i] = dash_list[i];
1101 total_length += dash_list[i];
1104 /* The dash offset here aligns the pattern to integer pixels
1105 * by starting the dash at the right side of the left border
1106 * Negative dash offsets in cairo don't work
1107 * (https://bugs.freedesktop.org/show_bug.cgi?id=2729)
1109 dash_offset = - *focus_width / 2.;
1110 while (dash_offset < 0)
1111 dash_offset += total_length;
1113 cairo_set_dash (cr, dashes, n_dashes, dash_offset);
1121 palette_drag_begin (GtkWidget *widget,
1122 GdkDragContext *context,
1127 palette_get_color (widget, colors);
1128 set_color_icon (context, colors);
1132 palette_drag_handle (GtkWidget *widget,
1133 GdkDragContext *context,
1134 GtkSelectionData *selection_data,
1142 palette_get_color (widget, colsrc);
1144 vals[0] = colsrc[COLORSEL_RED] * 0xffff;
1145 vals[1] = colsrc[COLORSEL_GREEN] * 0xffff;
1146 vals[2] = colsrc[COLORSEL_BLUE] * 0xffff;
1149 gtk_selection_data_set (selection_data,
1150 gdk_atom_intern_static_string ("application/x-color"),
1151 16, (guchar *)vals, 8);
1155 palette_drag_end (GtkWidget *widget,
1156 GdkDragContext *context,
1159 g_object_set_data (G_OBJECT (widget), I_("gtk-color-selection-drag-window"), NULL);
1163 get_current_colors (GtkColorSelection *colorsel)
1165 GtkSettings *settings;
1166 GdkColor *colors = NULL;
1170 settings = gtk_widget_get_settings (GTK_WIDGET (colorsel));
1171 g_object_get (settings,
1172 "gtk-color-palette", &palette,
1175 if (!gtk_color_selection_palette_from_string (palette, &colors, &n_colors))
1177 gtk_color_selection_palette_from_string (default_colors, &colors, &n_colors);
1181 /* If there are less colors provided than the number of slots in the
1182 * color selection, we fill in the rest from the defaults.
1184 if (n_colors < (GTK_CUSTOM_PALETTE_WIDTH * GTK_CUSTOM_PALETTE_HEIGHT))
1186 GdkColor *tmp_colors = colors;
1187 gint tmp_n_colors = n_colors;
1189 gtk_color_selection_palette_from_string (default_colors, &colors, &n_colors);
1190 memcpy (colors, tmp_colors, sizeof (GdkColor) * tmp_n_colors);
1192 g_free (tmp_colors);
1196 g_assert (n_colors >= GTK_CUSTOM_PALETTE_WIDTH * GTK_CUSTOM_PALETTE_HEIGHT);
1202 /* Changes the model color */
1204 palette_change_color (GtkWidget *drawing_area,
1205 GtkColorSelection *colorsel,
1209 ColorSelectionPrivate *priv;
1211 GdkColor *current_colors;
1214 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
1215 g_return_if_fail (GTK_IS_DRAWING_AREA (drawing_area));
1217 priv = colorsel->private_data;
1219 gdk_color.red = UNSCALE (color[0]);
1220 gdk_color.green = UNSCALE (color[1]);
1221 gdk_color.blue = UNSCALE (color[2]);
1222 gdk_color.pixel = 0;
1225 y = 0; /* Quiet GCC */
1226 while (x < GTK_CUSTOM_PALETTE_WIDTH)
1229 while (y < GTK_CUSTOM_PALETTE_HEIGHT)
1231 if (priv->custom_palette[x][y] == drawing_area)
1242 g_assert (x < GTK_CUSTOM_PALETTE_WIDTH || y < GTK_CUSTOM_PALETTE_HEIGHT);
1244 current_colors = get_current_colors (colorsel);
1245 current_colors[y * GTK_CUSTOM_PALETTE_WIDTH + x] = gdk_color;
1247 screen = gtk_widget_get_screen (GTK_WIDGET (colorsel));
1248 if (change_palette_hook != default_change_palette_func)
1249 (* change_palette_hook) (screen, current_colors,
1250 GTK_CUSTOM_PALETTE_WIDTH * GTK_CUSTOM_PALETTE_HEIGHT);
1251 else if (noscreen_change_palette_hook != default_noscreen_change_palette_func)
1253 if (screen != gdk_screen_get_default ())
1254 g_warning ("gtk_color_selection_set_change_palette_hook used by widget is not on the default screen.");
1255 (* noscreen_change_palette_hook) (current_colors,
1256 GTK_CUSTOM_PALETTE_WIDTH * GTK_CUSTOM_PALETTE_HEIGHT);
1259 (* change_palette_hook) (screen, current_colors,
1260 GTK_CUSTOM_PALETTE_WIDTH * GTK_CUSTOM_PALETTE_HEIGHT);
1262 g_free (current_colors);
1265 /* Changes the view color */
1267 palette_set_color (GtkWidget *drawing_area,
1268 GtkColorSelection *colorsel,
1271 gdouble *new_color = g_new (double, 4);
1274 gdk_color.red = UNSCALE (color[0]);
1275 gdk_color.green = UNSCALE (color[1]);
1276 gdk_color.blue = UNSCALE (color[2]);
1278 gtk_widget_modify_bg (drawing_area, GTK_STATE_NORMAL, &gdk_color);
1280 if (GPOINTER_TO_INT (g_object_get_data (G_OBJECT (drawing_area), "color_set")) == 0)
1282 static const GtkTargetEntry targets[] = {
1283 { "application/x-color", 0 }
1285 gtk_drag_source_set (drawing_area,
1286 GDK_BUTTON1_MASK | GDK_BUTTON3_MASK,
1288 GDK_ACTION_COPY | GDK_ACTION_MOVE);
1290 g_signal_connect (drawing_area, "drag-begin",
1291 G_CALLBACK (palette_drag_begin),
1293 g_signal_connect (drawing_area, "drag-data-get",
1294 G_CALLBACK (palette_drag_handle),
1297 g_object_set_data (G_OBJECT (drawing_area), I_("color_set"),
1298 GINT_TO_POINTER (1));
1301 new_color[0] = color[0];
1302 new_color[1] = color[1];
1303 new_color[2] = color[2];
1306 g_object_set_data_full (G_OBJECT (drawing_area), I_("color_val"), new_color, (GDestroyNotify)g_free);
1310 palette_expose (GtkWidget *drawing_area,
1311 GdkEventExpose *event,
1314 if (drawing_area->window == NULL)
1317 palette_paint (drawing_area, &(event->area), data);
1323 popup_position_func (GtkMenu *menu,
1331 gint root_x, root_y;
1334 widget = GTK_WIDGET (user_data);
1336 g_return_if_fail (gtk_widget_get_realized (widget));
1338 gdk_window_get_origin (widget->window, &root_x, &root_y);
1340 gtk_widget_size_request (GTK_WIDGET (menu), &req);
1342 /* Put corner of menu centered on color cell */
1343 *x = root_x + widget->allocation.width / 2;
1344 *y = root_y + widget->allocation.height / 2;
1347 screen = gtk_widget_get_screen (widget);
1348 *x = CLAMP (*x, 0, MAX (0, gdk_screen_get_width (screen) - req.width));
1349 *y = CLAMP (*y, 0, MAX (0, gdk_screen_get_height (screen) - req.height));
1353 save_color_selected (GtkWidget *menuitem,
1356 GtkColorSelection *colorsel;
1357 GtkWidget *drawing_area;
1358 ColorSelectionPrivate *priv;
1360 drawing_area = GTK_WIDGET (data);
1362 colorsel = GTK_COLOR_SELECTION (g_object_get_data (G_OBJECT (drawing_area),
1365 priv = colorsel->private_data;
1367 palette_change_color (drawing_area, colorsel, priv->color);
1371 do_popup (GtkColorSelection *colorsel,
1372 GtkWidget *drawing_area,
1378 g_object_set_data (G_OBJECT (drawing_area),
1379 I_("gtk-color-sel"),
1382 menu = gtk_menu_new ();
1384 mi = gtk_menu_item_new_with_mnemonic (_("_Save color here"));
1386 g_signal_connect (mi, "activate",
1387 G_CALLBACK (save_color_selected),
1390 gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
1392 gtk_widget_show_all (mi);
1394 gtk_menu_popup (GTK_MENU (menu), NULL, NULL,
1395 popup_position_func, drawing_area,
1401 palette_enter (GtkWidget *drawing_area,
1402 GdkEventCrossing *event,
1405 g_object_set_data (G_OBJECT (drawing_area),
1406 I_("gtk-colorsel-have-pointer"),
1407 GUINT_TO_POINTER (TRUE));
1413 palette_leave (GtkWidget *drawing_area,
1414 GdkEventCrossing *event,
1417 g_object_set_data (G_OBJECT (drawing_area),
1418 I_("gtk-colorsel-have-pointer"),
1425 palette_press (GtkWidget *drawing_area,
1426 GdkEventButton *event,
1429 GtkColorSelection *colorsel = GTK_COLOR_SELECTION (data);
1431 gtk_widget_grab_focus (drawing_area);
1433 if (event->button == 3 &&
1434 event->type == GDK_BUTTON_PRESS)
1436 do_popup (colorsel, drawing_area, event->time);
1444 palette_release (GtkWidget *drawing_area,
1445 GdkEventButton *event,
1448 GtkColorSelection *colorsel = GTK_COLOR_SELECTION (data);
1450 gtk_widget_grab_focus (drawing_area);
1452 if (event->button == 1 &&
1453 g_object_get_data (G_OBJECT (drawing_area),
1454 "gtk-colorsel-have-pointer") != NULL)
1456 if (GPOINTER_TO_INT (g_object_get_data (G_OBJECT (drawing_area), "color_set")) != 0)
1459 palette_get_color (drawing_area, color);
1460 set_color_internal (colorsel, color);
1468 palette_drop_handle (GtkWidget *widget,
1469 GdkDragContext *context,
1472 GtkSelectionData *selection_data,
1477 GtkColorSelection *colorsel = GTK_COLOR_SELECTION (data);
1481 if (selection_data->length < 0)
1484 /* We accept drops with the wrong format, since the KDE color
1485 * chooser incorrectly drops application/x-color with format 8.
1487 if (selection_data->length != 8)
1489 g_warning ("Received invalid color data\n");
1493 vals = (guint16 *)selection_data->data;
1495 color[0] = (gdouble)vals[0] / 0xffff;
1496 color[1] = (gdouble)vals[1] / 0xffff;
1497 color[2] = (gdouble)vals[2] / 0xffff;
1498 color[3] = (gdouble)vals[3] / 0xffff;
1499 palette_change_color (widget, colorsel, color);
1500 set_color_internal (colorsel, color);
1504 palette_activate (GtkWidget *widget,
1508 /* should have a drawing area subclass with an activate signal */
1509 if ((event->keyval == GDK_space) ||
1510 (event->keyval == GDK_Return) ||
1511 (event->keyval == GDK_ISO_Enter) ||
1512 (event->keyval == GDK_KP_Enter) ||
1513 (event->keyval == GDK_KP_Space))
1515 if (GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget), "color_set")) != 0)
1518 palette_get_color (widget, color);
1519 set_color_internal (GTK_COLOR_SELECTION (data), color);
1528 palette_popup (GtkWidget *widget,
1531 GtkColorSelection *colorsel = GTK_COLOR_SELECTION (data);
1533 do_popup (colorsel, widget, GDK_CURRENT_TIME);
1539 palette_new (GtkColorSelection *colorsel)
1542 ColorSelectionPrivate *priv;
1544 static const GtkTargetEntry targets[] = {
1545 { "application/x-color", 0 }
1548 priv = colorsel->private_data;
1550 retval = gtk_drawing_area_new ();
1552 gtk_widget_set_can_focus (retval, TRUE);
1554 g_object_set_data (G_OBJECT (retval), I_("color_set"), GINT_TO_POINTER (0));
1555 gtk_widget_set_events (retval, GDK_BUTTON_PRESS_MASK
1556 | GDK_BUTTON_RELEASE_MASK
1558 | GDK_ENTER_NOTIFY_MASK
1559 | GDK_LEAVE_NOTIFY_MASK);
1561 g_signal_connect (retval, "expose-event",
1562 G_CALLBACK (palette_expose), colorsel);
1563 g_signal_connect (retval, "button-press-event",
1564 G_CALLBACK (palette_press), colorsel);
1565 g_signal_connect (retval, "button-release-event",
1566 G_CALLBACK (palette_release), colorsel);
1567 g_signal_connect (retval, "enter-notify-event",
1568 G_CALLBACK (palette_enter), colorsel);
1569 g_signal_connect (retval, "leave-notify-event",
1570 G_CALLBACK (palette_leave), colorsel);
1571 g_signal_connect (retval, "key-press-event",
1572 G_CALLBACK (palette_activate), colorsel);
1573 g_signal_connect (retval, "popup-menu",
1574 G_CALLBACK (palette_popup), colorsel);
1576 gtk_drag_dest_set (retval,
1577 GTK_DEST_DEFAULT_HIGHLIGHT |
1578 GTK_DEST_DEFAULT_MOTION |
1579 GTK_DEST_DEFAULT_DROP,
1583 g_signal_connect (retval, "drag-end",
1584 G_CALLBACK (palette_drag_end), NULL);
1585 g_signal_connect (retval, "drag-data-received",
1586 G_CALLBACK (palette_drop_handle), colorsel);
1588 gtk_widget_set_tooltip_text (retval,
1589 _("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.\""));
1596 * The actual GtkColorSelection widget
1601 make_picker_cursor (GdkScreen *screen)
1605 cursor = gdk_cursor_new_from_name (gdk_screen_get_display (screen),
1610 GdkColor bg = { 0, 0xffff, 0xffff, 0xffff };
1611 GdkColor fg = { 0, 0x0000, 0x0000, 0x0000 };
1613 GdkPixmap *pixmap, *mask;
1615 window = gdk_screen_get_root_window (screen);
1618 gdk_bitmap_create_from_data (window, (gchar *) dropper_bits,
1619 DROPPER_WIDTH, DROPPER_HEIGHT);
1622 gdk_bitmap_create_from_data (window, (gchar *) dropper_mask,
1623 DROPPER_WIDTH, DROPPER_HEIGHT);
1625 cursor = gdk_cursor_new_from_pixmap (pixmap, mask, &fg, &bg,
1626 DROPPER_X_HOT, DROPPER_Y_HOT);
1628 g_object_unref (pixmap);
1629 g_object_unref (mask);
1636 grab_color_at_pointer (GdkScreen *screen,
1644 GtkColorSelection *colorsel = data;
1645 ColorSelectionPrivate *priv;
1647 GdkColormap *colormap = gdk_screen_get_system_colormap (screen);
1648 GdkWindow *root_window = gdk_screen_get_root_window (screen);
1650 priv = colorsel->private_data;
1652 image = gdk_drawable_get_image (root_window, x_root, y_root, 1, 1);
1656 GdkDisplay *display = gdk_screen_get_display (screen);
1657 GdkWindow *window = gdk_display_get_window_at_device_position (display, device, &x, &y);
1660 image = gdk_drawable_get_image (window, x, y, 1, 1);
1664 pixel = gdk_image_get_pixel (image, 0, 0);
1665 g_object_unref (image);
1667 gdk_colormap_query_color (colormap, pixel, &color);
1669 priv->color[COLORSEL_RED] = SCALE (color.red);
1670 priv->color[COLORSEL_GREEN] = SCALE (color.green);
1671 priv->color[COLORSEL_BLUE] = SCALE (color.blue);
1673 gtk_rgb_to_hsv (priv->color[COLORSEL_RED],
1674 priv->color[COLORSEL_GREEN],
1675 priv->color[COLORSEL_BLUE],
1676 &priv->color[COLORSEL_HUE],
1677 &priv->color[COLORSEL_SATURATION],
1678 &priv->color[COLORSEL_VALUE]);
1680 update_color (colorsel);
1684 shutdown_eyedropper (GtkWidget *widget)
1686 GtkColorSelection *colorsel;
1687 ColorSelectionPrivate *priv;
1689 colorsel = GTK_COLOR_SELECTION (widget);
1690 priv = colorsel->private_data;
1694 gdk_device_ungrab (priv->keyboard_device, priv->grab_time);
1695 gdk_device_ungrab (priv->pointer_device, priv->grab_time);
1696 gtk_device_grab_remove (priv->dropper_grab_widget, priv->pointer_device);
1698 priv->has_grab = FALSE;
1699 priv->keyboard_device = NULL;
1700 priv->pointer_device = NULL;
1705 mouse_motion (GtkWidget *invisible,
1706 GdkEventMotion *event,
1709 grab_color_at_pointer (gdk_event_get_screen ((GdkEvent *) event),
1710 gdk_event_get_device ((GdkEvent *) event),
1711 event->x_root, event->y_root, data);
1715 mouse_release (GtkWidget *invisible,
1716 GdkEventButton *event,
1719 /* GtkColorSelection *colorsel = data; */
1721 if (event->button != 1)
1724 grab_color_at_pointer (gdk_event_get_screen ((GdkEvent *) event),
1725 gdk_event_get_device ((GdkEvent *) event),
1726 event->x_root, event->y_root, data);
1728 shutdown_eyedropper (GTK_WIDGET (data));
1730 g_signal_handlers_disconnect_by_func (invisible,
1733 g_signal_handlers_disconnect_by_func (invisible,
1740 /* Helper Functions */
1743 key_press (GtkWidget *invisible,
1747 GdkDisplay *display = gtk_widget_get_display (invisible);
1748 GdkScreen *screen = gdk_event_get_screen ((GdkEvent *) event);
1749 GdkDevice *device, *pointer_device;
1750 guint state = event->state & gtk_accelerator_get_default_mod_mask ();
1754 device = gdk_event_get_device ((GdkEvent * ) event);
1755 pointer_device = gdk_device_get_associated_device (device);
1756 gdk_display_get_device_state (display, pointer_device, NULL, &x, &y, NULL);
1761 switch (event->keyval)
1768 grab_color_at_pointer (screen, pointer_device, x, y, data);
1772 shutdown_eyedropper (data);
1774 g_signal_handlers_disconnect_by_func (invisible,
1777 g_signal_handlers_disconnect_by_func (invisible,
1783 #if defined GDK_WINDOWING_X11 || defined GDK_WINDOWING_WIN32
1786 dy = state == GDK_MOD1_MASK ? -BIG_STEP : -1;
1791 dy = state == GDK_MOD1_MASK ? BIG_STEP : 1;
1796 dx = state == GDK_MOD1_MASK ? -BIG_STEP : -1;
1801 dx = state == GDK_MOD1_MASK ? BIG_STEP : 1;
1809 gdk_display_warp_device (display, pointer_device, screen, x + dx, y + dy);
1816 mouse_press (GtkWidget *invisible,
1817 GdkEventButton *event,
1820 /* GtkColorSelection *colorsel = data; */
1822 if (event->type == GDK_BUTTON_PRESS &&
1825 g_signal_connect (invisible, "motion-notify-event",
1826 G_CALLBACK (mouse_motion),
1828 g_signal_connect (invisible, "button-release-event",
1829 G_CALLBACK (mouse_release),
1831 g_signal_handlers_disconnect_by_func (invisible,
1834 g_signal_handlers_disconnect_by_func (invisible,
1843 /* when the button is clicked */
1845 get_screen_color (GtkWidget *button)
1847 GtkColorSelection *colorsel = g_object_get_data (G_OBJECT (button), "COLORSEL");
1848 ColorSelectionPrivate *priv = colorsel->private_data;
1849 GdkScreen *screen = gtk_widget_get_screen (GTK_WIDGET (button));
1850 GdkDevice *device, *keyb_device, *pointer_device;
1851 GdkCursor *picker_cursor;
1852 GdkGrabStatus grab_status;
1853 GtkWidget *grab_widget, *toplevel;
1855 guint32 time = gtk_get_current_event_time ();
1857 device = gtk_get_current_event_device ();
1859 if (device->source == GDK_SOURCE_KEYBOARD)
1861 keyb_device = device;
1862 pointer_device = gdk_device_get_associated_device (device);
1866 pointer_device = device;
1867 keyb_device = gdk_device_get_associated_device (device);
1870 if (priv->dropper_grab_widget == NULL)
1872 grab_widget = gtk_window_new (GTK_WINDOW_POPUP);
1873 gtk_window_set_screen (GTK_WINDOW (grab_widget), screen);
1874 gtk_window_resize (GTK_WINDOW (grab_widget), 1, 1);
1875 gtk_window_move (GTK_WINDOW (grab_widget), -100, -100);
1876 gtk_widget_show (grab_widget);
1878 gtk_widget_add_events (grab_widget,
1879 GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_PRESS_MASK | GDK_POINTER_MOTION_MASK);
1881 toplevel = gtk_widget_get_toplevel (GTK_WIDGET (colorsel));
1883 if (GTK_IS_WINDOW (toplevel))
1885 if (GTK_WINDOW (toplevel)->group)
1886 gtk_window_group_add_window (GTK_WINDOW (toplevel)->group,
1887 GTK_WINDOW (grab_widget));
1890 priv->dropper_grab_widget = grab_widget;
1893 if (gdk_device_grab (keyb_device,
1894 priv->dropper_grab_widget->window,
1895 GDK_OWNERSHIP_APPLICATION, FALSE,
1896 GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK,
1897 NULL, time) != GDK_GRAB_SUCCESS)
1900 picker_cursor = make_picker_cursor (screen);
1901 grab_status = gdk_device_grab (pointer_device,
1902 priv->dropper_grab_widget->window,
1903 GDK_OWNERSHIP_APPLICATION,
1905 GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_PRESS_MASK | GDK_POINTER_MOTION_MASK,
1908 gdk_cursor_unref (picker_cursor);
1910 if (grab_status != GDK_GRAB_SUCCESS)
1912 gdk_device_ungrab (keyb_device, time);
1916 gtk_device_grab_add (priv->dropper_grab_widget,
1920 priv->grab_time = time;
1921 priv->has_grab = TRUE;
1922 priv->keyboard_device = keyb_device;
1923 priv->pointer_device = pointer_device;
1925 g_signal_connect (priv->dropper_grab_widget, "button-press-event",
1926 G_CALLBACK (mouse_press), colorsel);
1927 g_signal_connect (priv->dropper_grab_widget, "key-press-event",
1928 G_CALLBACK (key_press), colorsel);
1932 hex_changed (GtkWidget *hex_entry,
1935 GtkColorSelection *colorsel;
1936 ColorSelectionPrivate *priv;
1940 colorsel = GTK_COLOR_SELECTION (data);
1941 priv = colorsel->private_data;
1946 text = gtk_editable_get_chars (GTK_EDITABLE (priv->hex_entry), 0, -1);
1947 if (gdk_color_parse (text, &color))
1949 priv->color[COLORSEL_RED] = CLAMP (color.red/65535.0, 0.0, 1.0);
1950 priv->color[COLORSEL_GREEN] = CLAMP (color.green/65535.0, 0.0, 1.0);
1951 priv->color[COLORSEL_BLUE] = CLAMP (color.blue/65535.0, 0.0, 1.0);
1952 gtk_rgb_to_hsv (priv->color[COLORSEL_RED],
1953 priv->color[COLORSEL_GREEN],
1954 priv->color[COLORSEL_BLUE],
1955 &priv->color[COLORSEL_HUE],
1956 &priv->color[COLORSEL_SATURATION],
1957 &priv->color[COLORSEL_VALUE]);
1958 update_color (colorsel);
1964 hex_focus_out (GtkWidget *hex_entry,
1965 GdkEventFocus *event,
1968 hex_changed (hex_entry, data);
1974 hsv_changed (GtkWidget *hsv,
1977 GtkColorSelection *colorsel;
1978 ColorSelectionPrivate *priv;
1980 colorsel = GTK_COLOR_SELECTION (data);
1981 priv = colorsel->private_data;
1986 gtk_hsv_get_color (GTK_HSV (hsv),
1987 &priv->color[COLORSEL_HUE],
1988 &priv->color[COLORSEL_SATURATION],
1989 &priv->color[COLORSEL_VALUE]);
1990 gtk_hsv_to_rgb (priv->color[COLORSEL_HUE],
1991 priv->color[COLORSEL_SATURATION],
1992 priv->color[COLORSEL_VALUE],
1993 &priv->color[COLORSEL_RED],
1994 &priv->color[COLORSEL_GREEN],
1995 &priv->color[COLORSEL_BLUE]);
1996 update_color (colorsel);
2000 adjustment_changed (GtkAdjustment *adjustment,
2003 GtkColorSelection *colorsel;
2004 ColorSelectionPrivate *priv;
2006 colorsel = GTK_COLOR_SELECTION (g_object_get_data (G_OBJECT (adjustment), "COLORSEL"));
2007 priv = colorsel->private_data;
2012 switch (GPOINTER_TO_INT (data))
2014 case COLORSEL_SATURATION:
2015 case COLORSEL_VALUE:
2016 priv->color[GPOINTER_TO_INT (data)] = adjustment->value / 100;
2017 gtk_hsv_to_rgb (priv->color[COLORSEL_HUE],
2018 priv->color[COLORSEL_SATURATION],
2019 priv->color[COLORSEL_VALUE],
2020 &priv->color[COLORSEL_RED],
2021 &priv->color[COLORSEL_GREEN],
2022 &priv->color[COLORSEL_BLUE]);
2025 priv->color[GPOINTER_TO_INT (data)] = adjustment->value / 360;
2026 gtk_hsv_to_rgb (priv->color[COLORSEL_HUE],
2027 priv->color[COLORSEL_SATURATION],
2028 priv->color[COLORSEL_VALUE],
2029 &priv->color[COLORSEL_RED],
2030 &priv->color[COLORSEL_GREEN],
2031 &priv->color[COLORSEL_BLUE]);
2034 case COLORSEL_GREEN:
2036 priv->color[GPOINTER_TO_INT (data)] = adjustment->value / 255;
2038 gtk_rgb_to_hsv (priv->color[COLORSEL_RED],
2039 priv->color[COLORSEL_GREEN],
2040 priv->color[COLORSEL_BLUE],
2041 &priv->color[COLORSEL_HUE],
2042 &priv->color[COLORSEL_SATURATION],
2043 &priv->color[COLORSEL_VALUE]);
2046 priv->color[GPOINTER_TO_INT (data)] = adjustment->value / 255;
2049 update_color (colorsel);
2053 opacity_entry_changed (GtkWidget *opacity_entry,
2056 GtkColorSelection *colorsel;
2057 ColorSelectionPrivate *priv;
2061 colorsel = GTK_COLOR_SELECTION (data);
2062 priv = colorsel->private_data;
2067 text = gtk_editable_get_chars (GTK_EDITABLE (priv->opacity_entry), 0, -1);
2068 adj = gtk_range_get_adjustment (GTK_RANGE (priv->opacity_slider));
2069 gtk_adjustment_set_value (adj, g_strtod (text, NULL));
2071 update_color (colorsel);
2077 make_label_spinbutton (GtkColorSelection *colorsel,
2078 GtkWidget **spinbutton,
2084 const gchar *tooltip)
2087 GtkAdjustment *adjust;
2089 if (channel_type == COLORSEL_HUE)
2091 adjust = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 360.0, 1.0, 1.0, 0.0));
2093 else if (channel_type == COLORSEL_SATURATION ||
2094 channel_type == COLORSEL_VALUE)
2096 adjust = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 100.0, 1.0, 1.0, 0.0));
2100 adjust = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 255.0, 1.0, 1.0, 0.0));
2102 g_object_set_data (G_OBJECT (adjust), I_("COLORSEL"), colorsel);
2103 *spinbutton = gtk_spin_button_new (adjust, 10.0, 0);
2105 gtk_widget_set_tooltip_text (*spinbutton, tooltip);
2107 g_signal_connect (adjust, "value-changed",
2108 G_CALLBACK (adjustment_changed),
2109 GINT_TO_POINTER (channel_type));
2110 label = gtk_label_new_with_mnemonic (text);
2111 gtk_label_set_mnemonic_widget (GTK_LABEL (label), *spinbutton);
2113 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
2114 gtk_table_attach_defaults (GTK_TABLE (table), label, i, i+1, j, j+1);
2115 gtk_table_attach_defaults (GTK_TABLE (table), *spinbutton, i+1, i+2, j, j+1);
2119 make_palette_frame (GtkColorSelection *colorsel,
2125 ColorSelectionPrivate *priv;
2127 priv = colorsel->private_data;
2128 frame = gtk_frame_new (NULL);
2129 gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
2130 priv->custom_palette[i][j] = palette_new (colorsel);
2131 gtk_widget_set_size_request (priv->custom_palette[i][j], CUSTOM_PALETTE_ENTRY_WIDTH, CUSTOM_PALETTE_ENTRY_HEIGHT);
2132 gtk_container_add (GTK_CONTAINER (frame), priv->custom_palette[i][j]);
2133 gtk_table_attach_defaults (GTK_TABLE (table), frame, i, i+1, j, j+1);
2136 /* Set the palette entry [x][y] to be the currently selected one. */
2138 set_selected_palette (GtkColorSelection *colorsel, int x, int y)
2140 ColorSelectionPrivate *priv = colorsel->private_data;
2142 gtk_widget_grab_focus (priv->custom_palette[x][y]);
2146 scale_round (double val, double factor)
2148 val = floor (val * factor + 0.5);
2150 val = MIN (val, factor);
2155 update_color (GtkColorSelection *colorsel)
2157 ColorSelectionPrivate *priv = colorsel->private_data;
2159 gchar opacity_text[32];
2162 priv->changing = TRUE;
2163 color_sample_update_samples (colorsel);
2165 gtk_hsv_set_color (GTK_HSV (priv->triangle_colorsel),
2166 priv->color[COLORSEL_HUE],
2167 priv->color[COLORSEL_SATURATION],
2168 priv->color[COLORSEL_VALUE]);
2169 gtk_adjustment_set_value (gtk_spin_button_get_adjustment
2170 (GTK_SPIN_BUTTON (priv->hue_spinbutton)),
2171 scale_round (priv->color[COLORSEL_HUE], 360));
2172 gtk_adjustment_set_value (gtk_spin_button_get_adjustment
2173 (GTK_SPIN_BUTTON (priv->sat_spinbutton)),
2174 scale_round (priv->color[COLORSEL_SATURATION], 100));
2175 gtk_adjustment_set_value (gtk_spin_button_get_adjustment
2176 (GTK_SPIN_BUTTON (priv->val_spinbutton)),
2177 scale_round (priv->color[COLORSEL_VALUE], 100));
2178 gtk_adjustment_set_value (gtk_spin_button_get_adjustment
2179 (GTK_SPIN_BUTTON (priv->red_spinbutton)),
2180 scale_round (priv->color[COLORSEL_RED], 255));
2181 gtk_adjustment_set_value (gtk_spin_button_get_adjustment
2182 (GTK_SPIN_BUTTON (priv->green_spinbutton)),
2183 scale_round (priv->color[COLORSEL_GREEN], 255));
2184 gtk_adjustment_set_value (gtk_spin_button_get_adjustment
2185 (GTK_SPIN_BUTTON (priv->blue_spinbutton)),
2186 scale_round (priv->color[COLORSEL_BLUE], 255));
2187 gtk_adjustment_set_value (gtk_range_get_adjustment
2188 (GTK_RANGE (priv->opacity_slider)),
2189 scale_round (priv->color[COLORSEL_OPACITY], 255));
2191 g_snprintf (opacity_text, 32, "%.0f", scale_round (priv->color[COLORSEL_OPACITY], 255));
2192 gtk_entry_set_text (GTK_ENTRY (priv->opacity_entry), opacity_text);
2194 g_snprintf (entryval, 11, "#%2X%2X%2X",
2195 (guint) (scale_round (priv->color[COLORSEL_RED], 255)),
2196 (guint) (scale_round (priv->color[COLORSEL_GREEN], 255)),
2197 (guint) (scale_round (priv->color[COLORSEL_BLUE], 255)));
2199 for (ptr = entryval; *ptr; ptr++)
2202 gtk_entry_set_text (GTK_ENTRY (priv->hex_entry), entryval);
2203 priv->changing = FALSE;
2205 g_object_ref (colorsel);
2207 g_signal_emit (colorsel, color_selection_signals[COLOR_CHANGED], 0);
2209 g_object_freeze_notify (G_OBJECT (colorsel));
2210 g_object_notify (G_OBJECT (colorsel), "current-color");
2211 g_object_notify (G_OBJECT (colorsel), "current-alpha");
2212 g_object_thaw_notify (G_OBJECT (colorsel));
2214 g_object_unref (colorsel);
2218 update_palette (GtkColorSelection *colorsel)
2220 GdkColor *current_colors;
2223 current_colors = get_current_colors (colorsel);
2225 for (i = 0; i < GTK_CUSTOM_PALETTE_HEIGHT; i++)
2227 for (j = 0; j < GTK_CUSTOM_PALETTE_WIDTH; j++)
2231 index = i * GTK_CUSTOM_PALETTE_WIDTH + j;
2233 gtk_color_selection_set_palette_color (colorsel,
2235 ¤t_colors[index]);
2239 g_free (current_colors);
2243 palette_change_notify_instance (GObject *object,
2247 update_palette (GTK_COLOR_SELECTION (data));
2251 default_noscreen_change_palette_func (const GdkColor *colors,
2254 default_change_palette_func (gdk_screen_get_default (), colors, n_colors);
2258 default_change_palette_func (GdkScreen *screen,
2259 const GdkColor *colors,
2264 str = gtk_color_selection_palette_to_string (colors, n_colors);
2266 gtk_settings_set_string_property (gtk_settings_get_for_screen (screen),
2267 "gtk-color-palette",
2269 "gtk_color_selection_palette_to_string");
2275 * gtk_color_selection_new:
2277 * Creates a new GtkColorSelection.
2279 * Return value: a new #GtkColorSelection
2282 gtk_color_selection_new (void)
2284 GtkColorSelection *colorsel;
2285 ColorSelectionPrivate *priv;
2292 colorsel = g_object_new (GTK_TYPE_COLOR_SELECTION, NULL);
2293 priv = colorsel->private_data;
2294 set_color_internal (colorsel, color);
2295 gtk_color_selection_set_has_opacity_control (colorsel, TRUE);
2297 /* We want to make sure that default_set is FALSE */
2298 /* This way the user can still set it */
2299 priv->default_set = FALSE;
2300 priv->default_alpha_set = FALSE;
2302 return GTK_WIDGET (colorsel);
2306 * gtk_color_selection_get_has_opacity_control:
2307 * @colorsel: a #GtkColorSelection.
2309 * Determines whether the colorsel has an opacity control.
2311 * Return value: %TRUE if the @colorsel has an opacity control. %FALSE if it does't.
2314 gtk_color_selection_get_has_opacity_control (GtkColorSelection *colorsel)
2316 ColorSelectionPrivate *priv;
2318 g_return_val_if_fail (GTK_IS_COLOR_SELECTION (colorsel), FALSE);
2320 priv = colorsel->private_data;
2322 return priv->has_opacity;
2326 * gtk_color_selection_set_has_opacity_control:
2327 * @colorsel: a #GtkColorSelection.
2328 * @has_opacity: %TRUE if @colorsel can set the opacity, %FALSE otherwise.
2330 * Sets the @colorsel to use or not use opacity.
2334 gtk_color_selection_set_has_opacity_control (GtkColorSelection *colorsel,
2335 gboolean has_opacity)
2337 ColorSelectionPrivate *priv;
2339 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2341 priv = colorsel->private_data;
2342 has_opacity = has_opacity != FALSE;
2344 if (priv->has_opacity != has_opacity)
2346 priv->has_opacity = has_opacity;
2349 gtk_widget_show (priv->opacity_slider);
2350 gtk_widget_show (priv->opacity_label);
2351 gtk_widget_show (priv->opacity_entry);
2355 gtk_widget_hide (priv->opacity_slider);
2356 gtk_widget_hide (priv->opacity_label);
2357 gtk_widget_hide (priv->opacity_entry);
2359 color_sample_update_samples (colorsel);
2361 g_object_notify (G_OBJECT (colorsel), "has-opacity-control");
2366 * gtk_color_selection_get_has_palette:
2367 * @colorsel: a #GtkColorSelection.
2369 * Determines whether the color selector has a color palette.
2371 * Return value: %TRUE if the selector has a palette. %FALSE if it hasn't.
2374 gtk_color_selection_get_has_palette (GtkColorSelection *colorsel)
2376 ColorSelectionPrivate *priv;
2378 g_return_val_if_fail (GTK_IS_COLOR_SELECTION (colorsel), FALSE);
2380 priv = colorsel->private_data;
2382 return priv->has_palette;
2386 * gtk_color_selection_set_has_palette:
2387 * @colorsel: a #GtkColorSelection.
2388 * @has_palette: %TRUE if palette is to be visible, %FALSE otherwise.
2390 * Shows and hides the palette based upon the value of @has_palette.
2394 gtk_color_selection_set_has_palette (GtkColorSelection *colorsel,
2395 gboolean has_palette)
2397 ColorSelectionPrivate *priv;
2398 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2400 priv = colorsel->private_data;
2401 has_palette = has_palette != FALSE;
2403 if (priv->has_palette != has_palette)
2405 priv->has_palette = has_palette;
2407 gtk_widget_show (priv->palette_frame);
2409 gtk_widget_hide (priv->palette_frame);
2411 update_tooltips (colorsel);
2413 g_object_notify (G_OBJECT (colorsel), "has-palette");
2418 * gtk_color_selection_set_current_color:
2419 * @colorsel: a #GtkColorSelection.
2420 * @color: A #GdkColor to set the current color with.
2422 * Sets the current color to be @color. The first time this is called, it will
2423 * also set the original color to be @color too.
2426 gtk_color_selection_set_current_color (GtkColorSelection *colorsel,
2427 const GdkColor *color)
2429 ColorSelectionPrivate *priv;
2432 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2433 g_return_if_fail (color != NULL);
2435 priv = colorsel->private_data;
2436 priv->changing = TRUE;
2437 priv->color[COLORSEL_RED] = SCALE (color->red);
2438 priv->color[COLORSEL_GREEN] = SCALE (color->green);
2439 priv->color[COLORSEL_BLUE] = SCALE (color->blue);
2440 gtk_rgb_to_hsv (priv->color[COLORSEL_RED],
2441 priv->color[COLORSEL_GREEN],
2442 priv->color[COLORSEL_BLUE],
2443 &priv->color[COLORSEL_HUE],
2444 &priv->color[COLORSEL_SATURATION],
2445 &priv->color[COLORSEL_VALUE]);
2446 if (priv->default_set == FALSE)
2448 for (i = 0; i < COLORSEL_NUM_CHANNELS; i++)
2449 priv->old_color[i] = priv->color[i];
2451 priv->default_set = TRUE;
2452 update_color (colorsel);
2456 * gtk_color_selection_set_current_alpha:
2457 * @colorsel: a #GtkColorSelection.
2458 * @alpha: an integer between 0 and 65535.
2460 * Sets the current opacity to be @alpha. The first time this is called, it will
2461 * also set the original opacity to be @alpha too.
2464 gtk_color_selection_set_current_alpha (GtkColorSelection *colorsel,
2467 ColorSelectionPrivate *priv;
2470 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2472 priv = colorsel->private_data;
2473 priv->changing = TRUE;
2474 priv->color[COLORSEL_OPACITY] = SCALE (alpha);
2475 if (priv->default_alpha_set == FALSE)
2477 for (i = 0; i < COLORSEL_NUM_CHANNELS; i++)
2478 priv->old_color[i] = priv->color[i];
2480 priv->default_alpha_set = TRUE;
2481 update_color (colorsel);
2485 * gtk_color_selection_get_current_color:
2486 * @colorsel: a #GtkColorSelection.
2487 * @color: a #GdkColor to fill in with the current color.
2489 * Sets @color to be the current color in the GtkColorSelection widget.
2492 gtk_color_selection_get_current_color (GtkColorSelection *colorsel,
2495 ColorSelectionPrivate *priv;
2497 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2498 g_return_if_fail (color != NULL);
2500 priv = colorsel->private_data;
2501 color->red = UNSCALE (priv->color[COLORSEL_RED]);
2502 color->green = UNSCALE (priv->color[COLORSEL_GREEN]);
2503 color->blue = UNSCALE (priv->color[COLORSEL_BLUE]);
2507 * gtk_color_selection_get_current_alpha:
2508 * @colorsel: a #GtkColorSelection.
2510 * Returns the current alpha value.
2512 * Return value: an integer between 0 and 65535.
2515 gtk_color_selection_get_current_alpha (GtkColorSelection *colorsel)
2517 ColorSelectionPrivate *priv;
2519 g_return_val_if_fail (GTK_IS_COLOR_SELECTION (colorsel), 0);
2521 priv = colorsel->private_data;
2522 return priv->has_opacity ? UNSCALE (priv->color[COLORSEL_OPACITY]) : 65535;
2526 * gtk_color_selection_set_previous_color:
2527 * @colorsel: a #GtkColorSelection.
2528 * @color: a #GdkColor to set the previous color with.
2530 * Sets the 'previous' color to be @color. This function should be called with
2531 * some hesitations, as it might seem confusing to have that color change.
2532 * Calling gtk_color_selection_set_current_color() will also set this color the first
2533 * time it is called.
2536 gtk_color_selection_set_previous_color (GtkColorSelection *colorsel,
2537 const GdkColor *color)
2539 ColorSelectionPrivate *priv;
2541 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2542 g_return_if_fail (color != NULL);
2544 priv = colorsel->private_data;
2545 priv->changing = TRUE;
2546 priv->old_color[COLORSEL_RED] = SCALE (color->red);
2547 priv->old_color[COLORSEL_GREEN] = SCALE (color->green);
2548 priv->old_color[COLORSEL_BLUE] = SCALE (color->blue);
2549 gtk_rgb_to_hsv (priv->old_color[COLORSEL_RED],
2550 priv->old_color[COLORSEL_GREEN],
2551 priv->old_color[COLORSEL_BLUE],
2552 &priv->old_color[COLORSEL_HUE],
2553 &priv->old_color[COLORSEL_SATURATION],
2554 &priv->old_color[COLORSEL_VALUE]);
2555 color_sample_update_samples (colorsel);
2556 priv->default_set = TRUE;
2557 priv->changing = FALSE;
2561 * gtk_color_selection_set_previous_alpha:
2562 * @colorsel: a #GtkColorSelection.
2563 * @alpha: an integer between 0 and 65535.
2565 * Sets the 'previous' alpha to be @alpha. This function should be called with
2566 * some hesitations, as it might seem confusing to have that alpha change.
2569 gtk_color_selection_set_previous_alpha (GtkColorSelection *colorsel,
2572 ColorSelectionPrivate *priv;
2574 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2576 priv = colorsel->private_data;
2577 priv->changing = TRUE;
2578 priv->old_color[COLORSEL_OPACITY] = SCALE (alpha);
2579 color_sample_update_samples (colorsel);
2580 priv->default_alpha_set = TRUE;
2581 priv->changing = FALSE;
2586 * gtk_color_selection_get_previous_color:
2587 * @colorsel: a #GtkColorSelection.
2588 * @color: a #GdkColor to fill in with the original color value.
2590 * Fills @color in with the original color value.
2593 gtk_color_selection_get_previous_color (GtkColorSelection *colorsel,
2596 ColorSelectionPrivate *priv;
2598 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2599 g_return_if_fail (color != NULL);
2601 priv = colorsel->private_data;
2602 color->red = UNSCALE (priv->old_color[COLORSEL_RED]);
2603 color->green = UNSCALE (priv->old_color[COLORSEL_GREEN]);
2604 color->blue = UNSCALE (priv->old_color[COLORSEL_BLUE]);
2608 * gtk_color_selection_get_previous_alpha:
2609 * @colorsel: a #GtkColorSelection.
2611 * Returns the previous alpha value.
2613 * Return value: an integer between 0 and 65535.
2616 gtk_color_selection_get_previous_alpha (GtkColorSelection *colorsel)
2618 ColorSelectionPrivate *priv;
2620 g_return_val_if_fail (GTK_IS_COLOR_SELECTION (colorsel), 0);
2622 priv = colorsel->private_data;
2623 return priv->has_opacity ? UNSCALE (priv->old_color[COLORSEL_OPACITY]) : 65535;
2627 * gtk_color_selection_set_palette_color:
2628 * @colorsel: a #GtkColorSelection.
2629 * @index: the color index of the palette.
2630 * @color: A #GdkColor to set the palette with.
2632 * Sets the palette located at @index to have @color as its color.
2636 gtk_color_selection_set_palette_color (GtkColorSelection *colorsel,
2640 ColorSelectionPrivate *priv;
2644 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2645 g_return_if_fail (index >= 0 && index < GTK_CUSTOM_PALETTE_WIDTH*GTK_CUSTOM_PALETTE_HEIGHT);
2647 x = index % GTK_CUSTOM_PALETTE_WIDTH;
2648 y = index / GTK_CUSTOM_PALETTE_WIDTH;
2650 priv = colorsel->private_data;
2651 col[0] = SCALE (color->red);
2652 col[1] = SCALE (color->green);
2653 col[2] = SCALE (color->blue);
2655 palette_set_color (priv->custom_palette[x][y], colorsel, col);
2659 * gtk_color_selection_is_adjusting:
2660 * @colorsel: a #GtkColorSelection.
2662 * Gets the current state of the @colorsel.
2664 * Return value: %TRUE if the user is currently dragging a color around, and %FALSE
2665 * if the selection has stopped.
2668 gtk_color_selection_is_adjusting (GtkColorSelection *colorsel)
2670 ColorSelectionPrivate *priv;
2672 g_return_val_if_fail (GTK_IS_COLOR_SELECTION (colorsel), FALSE);
2674 priv = colorsel->private_data;
2676 return (gtk_hsv_is_adjusting (GTK_HSV (priv->triangle_colorsel)));
2681 * gtk_color_selection_palette_from_string:
2682 * @str: a string encoding a color palette.
2683 * @colors: return location for allocated array of #GdkColor.
2684 * @n_colors: return location for length of array.
2686 * Parses a color palette string; the string is a colon-separated
2687 * list of color names readable by gdk_color_parse().
2689 * Return value: %TRUE if a palette was successfully parsed.
2692 gtk_color_selection_palette_from_string (const gchar *str,
2704 copy = g_strdup (str);
2710 if (*p == ':' || *p == '\0')
2712 gboolean done = TRUE;
2716 goto failed; /* empty entry */
2725 retval = g_renew (GdkColor, retval, count + 1);
2726 if (!gdk_color_parse (start, retval + count))
2767 * gtk_color_selection_palette_to_string:
2768 * @colors: an array of colors.
2769 * @n_colors: length of the array.
2771 * Encodes a palette as a string, useful for persistent storage.
2773 * Return value: allocated string encoding the palette.
2776 gtk_color_selection_palette_to_string (const GdkColor *colors,
2780 gchar **strs = NULL;
2784 return g_strdup ("");
2786 strs = g_new0 (gchar*, n_colors + 1);
2789 while (i < n_colors)
2794 g_strdup_printf ("#%2X%2X%2X",
2795 colors[i].red / 256,
2796 colors[i].green / 256,
2797 colors[i].blue / 256);
2799 for (ptr = strs[i]; *ptr; ptr++)
2806 retval = g_strjoinv (":", strs);
2814 * gtk_color_selection_set_change_palette_with_screen_hook:
2815 * @func: a function to call when the custom palette needs saving.
2817 * Installs a global function to be called whenever the user tries to
2818 * modify the palette in a color selection. This function should save
2819 * the new palette contents, and update the GtkSettings property
2820 * "gtk-color-palette" so all GtkColorSelection widgets will be modified.
2822 * Return value: the previous change palette hook (that was replaced).
2826 GtkColorSelectionChangePaletteWithScreenFunc
2827 gtk_color_selection_set_change_palette_with_screen_hook (GtkColorSelectionChangePaletteWithScreenFunc func)
2829 GtkColorSelectionChangePaletteWithScreenFunc old;
2831 old = change_palette_hook;
2833 change_palette_hook = func;
2839 make_control_relations (AtkObject *atk_obj,
2844 obj = gtk_widget_get_accessible (widget);
2845 atk_object_add_relationship (atk_obj, ATK_RELATION_CONTROLLED_BY, obj);
2846 atk_object_add_relationship (obj, ATK_RELATION_CONTROLLER_FOR, atk_obj);
2850 make_all_relations (AtkObject *atk_obj,
2851 ColorSelectionPrivate *priv)
2853 make_control_relations (atk_obj, priv->hue_spinbutton);
2854 make_control_relations (atk_obj, priv->sat_spinbutton);
2855 make_control_relations (atk_obj, priv->val_spinbutton);
2856 make_control_relations (atk_obj, priv->red_spinbutton);
2857 make_control_relations (atk_obj, priv->green_spinbutton);
2858 make_control_relations (atk_obj, priv->blue_spinbutton);
2861 #define __GTK_COLOR_SELECTION_C__
2862 #include "gtkaliasdef.c"