1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 #include "gtkcolorsel.h"
22 #define DEGTORAD(a) (2.0*M_PI*a/360.0)
25 #define TIMER_DELAY 300
27 #define CIRCLE_RADIUS 65
29 #define WHEEL_WIDTH 2*CIRCLE_RADIUS+2
30 #define WHEEL_HEIGHT 2*CIRCLE_RADIUS+2
32 #define VALUE_WIDTH 32
33 #define VALUE_HEIGHT WHEEL_HEIGHT
35 #define SAMPLE_WIDTH WHEEL_WIDTH+VALUE_WIDTH+5
36 #define SAMPLE_HEIGHT 28
49 OPACITY_INPUTS = 1 << 2
74 gfloat lower, upper, step_inc, page_inc;
75 GtkSignalFunc updater;
79 #define HSV_TO_RGB() gtk_color_selection_hsv_to_rgb( \
80 colorsel->values[HUE], \
81 colorsel->values[SATURATION], \
82 colorsel->values[VALUE], \
83 &colorsel->values[RED], \
84 &colorsel->values[GREEN], \
85 &colorsel->values[BLUE])
87 #define RGB_TO_HSV() gtk_color_selection_rgb_to_hsv( \
88 colorsel->values[RED], \
89 colorsel->values[GREEN], \
90 colorsel->values[BLUE], \
91 &colorsel->values[HUE], \
92 &colorsel->values[SATURATION], \
93 &colorsel->values[VALUE])
96 static void gtk_color_selection_hsv_updater (GtkWidget *widget,
98 static void gtk_color_selection_rgb_updater (GtkWidget *widget,
100 static void gtk_color_selection_opacity_updater (GtkWidget *widget,
102 static void gtk_color_selection_realize (GtkWidget *widget);
103 static void gtk_color_selection_destroy (GtkObject *object);
104 static void gtk_color_selection_color_changed (GtkColorSelection *colorsel);
105 static void gtk_color_selection_update_input (GtkWidget *scale,
108 static void gtk_color_selection_update_inputs (GtkColorSelection *colorsel,
111 static void gtk_color_selection_update_value (GtkColorSelection *colorsel,
113 static void gtk_color_selection_update_wheel (GtkColorSelection *colorsel,
116 static void gtk_color_selection_value_resize (GtkWidget *widget,
118 static gint gtk_color_selection_value_events (GtkWidget *area,
120 static gint gtk_color_selection_value_timeout (GtkColorSelection *colorsel);
121 static void gtk_color_selection_wheel_resize (GtkWidget *widget,
123 static gint gtk_color_selection_wheel_events (GtkWidget *area,
125 static gint gtk_color_selection_wheel_timeout (GtkColorSelection *colorsel);
126 static void gtk_color_selection_sample_resize (GtkWidget *widget,
128 static void gtk_color_selection_drop_handle (GtkWidget *widget,
130 static void gtk_color_selection_drag_handle (GtkWidget *widget,
132 static void gtk_color_selection_draw_wheel_marker (GtkColorSelection *colorsel);
133 static void gtk_color_selection_draw_wheel_frame (GtkColorSelection *colorsel);
134 static void gtk_color_selection_draw_value_marker (GtkColorSelection *colorsel);
135 static void gtk_color_selection_draw_value_bar (GtkColorSelection *colorsel,
137 static void gtk_color_selection_draw_wheel (GtkColorSelection *colorsel,
139 static void gtk_color_selection_draw_sample (GtkColorSelection *colorsel,
142 static gint gtk_color_selection_eval_wheel (gint x, gint y,
143 gdouble cx, gdouble cy,
144 gdouble *h, gdouble *s);
146 static void gtk_color_selection_hsv_to_rgb (gdouble h, gdouble s, gdouble v,
147 gdouble *r, gdouble *g, gdouble *b);
148 static void gtk_color_selection_rgb_to_hsv (gdouble r, gdouble g, gdouble b,
149 gdouble *h, gdouble *s, gdouble *v);
151 static void gtk_color_selection_dialog_destroy (GtkObject *object);
154 static GtkVBoxClass *color_selection_parent_class = NULL;
155 static GtkWindowClass *color_selection_dialog_parent_class = NULL;
158 static gint color_selection_signals[LAST_SIGNAL] = {0};
161 #define SF GtkSignalFunc
164 scale_val_type scale_vals[NUM_CHANNELS] =
166 {"Hue:", 0.0, 360.0, 1.00, 10.00, (SF) gtk_color_selection_hsv_updater},
167 {"Saturation:", 0.0, 1.0, 0.01, 0.01, (SF) gtk_color_selection_hsv_updater},
168 {"Value:", 0.0, 1.0, 0.01, 0.01, (SF) gtk_color_selection_hsv_updater},
169 {"Red:", 0.0, 1.0, 0.01, 0.01, (SF) gtk_color_selection_rgb_updater},
170 {"Green:", 0.0, 1.0, 0.01, 0.01, (SF) gtk_color_selection_rgb_updater},
171 {"Blue:", 0.0, 1.0, 0.01, 0.01, (SF) gtk_color_selection_rgb_updater},
172 {"Opacity:", 0.0, 1.0, 0.01, 0.01, (SF) gtk_color_selection_opacity_updater}
176 gtk_color_selection_get_type ()
178 static guint color_selection_type = 0;
180 if (!color_selection_type)
182 GtkTypeInfo colorsel_info =
184 "color selection widget",
185 sizeof (GtkColorSelection),
186 sizeof (GtkColorSelectionClass),
187 (GtkClassInitFunc) gtk_color_selection_class_init,
188 (GtkObjectInitFunc) gtk_color_selection_init,
191 color_selection_type = gtk_type_unique (gtk_vbox_get_type (), &colorsel_info);
194 return color_selection_type;
198 gtk_color_selection_class_init (GtkColorSelectionClass *klass)
200 GtkObjectClass *object_class;
201 GtkWidgetClass *widget_class;
202 GtkContainerClass *container_class;
204 object_class = (GtkObjectClass*) klass;
205 widget_class = (GtkWidgetClass*) klass;
206 container_class = (GtkContainerClass*) klass;
208 color_selection_parent_class = gtk_type_class (gtk_vbox_get_type ());
210 color_selection_signals[COLOR_CHANGED] =
211 gtk_signal_new ("color_changed",
214 GTK_SIGNAL_OFFSET (GtkColorSelectionClass, color_changed),
215 gtk_signal_default_marshaller, GTK_TYPE_NONE, 0);
217 gtk_object_class_add_signals (object_class, color_selection_signals, LAST_SIGNAL);
219 object_class->destroy = gtk_color_selection_destroy;
221 widget_class->realize = gtk_color_selection_realize;
225 gtk_color_selection_init (GtkColorSelection *colorsel)
227 GtkWidget *frame, *hbox, *vbox, *hbox2, *label, *table;
232 for (n = RED; n <= OPACITY; n++)
233 colorsel->values[n] = 1.0;
237 for (n = HUE; n <= OPACITY; n++)
238 colorsel->old_values[n] = colorsel->values[n];
240 colorsel->wheel_gc = NULL;
241 colorsel->value_gc = NULL;
242 colorsel->sample_gc = NULL;
243 colorsel->wheel_buf = NULL;
244 colorsel->value_buf = NULL;
245 colorsel->sample_buf = NULL;
247 colorsel->use_opacity = FALSE;
248 colorsel->timer_active = FALSE;
249 colorsel->policy = GTK_UPDATE_CONTINUOUS;
251 hbox = gtk_hbox_new (FALSE, 5);
252 gtk_container_border_width (GTK_CONTAINER (hbox), 5);
253 gtk_container_add (GTK_CONTAINER (colorsel), hbox);
255 vbox = gtk_vbox_new (FALSE, 5);
256 gtk_container_add (GTK_CONTAINER (hbox), vbox);
257 gtk_widget_show (vbox);
259 hbox2 = gtk_hbox_new (FALSE, 5);
260 gtk_container_add (GTK_CONTAINER (vbox), hbox2);
261 gtk_widget_show (hbox2);
263 colorsel->wheel_area = gtk_preview_new (GTK_PREVIEW_COLOR);
264 gtk_widget_set_events (colorsel->wheel_area,
266 GDK_BUTTON_PRESS_MASK |
267 GDK_BUTTON_RELEASE_MASK |
268 GDK_BUTTON_MOTION_MASK |
269 GDK_POINTER_MOTION_HINT_MASK);
270 gtk_preview_size (GTK_PREVIEW (colorsel->wheel_area), WHEEL_WIDTH, WHEEL_HEIGHT);
271 gtk_preview_set_expand (GTK_PREVIEW (colorsel->wheel_area), TRUE);
272 gtk_container_add (GTK_CONTAINER (hbox2), colorsel->wheel_area);
273 gtk_widget_show (colorsel->wheel_area);
275 old_mask = gtk_widget_get_events (colorsel->wheel_area);
277 gtk_signal_connect (GTK_OBJECT (colorsel->wheel_area), "event",
278 (SF) gtk_color_selection_wheel_events, (gpointer) colorsel->wheel_area);
279 gtk_signal_connect_after (GTK_OBJECT (colorsel->wheel_area), "expose_event",
280 (SF) gtk_color_selection_wheel_events, (gpointer) colorsel->wheel_area);
281 gtk_signal_connect_after (GTK_OBJECT (colorsel->wheel_area), "size_allocate",
282 (SF) gtk_color_selection_wheel_resize, (gpointer) colorsel->wheel_area);
283 gtk_object_set_data (GTK_OBJECT (colorsel->wheel_area), "_GtkColorSelection", (gpointer) colorsel);
285 frame = gtk_frame_new (NULL);
286 gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
287 gtk_container_border_width (GTK_CONTAINER (frame), 0);
288 gtk_box_pack_start (GTK_BOX (hbox2), frame, FALSE, TRUE, 0);
289 gtk_widget_show (frame);
291 colorsel->value_area = gtk_preview_new (GTK_PREVIEW_COLOR);
292 gtk_preview_size (GTK_PREVIEW (colorsel->value_area), VALUE_WIDTH, VALUE_HEIGHT);
293 gtk_preview_set_expand (GTK_PREVIEW (colorsel->value_area), TRUE);
294 gtk_container_add (GTK_CONTAINER (frame), colorsel->value_area);
295 gtk_widget_show (colorsel->value_area);
297 old_mask = gtk_widget_get_events (colorsel->value_area);
298 gtk_widget_set_events (colorsel->value_area,
300 GDK_BUTTON_PRESS_MASK |
301 GDK_BUTTON_RELEASE_MASK |
302 GDK_BUTTON_MOTION_MASK |
303 GDK_POINTER_MOTION_HINT_MASK);
305 gtk_signal_connect_after (GTK_OBJECT (colorsel->value_area), "expose_event",
306 (SF) gtk_color_selection_value_events, (gpointer) colorsel->value_area);
307 gtk_signal_connect_after (GTK_OBJECT (colorsel->value_area), "size_allocate",
308 (SF) gtk_color_selection_value_resize, (gpointer) colorsel->value_area);
309 gtk_signal_connect (GTK_OBJECT (colorsel->value_area), "event",
310 (SF) gtk_color_selection_value_events, (gpointer) colorsel->value_area);
311 gtk_object_set_data (GTK_OBJECT (colorsel->value_area), "_GtkColorSelection", (gpointer) colorsel);
313 /* New/old color samples */
314 /* ===================== */
316 frame = gtk_frame_new (NULL);
317 gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
318 gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0);
319 gtk_widget_show (frame);
321 /* colorsel->sample_area_eb = gtk_button_new ();
322 gtk_container_add (GTK_CONTAINER (frame), colorsel->sample_area_eb);
323 gtk_widget_show (colorsel->sample_area_eb); */
325 colorsel->sample_area = gtk_preview_new (GTK_PREVIEW_COLOR);
326 gtk_preview_size (GTK_PREVIEW (colorsel->sample_area), SAMPLE_WIDTH, SAMPLE_HEIGHT);
327 gtk_preview_set_expand (GTK_PREVIEW (colorsel->sample_area), TRUE);
328 gtk_container_add (GTK_CONTAINER (frame),
329 colorsel->sample_area);
330 gtk_widget_set_events(colorsel->sample_area,
331 gtk_widget_get_events(colorsel->sample_area)
332 | GDK_BUTTON_MOTION_MASK
333 | GDK_BUTTON_PRESS_MASK
334 | GDK_BUTTON_RELEASE_MASK
335 | GDK_ENTER_NOTIFY_MASK
336 | GDK_LEAVE_NOTIFY_MASK);
337 gtk_widget_show (colorsel->sample_area);
339 gtk_signal_connect_after (GTK_OBJECT (colorsel->sample_area),
341 GTK_SIGNAL_FUNC (gtk_color_selection_sample_resize),
342 colorsel->sample_area);
343 gtk_object_set_data (GTK_OBJECT (colorsel->sample_area), "_GtkColorSelection", (gpointer) colorsel);
345 table = gtk_table_new (NUM_CHANNELS, 3, FALSE);
346 gtk_table_set_col_spacings (GTK_TABLE (table), 3);
347 gtk_box_pack_start (GTK_BOX (hbox), table, FALSE, TRUE, 0);
349 for (n = HUE; n <= OPACITY; n++)
351 label = gtk_label_new (scale_vals[n].label);
352 gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5);
353 gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, n, n + 1);
355 adj = gtk_adjustment_new (colorsel->values[n], scale_vals[n].lower,
356 scale_vals[n].upper, scale_vals[n].step_inc,
357 scale_vals[n].page_inc, 0.0);
358 colorsel->scales[n] = gtk_hscale_new (GTK_ADJUSTMENT (adj));
359 gtk_widget_set_usize (colorsel->scales[n], 128, 0);
360 gtk_scale_set_value_pos (GTK_SCALE (colorsel->scales[n]), GTK_POS_TOP);
362 gtk_range_set_update_policy (GTK_RANGE (colorsel->scales[n]), colorsel->policy);
363 gtk_scale_set_draw_value (GTK_SCALE (colorsel->scales[n]), FALSE);
364 gtk_scale_set_digits (GTK_SCALE (colorsel->scales[n]), 2);
365 gtk_table_attach_defaults (GTK_TABLE (table), colorsel->scales[n], 1, 2, n, n + 1);
367 colorsel->entries[n] = gtk_entry_new ();
368 gtk_widget_set_usize (colorsel->entries[n], 40, 0);
369 sprintf (txt, "%.2f", colorsel->values[n]);
370 gtk_entry_set_text (GTK_ENTRY (colorsel->entries[n]), txt);
371 gtk_table_attach_defaults (GTK_TABLE (table), colorsel->entries[n], 2, 3, n, n + 1);
375 gtk_widget_show (label);
376 gtk_widget_show (colorsel->scales[n]);
377 gtk_widget_show (colorsel->entries[n]);
380 gtk_signal_connect_object (GTK_OBJECT (adj), "value_changed",
381 scale_vals[n].updater, (gpointer) colorsel->scales[n]);
382 gtk_object_set_data (GTK_OBJECT (colorsel->scales[n]), "_GtkColorSelection", (gpointer) colorsel);
383 gtk_object_set_data (GTK_OBJECT (colorsel->scales[n]), "_ValueIndex", (gpointer) n);
384 gtk_signal_connect_object (GTK_OBJECT (colorsel->entries[n]), "changed",
385 scale_vals[n].updater, (gpointer) colorsel->entries[n]);
386 gtk_object_set_data (GTK_OBJECT (colorsel->entries[n]), "_GtkColorSelection", (gpointer) colorsel);
387 gtk_object_set_data (GTK_OBJECT (colorsel->entries[n]), "_ValueIndex", (gpointer) n);
390 colorsel->opacity_label = label;
392 gtk_widget_show (table);
393 gtk_widget_show (hbox);
397 gtk_color_selection_new (void)
399 GtkColorSelection *colorsel;
401 colorsel = gtk_type_new (gtk_color_selection_get_type ());
403 return GTK_WIDGET (colorsel);
407 gtk_color_selection_set_update_policy (GtkColorSelection *colorsel,
408 GtkUpdateType policy)
412 g_return_if_fail (colorsel != NULL);
414 if (policy != colorsel->policy)
416 colorsel->policy = policy;
418 for (n = 0; n < NUM_CHANNELS; n++)
419 gtk_range_set_update_policy (GTK_RANGE (colorsel->scales[n]), policy);
425 gtk_color_selection_set_color (GtkColorSelection *colorsel,
430 g_return_if_fail (colorsel != NULL);
431 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
433 if (GTK_WIDGET_DRAWABLE (GTK_WIDGET (colorsel)))
434 gtk_color_selection_draw_wheel_marker (colorsel);
436 for (n = RED; n <= BLUE; n++)
438 colorsel->old_values[n] = colorsel->values[n];
439 colorsel->values[n] = color[i++];
442 if (colorsel->use_opacity == TRUE)
444 colorsel->old_values[OPACITY] = colorsel->values[OPACITY];
445 colorsel->values[OPACITY] = color[i];
450 gtk_color_selection_update_inputs (colorsel, RGB_INPUTS | HSV_INPUTS | OPACITY_INPUTS, BOTH);
452 if (GTK_WIDGET_DRAWABLE (GTK_WIDGET (colorsel)))
454 gtk_color_selection_draw_value_bar (colorsel, FALSE);
455 gtk_color_selection_draw_sample (colorsel, FALSE);
456 gtk_color_selection_draw_wheel_marker (colorsel);
461 gtk_color_selection_get_color (GtkColorSelection *colorsel,
466 g_return_if_fail (colorsel != NULL);
467 g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
469 for (n = RED; n <= BLUE; n++)
470 color[i++] = colorsel->values[n];
471 if (colorsel->use_opacity == TRUE)
472 color[i] = colorsel->values[OPACITY];
476 gtk_color_selection_realize (GtkWidget *widget)
478 GtkColorSelection *colorsel;
479 gchar *type_accept_list[] = {"application/x-color"};
481 g_return_if_fail (widget != NULL);
482 g_return_if_fail (GTK_IS_COLOR_SELECTION (widget));
484 colorsel = GTK_COLOR_SELECTION (widget);
486 if (GTK_WIDGET_CLASS (color_selection_parent_class)->realize)
487 (*GTK_WIDGET_CLASS (color_selection_parent_class)->realize) (widget);
489 gtk_widget_dnd_drag_set (colorsel->sample_area,
490 1, type_accept_list, 1);
491 gtk_widget_dnd_drop_set (colorsel->sample_area,
492 1, type_accept_list, 1, 0);
493 gtk_signal_connect_after (GTK_OBJECT (colorsel->sample_area),
494 "drop_data_available_event",
495 GTK_SIGNAL_FUNC (gtk_color_selection_drop_handle),
497 gtk_signal_connect_after (GTK_OBJECT (colorsel->sample_area),
498 "drag_request_event",
499 GTK_SIGNAL_FUNC (gtk_color_selection_drag_handle),
504 gtk_color_selection_destroy (GtkObject *object)
506 GtkColorSelection *colorsel;
508 g_return_if_fail (object != NULL);
509 g_return_if_fail (GTK_IS_COLOR_SELECTION (object));
511 colorsel = GTK_COLOR_SELECTION (object);
513 if (colorsel->wheel_buf != NULL)
514 g_free (colorsel->wheel_buf);
515 if (colorsel->value_buf != NULL)
516 g_free (colorsel->value_buf);
517 if (colorsel->sample_buf != NULL)
518 g_free (colorsel->sample_buf);
520 if (GTK_OBJECT_CLASS (color_selection_parent_class)->destroy)
521 (*GTK_OBJECT_CLASS (color_selection_parent_class)->destroy) (object);
525 gtk_color_selection_color_changed (GtkColorSelection *colorsel)
527 gtk_signal_emit (GTK_OBJECT (colorsel), color_selection_signals[COLOR_CHANGED]);
531 gtk_color_selection_update_input (GtkWidget *scale,
540 adj = gtk_range_get_adjustment (GTK_RANGE (scale));
541 adj->value = (gfloat) value;
542 gtk_signal_handler_block_by_data (GTK_OBJECT (adj), (gpointer) scale);
543 gtk_signal_emit_by_name (GTK_OBJECT (adj), "value_changed");
544 gtk_range_slider_update (GTK_RANGE (scale));
545 gtk_signal_handler_unblock_by_data (GTK_OBJECT (adj), (gpointer) scale);
550 gtk_signal_handler_block_by_data (GTK_OBJECT (entry), (gpointer) entry);
551 sprintf (txt, "%.2f", value);
552 gtk_entry_set_text (GTK_ENTRY (entry), txt);
553 gtk_signal_handler_unblock_by_data (GTK_OBJECT (entry), (gpointer) entry);
558 gtk_color_selection_update_inputs (GtkColorSelection *colorsel,
567 if ((inputs & RGB_INPUTS) != 0)
568 for (n = RED; n <= BLUE; n++)
569 gtk_color_selection_update_input (colorsel->scales[n], NULL,
570 colorsel->values[n]);
571 if ((inputs & HSV_INPUTS) != 0)
572 for (n = HUE; n <= VALUE; n++)
573 gtk_color_selection_update_input (colorsel->scales[n], NULL,
574 colorsel->values[n]);
575 if ((inputs & OPACITY_INPUTS) != 0)
576 gtk_color_selection_update_input(colorsel->scales[OPACITY], NULL,
577 colorsel->values[OPACITY]);
580 if ((inputs & RGB_INPUTS) != 0)
581 for (n = RED; n <= BLUE; n++)
582 gtk_color_selection_update_input (NULL, colorsel->entries[n], colorsel->values[n]);
583 if ((inputs & HSV_INPUTS) != 0)
584 for (n = HUE; n <= VALUE; n++)
585 gtk_color_selection_update_input (NULL, colorsel->entries[n], colorsel->values[n]);
586 if ((inputs & OPACITY_INPUTS) != 0)
587 gtk_color_selection_update_input(NULL, colorsel->entries[OPACITY], colorsel->values[OPACITY]);
590 if ((inputs & RGB_INPUTS) != 0)
591 for (n = RED; n <= BLUE; n++)
592 gtk_color_selection_update_input (colorsel->scales[n], colorsel->entries[n],
593 colorsel->values[n]);
594 if ((inputs & HSV_INPUTS) != 0)
595 for (n = HUE; n <= VALUE; n++)
596 gtk_color_selection_update_input (colorsel->scales[n], colorsel->entries[n],
597 colorsel->values[n]);
598 if ((inputs & OPACITY_INPUTS) != 0)
599 gtk_color_selection_update_input(colorsel->scales[OPACITY], colorsel->entries[OPACITY],
600 colorsel->values[OPACITY]);
606 gtk_color_selection_hsv_updater (GtkWidget *widget,
609 GtkColorSelection *colorsel;
612 gint i, which = SCALE;
614 if (GTK_WIDGET_DRAWABLE (GTK_WIDGET (widget)))
616 colorsel = (GtkColorSelection*) gtk_object_get_data (GTK_OBJECT (widget), "_GtkColorSelection");
617 i = (gint) gtk_object_get_data (GTK_OBJECT (widget), "_ValueIndex");
619 if (GTK_IS_SCALE (widget))
621 adj = gtk_range_get_adjustment (GTK_RANGE (GTK_SCALE (widget)));
622 newvalue = (gdouble) adj->value;
626 newvalue = (gdouble) atof (gtk_entry_get_text (GTK_ENTRY (widget)));
630 gtk_color_selection_draw_value_marker (colorsel);
631 colorsel->values[i] = newvalue;
635 gtk_color_selection_draw_value_marker (colorsel);
639 gtk_color_selection_draw_wheel_marker (colorsel);
640 colorsel->values[i] = newvalue;
644 gtk_color_selection_draw_wheel_marker (colorsel);
645 gtk_color_selection_draw_value_bar (colorsel, FALSE);
648 gtk_color_selection_draw_sample (colorsel, FALSE);
649 gtk_color_selection_color_changed (colorsel);
650 gtk_color_selection_update_inputs (colorsel, HSV_INPUTS, which);
651 gtk_color_selection_update_inputs (colorsel, RGB_INPUTS, BOTH);
656 gtk_color_selection_rgb_updater (GtkWidget *widget,
659 GtkColorSelection *colorsel;
662 gint i, which = SCALE;
664 if (GTK_WIDGET_DRAWABLE (GTK_WIDGET (widget)))
666 colorsel = (GtkColorSelection*) gtk_object_get_data (GTK_OBJECT (widget), "_GtkColorSelection");
667 i = (gint) gtk_object_get_data (GTK_OBJECT (widget), "_ValueIndex");
669 if (GTK_IS_SCALE (widget))
671 adj = gtk_range_get_adjustment (GTK_RANGE (GTK_SCALE (widget)));
672 newvalue = (gdouble) adj->value;
676 newvalue = (gdouble) atof (gtk_entry_get_text (GTK_ENTRY (widget)));
678 gtk_color_selection_draw_wheel_marker (colorsel);
680 colorsel->values[i] = newvalue;
683 gtk_color_selection_draw_wheel_marker (colorsel);
684 gtk_color_selection_draw_value_bar (colorsel, FALSE);
685 gtk_color_selection_draw_sample (colorsel, FALSE);
686 gtk_color_selection_color_changed (colorsel);
687 gtk_color_selection_update_inputs (colorsel, RGB_INPUTS, which);
688 gtk_color_selection_update_inputs (colorsel, HSV_INPUTS, BOTH);
693 gtk_color_selection_opacity_updater (GtkWidget *widget,
696 GtkColorSelection *colorsel;
699 colorsel = (GtkColorSelection*) gtk_object_get_data (GTK_OBJECT (widget), "_GtkColorSelection");
701 if (GTK_IS_SCALE (widget))
703 adj = gtk_range_get_adjustment (GTK_RANGE (widget));
704 colorsel->values[OPACITY] = (gdouble) adj->value;
705 gtk_color_selection_update_input (NULL, colorsel->entries[OPACITY], colorsel->values[OPACITY]);
709 colorsel->values[OPACITY] = (gdouble) atof (gtk_entry_get_text (GTK_ENTRY (widget)));
710 gtk_color_selection_update_input (colorsel->scales[OPACITY], NULL, colorsel->values[OPACITY]);
713 gtk_color_selection_draw_sample (colorsel, FALSE);
714 gtk_color_selection_color_changed (colorsel);
718 gtk_color_selection_set_opacity (GtkColorSelection *colorsel,
721 g_return_if_fail (colorsel != NULL);
723 colorsel->use_opacity = use_opacity;
725 if (use_opacity == FALSE && GTK_WIDGET_VISIBLE (colorsel->scales[OPACITY]))
727 gtk_widget_hide (colorsel->opacity_label);
728 gtk_widget_hide (colorsel->scales[OPACITY]);
729 gtk_widget_hide (colorsel->entries[OPACITY]);
731 else if (use_opacity == TRUE && !GTK_WIDGET_VISIBLE (colorsel->scales[OPACITY]))
733 gtk_widget_show (colorsel->opacity_label);
734 gtk_widget_show (colorsel->scales[OPACITY]);
735 gtk_widget_show (colorsel->entries[OPACITY]);
738 if (GTK_WIDGET_DRAWABLE (colorsel->sample_area))
739 gtk_color_selection_draw_sample (colorsel, FALSE);
743 gtk_color_selection_value_resize (GtkWidget *widget,
746 GtkColorSelection *colorsel;
748 colorsel = (GtkColorSelection*) gtk_object_get_data (GTK_OBJECT (widget), "_GtkColorSelection");
749 gtk_color_selection_draw_value_bar (colorsel, TRUE);
753 gtk_color_selection_wheel_resize (GtkWidget *widget,
756 GtkColorSelection *colorsel;
758 colorsel = (GtkColorSelection*) gtk_object_get_data (GTK_OBJECT (widget), "_GtkColorSelection");
759 gtk_color_selection_draw_wheel (colorsel, TRUE);
763 gtk_color_selection_sample_resize (GtkWidget *widget,
766 GtkColorSelection *colorsel;
768 colorsel = (GtkColorSelection*) gtk_object_get_data (GTK_OBJECT (widget), "_GtkColorSelection");
769 gtk_color_selection_draw_sample (colorsel, TRUE);
773 gtk_color_selection_drop_handle (GtkWidget *widget, GdkEvent *event)
776 GtkColorSelection *w;
778 g_print("Handling drop in color selection\n");
779 gtk_color_selection_set_color(GTK_COLOR_SELECTION(widget),
780 event->dropdataavailable.data);
781 g_free(event->dropdataavailable.data);
782 g_free(event->dropdataavailable.data_type);
786 gtk_color_selection_drag_handle (GtkWidget *widget, GdkEvent *event)
788 g_print("Handling drag in color selector\n");
789 gtk_widget_dnd_data_set(widget, event, GTK_COLOR_SELECTION(widget)->values,
790 sizeof(GTK_COLOR_SELECTION(widget)->values));
794 gtk_color_selection_draw_wheel_marker (GtkColorSelection *colorsel)
798 gdk_gc_set_function (colorsel->wheel_gc, GDK_INVERT);
800 xpos = (gint) ((-(gdouble) (colorsel->wheel_area->allocation.width) / 2.0) *
801 colorsel->values[SATURATION] * cos (DEGTORAD ((colorsel->values[HUE] - 90)))) +
802 (colorsel->wheel_area->allocation.width >> 1) - 4;
803 ypos = (gint) (((gdouble) (colorsel->wheel_area->allocation.height) / 2.0) *
804 colorsel->values[SATURATION] * sin (DEGTORAD ((colorsel->values[HUE] - 90)))) +
805 (colorsel->wheel_area->allocation.height >> 1) - 4;
807 gdk_draw_arc (colorsel->wheel_area->window, colorsel->wheel_gc, FALSE, xpos, ypos, 8, 8, 0, 360 * 64);
811 gtk_color_selection_draw_value_marker (GtkColorSelection *colorsel)
815 gdk_gc_set_function (colorsel->value_gc, GDK_INVERT);
817 y = (gint) ((gdouble) (colorsel->value_area->allocation.height) * (1.0 - colorsel->values[VALUE]));
818 gdk_draw_line (colorsel->value_area->window, colorsel->value_gc,
819 0, y, colorsel->value_area->allocation.width, y);
823 gtk_color_selection_update_value (GtkColorSelection *colorsel,
826 gtk_color_selection_draw_value_marker (colorsel);
830 else if (y > colorsel->value_area->allocation.height - 1)
831 y = colorsel->value_area->allocation.height - 1;
833 colorsel->values[VALUE] = 1.0 - (gdouble) y / (gdouble) (colorsel->value_area->allocation.height);
837 gtk_color_selection_draw_value_marker (colorsel);
838 gtk_color_selection_draw_sample (colorsel, FALSE);
839 gtk_color_selection_update_input (colorsel->scales[VALUE], colorsel->entries[VALUE],
840 colorsel->values[VALUE]);
841 gtk_color_selection_update_inputs (colorsel, RGB_INPUTS, BOTH);
845 gtk_color_selection_update_wheel (GtkColorSelection *colorsel,
852 gtk_color_selection_draw_wheel_marker (colorsel);
854 wid = (gdouble) (colorsel->wheel_area->allocation.width) / 2.0;
855 heig = (gdouble) (colorsel->wheel_area->allocation.height) / 2.0;
857 res = gtk_color_selection_eval_wheel (x, y, wid, heig, &colorsel->values[HUE],
858 &colorsel->values[SATURATION]);
862 gtk_color_selection_draw_wheel_marker (colorsel);
863 gtk_color_selection_draw_value_bar (colorsel, FALSE);
864 gtk_color_selection_draw_sample (colorsel, FALSE);
865 gtk_color_selection_update_inputs (colorsel, RGB_INPUTS | HSV_INPUTS, BOTH);
869 gtk_color_selection_value_timeout (GtkColorSelection *colorsel)
873 gdk_window_get_pointer (colorsel->value_area->window, &x, &y, NULL);
874 gtk_color_selection_update_value (colorsel, y);
875 gtk_color_selection_color_changed (colorsel);
881 gtk_color_selection_value_events (GtkWidget *area,
884 GtkColorSelection *colorsel;
887 colorsel = (GtkColorSelection*) gtk_object_get_data (GTK_OBJECT (area), "_GtkColorSelection");
892 gtk_color_selection_draw_value_marker (colorsel);
895 if (colorsel->value_gc == NULL)
896 colorsel->value_gc = gdk_gc_new (colorsel->value_area->window);
897 gtk_color_selection_draw_value_marker (colorsel);
899 case GDK_BUTTON_PRESS:
901 gtk_color_selection_update_value (colorsel, event->button.y);
902 gtk_color_selection_color_changed (colorsel);
904 case GDK_BUTTON_RELEASE:
905 gtk_grab_remove (area);
906 if (colorsel->timer_active == TRUE)
907 gtk_timeout_remove (colorsel->timer_tag);
908 colorsel->timer_active = FALSE;
911 if (event->button.window != area->window)
912 gdk_window_get_pointer (area->window, NULL, &y, NULL);
914 gtk_color_selection_update_value (colorsel, y);
915 gtk_color_selection_color_changed (colorsel);
917 case GDK_MOTION_NOTIFY:
920 if (event->motion.is_hint || (event->motion.window != area->window))
921 gdk_window_get_pointer (area->window, NULL, &y, NULL);
923 switch (colorsel->policy)
925 case GTK_UPDATE_CONTINUOUS:
926 gtk_color_selection_update_value (colorsel, y);
927 gtk_color_selection_color_changed (colorsel);
929 case GTK_UPDATE_DELAYED:
930 if (colorsel->timer_active == TRUE)
931 gtk_timeout_remove (colorsel->timer_tag);
933 colorsel->timer_tag = gtk_timeout_add (TIMER_DELAY,
934 (GtkFunction) gtk_color_selection_value_timeout,
935 (gpointer) colorsel);
936 colorsel->timer_active = TRUE;
950 gtk_color_selection_wheel_timeout (GtkColorSelection *colorsel)
954 gdk_window_get_pointer (colorsel->wheel_area->window, &x, &y, NULL);
955 gtk_color_selection_update_wheel (colorsel, x, y);
956 gtk_color_selection_color_changed (colorsel);
962 gtk_color_selection_wheel_events (GtkWidget *area,
965 GtkColorSelection *colorsel;
968 colorsel = (GtkColorSelection*) gtk_object_get_data (GTK_OBJECT (area), "_GtkColorSelection");
973 gtk_color_selection_draw_wheel (colorsel, TRUE);
974 gtk_color_selection_draw_wheel_marker (colorsel);
975 gtk_color_selection_draw_sample (colorsel, TRUE);
978 if (colorsel->wheel_gc == NULL)
979 colorsel->wheel_gc = gdk_gc_new (colorsel->wheel_area->window);
980 if (colorsel->sample_gc == NULL)
981 colorsel->sample_gc = gdk_gc_new (colorsel->sample_area->window);
982 if (colorsel->value_gc == NULL)
983 colorsel->value_gc = gdk_gc_new (colorsel->value_area->window);
984 gtk_color_selection_draw_wheel_marker (colorsel);
985 gtk_color_selection_draw_wheel_frame (colorsel);
987 case GDK_BUTTON_PRESS:
989 gtk_color_selection_update_wheel (colorsel, event->button.x, event->button.y);
990 gtk_color_selection_color_changed (colorsel);
992 case GDK_BUTTON_RELEASE:
993 gtk_grab_remove (area);
994 if (colorsel->timer_active == TRUE)
995 gtk_timeout_remove (colorsel->timer_tag);
996 colorsel->timer_active = FALSE;
1001 if (event->button.window != area->window)
1002 gdk_window_get_pointer (area->window, &x, &y, NULL);
1004 gtk_color_selection_update_wheel (colorsel, x, y);
1005 gtk_color_selection_color_changed (colorsel);
1007 case GDK_MOTION_NOTIFY:
1008 x = event->motion.x;
1009 y = event->motion.y;
1011 if (event->motion.is_hint || (event->motion.window != area->window))
1012 gdk_window_get_pointer (area->window, &x, &y, NULL);
1014 switch (colorsel->policy)
1016 case GTK_UPDATE_CONTINUOUS:
1017 gtk_color_selection_update_wheel (colorsel, x, y);
1018 gtk_color_selection_color_changed (colorsel);
1020 case GTK_UPDATE_DELAYED:
1021 if (colorsel->timer_active == TRUE)
1022 gtk_timeout_remove (colorsel->timer_tag);
1023 colorsel->timer_tag = gtk_timeout_add (TIMER_DELAY,
1024 (GtkFunction) gtk_color_selection_wheel_timeout,
1025 (gpointer) colorsel);
1026 colorsel->timer_active = TRUE;
1040 gtk_color_selection_draw_value_bar (GtkColorSelection *colorsel,
1043 gint x, y, i, wid, heig, n;
1044 gdouble sv, v, c[3];
1047 wid = colorsel->value_area->allocation.width;
1048 heig = colorsel->value_area->allocation.height;
1052 if (colorsel->value_buf != NULL)
1053 g_free (colorsel->value_buf);
1055 colorsel->value_buf = g_new(guchar, 3 * wid);
1059 sv = 1.0 / (gdouble) (heig - 1);
1061 for (y = 0; y < heig; y++)
1065 gtk_color_selection_hsv_to_rgb (colorsel->values[HUE],colorsel->values[SATURATION],v,
1066 &c[0], &c[1], &c[2]);
1068 for (n = 0; n < 3; n++)
1069 rc[n] = (guchar) (255.0 * c[n]);
1071 for (x = 0; x < wid; x++)
1073 for (n = 0; n < 3; n++)
1074 colorsel->value_buf[i++] = rc[n];
1077 gtk_preview_draw_row (GTK_PREVIEW (colorsel->value_area), colorsel->value_buf, 0, y, wid);
1081 gtk_widget_draw (colorsel->value_area, NULL);
1085 gtk_color_selection_draw_wheel_frame (GtkColorSelection *colorsel)
1090 style = gtk_widget_get_style (GTK_WIDGET (colorsel));
1092 w = colorsel->wheel_area->allocation.width;
1093 h = colorsel->wheel_area->allocation.height;
1095 gdk_draw_arc (colorsel->wheel_area->window, style->black_gc,
1096 FALSE, 1, 1, w - 1, h - 1, 30 * 64, 180 * 64);
1097 gdk_draw_arc (colorsel->wheel_area->window, style->mid_gc[GTK_STATE_NORMAL],
1098 FALSE, 0, 0, w, h, 30 * 64, 180 * 64);
1100 gdk_draw_arc (colorsel->wheel_area->window, style->bg_gc[GTK_STATE_NORMAL],
1101 FALSE, 1, 1, w - 1, h - 1, 210 * 64, 180 * 64);
1102 gdk_draw_arc (colorsel->wheel_area->window, style->light_gc[GTK_STATE_NORMAL],
1103 FALSE, 0, 0, w, h, 210 * 64, 180 * 64);
1107 gtk_color_selection_draw_wheel (GtkColorSelection *colorsel,
1110 gint x, y, i, wid, heig, n;
1111 gdouble cx, cy, h, s, c[3];
1113 GtkStyle *style = gtk_widget_get_style (GTK_WIDGET (colorsel));
1115 wid = colorsel->wheel_area->allocation.width;
1116 heig = colorsel->wheel_area->allocation.height;
1120 if (colorsel->wheel_buf != NULL)
1121 g_free (colorsel->wheel_buf);
1123 colorsel->wheel_buf = g_new(guchar, 3 * wid);
1126 cx = (gdouble) (wid) / 2.0;
1127 cy = (gdouble) (heig) / 2.0;
1129 bg[0] = style->bg[GTK_STATE_NORMAL].red >> 8;
1130 bg[1] = style->bg[GTK_STATE_NORMAL].green >> 8;
1131 bg[2] = style->bg[GTK_STATE_NORMAL].blue >> 8;
1133 for (y = 0; y < heig; y++)
1136 for (x = 0; x < wid; x++)
1138 if (gtk_color_selection_eval_wheel (x, y, cx, cy, &h, &s) == TRUE)
1140 for (n = 0; n < 3; n++)
1141 colorsel->wheel_buf[i++] = bg[n];
1145 gtk_color_selection_hsv_to_rgb (h, s, 1.0, &c[0], &c[1], &c[2]);
1146 for (n = 0; n < 3; n++)
1147 colorsel->wheel_buf[i++] = (guchar) (255.0 * c[n]);
1151 gtk_preview_draw_row (GTK_PREVIEW (colorsel->wheel_area), colorsel->wheel_buf, 0, y, wid);
1154 gtk_widget_draw (colorsel->wheel_area, NULL);
1158 gtk_color_selection_draw_sample (GtkColorSelection *colorsel,
1161 gint x, y, i, wid, heig, f, half, n;
1162 guchar c[3 * 2], cc[3 * 4], *cp = c;
1165 wid = colorsel->sample_area->allocation.width;
1166 heig = colorsel->sample_area->allocation.height;
1171 if (colorsel->sample_buf != NULL)
1172 g_free (colorsel->sample_buf);
1174 colorsel->sample_buf = g_new(guchar, 3 * wid);
1178 for (n = 0; n < 3; n++)
1180 c[n] = (guchar) (255.0 * colorsel->old_values[i]);
1181 c[n + 3] = (guchar) (255.0 * colorsel->values[i++]);
1184 if (colorsel->use_opacity == TRUE)
1186 o = colorsel->values[OPACITY];
1187 oldo = colorsel->old_values[OPACITY];
1189 for (n = 0; n < 3; n++)
1191 cc[n] = (guchar) ((1.0 - oldo) * 192 + (oldo * (gdouble) c[n]));
1192 cc[n + 3] = (guchar) ((1.0 - oldo) * 128 + (oldo * (gdouble) c[n]));
1193 cc[n + 6] = (guchar) ((1.0 - o) * 192 + (o * (gdouble) c[n + 3]));
1194 cc[n + 9] = (guchar) ((1.0 - o) * 128 + (o * (gdouble) c[n + 3]));
1199 for (y = 0; y < heig; y++)
1202 for (x = 0; x < wid; x++)
1204 if (colorsel->use_opacity)
1206 f = 3 * (((x % 32) < 16) ^ ((y % 32) < 16));
1207 f += (x > half) * 6;
1212 for (n = 0; n < 3; n++)
1213 colorsel->sample_buf[i++] = cp[n + f];
1216 gtk_preview_draw_row (GTK_PREVIEW (colorsel->sample_area), colorsel->sample_buf, 0, y, wid);
1219 gtk_widget_draw (colorsel->sample_area, NULL);
1223 gtk_color_selection_eval_wheel (gint x, gint y,
1224 gdouble cx, gdouble cy,
1225 gdouble *h, gdouble *s)
1227 gdouble d, r, rx, ry, l;
1229 rx = (gdouble) x - cx;
1230 ry = (gdouble) y - cy;
1232 d = (SQR (cy) * SQR (rx) + SQR (cx) * SQR (ry) - SQR (cx) * SQR (cy));
1234 r = sqrt (SQR (rx) + SQR (ry));
1237 *h = atan2 (rx / r, ry / r);
1241 l = sqrt (SQR ((cx * cos (*h + 0.5 * M_PI))) + SQR ((cy * sin (*h + 0.5 * M_PI))));
1243 *h = 360.0 * (*h) / (2.0 * M_PI) + 180;
1254 gtk_color_selection_hsv_to_rgb (gdouble h, gdouble s, gdouble v,
1255 gdouble *r, gdouble *g, gdouble *b)
1277 q = v * (1.0 - (s * f));
1278 t = v * (1.0 - (s * (1.0 - f)));
1317 gtk_color_selection_rgb_to_hsv (gdouble r, gdouble g, gdouble b,
1318 gdouble *h, gdouble *s, gdouble *v)
1320 double max, min, delta;
1337 *s = (max - min) / max;
1348 *h = (g - b) / delta;
1350 *h = 2.0 + (b - r) / delta;
1352 *h = 4.0 + (r - g) / delta;
1361 /***************************/
1362 /* GtkColorSelectionDialog */
1363 /***************************/
1366 gtk_color_selection_dialog_get_type ()
1368 static guint color_selection_dialog_type = 0;
1370 if (!color_selection_dialog_type)
1372 GtkTypeInfo colorsel_diag_info =
1374 "color selection dialog",
1375 sizeof (GtkColorSelectionDialog),
1376 sizeof (GtkColorSelectionDialogClass),
1377 (GtkClassInitFunc) gtk_color_selection_dialog_class_init,
1378 (GtkObjectInitFunc) gtk_color_selection_dialog_init,
1381 color_selection_dialog_type = gtk_type_unique (gtk_window_get_type (), &colorsel_diag_info);
1384 return color_selection_dialog_type;
1388 gtk_color_selection_dialog_class_init (GtkColorSelectionDialogClass *class)
1390 GtkObjectClass *object_class;
1392 object_class = (GtkObjectClass*) class;
1394 color_selection_dialog_parent_class = gtk_type_class (gtk_window_get_type ());
1396 object_class->destroy = gtk_color_selection_dialog_destroy;
1400 gtk_color_selection_dialog_init (GtkColorSelectionDialog *colorseldiag)
1402 GtkWidget *action_area, *frame;
1404 colorseldiag->main_vbox = gtk_vbox_new (FALSE, 10);
1405 gtk_container_border_width (GTK_CONTAINER (colorseldiag), 10);
1406 gtk_container_add (GTK_CONTAINER (colorseldiag), colorseldiag->main_vbox);
1407 gtk_widget_show (colorseldiag->main_vbox);
1409 frame = gtk_frame_new (NULL);
1410 gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN);
1411 gtk_container_add (GTK_CONTAINER (colorseldiag->main_vbox), frame);
1412 gtk_widget_show (frame);
1414 colorseldiag->colorsel = gtk_color_selection_new ();
1415 gtk_container_add (GTK_CONTAINER (frame), colorseldiag->colorsel);
1416 gtk_widget_show (colorseldiag->colorsel);
1418 action_area = gtk_hbox_new (TRUE, 10);
1419 gtk_box_pack_end (GTK_BOX (colorseldiag->main_vbox), action_area, FALSE, FALSE, 0);
1420 gtk_widget_show (action_area);
1422 colorseldiag->ok_button = gtk_button_new_with_label ("OK");
1423 GTK_WIDGET_SET_FLAGS (colorseldiag->ok_button, GTK_CAN_DEFAULT);
1424 gtk_box_pack_start (GTK_BOX (action_area), colorseldiag->ok_button, TRUE, TRUE, 0);
1425 gtk_widget_grab_default (colorseldiag->ok_button);
1426 gtk_widget_show (colorseldiag->ok_button);
1428 colorseldiag->cancel_button = gtk_button_new_with_label ("Cancel");
1429 GTK_WIDGET_SET_FLAGS (colorseldiag->cancel_button, GTK_CAN_DEFAULT);
1430 gtk_box_pack_start (GTK_BOX (action_area), colorseldiag->cancel_button, TRUE, TRUE, 0);
1431 gtk_widget_show (colorseldiag->cancel_button);
1433 colorseldiag->help_button = gtk_button_new_with_label ("Help");
1434 GTK_WIDGET_SET_FLAGS (colorseldiag->help_button, GTK_CAN_DEFAULT);
1435 gtk_box_pack_start (GTK_BOX (action_area), colorseldiag->help_button, TRUE, TRUE, 0);
1436 gtk_widget_show (colorseldiag->help_button);
1440 gtk_color_selection_dialog_new (const gchar *title)
1442 GtkColorSelectionDialog *colorseldiag;
1444 colorseldiag = gtk_type_new (gtk_color_selection_dialog_get_type ());
1445 gtk_window_set_title (GTK_WINDOW (colorseldiag), title);
1447 return GTK_WIDGET (colorseldiag);
1451 gtk_color_selection_dialog_destroy (GtkObject *object)
1453 GtkColorSelectionDialog *colorseldiag;
1455 g_return_if_fail (object != NULL);
1456 g_return_if_fail (GTK_IS_COLOR_SELECTION_DIALOG (object));
1458 colorseldiag = GTK_COLOR_SELECTION_DIALOG (object);
1461 if (GTK_OBJECT_CLASS (color_selection_dialog_parent_class)->destroy)
1462 (*GTK_OBJECT_CLASS (color_selection_dialog_parent_class)->destroy) (object);