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"
63 /* Number of elements in the custom palatte */
64 #define GTK_CUSTOM_PALETTE_WIDTH 10
65 #define GTK_CUSTOM_PALETTE_HEIGHT 2
67 #define CUSTOM_PALETTE_ENTRY_WIDTH 20
68 #define CUSTOM_PALETTE_ENTRY_HEIGHT 20
70 /* The cursor for the dropper */
71 #define DROPPER_WIDTH 17
72 #define DROPPER_HEIGHT 17
73 #define DROPPER_STRIDE 4
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
114 struct _GtkColorSelectionPrivate
116 guint has_opacity : 1;
117 guint has_palette : 1;
119 guint default_set : 1;
120 guint default_alpha_set : 1;
123 gdouble color[COLORSEL_NUM_CHANNELS];
124 gdouble old_color[COLORSEL_NUM_CHANNELS];
126 GtkWidget *triangle_colorsel;
127 GtkWidget *hue_spinbutton;
128 GtkWidget *sat_spinbutton;
129 GtkWidget *val_spinbutton;
130 GtkWidget *red_spinbutton;
131 GtkWidget *green_spinbutton;
132 GtkWidget *blue_spinbutton;
133 GtkWidget *opacity_slider;
134 GtkWidget *opacity_label;
135 GtkWidget *opacity_entry;
136 GtkWidget *palette_frame;
137 GtkWidget *hex_entry;
139 /* The Palette code */
140 GtkWidget *custom_palette [GTK_CUSTOM_PALETTE_WIDTH][GTK_CUSTOM_PALETTE_HEIGHT];
142 /* The color_sample stuff */
143 GtkWidget *sample_area;
144 GtkWidget *old_sample;
145 GtkWidget *cur_sample;
148 /* Window for grabbing on */
149 GtkWidget *dropper_grab_widget;
151 GdkDevice *keyboard_device;
152 GdkDevice *pointer_device;
154 /* Connection to settings */
155 gulong settings_connection;
159 static void gtk_color_selection_destroy (GtkObject *object);
160 static void gtk_color_selection_finalize (GObject *object);
161 static void update_color (GtkColorSelection *colorsel);
162 static void gtk_color_selection_set_property (GObject *object,
166 static void gtk_color_selection_get_property (GObject *object,
171 static void gtk_color_selection_realize (GtkWidget *widget);
172 static void gtk_color_selection_unrealize (GtkWidget *widget);
173 static void gtk_color_selection_show_all (GtkWidget *widget);
174 static gboolean gtk_color_selection_grab_broken (GtkWidget *widget,
175 GdkEventGrabBroken *event);
177 static void gtk_color_selection_set_palette_color (GtkColorSelection *colorsel,
180 static void set_focus_line_attributes (GtkWidget *drawing_area,
183 static void default_noscreen_change_palette_func (const GdkColor *colors,
185 static void default_change_palette_func (GdkScreen *screen,
186 const GdkColor *colors,
188 static void make_control_relations (AtkObject *atk_obj,
190 static void make_all_relations (AtkObject *atk_obj,
191 GtkColorSelectionPrivate *priv);
193 static void hsv_changed (GtkWidget *hsv,
195 static void get_screen_color (GtkWidget *button);
196 static void adjustment_changed (GtkAdjustment *adjustment,
198 static void opacity_entry_changed (GtkWidget *opacity_entry,
200 static void hex_changed (GtkWidget *hex_entry,
202 static gboolean hex_focus_out (GtkWidget *hex_entry,
203 GdkEventFocus *event,
205 static void color_sample_new (GtkColorSelection *colorsel);
206 static void make_label_spinbutton (GtkColorSelection *colorsel,
207 GtkWidget **spinbutton,
213 const gchar *tooltip);
214 static void make_palette_frame (GtkColorSelection *colorsel,
218 static void set_selected_palette (GtkColorSelection *colorsel,
221 static void set_focus_line_attributes (GtkWidget *drawing_area,
224 static gboolean mouse_press (GtkWidget *invisible,
225 GdkEventButton *event,
227 static void palette_change_notify_instance (GObject *object,
230 static void update_palette (GtkColorSelection *colorsel);
231 static void shutdown_eyedropper (GtkWidget *widget);
233 static guint color_selection_signals[LAST_SIGNAL] = { 0 };
235 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";
237 static GtkColorSelectionChangePaletteFunc noscreen_change_palette_hook = default_noscreen_change_palette_func;
238 static GtkColorSelectionChangePaletteWithScreenFunc change_palette_hook = default_change_palette_func;
240 static const guchar dropper_bits[] = {
241 0xff, 0x8f, 0x01, 0x00, 0xff, 0x77, 0x01, 0x00,
242 0xff, 0xfb, 0x00, 0x00, 0xff, 0xf8, 0x00, 0x00,
243 0x7f, 0xff, 0x00, 0x00, 0xff, 0x7e, 0x01, 0x00,
244 0xff, 0x9d, 0x01, 0x00, 0xff, 0xd8, 0x01, 0x00,
245 0x7f, 0xd4, 0x01, 0x00, 0x3f, 0xee, 0x01, 0x00,
246 0x1f, 0xff, 0x01, 0x00, 0x8f, 0xff, 0x01, 0x00,
247 0xc7, 0xff, 0x01, 0x00, 0xe3, 0xff, 0x01, 0x00,
248 0xf3, 0xff, 0x01, 0x00, 0xfd, 0xff, 0x01, 0x00,
249 0xff, 0xff, 0x01, 0x00 };
251 static const guchar dropper_mask[] = {
252 0x00, 0x70, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00,
253 0x00, 0xfc, 0x01, 0x00, 0x00, 0xff, 0x01, 0x00,
254 0x80, 0xff, 0x01, 0x00, 0x00, 0xff, 0x00, 0x00,
255 0x00, 0x7f, 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00,
256 0xc0, 0x3f, 0x00, 0x00, 0xe0, 0x13, 0x00, 0x00,
257 0xf0, 0x01, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00,
258 0x7c, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00,
259 0x1e, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
260 0x02, 0x00, 0x00, 0x00 };
262 G_DEFINE_TYPE (GtkColorSelection, gtk_color_selection, GTK_TYPE_VBOX)
265 gtk_color_selection_class_init (GtkColorSelectionClass *klass)
267 GObjectClass *gobject_class;
268 GtkObjectClass *object_class;
269 GtkWidgetClass *widget_class;
271 gobject_class = G_OBJECT_CLASS (klass);
272 gobject_class->finalize = gtk_color_selection_finalize;
273 gobject_class->set_property = gtk_color_selection_set_property;
274 gobject_class->get_property = gtk_color_selection_get_property;
276 object_class = GTK_OBJECT_CLASS (klass);
277 object_class->destroy = gtk_color_selection_destroy;
279 widget_class = GTK_WIDGET_CLASS (klass);
280 widget_class->realize = gtk_color_selection_realize;
281 widget_class->unrealize = gtk_color_selection_unrealize;
282 widget_class->show_all = gtk_color_selection_show_all;
283 widget_class->grab_broken_event = gtk_color_selection_grab_broken;
285 g_object_class_install_property (gobject_class,
286 PROP_HAS_OPACITY_CONTROL,
287 g_param_spec_boolean ("has-opacity-control",
288 P_("Has Opacity Control"),
289 P_("Whether the color selector should allow setting opacity"),
291 GTK_PARAM_READWRITE));
292 g_object_class_install_property (gobject_class,
294 g_param_spec_boolean ("has-palette",
296 P_("Whether a palette should be used"),
298 GTK_PARAM_READWRITE));
299 g_object_class_install_property (gobject_class,
301 g_param_spec_boxed ("current-color",
303 P_("The current color"),
305 GTK_PARAM_READWRITE));
306 g_object_class_install_property (gobject_class,
308 g_param_spec_uint ("current-alpha",
310 P_("The current opacity value (0 fully transparent, 65535 fully opaque)"),
312 GTK_PARAM_READWRITE));
314 color_selection_signals[COLOR_CHANGED] =
315 g_signal_new (I_("color-changed"),
316 G_OBJECT_CLASS_TYPE (object_class),
318 G_STRUCT_OFFSET (GtkColorSelectionClass, color_changed),
320 _gtk_marshal_VOID__VOID,
323 gtk_settings_install_property (g_param_spec_string ("gtk-color-palette",
324 P_("Custom palette"),
325 P_("Palette to use in the color selector"),
327 GTK_PARAM_READWRITE));
329 g_type_class_add_private (gobject_class, sizeof (GtkColorSelectionPrivate));
333 gtk_color_selection_init (GtkColorSelection *colorsel)
336 GtkWidget *top_right_vbox;
337 GtkWidget *table, *label, *hbox, *frame, *vbox, *button;
338 GtkAdjustment *adjust;
339 GtkWidget *picker_image;
341 GtkColorSelectionPrivate *priv;
343 GList *focus_chain = NULL;
345 gtk_widget_push_composite_child ();
347 priv = colorsel->private_data = G_TYPE_INSTANCE_GET_PRIVATE (colorsel, GTK_TYPE_COLOR_SELECTION, GtkColorSelectionPrivate);
348 priv->changing = FALSE;
349 priv->default_set = FALSE;
350 priv->default_alpha_set = FALSE;
352 top_hbox = gtk_hbox_new (FALSE, 12);
353 gtk_box_pack_start (GTK_BOX (colorsel), top_hbox, FALSE, FALSE, 0);
355 vbox = gtk_vbox_new (FALSE, 6);
356 priv->triangle_colorsel = gtk_hsv_new ();
357 g_signal_connect (priv->triangle_colorsel, "changed",
358 G_CALLBACK (hsv_changed), colorsel);
359 gtk_hsv_set_metrics (GTK_HSV (priv->triangle_colorsel), 174, 15);
360 gtk_box_pack_start (GTK_BOX (top_hbox), vbox, FALSE, FALSE, 0);
361 gtk_box_pack_start (GTK_BOX (vbox), priv->triangle_colorsel, FALSE, FALSE, 0);
362 gtk_widget_set_tooltip_text (priv->triangle_colorsel,
363 _("Select the color you want from the outer ring. Select the darkness or lightness of that color using the inner triangle."));
365 hbox = gtk_hbox_new (FALSE, 6);
366 gtk_box_pack_end (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
368 frame = gtk_frame_new (NULL);
369 gtk_widget_set_size_request (frame, -1, 30);
370 gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
371 color_sample_new (colorsel);
372 gtk_container_add (GTK_CONTAINER (frame), priv->sample_area);
373 gtk_box_pack_start (GTK_BOX (hbox), frame, TRUE, TRUE, 0);
375 button = gtk_button_new ();
377 gtk_widget_set_events (button, GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK);
378 g_object_set_data (G_OBJECT (button), I_("COLORSEL"), colorsel);
379 g_signal_connect (button, "clicked",
380 G_CALLBACK (get_screen_color), NULL);
381 picker_image = gtk_image_new_from_stock (GTK_STOCK_COLOR_PICKER, GTK_ICON_SIZE_BUTTON);
382 gtk_container_add (GTK_CONTAINER (button), picker_image);
383 gtk_widget_show (GTK_WIDGET (picker_image));
384 gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
386 gtk_widget_set_tooltip_text (button,
387 _("Click the eyedropper, then click a color anywhere on your screen to select that color."));
389 top_right_vbox = gtk_vbox_new (FALSE, 6);
390 gtk_box_pack_start (GTK_BOX (top_hbox), top_right_vbox, FALSE, FALSE, 0);
391 table = gtk_table_new (8, 6, FALSE);
392 gtk_box_pack_start (GTK_BOX (top_right_vbox), table, FALSE, FALSE, 0);
393 gtk_table_set_row_spacings (GTK_TABLE (table), 6);
394 gtk_table_set_col_spacings (GTK_TABLE (table), 12);
396 make_label_spinbutton (colorsel, &priv->hue_spinbutton, _("_Hue:"), table, 0, 0, COLORSEL_HUE,
397 _("Position on the color wheel."));
398 gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (priv->hue_spinbutton), TRUE);
399 make_label_spinbutton (colorsel, &priv->sat_spinbutton, _("_Saturation:"), table, 0, 1, COLORSEL_SATURATION,
400 _("Intensity of the color."));
401 make_label_spinbutton (colorsel, &priv->val_spinbutton, _("_Value:"), table, 0, 2, COLORSEL_VALUE,
402 _("Brightness of the color."));
403 make_label_spinbutton (colorsel, &priv->red_spinbutton, _("_Red:"), table, 6, 0, COLORSEL_RED,
404 _("Amount of red light in the color."));
405 make_label_spinbutton (colorsel, &priv->green_spinbutton, _("_Green:"), table, 6, 1, COLORSEL_GREEN,
406 _("Amount of green light in the color."));
407 make_label_spinbutton (colorsel, &priv->blue_spinbutton, _("_Blue:"), table, 6, 2, COLORSEL_BLUE,
408 _("Amount of blue light in the color."));
409 gtk_table_attach_defaults (GTK_TABLE (table), gtk_hseparator_new (), 0, 8, 3, 4);
411 priv->opacity_label = gtk_label_new_with_mnemonic (_("Op_acity:"));
412 gtk_misc_set_alignment (GTK_MISC (priv->opacity_label), 0.0, 0.5);
413 gtk_table_attach_defaults (GTK_TABLE (table), priv->opacity_label, 0, 1, 4, 5);
414 adjust = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 255.0, 1.0, 1.0, 0.0));
415 g_object_set_data (G_OBJECT (adjust), I_("COLORSEL"), colorsel);
416 priv->opacity_slider = gtk_hscale_new (adjust);
417 gtk_widget_set_tooltip_text (priv->opacity_slider,
418 _("Transparency of the color."));
419 gtk_label_set_mnemonic_widget (GTK_LABEL (priv->opacity_label),
420 priv->opacity_slider);
421 gtk_scale_set_draw_value (GTK_SCALE (priv->opacity_slider), FALSE);
422 g_signal_connect (adjust, "value-changed",
423 G_CALLBACK (adjustment_changed),
424 GINT_TO_POINTER (COLORSEL_OPACITY));
425 gtk_table_attach_defaults (GTK_TABLE (table), priv->opacity_slider, 1, 7, 4, 5);
426 priv->opacity_entry = gtk_entry_new ();
427 gtk_widget_set_tooltip_text (priv->opacity_entry,
428 _("Transparency of the color."));
429 gtk_widget_set_size_request (priv->opacity_entry, 40, -1);
431 g_signal_connect (priv->opacity_entry, "activate",
432 G_CALLBACK (opacity_entry_changed), colorsel);
433 gtk_table_attach_defaults (GTK_TABLE (table), priv->opacity_entry, 7, 8, 4, 5);
435 label = gtk_label_new_with_mnemonic (_("Color _name:"));
436 gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 5, 6);
437 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
438 priv->hex_entry = gtk_entry_new ();
440 gtk_label_set_mnemonic_widget (GTK_LABEL (label), priv->hex_entry);
442 g_signal_connect (priv->hex_entry, "activate",
443 G_CALLBACK (hex_changed), colorsel);
445 g_signal_connect (priv->hex_entry, "focus-out-event",
446 G_CALLBACK (hex_focus_out), colorsel);
448 gtk_widget_set_tooltip_text (priv->hex_entry,
449 _("You can enter an HTML-style hexadecimal color value, or simply a color name such as 'orange' in this entry."));
451 gtk_entry_set_width_chars (GTK_ENTRY (priv->hex_entry), 7);
452 gtk_table_attach_defaults (GTK_TABLE (table), priv->hex_entry, 1, 5, 5, 6);
454 focus_chain = g_list_append (focus_chain, priv->hue_spinbutton);
455 focus_chain = g_list_append (focus_chain, priv->sat_spinbutton);
456 focus_chain = g_list_append (focus_chain, priv->val_spinbutton);
457 focus_chain = g_list_append (focus_chain, priv->red_spinbutton);
458 focus_chain = g_list_append (focus_chain, priv->green_spinbutton);
459 focus_chain = g_list_append (focus_chain, priv->blue_spinbutton);
460 focus_chain = g_list_append (focus_chain, priv->opacity_slider);
461 focus_chain = g_list_append (focus_chain, priv->opacity_entry);
462 focus_chain = g_list_append (focus_chain, priv->hex_entry);
463 gtk_container_set_focus_chain (GTK_CONTAINER (table), focus_chain);
464 g_list_free (focus_chain);
466 /* Set up the palette */
467 table = gtk_table_new (GTK_CUSTOM_PALETTE_HEIGHT, GTK_CUSTOM_PALETTE_WIDTH, TRUE);
468 gtk_table_set_row_spacings (GTK_TABLE (table), 1);
469 gtk_table_set_col_spacings (GTK_TABLE (table), 1);
470 for (i = 0; i < GTK_CUSTOM_PALETTE_WIDTH; i++)
472 for (j = 0; j < GTK_CUSTOM_PALETTE_HEIGHT; j++)
474 make_palette_frame (colorsel, table, i, j);
477 set_selected_palette (colorsel, 0, 0);
478 priv->palette_frame = gtk_vbox_new (FALSE, 6);
479 label = gtk_label_new_with_mnemonic (_("_Palette:"));
480 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
481 gtk_box_pack_start (GTK_BOX (priv->palette_frame), label, FALSE, FALSE, 0);
483 gtk_label_set_mnemonic_widget (GTK_LABEL (label),
484 priv->custom_palette[0][0]);
486 gtk_box_pack_end (GTK_BOX (top_right_vbox), priv->palette_frame, FALSE, FALSE, 0);
487 gtk_box_pack_start (GTK_BOX (priv->palette_frame), table, FALSE, FALSE, 0);
489 gtk_widget_show_all (top_hbox);
491 /* hide unused stuff */
493 if (priv->has_opacity == FALSE)
495 gtk_widget_hide (priv->opacity_label);
496 gtk_widget_hide (priv->opacity_slider);
497 gtk_widget_hide (priv->opacity_entry);
500 if (priv->has_palette == FALSE)
502 gtk_widget_hide (priv->palette_frame);
505 atk_obj = gtk_widget_get_accessible (priv->triangle_colorsel);
506 if (GTK_IS_ACCESSIBLE (atk_obj))
508 atk_object_set_name (atk_obj, _("Color Wheel"));
509 atk_object_set_role (gtk_widget_get_accessible (GTK_WIDGET (colorsel)), ATK_ROLE_COLOR_CHOOSER);
510 make_all_relations (atk_obj, priv);
513 gtk_widget_pop_composite_child ();
516 /* GObject methods */
518 gtk_color_selection_finalize (GObject *object)
520 G_OBJECT_CLASS (gtk_color_selection_parent_class)->finalize (object);
524 gtk_color_selection_set_property (GObject *object,
529 GtkColorSelection *colorsel = GTK_COLOR_SELECTION (object);
533 case PROP_HAS_OPACITY_CONTROL:
534 gtk_color_selection_set_has_opacity_control (colorsel,
535 g_value_get_boolean (value));
537 case PROP_HAS_PALETTE:
538 gtk_color_selection_set_has_palette (colorsel,
539 g_value_get_boolean (value));
541 case PROP_CURRENT_COLOR:
542 gtk_color_selection_set_current_color (colorsel, g_value_get_boxed (value));
544 case PROP_CURRENT_ALPHA:
545 gtk_color_selection_set_current_alpha (colorsel, g_value_get_uint (value));
548 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
555 gtk_color_selection_get_property (GObject *object,
560 GtkColorSelection *colorsel = GTK_COLOR_SELECTION (object);
565 case PROP_HAS_OPACITY_CONTROL:
566 g_value_set_boolean (value, gtk_color_selection_get_has_opacity_control (colorsel));
568 case PROP_HAS_PALETTE:
569 g_value_set_boolean (value, gtk_color_selection_get_has_palette (colorsel));
571 case PROP_CURRENT_COLOR:
572 gtk_color_selection_get_current_color (colorsel, &color);
573 g_value_set_boxed (value, &color);
575 case PROP_CURRENT_ALPHA:
576 g_value_set_uint (value, gtk_color_selection_get_current_alpha (colorsel));
579 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
584 /* GtkObject methods */
587 gtk_color_selection_destroy (GtkObject *object)
589 GtkColorSelection *cselection = GTK_COLOR_SELECTION (object);
590 GtkColorSelectionPrivate *priv = cselection->private_data;
592 if (priv->dropper_grab_widget)
594 gtk_widget_destroy (priv->dropper_grab_widget);
595 priv->dropper_grab_widget = NULL;
598 GTK_OBJECT_CLASS (gtk_color_selection_parent_class)->destroy (object);
601 /* GtkWidget methods */
604 gtk_color_selection_realize (GtkWidget *widget)
606 GtkColorSelection *colorsel = GTK_COLOR_SELECTION (widget);
607 GtkColorSelectionPrivate *priv = colorsel->private_data;
608 GtkSettings *settings = gtk_widget_get_settings (widget);
610 priv->settings_connection = g_signal_connect (settings,
611 "notify::gtk-color-palette",
612 G_CALLBACK (palette_change_notify_instance),
614 update_palette (colorsel);
616 GTK_WIDGET_CLASS (gtk_color_selection_parent_class)->realize (widget);
620 gtk_color_selection_unrealize (GtkWidget *widget)
622 GtkColorSelection *colorsel = GTK_COLOR_SELECTION (widget);
623 GtkColorSelectionPrivate *priv = colorsel->private_data;
624 GtkSettings *settings = gtk_widget_get_settings (widget);
626 g_signal_handler_disconnect (settings, priv->settings_connection);
628 GTK_WIDGET_CLASS (gtk_color_selection_parent_class)->unrealize (widget);
631 /* We override show-all since we have internal widgets that
632 * shouldn't be shown when you call show_all(), like the
633 * palette and opacity sliders.
636 gtk_color_selection_show_all (GtkWidget *widget)
638 gtk_widget_show (widget);
642 gtk_color_selection_grab_broken (GtkWidget *widget,
643 GdkEventGrabBroken *event)
645 shutdown_eyedropper (widget);
656 static void color_sample_draw_sample (GtkColorSelection *colorsel, int which);
657 static void color_sample_update_samples (GtkColorSelection *colorsel);
660 set_color_internal (GtkColorSelection *colorsel,
663 GtkColorSelectionPrivate *priv;
666 priv = colorsel->private_data;
667 priv->changing = TRUE;
668 priv->color[COLORSEL_RED] = color[0];
669 priv->color[COLORSEL_GREEN] = color[1];
670 priv->color[COLORSEL_BLUE] = color[2];
671 priv->color[COLORSEL_OPACITY] = color[3];
672 gtk_rgb_to_hsv (priv->color[COLORSEL_RED],
673 priv->color[COLORSEL_GREEN],
674 priv->color[COLORSEL_BLUE],
675 &priv->color[COLORSEL_HUE],
676 &priv->color[COLORSEL_SATURATION],
677 &priv->color[COLORSEL_VALUE]);
678 if (priv->default_set == FALSE)
680 for (i = 0; i < COLORSEL_NUM_CHANNELS; i++)
681 priv->old_color[i] = priv->color[i];
683 priv->default_set = TRUE;
684 priv->default_alpha_set = TRUE;
685 update_color (colorsel);
689 set_color_icon (GdkDragContext *context,
695 pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE,
698 pixel = (((UNSCALE (colors[COLORSEL_RED]) & 0xff00) << 16) |
699 ((UNSCALE (colors[COLORSEL_GREEN]) & 0xff00) << 8) |
700 ((UNSCALE (colors[COLORSEL_BLUE]) & 0xff00)));
702 gdk_pixbuf_fill (pixbuf, pixel);
704 gtk_drag_set_icon_pixbuf (context, pixbuf, -2, -2);
705 g_object_unref (pixbuf);
709 color_sample_drag_begin (GtkWidget *widget,
710 GdkDragContext *context,
713 GtkColorSelection *colorsel = data;
714 GtkColorSelectionPrivate *priv;
717 priv = colorsel->private_data;
719 if (widget == priv->old_sample)
720 colsrc = priv->old_color;
722 colsrc = priv->color;
724 set_color_icon (context, colsrc);
728 color_sample_drag_end (GtkWidget *widget,
729 GdkDragContext *context,
732 g_object_set_data (G_OBJECT (widget), I_("gtk-color-selection-drag-window"), NULL);
736 color_sample_drop_handle (GtkWidget *widget,
737 GdkDragContext *context,
740 GtkSelectionData *selection_data,
745 GtkColorSelection *colorsel = data;
746 GtkColorSelectionPrivate *priv;
749 priv = colorsel->private_data;
751 /* This is currently a guint16 array of the format:
758 if (selection_data->length < 0)
761 /* We accept drops with the wrong format, since the KDE color
762 * chooser incorrectly drops application/x-color with format 8.
764 if (selection_data->length != 8)
766 g_warning ("Received invalid color data\n");
770 vals = (guint16 *)selection_data->data;
772 if (widget == priv->cur_sample)
774 color[0] = (gdouble)vals[0] / 0xffff;
775 color[1] = (gdouble)vals[1] / 0xffff;
776 color[2] = (gdouble)vals[2] / 0xffff;
777 color[3] = (gdouble)vals[3] / 0xffff;
779 set_color_internal (colorsel, color);
784 color_sample_drag_handle (GtkWidget *widget,
785 GdkDragContext *context,
786 GtkSelectionData *selection_data,
791 GtkColorSelection *colorsel = data;
792 GtkColorSelectionPrivate *priv;
796 priv = colorsel->private_data;
798 if (widget == priv->old_sample)
799 colsrc = priv->old_color;
801 colsrc = priv->color;
803 vals[0] = colsrc[COLORSEL_RED] * 0xffff;
804 vals[1] = colsrc[COLORSEL_GREEN] * 0xffff;
805 vals[2] = colsrc[COLORSEL_BLUE] * 0xffff;
806 vals[3] = priv->has_opacity ? colsrc[COLORSEL_OPACITY] * 0xffff : 0xffff;
808 gtk_selection_data_set (selection_data,
809 gdk_atom_intern_static_string ("application/x-color"),
810 16, (guchar *)vals, 8);
813 /* which = 0 means draw old sample, which = 1 means draw new */
815 color_sample_draw_sample (GtkColorSelection *colorsel, int which)
817 GtkAllocation allocation;
819 gint x, y, wid, heig, goff;
820 GtkColorSelectionPrivate *priv;
823 g_return_if_fail (colorsel != NULL);
824 priv = colorsel->private_data;
826 g_return_if_fail (priv->sample_area != NULL);
827 if (!gtk_widget_is_drawable (priv->sample_area))
832 da = priv->old_sample;
837 GtkAllocation old_sample_allocation;
839 da = priv->cur_sample;
840 gtk_widget_get_allocation (priv->old_sample, &old_sample_allocation);
841 goff = old_sample_allocation.width % 32;
844 cr = gdk_cairo_create (gtk_widget_get_window (da));
846 gtk_widget_get_allocation (da, &allocation);
847 wid = allocation.width;
848 heig = allocation.height;
850 /* Below needs tweaking for non-power-of-two */
852 if (priv->has_opacity)
854 /* Draw checks in background */
856 cairo_set_source_rgb (cr, 0.5, 0.5, 0.5);
857 cairo_rectangle (cr, 0, 0, wid, heig);
860 cairo_set_source_rgb (cr, 0.75, 0.75, 0.75);
861 for (x = goff & -CHECK_SIZE; x < goff + wid; x += CHECK_SIZE)
862 for (y = 0; y < heig; y += CHECK_SIZE)
863 if ((x / CHECK_SIZE + y / CHECK_SIZE) % 2 == 0)
864 cairo_rectangle (cr, x - goff, y, CHECK_SIZE, CHECK_SIZE);
870 cairo_set_source_rgba (cr,
871 priv->old_color[COLORSEL_RED],
872 priv->old_color[COLORSEL_GREEN],
873 priv->old_color[COLORSEL_BLUE],
875 priv->old_color[COLORSEL_OPACITY] : 1.0);
879 cairo_set_source_rgba (cr,
880 priv->color[COLORSEL_RED],
881 priv->color[COLORSEL_GREEN],
882 priv->color[COLORSEL_BLUE],
884 priv->color[COLORSEL_OPACITY] : 1.0);
887 cairo_rectangle (cr, 0, 0, wid, heig);
895 color_sample_update_samples (GtkColorSelection *colorsel)
897 GtkColorSelectionPrivate *priv = colorsel->private_data;
898 gtk_widget_queue_draw (priv->old_sample);
899 gtk_widget_queue_draw (priv->cur_sample);
903 color_old_sample_expose (GtkWidget *da,
904 GdkEventExpose *event,
905 GtkColorSelection *colorsel)
907 color_sample_draw_sample (colorsel, 0);
913 color_cur_sample_expose (GtkWidget *da,
914 GdkEventExpose *event,
915 GtkColorSelection *colorsel)
917 color_sample_draw_sample (colorsel, 1);
922 color_sample_setup_dnd (GtkColorSelection *colorsel, GtkWidget *sample)
924 static const GtkTargetEntry targets[] = {
925 { "application/x-color", 0 }
927 GtkColorSelectionPrivate *priv;
928 priv = colorsel->private_data;
930 gtk_drag_source_set (sample,
931 GDK_BUTTON1_MASK | GDK_BUTTON3_MASK,
933 GDK_ACTION_COPY | GDK_ACTION_MOVE);
935 g_signal_connect (sample, "drag-begin",
936 G_CALLBACK (color_sample_drag_begin),
938 if (sample == priv->cur_sample)
941 gtk_drag_dest_set (sample,
942 GTK_DEST_DEFAULT_HIGHLIGHT |
943 GTK_DEST_DEFAULT_MOTION |
944 GTK_DEST_DEFAULT_DROP,
948 g_signal_connect (sample, "drag-end",
949 G_CALLBACK (color_sample_drag_end),
953 g_signal_connect (sample, "drag-data-get",
954 G_CALLBACK (color_sample_drag_handle),
956 g_signal_connect (sample, "drag-data-received",
957 G_CALLBACK (color_sample_drop_handle),
963 update_tooltips (GtkColorSelection *colorsel)
965 GtkColorSelectionPrivate *priv;
967 priv = colorsel->private_data;
969 if (priv->has_palette == TRUE)
971 gtk_widget_set_tooltip_text (priv->old_sample,
972 _("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."));
974 gtk_widget_set_tooltip_text (priv->cur_sample,
975 _("The color you've chosen. You can drag this color to a palette entry to save it for use in the future."));
979 gtk_widget_set_tooltip_text (priv->old_sample,
980 _("The previously-selected color, for comparison to the color you're selecting now."));
982 gtk_widget_set_tooltip_text (priv->cur_sample,
983 _("The color you've chosen."));
988 color_sample_new (GtkColorSelection *colorsel)
990 GtkColorSelectionPrivate *priv;
992 priv = colorsel->private_data;
994 priv->sample_area = gtk_hbox_new (FALSE, 0);
995 priv->old_sample = gtk_drawing_area_new ();
996 priv->cur_sample = gtk_drawing_area_new ();
998 gtk_box_pack_start (GTK_BOX (priv->sample_area), priv->old_sample,
1000 gtk_box_pack_start (GTK_BOX (priv->sample_area), priv->cur_sample,
1003 g_signal_connect (priv->old_sample, "expose-event",
1004 G_CALLBACK (color_old_sample_expose),
1006 g_signal_connect (priv->cur_sample, "expose-event",
1007 G_CALLBACK (color_cur_sample_expose),
1010 color_sample_setup_dnd (colorsel, priv->old_sample);
1011 color_sample_setup_dnd (colorsel, priv->cur_sample);
1013 update_tooltips (colorsel);
1015 gtk_widget_show_all (priv->sample_area);
1021 * The palette area code
1026 palette_get_color (GtkWidget *drawing_area, gdouble *color)
1030 g_return_if_fail (color != NULL);
1032 color_val = g_object_get_data (G_OBJECT (drawing_area), "color_val");
1033 if (color_val == NULL)
1035 /* Default to white for no good reason */
1043 color[0] = color_val[0];
1044 color[1] = color_val[1];
1045 color[2] = color_val[2];
1050 palette_paint (GtkWidget *drawing_area,
1058 window = gtk_widget_get_window (drawing_area);
1063 cr = gdk_cairo_create (window);
1065 gdk_cairo_set_source_color (cr, >k_widget_get_style (drawing_area)->bg[GTK_STATE_NORMAL]);
1066 gdk_cairo_rectangle (cr, area);
1069 if (gtk_widget_has_focus (drawing_area))
1071 GtkAllocation allocation;
1073 set_focus_line_attributes (drawing_area, cr, &focus_width);
1075 gtk_widget_get_allocation (drawing_area, &allocation);
1076 cairo_rectangle (cr,
1077 focus_width / 2., focus_width / 2.,
1078 allocation.width - focus_width,
1079 allocation.height - focus_width);
1087 set_focus_line_attributes (GtkWidget *drawing_area,
1094 gtk_widget_style_get (drawing_area,
1095 "focus-line-width", focus_width,
1096 "focus-line-pattern", (gchar *)&dash_list,
1099 palette_get_color (drawing_area, color);
1101 if (INTENSITY (color[0], color[1], color[2]) > 0.5)
1102 cairo_set_source_rgb (cr, 0., 0., 0.);
1104 cairo_set_source_rgb (cr, 1., 1., 1.);
1106 cairo_set_line_width (cr, *focus_width);
1110 gint n_dashes = strlen ((gchar *)dash_list);
1111 gdouble *dashes = g_new (gdouble, n_dashes);
1112 gdouble total_length = 0;
1113 gdouble dash_offset;
1116 for (i = 0; i < n_dashes; i++)
1118 dashes[i] = dash_list[i];
1119 total_length += dash_list[i];
1122 /* The dash offset here aligns the pattern to integer pixels
1123 * by starting the dash at the right side of the left border
1124 * Negative dash offsets in cairo don't work
1125 * (https://bugs.freedesktop.org/show_bug.cgi?id=2729)
1127 dash_offset = - *focus_width / 2.;
1128 while (dash_offset < 0)
1129 dash_offset += total_length;
1131 cairo_set_dash (cr, dashes, n_dashes, dash_offset);
1139 palette_drag_begin (GtkWidget *widget,
1140 GdkDragContext *context,
1145 palette_get_color (widget, colors);
1146 set_color_icon (context, colors);
1150 palette_drag_handle (GtkWidget *widget,
1151 GdkDragContext *context,
1152 GtkSelectionData *selection_data,
1160 palette_get_color (widget, colsrc);
1162 vals[0] = colsrc[COLORSEL_RED] * 0xffff;
1163 vals[1] = colsrc[COLORSEL_GREEN] * 0xffff;
1164 vals[2] = colsrc[COLORSEL_BLUE] * 0xffff;
1167 gtk_selection_data_set (selection_data,
1168 gdk_atom_intern_static_string ("application/x-color"),
1169 16, (guchar *)vals, 8);
1173 palette_drag_end (GtkWidget *widget,
1174 GdkDragContext *context,
1177 g_object_set_data (G_OBJECT (widget), I_("gtk-color-selection-drag-window"), NULL);
1181 get_current_colors (GtkColorSelection *colorsel)
1183 GtkSettings *settings;
1184 GdkColor *colors = NULL;
1188 settings = gtk_widget_get_settings (GTK_WIDGET (colorsel));
1189 g_object_get (settings,
1190 "gtk-color-palette", &palette,
1193 if (!gtk_color_selection_palette_from_string (palette, &colors, &n_colors))
1195 gtk_color_selection_palette_from_string (default_colors, &colors, &n_colors);
1199 /* If there are less colors provided than the number of slots in the
1200 * color selection, we fill in the rest from the defaults.
1202 if (n_colors < (GTK_CUSTOM_PALETTE_WIDTH * GTK_CUSTOM_PALETTE_HEIGHT))
1204 GdkColor *tmp_colors = colors;
1205 gint tmp_n_colors = n_colors;
1207 gtk_color_selection_palette_from_string (default_colors, &colors, &n_colors);
1208 memcpy (colors, tmp_colors, sizeof (GdkColor) * tmp_n_colors);
1210 g_free (tmp_colors);
1214 g_assert (n_colors >= GTK_CUSTOM_PALETTE_WIDTH * GTK_CUSTOM_PALETTE_HEIGHT);
1220 /* Changes the model color */
1222 palette_change_color (GtkWidget *drawing_area,
1223 GtkColorSelection *colorsel,
1227 GtkColorSelectionPrivate *priv;
1229 GdkColor *current_colors;
1232 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
1233 g_return_if_fail (GTK_IS_DRAWING_AREA (drawing_area));
1235 priv = colorsel->private_data;
1237 gdk_color.red = UNSCALE (color[0]);
1238 gdk_color.green = UNSCALE (color[1]);
1239 gdk_color.blue = UNSCALE (color[2]);
1240 gdk_color.pixel = 0;
1243 y = 0; /* Quiet GCC */
1244 while (x < GTK_CUSTOM_PALETTE_WIDTH)
1247 while (y < GTK_CUSTOM_PALETTE_HEIGHT)
1249 if (priv->custom_palette[x][y] == drawing_area)
1260 g_assert (x < GTK_CUSTOM_PALETTE_WIDTH || y < GTK_CUSTOM_PALETTE_HEIGHT);
1262 current_colors = get_current_colors (colorsel);
1263 current_colors[y * GTK_CUSTOM_PALETTE_WIDTH + x] = gdk_color;
1265 screen = gtk_widget_get_screen (GTK_WIDGET (colorsel));
1266 if (change_palette_hook != default_change_palette_func)
1267 (* change_palette_hook) (screen, current_colors,
1268 GTK_CUSTOM_PALETTE_WIDTH * GTK_CUSTOM_PALETTE_HEIGHT);
1269 else if (noscreen_change_palette_hook != default_noscreen_change_palette_func)
1271 if (screen != gdk_screen_get_default ())
1272 g_warning ("gtk_color_selection_set_change_palette_hook used by widget is not on the default screen.");
1273 (* noscreen_change_palette_hook) (current_colors,
1274 GTK_CUSTOM_PALETTE_WIDTH * GTK_CUSTOM_PALETTE_HEIGHT);
1277 (* change_palette_hook) (screen, current_colors,
1278 GTK_CUSTOM_PALETTE_WIDTH * GTK_CUSTOM_PALETTE_HEIGHT);
1280 g_free (current_colors);
1283 /* Changes the view color */
1285 palette_set_color (GtkWidget *drawing_area,
1286 GtkColorSelection *colorsel,
1289 gdouble *new_color = g_new (double, 4);
1292 gdk_color.red = UNSCALE (color[0]);
1293 gdk_color.green = UNSCALE (color[1]);
1294 gdk_color.blue = UNSCALE (color[2]);
1296 gtk_widget_modify_bg (drawing_area, GTK_STATE_NORMAL, &gdk_color);
1298 if (GPOINTER_TO_INT (g_object_get_data (G_OBJECT (drawing_area), "color_set")) == 0)
1300 static const GtkTargetEntry targets[] = {
1301 { "application/x-color", 0 }
1303 gtk_drag_source_set (drawing_area,
1304 GDK_BUTTON1_MASK | GDK_BUTTON3_MASK,
1306 GDK_ACTION_COPY | GDK_ACTION_MOVE);
1308 g_signal_connect (drawing_area, "drag-begin",
1309 G_CALLBACK (palette_drag_begin),
1311 g_signal_connect (drawing_area, "drag-data-get",
1312 G_CALLBACK (palette_drag_handle),
1315 g_object_set_data (G_OBJECT (drawing_area), I_("color_set"),
1316 GINT_TO_POINTER (1));
1319 new_color[0] = color[0];
1320 new_color[1] = color[1];
1321 new_color[2] = color[2];
1324 g_object_set_data_full (G_OBJECT (drawing_area), I_("color_val"), new_color, (GDestroyNotify)g_free);
1328 palette_expose (GtkWidget *drawing_area,
1329 GdkEventExpose *event,
1332 if (gtk_widget_get_window (drawing_area) == NULL)
1335 palette_paint (drawing_area, &(event->area), data);
1341 popup_position_func (GtkMenu *menu,
1347 GtkAllocation allocation;
1350 gint root_x, root_y;
1353 widget = GTK_WIDGET (user_data);
1355 g_return_if_fail (gtk_widget_get_realized (widget));
1357 gdk_window_get_origin (gtk_widget_get_window (widget),
1360 gtk_widget_size_request (GTK_WIDGET (menu), &req);
1361 gtk_widget_get_allocation (widget, &allocation);
1363 /* Put corner of menu centered on color cell */
1364 *x = root_x + allocation.width / 2;
1365 *y = root_y + allocation.height / 2;
1368 screen = gtk_widget_get_screen (widget);
1369 *x = CLAMP (*x, 0, MAX (0, gdk_screen_get_width (screen) - req.width));
1370 *y = CLAMP (*y, 0, MAX (0, gdk_screen_get_height (screen) - req.height));
1374 save_color_selected (GtkWidget *menuitem,
1377 GtkColorSelection *colorsel;
1378 GtkWidget *drawing_area;
1379 GtkColorSelectionPrivate *priv;
1381 drawing_area = GTK_WIDGET (data);
1383 colorsel = GTK_COLOR_SELECTION (g_object_get_data (G_OBJECT (drawing_area),
1386 priv = colorsel->private_data;
1388 palette_change_color (drawing_area, colorsel, priv->color);
1392 do_popup (GtkColorSelection *colorsel,
1393 GtkWidget *drawing_area,
1399 g_object_set_data (G_OBJECT (drawing_area),
1400 I_("gtk-color-sel"),
1403 menu = gtk_menu_new ();
1405 mi = gtk_menu_item_new_with_mnemonic (_("_Save color here"));
1407 g_signal_connect (mi, "activate",
1408 G_CALLBACK (save_color_selected),
1411 gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
1413 gtk_widget_show_all (mi);
1415 gtk_menu_popup (GTK_MENU (menu), NULL, NULL,
1416 popup_position_func, drawing_area,
1422 palette_enter (GtkWidget *drawing_area,
1423 GdkEventCrossing *event,
1426 g_object_set_data (G_OBJECT (drawing_area),
1427 I_("gtk-colorsel-have-pointer"),
1428 GUINT_TO_POINTER (TRUE));
1434 palette_leave (GtkWidget *drawing_area,
1435 GdkEventCrossing *event,
1438 g_object_set_data (G_OBJECT (drawing_area),
1439 I_("gtk-colorsel-have-pointer"),
1446 palette_press (GtkWidget *drawing_area,
1447 GdkEventButton *event,
1450 GtkColorSelection *colorsel = GTK_COLOR_SELECTION (data);
1452 gtk_widget_grab_focus (drawing_area);
1454 if (event->button == 3 &&
1455 event->type == GDK_BUTTON_PRESS)
1457 do_popup (colorsel, drawing_area, event->time);
1465 palette_release (GtkWidget *drawing_area,
1466 GdkEventButton *event,
1469 GtkColorSelection *colorsel = GTK_COLOR_SELECTION (data);
1471 gtk_widget_grab_focus (drawing_area);
1473 if (event->button == 1 &&
1474 g_object_get_data (G_OBJECT (drawing_area),
1475 "gtk-colorsel-have-pointer") != NULL)
1477 if (GPOINTER_TO_INT (g_object_get_data (G_OBJECT (drawing_area), "color_set")) != 0)
1480 palette_get_color (drawing_area, color);
1481 set_color_internal (colorsel, color);
1489 palette_drop_handle (GtkWidget *widget,
1490 GdkDragContext *context,
1493 GtkSelectionData *selection_data,
1498 GtkColorSelection *colorsel = GTK_COLOR_SELECTION (data);
1502 if (selection_data->length < 0)
1505 /* We accept drops with the wrong format, since the KDE color
1506 * chooser incorrectly drops application/x-color with format 8.
1508 if (selection_data->length != 8)
1510 g_warning ("Received invalid color data\n");
1514 vals = (guint16 *)selection_data->data;
1516 color[0] = (gdouble)vals[0] / 0xffff;
1517 color[1] = (gdouble)vals[1] / 0xffff;
1518 color[2] = (gdouble)vals[2] / 0xffff;
1519 color[3] = (gdouble)vals[3] / 0xffff;
1520 palette_change_color (widget, colorsel, color);
1521 set_color_internal (colorsel, color);
1525 palette_activate (GtkWidget *widget,
1529 /* should have a drawing area subclass with an activate signal */
1530 if ((event->keyval == GDK_space) ||
1531 (event->keyval == GDK_Return) ||
1532 (event->keyval == GDK_ISO_Enter) ||
1533 (event->keyval == GDK_KP_Enter) ||
1534 (event->keyval == GDK_KP_Space))
1536 if (GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget), "color_set")) != 0)
1539 palette_get_color (widget, color);
1540 set_color_internal (GTK_COLOR_SELECTION (data), color);
1549 palette_popup (GtkWidget *widget,
1552 GtkColorSelection *colorsel = GTK_COLOR_SELECTION (data);
1554 do_popup (colorsel, widget, GDK_CURRENT_TIME);
1560 palette_new (GtkColorSelection *colorsel)
1563 GtkColorSelectionPrivate *priv;
1565 static const GtkTargetEntry targets[] = {
1566 { "application/x-color", 0 }
1569 priv = colorsel->private_data;
1571 retval = gtk_drawing_area_new ();
1573 gtk_widget_set_can_focus (retval, TRUE);
1575 g_object_set_data (G_OBJECT (retval), I_("color_set"), GINT_TO_POINTER (0));
1576 gtk_widget_set_events (retval, GDK_BUTTON_PRESS_MASK
1577 | GDK_BUTTON_RELEASE_MASK
1579 | GDK_ENTER_NOTIFY_MASK
1580 | GDK_LEAVE_NOTIFY_MASK);
1582 g_signal_connect (retval, "expose-event",
1583 G_CALLBACK (palette_expose), colorsel);
1584 g_signal_connect (retval, "button-press-event",
1585 G_CALLBACK (palette_press), colorsel);
1586 g_signal_connect (retval, "button-release-event",
1587 G_CALLBACK (palette_release), colorsel);
1588 g_signal_connect (retval, "enter-notify-event",
1589 G_CALLBACK (palette_enter), colorsel);
1590 g_signal_connect (retval, "leave-notify-event",
1591 G_CALLBACK (palette_leave), colorsel);
1592 g_signal_connect (retval, "key-press-event",
1593 G_CALLBACK (palette_activate), colorsel);
1594 g_signal_connect (retval, "popup-menu",
1595 G_CALLBACK (palette_popup), colorsel);
1597 gtk_drag_dest_set (retval,
1598 GTK_DEST_DEFAULT_HIGHLIGHT |
1599 GTK_DEST_DEFAULT_MOTION |
1600 GTK_DEST_DEFAULT_DROP,
1604 g_signal_connect (retval, "drag-end",
1605 G_CALLBACK (palette_drag_end), NULL);
1606 g_signal_connect (retval, "drag-data-received",
1607 G_CALLBACK (palette_drop_handle), colorsel);
1609 gtk_widget_set_tooltip_text (retval,
1610 _("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.\""));
1617 * The actual GtkColorSelection widget
1622 make_picker_cursor (GdkScreen *screen)
1626 cursor = gdk_cursor_new_from_name (gdk_screen_get_display (screen),
1631 GdkColor bg = { 0, 0xffff, 0xffff, 0xffff };
1632 GdkColor fg = { 0, 0x0000, 0x0000, 0x0000 };
1634 GdkPixmap *pixmap, *mask;
1635 cairo_surface_t *image;
1638 window = gdk_screen_get_root_window (screen);
1641 pixmap = gdk_pixmap_new (window, DROPPER_WIDTH, DROPPER_HEIGHT, 1);
1643 cr = gdk_cairo_create (pixmap);
1644 cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
1645 image = cairo_image_surface_create_for_data ((guchar *) dropper_bits,
1650 cairo_set_source_surface (cr, image, 0, 0);
1651 cairo_surface_destroy (image);
1656 mask = gdk_pixmap_new (window, DROPPER_WIDTH, DROPPER_HEIGHT, 1);
1658 cr = gdk_cairo_create (mask);
1659 cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
1660 image = cairo_image_surface_create_for_data ((guchar *) dropper_mask,
1665 cairo_set_source_surface (cr, image, 0, 0);
1666 cairo_surface_destroy (image);
1670 cursor = gdk_cursor_new_from_pixmap (pixmap, mask, &fg, &bg,
1671 DROPPER_X_HOT, DROPPER_Y_HOT);
1673 g_object_unref (pixmap);
1674 g_object_unref (mask);
1681 grab_color_at_pointer (GdkScreen *screen,
1689 GtkColorSelection *colorsel = data;
1690 GtkColorSelectionPrivate *priv;
1692 GdkWindow *root_window = gdk_screen_get_root_window (screen);
1694 priv = colorsel->private_data;
1696 pixbuf = gdk_pixbuf_get_from_drawable (NULL, root_window, NULL,
1703 GdkDisplay *display = gdk_screen_get_display (screen);
1704 GdkWindow *window = gdk_display_get_window_at_device_position (display, device, &x, &y);
1707 pixbuf = gdk_pixbuf_get_from_drawable (NULL, window, NULL,
1714 pixels = gdk_pixbuf_get_pixels (pixbuf);
1715 color.red = pixels[0] * 0x101;
1716 color.green = pixels[1] * 0x101;
1717 color.blue = pixels[2] * 0x101;
1718 g_object_unref (pixbuf);
1720 priv->color[COLORSEL_RED] = SCALE (color.red);
1721 priv->color[COLORSEL_GREEN] = SCALE (color.green);
1722 priv->color[COLORSEL_BLUE] = SCALE (color.blue);
1724 gtk_rgb_to_hsv (priv->color[COLORSEL_RED],
1725 priv->color[COLORSEL_GREEN],
1726 priv->color[COLORSEL_BLUE],
1727 &priv->color[COLORSEL_HUE],
1728 &priv->color[COLORSEL_SATURATION],
1729 &priv->color[COLORSEL_VALUE]);
1731 update_color (colorsel);
1735 shutdown_eyedropper (GtkWidget *widget)
1737 GtkColorSelection *colorsel;
1738 GtkColorSelectionPrivate *priv;
1740 colorsel = GTK_COLOR_SELECTION (widget);
1741 priv = colorsel->private_data;
1745 gdk_device_ungrab (priv->keyboard_device, priv->grab_time);
1746 gdk_device_ungrab (priv->pointer_device, priv->grab_time);
1747 gtk_device_grab_remove (priv->dropper_grab_widget, priv->pointer_device);
1749 priv->has_grab = FALSE;
1750 priv->keyboard_device = NULL;
1751 priv->pointer_device = NULL;
1756 mouse_motion (GtkWidget *invisible,
1757 GdkEventMotion *event,
1760 grab_color_at_pointer (gdk_event_get_screen ((GdkEvent *) event),
1761 gdk_event_get_device ((GdkEvent *) event),
1762 event->x_root, event->y_root, data);
1766 mouse_release (GtkWidget *invisible,
1767 GdkEventButton *event,
1770 /* GtkColorSelection *colorsel = data; */
1772 if (event->button != 1)
1775 grab_color_at_pointer (gdk_event_get_screen ((GdkEvent *) event),
1776 gdk_event_get_device ((GdkEvent *) event),
1777 event->x_root, event->y_root, data);
1779 shutdown_eyedropper (GTK_WIDGET (data));
1781 g_signal_handlers_disconnect_by_func (invisible,
1784 g_signal_handlers_disconnect_by_func (invisible,
1791 /* Helper Functions */
1794 key_press (GtkWidget *invisible,
1798 GdkDisplay *display = gtk_widget_get_display (invisible);
1799 GdkScreen *screen = gdk_event_get_screen ((GdkEvent *) event);
1800 GdkDevice *device, *pointer_device;
1801 guint state = event->state & gtk_accelerator_get_default_mod_mask ();
1805 device = gdk_event_get_device ((GdkEvent * ) event);
1806 pointer_device = gdk_device_get_associated_device (device);
1807 gdk_display_get_device_state (display, pointer_device, NULL, &x, &y, NULL);
1812 switch (event->keyval)
1819 grab_color_at_pointer (screen, pointer_device, x, y, data);
1823 shutdown_eyedropper (data);
1825 g_signal_handlers_disconnect_by_func (invisible,
1828 g_signal_handlers_disconnect_by_func (invisible,
1834 #if defined GDK_WINDOWING_X11 || defined GDK_WINDOWING_WIN32
1837 dy = state == GDK_MOD1_MASK ? -BIG_STEP : -1;
1842 dy = state == GDK_MOD1_MASK ? BIG_STEP : 1;
1847 dx = state == GDK_MOD1_MASK ? -BIG_STEP : -1;
1852 dx = state == GDK_MOD1_MASK ? BIG_STEP : 1;
1860 gdk_display_warp_device (display, pointer_device, screen, x + dx, y + dy);
1867 mouse_press (GtkWidget *invisible,
1868 GdkEventButton *event,
1871 /* GtkColorSelection *colorsel = data; */
1873 if (event->type == GDK_BUTTON_PRESS &&
1876 g_signal_connect (invisible, "motion-notify-event",
1877 G_CALLBACK (mouse_motion),
1879 g_signal_connect (invisible, "button-release-event",
1880 G_CALLBACK (mouse_release),
1882 g_signal_handlers_disconnect_by_func (invisible,
1885 g_signal_handlers_disconnect_by_func (invisible,
1894 /* when the button is clicked */
1896 get_screen_color (GtkWidget *button)
1898 GtkColorSelection *colorsel = g_object_get_data (G_OBJECT (button), "COLORSEL");
1899 GtkColorSelectionPrivate *priv = colorsel->private_data;
1900 GdkScreen *screen = gtk_widget_get_screen (GTK_WIDGET (button));
1901 GdkDevice *device, *keyb_device, *pointer_device;
1902 GdkCursor *picker_cursor;
1903 GdkGrabStatus grab_status;
1905 GtkWidget *grab_widget, *toplevel;
1907 guint32 time = gtk_get_current_event_time ();
1909 device = gtk_get_current_event_device ();
1911 if (device->source == GDK_SOURCE_KEYBOARD)
1913 keyb_device = device;
1914 pointer_device = gdk_device_get_associated_device (device);
1918 pointer_device = device;
1919 keyb_device = gdk_device_get_associated_device (device);
1922 if (priv->dropper_grab_widget == NULL)
1924 grab_widget = gtk_window_new (GTK_WINDOW_POPUP);
1925 gtk_window_set_screen (GTK_WINDOW (grab_widget), screen);
1926 gtk_window_resize (GTK_WINDOW (grab_widget), 1, 1);
1927 gtk_window_move (GTK_WINDOW (grab_widget), -100, -100);
1928 gtk_widget_show (grab_widget);
1930 gtk_widget_add_events (grab_widget,
1931 GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_PRESS_MASK | GDK_POINTER_MOTION_MASK);
1933 toplevel = gtk_widget_get_toplevel (GTK_WIDGET (colorsel));
1935 if (GTK_IS_WINDOW (toplevel))
1937 if (gtk_window_has_group (GTK_WINDOW (toplevel)))
1938 gtk_window_group_add_window (gtk_window_get_group (GTK_WINDOW (toplevel)),
1939 GTK_WINDOW (grab_widget));
1942 priv->dropper_grab_widget = grab_widget;
1945 window = gtk_widget_get_window (priv->dropper_grab_widget);
1947 if (gdk_device_grab (keyb_device,
1949 GDK_OWNERSHIP_APPLICATION, FALSE,
1950 GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK,
1951 NULL, time) != GDK_GRAB_SUCCESS)
1954 picker_cursor = make_picker_cursor (screen);
1955 grab_status = gdk_device_grab (pointer_device,
1957 GDK_OWNERSHIP_APPLICATION,
1959 GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_PRESS_MASK | GDK_POINTER_MOTION_MASK,
1962 gdk_cursor_unref (picker_cursor);
1964 if (grab_status != GDK_GRAB_SUCCESS)
1966 gdk_device_ungrab (keyb_device, time);
1970 gtk_device_grab_add (priv->dropper_grab_widget,
1974 priv->grab_time = time;
1975 priv->has_grab = TRUE;
1976 priv->keyboard_device = keyb_device;
1977 priv->pointer_device = pointer_device;
1979 g_signal_connect (priv->dropper_grab_widget, "button-press-event",
1980 G_CALLBACK (mouse_press), colorsel);
1981 g_signal_connect (priv->dropper_grab_widget, "key-press-event",
1982 G_CALLBACK (key_press), colorsel);
1986 hex_changed (GtkWidget *hex_entry,
1989 GtkColorSelection *colorsel;
1990 GtkColorSelectionPrivate *priv;
1994 colorsel = GTK_COLOR_SELECTION (data);
1995 priv = colorsel->private_data;
2000 text = gtk_editable_get_chars (GTK_EDITABLE (priv->hex_entry), 0, -1);
2001 if (gdk_color_parse (text, &color))
2003 priv->color[COLORSEL_RED] = CLAMP (color.red/65535.0, 0.0, 1.0);
2004 priv->color[COLORSEL_GREEN] = CLAMP (color.green/65535.0, 0.0, 1.0);
2005 priv->color[COLORSEL_BLUE] = CLAMP (color.blue/65535.0, 0.0, 1.0);
2006 gtk_rgb_to_hsv (priv->color[COLORSEL_RED],
2007 priv->color[COLORSEL_GREEN],
2008 priv->color[COLORSEL_BLUE],
2009 &priv->color[COLORSEL_HUE],
2010 &priv->color[COLORSEL_SATURATION],
2011 &priv->color[COLORSEL_VALUE]);
2012 update_color (colorsel);
2018 hex_focus_out (GtkWidget *hex_entry,
2019 GdkEventFocus *event,
2022 hex_changed (hex_entry, data);
2028 hsv_changed (GtkWidget *hsv,
2031 GtkColorSelection *colorsel;
2032 GtkColorSelectionPrivate *priv;
2034 colorsel = GTK_COLOR_SELECTION (data);
2035 priv = colorsel->private_data;
2040 gtk_hsv_get_color (GTK_HSV (hsv),
2041 &priv->color[COLORSEL_HUE],
2042 &priv->color[COLORSEL_SATURATION],
2043 &priv->color[COLORSEL_VALUE]);
2044 gtk_hsv_to_rgb (priv->color[COLORSEL_HUE],
2045 priv->color[COLORSEL_SATURATION],
2046 priv->color[COLORSEL_VALUE],
2047 &priv->color[COLORSEL_RED],
2048 &priv->color[COLORSEL_GREEN],
2049 &priv->color[COLORSEL_BLUE]);
2050 update_color (colorsel);
2054 adjustment_changed (GtkAdjustment *adjustment,
2057 GtkColorSelection *colorsel;
2058 GtkColorSelectionPrivate *priv;
2060 colorsel = GTK_COLOR_SELECTION (g_object_get_data (G_OBJECT (adjustment), "COLORSEL"));
2061 priv = colorsel->private_data;
2066 switch (GPOINTER_TO_INT (data))
2068 case COLORSEL_SATURATION:
2069 case COLORSEL_VALUE:
2070 priv->color[GPOINTER_TO_INT (data)] = adjustment->value / 100;
2071 gtk_hsv_to_rgb (priv->color[COLORSEL_HUE],
2072 priv->color[COLORSEL_SATURATION],
2073 priv->color[COLORSEL_VALUE],
2074 &priv->color[COLORSEL_RED],
2075 &priv->color[COLORSEL_GREEN],
2076 &priv->color[COLORSEL_BLUE]);
2079 priv->color[GPOINTER_TO_INT (data)] = adjustment->value / 360;
2080 gtk_hsv_to_rgb (priv->color[COLORSEL_HUE],
2081 priv->color[COLORSEL_SATURATION],
2082 priv->color[COLORSEL_VALUE],
2083 &priv->color[COLORSEL_RED],
2084 &priv->color[COLORSEL_GREEN],
2085 &priv->color[COLORSEL_BLUE]);
2088 case COLORSEL_GREEN:
2090 priv->color[GPOINTER_TO_INT (data)] = adjustment->value / 255;
2092 gtk_rgb_to_hsv (priv->color[COLORSEL_RED],
2093 priv->color[COLORSEL_GREEN],
2094 priv->color[COLORSEL_BLUE],
2095 &priv->color[COLORSEL_HUE],
2096 &priv->color[COLORSEL_SATURATION],
2097 &priv->color[COLORSEL_VALUE]);
2100 priv->color[GPOINTER_TO_INT (data)] = adjustment->value / 255;
2103 update_color (colorsel);
2107 opacity_entry_changed (GtkWidget *opacity_entry,
2110 GtkColorSelection *colorsel;
2111 GtkColorSelectionPrivate *priv;
2115 colorsel = GTK_COLOR_SELECTION (data);
2116 priv = colorsel->private_data;
2121 text = gtk_editable_get_chars (GTK_EDITABLE (priv->opacity_entry), 0, -1);
2122 adj = gtk_range_get_adjustment (GTK_RANGE (priv->opacity_slider));
2123 gtk_adjustment_set_value (adj, g_strtod (text, NULL));
2125 update_color (colorsel);
2131 make_label_spinbutton (GtkColorSelection *colorsel,
2132 GtkWidget **spinbutton,
2138 const gchar *tooltip)
2141 GtkAdjustment *adjust;
2143 if (channel_type == COLORSEL_HUE)
2145 adjust = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 360.0, 1.0, 1.0, 0.0));
2147 else if (channel_type == COLORSEL_SATURATION ||
2148 channel_type == COLORSEL_VALUE)
2150 adjust = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 100.0, 1.0, 1.0, 0.0));
2154 adjust = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 255.0, 1.0, 1.0, 0.0));
2156 g_object_set_data (G_OBJECT (adjust), I_("COLORSEL"), colorsel);
2157 *spinbutton = gtk_spin_button_new (adjust, 10.0, 0);
2159 gtk_widget_set_tooltip_text (*spinbutton, tooltip);
2161 g_signal_connect (adjust, "value-changed",
2162 G_CALLBACK (adjustment_changed),
2163 GINT_TO_POINTER (channel_type));
2164 label = gtk_label_new_with_mnemonic (text);
2165 gtk_label_set_mnemonic_widget (GTK_LABEL (label), *spinbutton);
2167 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
2168 gtk_table_attach_defaults (GTK_TABLE (table), label, i, i+1, j, j+1);
2169 gtk_table_attach_defaults (GTK_TABLE (table), *spinbutton, i+1, i+2, j, j+1);
2173 make_palette_frame (GtkColorSelection *colorsel,
2179 GtkColorSelectionPrivate *priv;
2181 priv = colorsel->private_data;
2182 frame = gtk_frame_new (NULL);
2183 gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
2184 priv->custom_palette[i][j] = palette_new (colorsel);
2185 gtk_widget_set_size_request (priv->custom_palette[i][j], CUSTOM_PALETTE_ENTRY_WIDTH, CUSTOM_PALETTE_ENTRY_HEIGHT);
2186 gtk_container_add (GTK_CONTAINER (frame), priv->custom_palette[i][j]);
2187 gtk_table_attach_defaults (GTK_TABLE (table), frame, i, i+1, j, j+1);
2190 /* Set the palette entry [x][y] to be the currently selected one. */
2192 set_selected_palette (GtkColorSelection *colorsel, int x, int y)
2194 GtkColorSelectionPrivate *priv = colorsel->private_data;
2196 gtk_widget_grab_focus (priv->custom_palette[x][y]);
2200 scale_round (double val, double factor)
2202 val = floor (val * factor + 0.5);
2204 val = MIN (val, factor);
2209 update_color (GtkColorSelection *colorsel)
2211 GtkColorSelectionPrivate *priv = colorsel->private_data;
2213 gchar opacity_text[32];
2216 priv->changing = TRUE;
2217 color_sample_update_samples (colorsel);
2219 gtk_hsv_set_color (GTK_HSV (priv->triangle_colorsel),
2220 priv->color[COLORSEL_HUE],
2221 priv->color[COLORSEL_SATURATION],
2222 priv->color[COLORSEL_VALUE]);
2223 gtk_adjustment_set_value (gtk_spin_button_get_adjustment
2224 (GTK_SPIN_BUTTON (priv->hue_spinbutton)),
2225 scale_round (priv->color[COLORSEL_HUE], 360));
2226 gtk_adjustment_set_value (gtk_spin_button_get_adjustment
2227 (GTK_SPIN_BUTTON (priv->sat_spinbutton)),
2228 scale_round (priv->color[COLORSEL_SATURATION], 100));
2229 gtk_adjustment_set_value (gtk_spin_button_get_adjustment
2230 (GTK_SPIN_BUTTON (priv->val_spinbutton)),
2231 scale_round (priv->color[COLORSEL_VALUE], 100));
2232 gtk_adjustment_set_value (gtk_spin_button_get_adjustment
2233 (GTK_SPIN_BUTTON (priv->red_spinbutton)),
2234 scale_round (priv->color[COLORSEL_RED], 255));
2235 gtk_adjustment_set_value (gtk_spin_button_get_adjustment
2236 (GTK_SPIN_BUTTON (priv->green_spinbutton)),
2237 scale_round (priv->color[COLORSEL_GREEN], 255));
2238 gtk_adjustment_set_value (gtk_spin_button_get_adjustment
2239 (GTK_SPIN_BUTTON (priv->blue_spinbutton)),
2240 scale_round (priv->color[COLORSEL_BLUE], 255));
2241 gtk_adjustment_set_value (gtk_range_get_adjustment
2242 (GTK_RANGE (priv->opacity_slider)),
2243 scale_round (priv->color[COLORSEL_OPACITY], 255));
2245 g_snprintf (opacity_text, 32, "%.0f", scale_round (priv->color[COLORSEL_OPACITY], 255));
2246 gtk_entry_set_text (GTK_ENTRY (priv->opacity_entry), opacity_text);
2248 g_snprintf (entryval, 11, "#%2X%2X%2X",
2249 (guint) (scale_round (priv->color[COLORSEL_RED], 255)),
2250 (guint) (scale_round (priv->color[COLORSEL_GREEN], 255)),
2251 (guint) (scale_round (priv->color[COLORSEL_BLUE], 255)));
2253 for (ptr = entryval; *ptr; ptr++)
2256 gtk_entry_set_text (GTK_ENTRY (priv->hex_entry), entryval);
2257 priv->changing = FALSE;
2259 g_object_ref (colorsel);
2261 g_signal_emit (colorsel, color_selection_signals[COLOR_CHANGED], 0);
2263 g_object_freeze_notify (G_OBJECT (colorsel));
2264 g_object_notify (G_OBJECT (colorsel), "current-color");
2265 g_object_notify (G_OBJECT (colorsel), "current-alpha");
2266 g_object_thaw_notify (G_OBJECT (colorsel));
2268 g_object_unref (colorsel);
2272 update_palette (GtkColorSelection *colorsel)
2274 GdkColor *current_colors;
2277 current_colors = get_current_colors (colorsel);
2279 for (i = 0; i < GTK_CUSTOM_PALETTE_HEIGHT; i++)
2281 for (j = 0; j < GTK_CUSTOM_PALETTE_WIDTH; j++)
2285 index = i * GTK_CUSTOM_PALETTE_WIDTH + j;
2287 gtk_color_selection_set_palette_color (colorsel,
2289 ¤t_colors[index]);
2293 g_free (current_colors);
2297 palette_change_notify_instance (GObject *object,
2301 update_palette (GTK_COLOR_SELECTION (data));
2305 default_noscreen_change_palette_func (const GdkColor *colors,
2308 default_change_palette_func (gdk_screen_get_default (), colors, n_colors);
2312 default_change_palette_func (GdkScreen *screen,
2313 const GdkColor *colors,
2318 str = gtk_color_selection_palette_to_string (colors, n_colors);
2320 gtk_settings_set_string_property (gtk_settings_get_for_screen (screen),
2321 "gtk-color-palette",
2323 "gtk_color_selection_palette_to_string");
2329 * gtk_color_selection_new:
2331 * Creates a new GtkColorSelection.
2333 * Return value: a new #GtkColorSelection
2336 gtk_color_selection_new (void)
2338 GtkColorSelection *colorsel;
2339 GtkColorSelectionPrivate *priv;
2346 colorsel = g_object_new (GTK_TYPE_COLOR_SELECTION, NULL);
2347 priv = colorsel->private_data;
2348 set_color_internal (colorsel, color);
2349 gtk_color_selection_set_has_opacity_control (colorsel, TRUE);
2351 /* We want to make sure that default_set is FALSE */
2352 /* This way the user can still set it */
2353 priv->default_set = FALSE;
2354 priv->default_alpha_set = FALSE;
2356 return GTK_WIDGET (colorsel);
2360 * gtk_color_selection_get_has_opacity_control:
2361 * @colorsel: a #GtkColorSelection.
2363 * Determines whether the colorsel has an opacity control.
2365 * Return value: %TRUE if the @colorsel has an opacity control. %FALSE if it does't.
2368 gtk_color_selection_get_has_opacity_control (GtkColorSelection *colorsel)
2370 GtkColorSelectionPrivate *priv;
2372 g_return_val_if_fail (GTK_IS_COLOR_SELECTION (colorsel), FALSE);
2374 priv = colorsel->private_data;
2376 return priv->has_opacity;
2380 * gtk_color_selection_set_has_opacity_control:
2381 * @colorsel: a #GtkColorSelection.
2382 * @has_opacity: %TRUE if @colorsel can set the opacity, %FALSE otherwise.
2384 * Sets the @colorsel to use or not use opacity.
2388 gtk_color_selection_set_has_opacity_control (GtkColorSelection *colorsel,
2389 gboolean has_opacity)
2391 GtkColorSelectionPrivate *priv;
2393 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2395 priv = colorsel->private_data;
2396 has_opacity = has_opacity != FALSE;
2398 if (priv->has_opacity != has_opacity)
2400 priv->has_opacity = has_opacity;
2403 gtk_widget_show (priv->opacity_slider);
2404 gtk_widget_show (priv->opacity_label);
2405 gtk_widget_show (priv->opacity_entry);
2409 gtk_widget_hide (priv->opacity_slider);
2410 gtk_widget_hide (priv->opacity_label);
2411 gtk_widget_hide (priv->opacity_entry);
2413 color_sample_update_samples (colorsel);
2415 g_object_notify (G_OBJECT (colorsel), "has-opacity-control");
2420 * gtk_color_selection_get_has_palette:
2421 * @colorsel: a #GtkColorSelection.
2423 * Determines whether the color selector has a color palette.
2425 * Return value: %TRUE if the selector has a palette. %FALSE if it hasn't.
2428 gtk_color_selection_get_has_palette (GtkColorSelection *colorsel)
2430 GtkColorSelectionPrivate *priv;
2432 g_return_val_if_fail (GTK_IS_COLOR_SELECTION (colorsel), FALSE);
2434 priv = colorsel->private_data;
2436 return priv->has_palette;
2440 * gtk_color_selection_set_has_palette:
2441 * @colorsel: a #GtkColorSelection.
2442 * @has_palette: %TRUE if palette is to be visible, %FALSE otherwise.
2444 * Shows and hides the palette based upon the value of @has_palette.
2448 gtk_color_selection_set_has_palette (GtkColorSelection *colorsel,
2449 gboolean has_palette)
2451 GtkColorSelectionPrivate *priv;
2452 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2454 priv = colorsel->private_data;
2455 has_palette = has_palette != FALSE;
2457 if (priv->has_palette != has_palette)
2459 priv->has_palette = has_palette;
2461 gtk_widget_show (priv->palette_frame);
2463 gtk_widget_hide (priv->palette_frame);
2465 update_tooltips (colorsel);
2467 g_object_notify (G_OBJECT (colorsel), "has-palette");
2472 * gtk_color_selection_set_current_color:
2473 * @colorsel: a #GtkColorSelection.
2474 * @color: A #GdkColor to set the current color with.
2476 * Sets the current color to be @color. The first time this is called, it will
2477 * also set the original color to be @color too.
2480 gtk_color_selection_set_current_color (GtkColorSelection *colorsel,
2481 const GdkColor *color)
2483 GtkColorSelectionPrivate *priv;
2486 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2487 g_return_if_fail (color != NULL);
2489 priv = colorsel->private_data;
2490 priv->changing = TRUE;
2491 priv->color[COLORSEL_RED] = SCALE (color->red);
2492 priv->color[COLORSEL_GREEN] = SCALE (color->green);
2493 priv->color[COLORSEL_BLUE] = SCALE (color->blue);
2494 gtk_rgb_to_hsv (priv->color[COLORSEL_RED],
2495 priv->color[COLORSEL_GREEN],
2496 priv->color[COLORSEL_BLUE],
2497 &priv->color[COLORSEL_HUE],
2498 &priv->color[COLORSEL_SATURATION],
2499 &priv->color[COLORSEL_VALUE]);
2500 if (priv->default_set == FALSE)
2502 for (i = 0; i < COLORSEL_NUM_CHANNELS; i++)
2503 priv->old_color[i] = priv->color[i];
2505 priv->default_set = TRUE;
2506 update_color (colorsel);
2510 * gtk_color_selection_set_current_alpha:
2511 * @colorsel: a #GtkColorSelection.
2512 * @alpha: an integer between 0 and 65535.
2514 * Sets the current opacity to be @alpha. The first time this is called, it will
2515 * also set the original opacity to be @alpha too.
2518 gtk_color_selection_set_current_alpha (GtkColorSelection *colorsel,
2521 GtkColorSelectionPrivate *priv;
2524 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2526 priv = colorsel->private_data;
2527 priv->changing = TRUE;
2528 priv->color[COLORSEL_OPACITY] = SCALE (alpha);
2529 if (priv->default_alpha_set == FALSE)
2531 for (i = 0; i < COLORSEL_NUM_CHANNELS; i++)
2532 priv->old_color[i] = priv->color[i];
2534 priv->default_alpha_set = TRUE;
2535 update_color (colorsel);
2539 * gtk_color_selection_get_current_color:
2540 * @colorsel: a #GtkColorSelection.
2541 * @color: (out): a #GdkColor to fill in with the current color.
2543 * Sets @color to be the current color in the GtkColorSelection widget.
2546 gtk_color_selection_get_current_color (GtkColorSelection *colorsel,
2549 GtkColorSelectionPrivate *priv;
2551 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2552 g_return_if_fail (color != NULL);
2554 priv = colorsel->private_data;
2555 color->red = UNSCALE (priv->color[COLORSEL_RED]);
2556 color->green = UNSCALE (priv->color[COLORSEL_GREEN]);
2557 color->blue = UNSCALE (priv->color[COLORSEL_BLUE]);
2561 * gtk_color_selection_get_current_alpha:
2562 * @colorsel: a #GtkColorSelection.
2564 * Returns the current alpha value.
2566 * Return value: an integer between 0 and 65535.
2569 gtk_color_selection_get_current_alpha (GtkColorSelection *colorsel)
2571 GtkColorSelectionPrivate *priv;
2573 g_return_val_if_fail (GTK_IS_COLOR_SELECTION (colorsel), 0);
2575 priv = colorsel->private_data;
2576 return priv->has_opacity ? UNSCALE (priv->color[COLORSEL_OPACITY]) : 65535;
2580 * gtk_color_selection_set_previous_color:
2581 * @colorsel: a #GtkColorSelection.
2582 * @color: a #GdkColor to set the previous color with.
2584 * Sets the 'previous' color to be @color. This function should be called with
2585 * some hesitations, as it might seem confusing to have that color change.
2586 * Calling gtk_color_selection_set_current_color() will also set this color the first
2587 * time it is called.
2590 gtk_color_selection_set_previous_color (GtkColorSelection *colorsel,
2591 const GdkColor *color)
2593 GtkColorSelectionPrivate *priv;
2595 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2596 g_return_if_fail (color != NULL);
2598 priv = colorsel->private_data;
2599 priv->changing = TRUE;
2600 priv->old_color[COLORSEL_RED] = SCALE (color->red);
2601 priv->old_color[COLORSEL_GREEN] = SCALE (color->green);
2602 priv->old_color[COLORSEL_BLUE] = SCALE (color->blue);
2603 gtk_rgb_to_hsv (priv->old_color[COLORSEL_RED],
2604 priv->old_color[COLORSEL_GREEN],
2605 priv->old_color[COLORSEL_BLUE],
2606 &priv->old_color[COLORSEL_HUE],
2607 &priv->old_color[COLORSEL_SATURATION],
2608 &priv->old_color[COLORSEL_VALUE]);
2609 color_sample_update_samples (colorsel);
2610 priv->default_set = TRUE;
2611 priv->changing = FALSE;
2615 * gtk_color_selection_set_previous_alpha:
2616 * @colorsel: a #GtkColorSelection.
2617 * @alpha: an integer between 0 and 65535.
2619 * Sets the 'previous' alpha to be @alpha. This function should be called with
2620 * some hesitations, as it might seem confusing to have that alpha change.
2623 gtk_color_selection_set_previous_alpha (GtkColorSelection *colorsel,
2626 GtkColorSelectionPrivate *priv;
2628 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2630 priv = colorsel->private_data;
2631 priv->changing = TRUE;
2632 priv->old_color[COLORSEL_OPACITY] = SCALE (alpha);
2633 color_sample_update_samples (colorsel);
2634 priv->default_alpha_set = TRUE;
2635 priv->changing = FALSE;
2640 * gtk_color_selection_get_previous_color:
2641 * @colorsel: a #GtkColorSelection.
2642 * @color: a #GdkColor to fill in with the original color value.
2644 * Fills @color in with the original color value.
2647 gtk_color_selection_get_previous_color (GtkColorSelection *colorsel,
2650 GtkColorSelectionPrivate *priv;
2652 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2653 g_return_if_fail (color != NULL);
2655 priv = colorsel->private_data;
2656 color->red = UNSCALE (priv->old_color[COLORSEL_RED]);
2657 color->green = UNSCALE (priv->old_color[COLORSEL_GREEN]);
2658 color->blue = UNSCALE (priv->old_color[COLORSEL_BLUE]);
2662 * gtk_color_selection_get_previous_alpha:
2663 * @colorsel: a #GtkColorSelection.
2665 * Returns the previous alpha value.
2667 * Return value: an integer between 0 and 65535.
2670 gtk_color_selection_get_previous_alpha (GtkColorSelection *colorsel)
2672 GtkColorSelectionPrivate *priv;
2674 g_return_val_if_fail (GTK_IS_COLOR_SELECTION (colorsel), 0);
2676 priv = colorsel->private_data;
2677 return priv->has_opacity ? UNSCALE (priv->old_color[COLORSEL_OPACITY]) : 65535;
2681 * gtk_color_selection_set_palette_color:
2682 * @colorsel: a #GtkColorSelection.
2683 * @index: the color index of the palette.
2684 * @color: A #GdkColor to set the palette with.
2686 * Sets the palette located at @index to have @color as its color.
2690 gtk_color_selection_set_palette_color (GtkColorSelection *colorsel,
2694 GtkColorSelectionPrivate *priv;
2698 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
2699 g_return_if_fail (index >= 0 && index < GTK_CUSTOM_PALETTE_WIDTH*GTK_CUSTOM_PALETTE_HEIGHT);
2701 x = index % GTK_CUSTOM_PALETTE_WIDTH;
2702 y = index / GTK_CUSTOM_PALETTE_WIDTH;
2704 priv = colorsel->private_data;
2705 col[0] = SCALE (color->red);
2706 col[1] = SCALE (color->green);
2707 col[2] = SCALE (color->blue);
2709 palette_set_color (priv->custom_palette[x][y], colorsel, col);
2713 * gtk_color_selection_is_adjusting:
2714 * @colorsel: a #GtkColorSelection.
2716 * Gets the current state of the @colorsel.
2718 * Return value: %TRUE if the user is currently dragging a color around, and %FALSE
2719 * if the selection has stopped.
2722 gtk_color_selection_is_adjusting (GtkColorSelection *colorsel)
2724 GtkColorSelectionPrivate *priv;
2726 g_return_val_if_fail (GTK_IS_COLOR_SELECTION (colorsel), FALSE);
2728 priv = colorsel->private_data;
2730 return (gtk_hsv_is_adjusting (GTK_HSV (priv->triangle_colorsel)));
2735 * gtk_color_selection_palette_from_string:
2736 * @str: a string encoding a color palette.
2737 * @colors: return location for allocated array of #GdkColor.
2738 * @n_colors: return location for length of array.
2740 * Parses a color palette string; the string is a colon-separated
2741 * list of color names readable by gdk_color_parse().
2743 * Return value: %TRUE if a palette was successfully parsed.
2746 gtk_color_selection_palette_from_string (const gchar *str,
2758 copy = g_strdup (str);
2764 if (*p == ':' || *p == '\0')
2766 gboolean done = TRUE;
2770 goto failed; /* empty entry */
2779 retval = g_renew (GdkColor, retval, count + 1);
2780 if (!gdk_color_parse (start, retval + count))
2821 * gtk_color_selection_palette_to_string:
2822 * @colors: an array of colors.
2823 * @n_colors: length of the array.
2825 * Encodes a palette as a string, useful for persistent storage.
2827 * Return value: allocated string encoding the palette.
2830 gtk_color_selection_palette_to_string (const GdkColor *colors,
2834 gchar **strs = NULL;
2838 return g_strdup ("");
2840 strs = g_new0 (gchar*, n_colors + 1);
2843 while (i < n_colors)
2848 g_strdup_printf ("#%2X%2X%2X",
2849 colors[i].red / 256,
2850 colors[i].green / 256,
2851 colors[i].blue / 256);
2853 for (ptr = strs[i]; *ptr; ptr++)
2860 retval = g_strjoinv (":", strs);
2868 * gtk_color_selection_set_change_palette_with_screen_hook:
2869 * @func: a function to call when the custom palette needs saving.
2871 * Installs a global function to be called whenever the user tries to
2872 * modify the palette in a color selection. This function should save
2873 * the new palette contents, and update the GtkSettings property
2874 * "gtk-color-palette" so all GtkColorSelection widgets will be modified.
2876 * Return value: the previous change palette hook (that was replaced).
2880 GtkColorSelectionChangePaletteWithScreenFunc
2881 gtk_color_selection_set_change_palette_with_screen_hook (GtkColorSelectionChangePaletteWithScreenFunc func)
2883 GtkColorSelectionChangePaletteWithScreenFunc old;
2885 old = change_palette_hook;
2887 change_palette_hook = func;
2893 make_control_relations (AtkObject *atk_obj,
2898 obj = gtk_widget_get_accessible (widget);
2899 atk_object_add_relationship (atk_obj, ATK_RELATION_CONTROLLED_BY, obj);
2900 atk_object_add_relationship (obj, ATK_RELATION_CONTROLLER_FOR, atk_obj);
2904 make_all_relations (AtkObject *atk_obj,
2905 GtkColorSelectionPrivate *priv)
2907 make_control_relations (atk_obj, priv->hue_spinbutton);
2908 make_control_relations (atk_obj, priv->sat_spinbutton);
2909 make_control_relations (atk_obj, priv->val_spinbutton);
2910 make_control_relations (atk_obj, priv->red_spinbutton);
2911 make_control_relations (atk_obj, priv->green_spinbutton);
2912 make_control_relations (atk_obj, priv->blue_spinbutton);