2 * This file is a part of hildon
4 * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved.
6 * Author: Kuisma Salonen <kuisma.salonen@nokia.com>
7 * Contact: Rodrigo Novo <rodrigo.novo@nokia.com>
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public License
11 * as published by the Free Software Foundation; version 2.1 of
12 * the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
27 * SECTION:hildon-color-chooser
28 * @short_description: A widget used to select a color from an HSV colorspace.
29 * @see_also: #HildonColorChooserDialog
31 * HildonColorChooser is a widget that displays an HSV colorspace.
32 * The user can manipulate the colorspace and easily select and shade of any color
35 * Normally you should not need to use this widget directly. Using #HildonColorButton or
36 * #HildonColorChooserDialog is much more handy.
40 #undef HILDON_DISABLE_DEPRECATED
42 #include "hildon-color-chooser.h"
43 #include "hildon-color-chooser-private.h"
45 static GtkWidgetClass* parent_class = NULL;
47 /* "crosshair" is hardcoded for now */
48 static gchar crosshair[64] = { 0, 0, 0, 2, 2, 0, 0, 0,
49 0, 2, 2, 3, 3, 2, 2, 0,
50 0, 2, 3, 0, 0, 3, 2, 0,
51 2, 3, 0, 0, 0, 0, 3, 2,
52 2, 3, 0, 0, 0, 0, 3, 2,
53 0, 2, 3, 0, 0, 3, 2, 0,
54 0, 2, 2, 3, 3, 2, 2, 0,
55 0, 0, 0, 2, 2, 0, 0, 0};
58 hildon_color_chooser_init (HildonColorChooser *self);
61 hildon_color_chooser_class_init (HildonColorChooserClass *klass);
64 hildon_color_chooser_dispose (HildonColorChooser *self);
67 hildon_color_chooser_size_request (GtkWidget *widget,
71 hildon_color_chooser_size_allocate (GtkWidget *widget,
72 GtkAllocation *alloc);
75 hildon_color_chooser_realize (GtkWidget *widget);
78 hildon_color_chooser_unrealize (GtkWidget *widget);
81 hildon_color_chooser_map (GtkWidget *widget);
84 hildon_color_chooser_unmap (GtkWidget *widget);
87 hildon_color_chooser_expose (GtkWidget *widget,
88 GdkEventExpose *event);
91 hildon_color_chooser_button_press (GtkWidget *widget,
92 GdkEventButton *event);
95 hildon_color_chooser_button_release (GtkWidget *widget,
96 GdkEventButton *event);
99 hildon_color_chooser_pointer_motion (GtkWidget *widget,
100 GdkEventMotion *event);
103 get_border (GtkWidget *w,
108 init_borders (GtkWidget *w,
113 inline_clip_to_alloc (void *s,
117 inline_sub_times (GTimeVal *result,
122 inline_limited_expose (HildonColorChooser *self);
125 inline_draw_hue_bar (GtkWidget *widget,
134 inline_draw_hue_bar_dimmed (GtkWidget *widget,
143 inline_draw_sv_plane (HildonColorChooser *self,
150 inline_draw_sv_plane_dimmed (HildonColorChooser *self,
157 inline_draw_crosshair (unsigned char *buf,
164 inline_h2rgb (unsigned short hue,
168 hildon_color_chooser_expose_timer (gpointer data);
171 hildon_color_chooser_set_property (GObject *object,
177 hildon_color_chooser_get_property (GObject *object,
182 #define EXPOSE_INTERVAL 50000
184 #define FULL_COLOR8 0xff
186 #define FULL_COLOR 0x00ffffff
200 static guint color_chooser_signals [LAST_SIGNAL] = { 0 };
203 hildon_color_chooser_get_type (void)
205 static GType chooser_type = 0;
208 static const GTypeInfo chooser_info =
210 sizeof (HildonColorChooserClass),
213 (GClassInitFunc) hildon_color_chooser_class_init,
216 sizeof (HildonColorChooser),
218 (GInstanceInitFunc) hildon_color_chooser_init,
222 chooser_type = g_type_register_static (GTK_TYPE_WIDGET,
223 "HildonColorChooser",
231 hildon_color_chooser_init (HildonColorChooser *sel)
234 GTK_WIDGET_SET_FLAGS (sel, GTK_NO_WINDOW);
235 HildonColorChooserPrivate *priv = HILDON_COLOR_CHOOSER_GET_PRIVATE (sel);
242 priv->mousestate = 0;
243 priv->mousein = FALSE;
245 g_get_current_time (&priv->expose_info.last_expose_time);
247 priv->expose_info.last_expose_hue = priv->currhue;
248 priv->expose_info.expose_queued = 0;
250 priv->dimmed_plane = NULL;
251 priv->dimmed_bar = NULL;
255 hildon_color_chooser_class_init (HildonColorChooserClass *klass)
257 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
258 GObjectClass *object_class = G_OBJECT_CLASS (klass);
260 parent_class = g_type_class_peek_parent (klass);
262 object_class->dispose = (gpointer) hildon_color_chooser_dispose;
263 object_class->get_property = hildon_color_chooser_get_property;
264 object_class->set_property = hildon_color_chooser_set_property;
266 widget_class->size_request = hildon_color_chooser_size_request;
267 widget_class->size_allocate = hildon_color_chooser_size_allocate;
268 widget_class->realize = hildon_color_chooser_realize;
269 widget_class->unrealize = hildon_color_chooser_unrealize;
270 widget_class->map = hildon_color_chooser_map;
271 widget_class->unmap = hildon_color_chooser_unmap;
272 widget_class->expose_event = hildon_color_chooser_expose;
273 widget_class->button_press_event = hildon_color_chooser_button_press;
274 widget_class->button_release_event = hildon_color_chooser_button_release;
275 widget_class->motion_notify_event = hildon_color_chooser_pointer_motion;
277 gtk_widget_class_install_style_property (widget_class,
278 g_param_spec_boxed ("inner_size",
280 "Sizes of SV plane, H bar and spacing",
284 gtk_widget_class_install_style_property (widget_class,
285 g_param_spec_boxed ("outer_border",
287 "The outer border for the chooser",
291 gtk_widget_class_install_style_property (widget_class,
292 g_param_spec_boxed ("graphic_border",
294 "Size of graphical border",
299 * HildonColorChooser:color:
301 * The currently selected color.
303 g_object_class_install_property (object_class, PROP_COLOR,
304 g_param_spec_boxed ("color",
306 "The selected color",
310 color_chooser_signals[COLOR_CHANGED] = g_signal_new("color-changed",
311 G_OBJECT_CLASS_TYPE (object_class),
313 G_STRUCT_OFFSET (HildonColorChooserClass, color_changed),
316 g_cclosure_marshal_VOID__VOID,
320 g_type_class_add_private (klass, sizeof (HildonColorChooserPrivate));
324 hildon_color_chooser_dispose (HildonColorChooser *sel)
326 HildonColorChooserPrivate *priv = HILDON_COLOR_CHOOSER_GET_PRIVATE (sel);
329 if (priv->dimmed_bar != NULL) {
330 g_object_unref (priv->dimmed_bar);
331 priv->dimmed_bar = NULL;
334 if (priv->dimmed_plane != NULL) {
335 g_object_unref (priv->dimmed_plane);
336 priv->dimmed_plane = NULL;
339 G_OBJECT_CLASS (parent_class)->dispose (G_OBJECT (sel));
343 hildon_color_chooser_size_request (GtkWidget *widget,
346 GtkBorder inner, outer;
348 init_borders (widget, &inner, &outer);
350 req->width = inner.left + inner.top + inner.bottom + outer.left + outer.right;
351 req->height = inner.right + outer.top + outer.bottom;
355 hildon_color_chooser_size_allocate (GtkWidget *widget,
356 GtkAllocation *alloc)
358 HildonColorChooserPrivate *priv = HILDON_COLOR_CHOOSER_GET_PRIVATE (widget);
359 GtkBorder outer, inner;
363 widget->allocation = *alloc;
365 init_borders(widget, &inner, &outer);
367 priv->hba.height = alloc->height - outer.top - outer.bottom;
368 priv->hba.y = alloc->y + outer.top;
369 priv->hba.width = inner.top;
370 priv->hba.x = alloc->x + alloc->width - outer.right - inner.top;
372 priv->spa.x = alloc->x + outer.left;
373 priv->spa.y = alloc->y + outer.top;
374 priv->spa.height = alloc->height - outer.top - outer.bottom;
375 priv->spa.width = alloc->width - outer.left - outer.right - inner.top - inner.bottom;
377 if (GTK_WIDGET_REALIZED (widget)) {
378 gdk_window_move_resize (priv->event_window,
379 widget->allocation.x,
380 widget->allocation.y,
381 widget->allocation.width,
382 widget->allocation.height);
387 hildon_color_chooser_realize (GtkWidget *widget)
389 HildonColorChooserPrivate *priv = HILDON_COLOR_CHOOSER_GET_PRIVATE (widget);
392 GdkWindowAttr attributes;
393 gint attributes_mask;
395 attributes.x = widget->allocation.x;
396 attributes.y = widget->allocation.y;
397 attributes.width = widget->allocation.width;
398 attributes.height = widget->allocation.height;
399 attributes.wclass = GDK_INPUT_ONLY;
400 attributes.window_type = GDK_WINDOW_CHILD;
402 attributes.event_mask = gtk_widget_get_events (widget) |
403 GDK_BUTTON_PRESS_MASK |
404 GDK_BUTTON_RELEASE_MASK |
405 GDK_POINTER_MOTION_MASK |
406 GDK_POINTER_MOTION_HINT_MASK |
407 GDK_BUTTON_MOTION_MASK |
408 GDK_BUTTON1_MOTION_MASK;
410 attributes.visual = gtk_widget_get_visual (widget);
411 attributes.colormap = gtk_widget_get_colormap (widget);
413 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_WMCLASS;
414 priv->event_window = gdk_window_new (widget->parent->window, &attributes, attributes_mask);
417 gdk_window_set_user_data (priv->event_window, widget);
419 GTK_WIDGET_CLASS (parent_class)->realize (widget);
423 hildon_color_chooser_unrealize (GtkWidget *widget)
425 HildonColorChooserPrivate *priv = HILDON_COLOR_CHOOSER_GET_PRIVATE (widget);
429 if (priv->event_window) {
430 gdk_window_set_user_data (priv->event_window, NULL);
431 gdk_window_destroy (priv->event_window);
432 priv->event_window = NULL;
435 GTK_WIDGET_CLASS(parent_class)->unrealize(widget);
439 hildon_color_chooser_map (GtkWidget *widget)
441 HildonColorChooserPrivate *priv = HILDON_COLOR_CHOOSER_GET_PRIVATE (widget);
444 GTK_WIDGET_CLASS(parent_class)->map(widget);
446 if (priv->event_window) {
447 gdk_window_show (priv->event_window);
452 hildon_color_chooser_unmap (GtkWidget *widget)
454 HildonColorChooserPrivate *priv = HILDON_COLOR_CHOOSER_GET_PRIVATE (widget);
458 if (priv->event_window) {
459 gdk_window_hide (priv->event_window);
462 GTK_WIDGET_CLASS (parent_class)->unmap (widget);
466 inline_clip_to_alloc (void *s,
474 if (area->x < a->x) {
475 area->w -= a->x - area->x;
477 } if (area->y < a->y) {
478 area->h -= a->y - area->y;
481 if (area->x + area->w > a->x + a->width)
482 area->w = a->width - (area->x - a->x);
484 if (area->y + area->h > a->y + a->height)
485 area->h = a->height - (area->y - a->y);
489 hildon_color_chooser_expose (GtkWidget *widget,
490 GdkEventExpose *event)
492 HildonColorChooser *sel = HILDON_COLOR_CHOOSER (widget);
493 HildonColorChooserPrivate *priv = HILDON_COLOR_CHOOSER_GET_PRIVATE (widget);
497 GtkBorder graphical_border;
504 if(! GTK_WIDGET_REALIZED (widget)) {
508 get_border (widget, "graphic_border", &graphical_border);
510 if (event->area.width || event->area.height) {
512 gdk_draw_rectangle (widget->window,
513 widget->style->black_gc,
518 priv->hba.height + 3);
520 gdk_draw_rectangle (widget->window,
521 widget->style->black_gc,
526 priv->spa.height + 3);
529 if (priv->expose_info.expose_queued) {
530 if (GTK_WIDGET_SENSITIVE (widget)) {
531 inline_draw_hue_bar (widget, priv->hba.x, priv->hba.y, priv->hba.width, priv->hba.height, priv->hba.y, priv->hba.height);
533 inline_draw_sv_plane (sel, priv->spa.x, priv->spa.y, priv->spa.width, priv->spa.height);
535 inline_draw_hue_bar_dimmed (widget, priv->hba.x, priv->hba.y, priv->hba.width, priv->hba.height, priv->hba.y, priv->hba.height);
537 inline_draw_sv_plane_dimmed (sel, priv->spa.x, priv->spa.y, priv->spa.width, priv->spa.height);
540 priv->expose_info.expose_queued = 0;
542 g_get_current_time (&priv->expose_info.last_expose_time);
545 /* clip hue bar region */
546 area.x = event->area.x;
547 area.y = event->area.y;
548 area.w = event->area.width;
549 area.h = event->area.height;
551 inline_clip_to_alloc (&area, &priv->hba);
553 if(GTK_WIDGET_SENSITIVE (widget)) {
554 inline_draw_hue_bar (widget, area.x, area.y, area.w, area.h, priv->hba.y, priv->hba.height);
556 inline_draw_hue_bar_dimmed (widget, area.x, area.y, area.w, area.h, priv->hba.y, priv->hba.height);
559 area.x = event->area.x;
560 area.y = event->area.y;
561 area.w = event->area.width;
562 area.h = event->area.height;
564 inline_clip_to_alloc (&area, &priv->spa);
566 if (GTK_WIDGET_SENSITIVE (widget)) {
567 inline_draw_sv_plane (sel, area.x, area.y, area.w, area.h);
569 inline_draw_sv_plane_dimmed (sel, area.x, area.y, area.w, area.h);
578 inline_sub_times (GTimeVal *result,
582 result->tv_sec = greater->tv_sec - lesser->tv_sec;
583 result->tv_usec = greater->tv_usec - lesser->tv_usec;
585 if (result->tv_usec < 0) {
587 result->tv_usec += 1000000;
592 inline_limited_expose (HildonColorChooser *sel)
594 GTimeVal curr_time, result;
595 GdkEventExpose event;
596 HildonColorChooserPrivate *priv;
598 if (! GTK_WIDGET_REALIZED (GTK_WIDGET (sel))) {
602 priv = HILDON_COLOR_CHOOSER_GET_PRIVATE (sel);
605 if(priv->currhue == priv->expose_info.last_expose_hue) {
606 return; /* no need to redraw */
609 priv->expose_info.last_expose_hue = priv->currhue;
611 g_get_current_time (&curr_time);
613 inline_sub_times (&result, &curr_time, &priv->expose_info.last_expose_time);
615 if(result.tv_sec != 0 || result.tv_usec >= EXPOSE_INTERVAL) {
617 priv->expose_info.expose_queued = 1;
619 event.type = GDK_EXPOSE;
620 event.area.width = 0;
621 event.area.height = 0;
622 event.window = GTK_WIDGET(sel)->window;
624 gtk_widget_send_expose(GTK_WIDGET(sel), (GdkEvent *)&event);
626 } else if(! priv->expose_info.expose_queued) {
627 priv->expose_info.expose_queued = 1;
628 gdk_threads_add_timeout ((EXPOSE_INTERVAL - result.tv_usec) / 1000, hildon_color_chooser_expose_timer, sel);
633 hildon_color_chooser_button_press (GtkWidget *widget,
634 GdkEventButton *event)
636 HildonColorChooser *sel = HILDON_COLOR_CHOOSER (widget);
637 HildonColorChooserPrivate *priv = HILDON_COLOR_CHOOSER_GET_PRIVATE (widget);
642 x = (int) event->x + widget->allocation.x;
643 y = (int) event->y + widget->allocation.y;
645 if (x >= priv->spa.x && x <= priv->spa.x + priv->spa.width &&
646 y >= priv->spa.y && y <= priv->spa.y + priv->spa.height) {
648 tmp = y - priv->spa.y;
649 priv->currsat = tmp * 0xffff / priv->spa.height;
650 tmp = x - priv->spa.x;
651 priv->currval = tmp * 0xffff / priv->spa.width;
653 g_signal_emit (sel, color_chooser_signals[COLOR_CHANGED], 0);
654 gtk_widget_queue_draw (widget);
656 priv->mousestate = 1;
657 priv->mousein = TRUE;
659 gtk_grab_add(widget);
661 } else if (x >= priv->hba.x && x <= priv->hba.x + priv->hba.width &&
662 y >= priv->hba.y && y <= priv->hba.y + priv->hba.height) {
664 tmp = y - priv->hba.y;
665 priv->currhue = tmp * 0xffff / priv->hba.height;
667 g_signal_emit (sel, color_chooser_signals[COLOR_CHANGED], 0);
668 inline_limited_expose (sel);
670 priv->mousestate = 2;
671 priv->mousein = TRUE;
673 gtk_grab_add (widget);
680 hildon_color_chooser_button_release (GtkWidget *widget,
681 GdkEventButton *event)
683 HildonColorChooserPrivate *priv = HILDON_COLOR_CHOOSER_GET_PRIVATE (widget);
687 if (priv->mousestate) {
688 gtk_grab_remove (widget);
691 priv->mousestate = 0;
692 priv->mousein = FALSE;
698 hildon_color_chooser_pointer_motion (GtkWidget *widget,
699 GdkEventMotion *event)
701 HildonColorChooser *sel = HILDON_COLOR_CHOOSER (widget);
702 HildonColorChooserPrivate *priv = HILDON_COLOR_CHOOSER_GET_PRIVATE (widget);
708 x = (int) event->x + widget->allocation.x;
709 y = (int) event->y + widget->allocation.y;
711 if (priv->mousestate == 1) {
712 if (x >= priv->spa.x && x <= priv->spa.x + priv->spa.width &&
713 y >= priv->spa.y && y <= priv->spa.y + priv->spa.height) {
715 priv->currsat = (((long)(y - priv->spa.y)) * 0xffff) / priv->spa.height;
716 priv->currval = (((long)(x - priv->spa.x)) * 0xffff) / priv->spa.width;
718 g_signal_emit (sel, color_chooser_signals[COLOR_CHANGED], 0);
719 gtk_widget_queue_draw(widget);
721 } else if (priv->mousein == TRUE) {
724 } else if (priv->mousestate == 2) {
725 if (x >= priv->hba.x && x <= priv->hba.x + priv->hba.width &&
726 y >= priv->hba.y && y <= priv->hba.y + priv->hba.height) {
727 tmp = y - priv->hba.y;
729 tmp /= priv->hba.height;
731 if(tmp != priv->currhue) {
734 g_signal_emit (sel, color_chooser_signals[COLOR_CHANGED], 0);
735 inline_limited_expose (sel);
738 } else if (priv->mousein == TRUE) {
742 gdk_event_request_motions (event);
748 get_border (GtkWidget *w,
752 GtkBorder *tb = NULL;
754 gtk_widget_style_get (w, name, &tb, NULL);
758 gtk_border_free (tb);
768 init_borders (GtkWidget *w,
774 get_border (w, "outer_border", outer);
776 gtk_widget_style_get (w, "inner_size", &tb, NULL);
780 gtk_border_free (tb);
788 if (inner->left < 2) inner->left = 2;
789 if (inner->right < 2) inner->right = 2;
790 if (inner->top < 2) inner->top = 2;
794 * hildon_color_chooser_set_color:
795 * @chooser: a #HildonColorChooser
796 * @color: a color to be set
798 * Sets the color selected in the widget.
799 * Will move the crosshair pointer to indicate the passed color.
802 hildon_color_chooser_set_color (HildonColorChooser *chooser,
805 unsigned short hue, sat, val;
806 unsigned long min, max;
807 signed long tmp, diff;
808 HildonColorChooserPrivate *priv;
810 g_return_if_fail (HILDON_IS_COLOR_CHOOSER (chooser));
811 g_return_if_fail (color != NULL);
813 priv = HILDON_COLOR_CHOOSER_GET_PRIVATE (chooser);
817 min = MIN (MIN (color->red, color->green), color->blue);
818 max = MAX (MAX (color->red, color->green), color->blue);
823 if (val > 0 && diff != 0) {
824 sat = (diff * 0x0000ffff) / max;
826 if (color->red == max) {
827 tmp = (signed) color->green - (signed) color->blue;
834 } else if (color->green == max) {
835 hue = (((signed long) color->blue - (signed long)color->red) * 10922 / diff) + 21844;
837 hue = (((signed long) color->red -(signed long) color->green) * 10922 / diff) + 43688;
848 inline_limited_expose (chooser);
849 g_signal_emit (chooser, color_chooser_signals[COLOR_CHANGED], 0);
853 inline_h2rgb (unsigned short hue,
856 unsigned short hue_rotation, hue_value;
858 hue_rotation = hue / 10922;
859 hue_value = hue % 10922;
861 switch (hue_rotation) {
866 rgb[1] = hue_value * 6*256;
871 rgb[0] = FULL_COLOR - (hue_value * 6*256);
879 rgb[2] = hue_value * 6*256;
884 rgb[1] = FULL_COLOR - (hue_value * 6*256);
889 rgb[0] = hue_value * 6*256;
897 rgb[2] = FULL_COLOR - (hue_value * 6*256);
909 intern_h2rgb8 (unsigned short hue,
912 unsigned short hue_rotation, hue_value;
915 hue_rotation = hue / 42;
916 hue_value = hue % 42;
918 switch (hue_rotation) {
921 rgb[0] = FULL_COLOR8;
922 rgb[1] = hue_value * 6;
927 rgb[0] = FULL_COLOR8 - (hue_value * 6);
928 rgb[1] = FULL_COLOR8;
934 rgb[1] = FULL_COLOR8;
935 rgb[2] = hue_value * 6;
940 rgb[1] = FULL_COLOR8 - (hue_value * 6);
941 rgb[2] = FULL_COLOR8;
945 rgb[0] = hue_value * 6;
947 rgb[2] = FULL_COLOR8;
951 rgb[0] = FULL_COLOR8;
953 rgb[2] = FULL_COLOR8 - (hue_value * 6);
964 /* optimization: do not ask hue for each round but have bilinear vectors */
965 /* rethink: benefits from handling data 8 bit? (no shift round) */
967 inline_draw_hue_bar (GtkWidget *widget,
975 HildonColorChooserPrivate *priv = HILDON_COLOR_CHOOSER_GET_PRIVATE (widget);
977 unsigned short hvec, hcurr;
978 unsigned char *buf, *ptr, tmp[3];
982 if (w <= 0 || h <= 0) {
986 buf = (unsigned char *) g_malloc (w * h * 3);
989 hcurr = hvec * (y - sy);
993 for (i = 0; i < h; i++) {
994 intern_h2rgb8 (hcurr, tmp);
996 for (j = 0; j < w; j++) {
1007 gdk_draw_rgb_image (widget->parent->window,
1008 widget->style->fg_gc[0],
1011 GDK_RGB_DITHER_NONE, buf, w * 3);
1013 tmpy = priv->hba.y + (priv->currhue * priv->hba.height / 0xffff);
1014 gdk_draw_line (widget->parent->window, widget->style->fg_gc[GTK_WIDGET_STATE(widget)], priv->hba.x, tmpy, priv->hba.x + priv->hba.width - 1, tmpy);
1016 if ((((priv->currhue * priv->hba.height) & 0xffff) > 0x8000) && (tmpy < (priv->hba.y + priv->hba.height))) {
1017 gdk_draw_line (widget->parent->window, widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
1018 priv->hba.x, tmpy+1, priv->hba.x + priv->hba.width - 1, tmpy+1);
1019 } else if (tmpy > priv->hba.y) {
1020 gdk_draw_line(widget->parent->window, widget->style->fg_gc[GTK_WIDGET_STATE(widget)], priv->hba.x,
1021 tmpy-1, priv->hba.x + priv->hba.width - 1, tmpy-1);
1028 inline_draw_hue_bar_dimmed (GtkWidget *widget,
1036 HildonColorChooser *sel = HILDON_COLOR_CHOOSER (widget);
1037 HildonColorChooserPrivate *priv;
1039 if (w <= 0 || h <= 0) {
1043 priv = HILDON_COLOR_CHOOSER_GET_PRIVATE (sel);
1046 /* We need to create (and cache) the pixbuf if we don't
1048 if (priv->dimmed_bar == NULL) {
1050 unsigned short hvec, hcurr, avg;
1051 unsigned char *buf, *ptr, tmp[3];
1052 buf = (unsigned char *) g_malloc (w * h * 3);
1055 hcurr = hvec * (y - sy);
1058 for (i = 0; i < h; i++) {
1059 intern_h2rgb8 (hcurr, tmp);
1061 for(j = 0; j < w; j++) {
1062 avg = ((unsigned short) tmp[0]*3 + (unsigned short) tmp[1]*2 + (unsigned short) tmp[2])/6;
1063 ptr[0] = ((((i % 2) + j) % 2) == 0) ? MIN ((avg * 0.7) + 180, 255) : MIN ((avg * 0.7) + 120, 255);
1064 ptr[1] = ((((i % 2) + j) % 2) == 0) ? MIN ((avg * 0.7) + 180, 255) : MIN ((avg * 0.7) + 120, 255);
1065 ptr[2] = ((((i % 2) + j) % 2) == 0) ? MIN ((avg * 0.7) + 180, 255) : MIN ((avg * 0.7) + 120, 255);
1072 priv->dimmed_bar = gdk_pixbuf_new_from_data (buf, GDK_COLORSPACE_RGB, FALSE, 8, w, h, w * 3, (gpointer) g_free, buf);
1075 gdk_draw_pixbuf (widget->parent->window, widget->style->fg_gc [0], priv->dimmed_bar, 0, 0, x, y, w, h, GDK_RGB_DITHER_NONE, 0, 0);
1079 inline_draw_crosshair (unsigned char *buf,
1087 /* bad "clipping", clip the loop to save cpu */
1088 for(i = 0; i < 8; i++) {
1089 for(j = 0; j < 8; j++) {
1090 sx = j + x; sy = i + y;
1092 if (sx >= 0 && sx < w && sy >= 0 && sy < h) {
1093 if (crosshair[j + 8*i]) {
1094 if (crosshair[j + 8*i] & 0x1) {
1095 buf[(sx)*3+(sy)*w*3+0] = 255;
1096 buf[(sx)*3+(sy)*w*3+1] = 255;
1097 buf[(sx)*3+(sy)*w*3+2] = 255;
1099 buf[(sx)*3+(sy)*w*3+0] = 0;
1100 buf[(sx)*3+(sy)*w*3+1] = 0;
1101 buf[(sx)*3+(sy)*w*3+2] = 0;
1110 inline_draw_sv_plane (HildonColorChooser *sel,
1116 GtkWidget *widget = GTK_WIDGET (sel);
1117 unsigned char *buf, *ptr;
1118 unsigned long rgbx[3] = { 0x00ffffff, 0x00ffffff, 0x00ffffff }, rgbtmp[3];
1119 signed long rgby[3];
1120 HildonColorChooserPrivate *priv;
1124 if (w <= 0 || h <= 0) {
1128 priv = HILDON_COLOR_CHOOSER_GET_PRIVATE (sel);
1130 tmp = priv->spa.width * priv->spa.height;
1132 buf = (unsigned char *) g_malloc (w * h * 3);
1135 inline_h2rgb (priv->currhue, rgbtmp);
1137 rgby[0] = rgbtmp[0] - rgbx[0];
1138 rgby[1] = rgbtmp[1] - rgbx[1];
1139 rgby[2] = rgbtmp[2] - rgbx[2];
1141 rgbx[0] /= priv->spa.width;
1142 rgbx[1] /= priv->spa.width;
1143 rgbx[2] /= priv->spa.width;
1149 rgbx[0] += (y - priv->spa.y) * rgby[0];
1150 rgbx[1] += (y - priv->spa.y) * rgby[1];
1151 rgbx[2] += (y - priv->spa.y) * rgby[2];
1153 for(i = 0; i < h; i++) {
1154 rgbtmp[0] = rgbx[0] * (x - priv->spa.x);
1155 rgbtmp[1] = rgbx[1] * (x - priv->spa.x);
1156 rgbtmp[2] = rgbx[2] * (x - priv->spa.x);
1158 for(j = 0; j < w; j++) {
1159 ptr[0] = rgbtmp[0] >> 16;
1160 ptr[1] = rgbtmp[1] >> 16;
1161 ptr[2] = rgbtmp[2] >> 16;
1162 rgbtmp[0] += rgbx[0];
1163 rgbtmp[1] += rgbx[1];
1164 rgbtmp[2] += rgbx[2];
1173 inline_draw_crosshair (buf,
1174 (priv->spa.width * priv->currval / 0xffff) - x + priv->spa.x - 4,
1175 (priv->spa.height * priv->currsat / 0xffff) - y + priv->spa.y - 4,
1178 gdk_draw_rgb_image (widget->parent->window, widget->style->fg_gc[0], x, y, w, h, GDK_RGB_DITHER_NONE, buf, w * 3);
1183 inline_draw_sv_plane_dimmed (HildonColorChooser *sel,
1189 GtkWidget *widget = GTK_WIDGET (sel);
1190 HildonColorChooserPrivate *priv = HILDON_COLOR_CHOOSER_GET_PRIVATE (sel);
1194 if (w <= 0 || h <= 0) {
1198 /* We need to create (and cache) the pixbuf if we don't
1200 if (priv->dimmed_plane == NULL) {
1201 unsigned char *buf, *ptr;
1202 unsigned long rgbx[3] = { 0x00ffffff, 0x00ffffff, 0x00ffffff }, rgbtmp[3];
1204 signed long rgby[3];
1205 int tmp = priv->spa.width * priv->spa.height, i, j;
1207 buf = (unsigned char *) g_malloc (w * h * 3);
1211 /* possibe optimization: as we are drawing grayscale plane, there might
1212 be some simpler algorithm to do this*/
1213 rgbtmp[0] = 0x00ffffff;
1214 rgbtmp[1] = 0x00000000;
1215 rgbtmp[2] = 0x00000000;
1217 rgby[0] = rgbtmp[0] - rgbx[0];
1218 rgby[1] = rgbtmp[1] - rgbx[1];
1219 rgby[2] = rgbtmp[2] - rgbx[2];
1221 rgbx[0] /= priv->spa.width;
1222 rgbx[1] /= priv->spa.width;
1223 rgbx[2] /= priv->spa.width;
1229 rgbx[0] += (y - priv->spa.y) * rgby[0];
1230 rgbx[1] += (y - priv->spa.y) * rgby[1];
1231 rgbx[2] += (y - priv->spa.y) * rgby[2];
1233 for(i = 0; i < h; i++) {
1234 rgbtmp[0] = rgbx[0] * (x - priv->spa.x);
1235 rgbtmp[1] = rgbx[1] * (x - priv->spa.x);
1236 rgbtmp[2] = rgbx[2] * (x - priv->spa.x);
1238 for(j = 0; j < w; j++) {
1239 avg = (rgbtmp[0] + rgbtmp[1] + rgbtmp[2])/3;
1241 ptr[0] = ((((i % 2) + j) % 2) == 0) ? MIN ((avg * 0.7) + 180, 255) : MIN ((avg * 0.7) + 120, 255);
1242 ptr[1] = ((((i % 2) + j) % 2) == 0) ? MIN ((avg * 0.7) + 180, 255) : MIN ((avg * 0.7) + 120, 255);
1243 ptr[2] = ((((i % 2) + j) % 2) == 0) ? MIN ((avg * 0.7) + 180, 255) : MIN ((avg * 0.7) + 120, 255);
1244 rgbtmp[0] += rgbx[0];
1245 rgbtmp[1] += rgbx[1];
1246 rgbtmp[2] += rgbx[2];
1255 priv->dimmed_plane = gdk_pixbuf_new_from_data (buf, GDK_COLORSPACE_RGB, FALSE, 8, w, h, w * 3, (gpointer) g_free, buf);
1258 gdk_draw_pixbuf (widget->parent->window, widget->style->fg_gc [0], priv->dimmed_plane, 0, 0, x, y, w, h, GDK_RGB_DITHER_NONE, 0, 0);
1263 hildon_color_chooser_expose_timer (gpointer data)
1265 HildonColorChooser *sel = HILDON_COLOR_CHOOSER (data);
1266 HildonColorChooserPrivate *priv = HILDON_COLOR_CHOOSER_GET_PRIVATE (sel);
1270 if (priv->expose_info.expose_queued) {
1271 gtk_widget_queue_draw (GTK_WIDGET (data));
1278 * hildon_color_chooser_get_color:
1279 * @chooser: a #HildonColorChooser
1280 * @color: a color structure to fill with the currently selected color
1282 * Retrives the currently selected color in the chooser.
1286 hildon_color_chooser_get_color (HildonColorChooser *chooser,
1289 HildonColorChooserPrivate *priv;
1290 GdkVisual *system_visual = gdk_visual_get_system ();
1291 unsigned long rgb[3], rgb2[3];
1293 g_return_if_fail (HILDON_IS_COLOR_CHOOSER (chooser));
1294 g_return_if_fail (color != NULL);
1296 priv = HILDON_COLOR_CHOOSER_GET_PRIVATE (chooser);
1299 inline_h2rgb (priv->currhue, rgb);
1301 rgb2[0] = 0xffffff - rgb[0];
1302 rgb2[1] = 0xffffff - rgb[1];
1303 rgb2[2] = 0xffffff - rgb[2];
1305 color->red = ((rgb[0] >> 8) + ((rgb2[0] >> 8) * (0xffff - priv->currsat) / 0xffff)) * priv->currval / 0xffff;
1306 color->green = ((rgb[1] >> 8) + ((rgb2[1] >> 8) * (0xffff - priv->currsat) / 0xffff)) * priv->currval / 0xffff;
1307 color->blue = ((rgb[2] >> 8) + ((rgb2[2] >> 8) * (0xffff - priv->currsat) / 0xffff)) * priv->currval / 0xffff;
1309 color->pixel = ((color->red >> (16 - system_visual->red_prec)) << system_visual->red_shift) |
1310 ((color->green >> (16 - system_visual->green_prec)) << system_visual->green_shift) |
1311 ((color->blue >> (16 - system_visual->blue_prec)) << system_visual->blue_shift);
1315 * hildon_color_chooser_new:
1317 * Creates a new #HildonColorChooser.
1319 * Returns: the new #HildonColorChooser
1322 hildon_color_chooser_new (void)
1324 return (GtkWidget *) g_object_new (HILDON_TYPE_COLOR_CHOOSER, NULL);
1328 hildon_color_chooser_set_property (GObject *object,
1330 const GValue *value,
1333 g_return_if_fail (HILDON_IS_COLOR_CHOOSER (object));
1339 GdkColor *color = g_value_get_boxed (value);
1340 hildon_color_chooser_set_color ((HildonColorChooser *) object, color);
1344 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
1350 hildon_color_chooser_get_property (GObject *object,
1355 g_return_if_fail (HILDON_IS_COLOR_CHOOSER (object));
1362 hildon_color_chooser_get_color ((HildonColorChooser *) object, &color);
1363 g_value_set_boxed (value, &color);
1367 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);