latest update
[hildon] / hildon-widgets / hildon-color-selector.c
1 /*
2  * This file is part of hildon-libs
3  *
4  * Copyright (C) 2005 Nokia Corporation.
5  *
6  * Contact: Luc Pionchon <luc.pionchon@nokia.com>
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public License
10  * as published by the Free Software Foundation; either version 2.1 of
11  * the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21  * 02110-1301 USA
22  *
23  */
24
25 /*
26  * @file hildon-color-selector.c
27  *
28  * This file contains the implementation of Hildon Color Selector
29  * widget containing the base color and custom color palette selector 
30  * and popup for selecting different colors based on RGB values.
31  */
32
33 #ifdef HAVE_CONFIG_H
34 #include <config.h>
35 #endif
36
37 #include <gtk/gtktable.h>
38 #include <gtk/gtkhbox.h>
39 #include <gtk/gtklabel.h>
40 #include <gtk/gtkdrawingarea.h>
41 #include <gtk/gtkbutton.h>
42 #include <gdk/gdkkeysyms.h>
43 #include <gconf/gconf-client.h> 
44
45 #include "hildon-color-selector.h"
46 #include "hildon-color-popup.h"
47
48 #include <libintl.h>
49 #define _(String) dgettext(PACKAGE, String)
50
51 /* Color amounts */
52 #define HILDON_BASE_COLOR_NUM             16
53 #define HILDON_CUSTOM_COLOR_NUM            8
54 #define HILDON_TOTAL_COLOR_NUM \
55   (HILDON_BASE_COLOR_NUM + HILDON_CUSTOM_COLOR_NUM)
56 #define BLACKIND                           0
57 #define GREYIND                            6
58 #define WHITEIND                           9
59
60 /* Pixel sizes */
61 #define HILDON_COLOR_SELECTOR_BOX_W       27
62 #define HILDON_COLOR_SELECTOR_BOX_H       27
63 #define HILDON_COLOR_SELECTOR_BOX_BORDER   2
64 #define HILDON_COLOR_SELECTOR_COLS         8
65 #define HILDON_COLOR_SELECTOR_ROWS         3
66 #define HILDON_COLOR_PALETTE_SIZE        120
67 #define HILDON_COLOR_CONTROLBAR_MAX       31
68 #define HILDON_COLOR_CONTROLBAR_MIN        0 
69 #define HILDON_COLOR_LABELS_LEFT_PAD      35
70 #define HILDON_COLOR_PALETTE_POS_PAD      45
71 #define HILDON_COLOR_BAR_WIDTH 449
72
73 /* gconf definitions */
74 #define HILDON_COLOR_GCONF_PATH  "/system/osso/af/color_selector"
75 #define HILDON_COLOR_GCONF_KEYS  "/system/osso/af/color_selector/custom_colors"
76 /*
77  * Pointer parent class 
78  */
79 static GtkDialogClass *parent_class;
80
81 struct _HildonColorSelectorPriv 
82 {
83     GConfClient *client;
84     GtkWidget *drawing_area;
85     GtkWidget *modify_button;
86     gint index;
87     guint notify_id;
88
89     /* one extra place for the modified base color */
90     GdkColor color[HILDON_TOTAL_COLOR_NUM + 1];
91 };
92
93 /* 
94  * Private function prototype definitions 
95  */
96 static void
97 hildon_color_selector_class_init (HildonColorSelectorClass * selector_class);
98
99 static void 
100 hildon_color_selector_init (HildonColorSelector * selector);
101
102 static gboolean
103 hildon_color_selector_expose (GtkWidget * widget,
104                               GdkEventExpose * event, 
105                               gpointer data);
106
107 static gboolean 
108 key_pressed (GtkWidget * widget, 
109              GdkEventKey * event);
110
111 static gboolean 
112 color_pressed (GtkWidget * widget, 
113                GdkEventButton * event, 
114                gpointer user_data);
115
116 static void
117 select_color (HildonColorSelector * selector, 
118               int event_x, 
119               int event_y,
120               gboolean motion);
121
122 static gboolean
123 color_moved (GtkWidget * widget, 
124              GdkEventMotion * event, 
125              gpointer data);
126
127 static void
128 modify_button_clicked (GtkWidget * button,
129                        HildonColorSelector * selector);
130
131 static void
132 modify_selected(HildonColorSelector * colselector);
133
134 GType
135 hildon_color_selector_get_type(void)
136 {
137     static GType selector_type = 0;
138
139     if (!selector_type) 
140     {
141         static const GTypeInfo selector_info = 
142             {
143                 sizeof(HildonColorSelectorClass),
144                 NULL,       /* base_init */
145                 NULL,       /* base_finalize */
146                 (GClassInitFunc) hildon_color_selector_class_init,
147                 NULL,       /* class_finalize */
148                 NULL,       /* class_data */
149                 sizeof(HildonColorSelector),
150                 0,  /* n_preallocs */
151                 (GInstanceInitFunc) hildon_color_selector_init,
152             };
153         selector_type = g_type_register_static(GTK_TYPE_DIALOG,
154                                                "HildonColorSelector",
155                                                &selector_info, 0);
156     }
157     return selector_type;
158 }
159
160 static void
161 hildon_color_selector_destroy(GtkObject *obj)
162 {
163   HildonColorSelectorPriv *priv = HILDON_COLOR_SELECTOR(obj)->priv;
164
165   if (priv->client)
166   {
167     gconf_client_notify_remove(priv->client, priv->notify_id);
168     g_object_unref(priv->client);
169     priv->client = NULL;
170   }
171
172   GTK_OBJECT_CLASS(parent_class)->destroy(obj);
173 }
174
175 static void
176 hildon_color_selector_class_init(HildonColorSelectorClass * selector_class)
177 {
178     GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(selector_class);
179
180     parent_class = g_type_class_peek_parent(selector_class);
181
182     widget_class->key_press_event = key_pressed;
183
184     g_type_class_add_private(selector_class,
185                              sizeof(HildonColorSelectorPriv));
186
187     GTK_OBJECT_CLASS(selector_class)->destroy = hildon_color_selector_destroy;
188 }
189
190
191 /**
192  * hildon_color_selector_new:
193  * @parent:  The parent window. The X window ID of the parent window
194  *           has to be the same as the X window ID of the application.
195  * @returns: new #HildonColorSelector.
196  *
197  * Creates a new #HildonColorSelector dialog with 3x8 layout of 
198  * Windows base colors and 'OK', 'More..' and 'Cancel' buttons.
199  **/
200 GtkWidget *hildon_color_selector_new(GtkWindow * parent)
201 {
202     GtkWidget *dialog = g_object_new(HILDON_TYPE_COLOR_SELECTOR, NULL);
203
204     g_assert(dialog);
205
206     if (parent) 
207     {
208         gtk_window_set_transient_for(GTK_WINDOW(dialog), parent);
209     }
210
211     return dialog;
212 }
213
214 static void
215 hildon_color_selector_set_custom_colors(
216   HildonColorSelector *selector,
217   GConfValue *value)
218 {
219   GSList *list;
220   int i;
221
222   g_assert(HILDON_IS_COLOR_SELECTOR(selector));
223
224   /* We have to be really carefull. At least gconftool's
225      stress test may generate unexpected value setups */
226   if (value == NULL || value->type != GCONF_VALUE_LIST ||
227     gconf_value_get_list_type(value) != GCONF_VALUE_STRING)
228     list = NULL;
229   else
230     list = gconf_value_get_list(value);
231
232   for ( i = 0; i < HILDON_CUSTOM_COLOR_NUM; ++i)
233   {
234     const gchar *color_string = NULL;
235
236     if (list) {
237       color_string = gconf_value_get_string(list->data);
238       list = list->next;
239     } else {
240       color_string = "#FFFFFF";
241     }
242
243 /*    g_print("custom_color: %s\n", color_string);  */
244
245     selector->priv->color[i].pixel = 0;
246     gdk_color_parse (color_string, 
247        &(selector->priv->color[HILDON_BASE_COLOR_NUM+i]));
248   }
249 }
250
251 static void
252 gconf_notify_func(GConfClient *client,
253                              guint cnxn_id,
254                              GConfEntry *entry,
255                              gpointer data)
256 {
257   hildon_color_selector_set_custom_colors(HILDON_COLOR_SELECTOR(data), 
258     gconf_entry_get_value(entry));
259   gtk_widget_queue_draw(GTK_WIDGET(data));
260 }
261
262 static void 
263 hildon_color_selector_init(HildonColorSelector * selector)
264 {
265     guint i;
266     GtkWidget *hbox;
267     GConfValue *value;
268
269     /* 16 standard Windows colors */
270     static char *base_colours[HILDON_BASE_COLOR_NUM] = {
271         "#000000", "#FFFFFF", "#FF0000", "#660000", "#0000FF", "#000066",
272         "#FF33FF", "#660066", "#33CC33", "#006600", "#FFCC00", "#CC9900",
273         "#999999", "#666666", "#00CCCC", "#006666"
274     };
275
276     selector->priv =
277         G_TYPE_INSTANCE_GET_PRIVATE(selector,
278                                     HILDON_TYPE_COLOR_SELECTOR,
279                                     HildonColorSelectorPriv);
280     
281     /*  ***********test GConf***********   */
282     selector->priv->client = gconf_client_get_default ();
283     gconf_client_set_error_handling (selector->priv->client, 
284       GCONF_CLIENT_HANDLE_UNRETURNED);
285     
286     /* Add our directory to the list of directories the GConfClient will
287        watch. */
288     gconf_client_add_dir (selector->priv->client, HILDON_COLOR_GCONF_PATH,
289                               GCONF_CLIENT_PRELOAD_NONE,
290                               NULL);
291     
292     value = gconf_client_get(selector->priv->client, 
293       HILDON_COLOR_GCONF_KEYS, NULL);    
294
295     hildon_color_selector_set_custom_colors(selector, value);    
296
297     if (value) {
298       gconf_value_free(value);
299     }
300     
301     /* Listen to changes to our key. */
302     selector->priv->notify_id = gconf_client_notify_add (selector->priv->client, 
303         HILDON_COLOR_GCONF_KEYS, gconf_notify_func, selector, NULL, NULL); 
304
305     /* ************************************  */
306
307     selector->priv->index = GREYIND;
308     
309     /* init base colors for color boxes */
310     for (i = 0; i < HILDON_BASE_COLOR_NUM; ++i) 
311     {
312         selector->priv->color[i].pixel = 0;
313         gdk_color_parse (base_colours[i], &(selector->priv->color[i]));
314     }
315     
316     gtk_dialog_set_has_separator(GTK_DIALOG(selector), FALSE);
317
318     /* create drawing area */
319     hbox = gtk_hbox_new(TRUE, 0);
320     selector->priv->drawing_area = gtk_drawing_area_new();
321     
322     /* receive focus from dialog buttons */
323     GTK_WIDGET_SET_FLAGS (selector->priv->drawing_area, GTK_CAN_FOCUS);
324
325     gtk_widget_add_events (selector->priv->drawing_area,
326                           GDK_BUTTON_PRESS_MASK | GDK_POINTER_MOTION_MASK);
327
328     gtk_widget_set_size_request (selector->priv->drawing_area,
329                                  (HILDON_COLOR_SELECTOR_BOX_W *
330                                   HILDON_COLOR_SELECTOR_COLS) +
331                                  (HILDON_COLOR_SELECTOR_BOX_BORDER *
332                                   2*HILDON_COLOR_SELECTOR_COLS),
333                                  (HILDON_COLOR_SELECTOR_BOX_H *
334                                   HILDON_COLOR_SELECTOR_ROWS) +
335                                  HILDON_COLOR_SELECTOR_BOX_BORDER *
336                                  2 * HILDON_COLOR_SELECTOR_ROWS);
337
338     gtk_box_pack_start (GTK_BOX(GTK_DIALOG(selector)->vbox), 
339                        hbox, FALSE, FALSE, 0);
340     gtk_box_pack_start (GTK_BOX(hbox), selector->priv->drawing_area,
341                        FALSE, FALSE, 0);
342
343     g_signal_connect (selector->priv->drawing_area, "expose_event",
344                       G_CALLBACK(hildon_color_selector_expose), selector);
345     g_signal_connect (selector->priv->drawing_area, "button_press_event", 
346                       G_CALLBACK(color_pressed), selector);
347     g_signal_connect (selector->priv->drawing_area, "motion-notify-event", 
348                       G_CALLBACK(color_moved), selector);
349
350     gtk_dialog_add_button (GTK_DIALOG(selector), 
351                            _("ecdg_bd_colour_selector_ok"), GTK_RESPONSE_OK);
352
353     selector->priv->modify_button =
354         gtk_button_new_with_label(_("ecdg_bd_colour_selector_modify"));
355     gtk_widget_set_sensitive(selector->priv->modify_button, FALSE);
356     gtk_box_pack_start(GTK_BOX(GTK_DIALOG(selector)->action_area),
357                        selector->priv->modify_button, FALSE, TRUE, 0);
358
359     g_signal_connect(selector->priv->modify_button, "clicked",
360                      G_CALLBACK(modify_button_clicked), selector);
361
362     gtk_dialog_add_button (GTK_DIALOG(selector),
363                            _("ecdg_bd_colour_selector_cancel"),
364                            GTK_RESPONSE_CANCEL);
365
366     gtk_dialog_set_default_response (GTK_DIALOG(selector), GTK_RESPONSE_OK);
367     
368     gtk_window_set_title ( GTK_WINDOW(selector),  
369                           _("ecdg_ti_colour_selector") );
370     gtk_widget_show_all (GTK_DIALOG(selector)->vbox);
371 }
372
373 static gboolean 
374 hildon_color_selector_expose(GtkWidget * widget,
375                              GdkEventExpose * event,
376                              gpointer data)
377 {
378     HildonColorSelector *selector;
379     GdkColor color;
380     GdkGC *gc;
381     gint x, y;
382
383     g_return_val_if_fail (GTK_IS_WIDGET(widget), FALSE);
384     g_return_val_if_fail (event, FALSE);
385     g_return_val_if_fail (HILDON_IS_COLOR_SELECTOR(data), FALSE);
386
387     if (!GTK_WIDGET_DRAWABLE(widget))
388       return FALSE;
389
390     selector = HILDON_COLOR_SELECTOR(data);
391     gc = gdk_gc_new (widget->window); 
392
393     /* draw the color boxes and a focus for one of them */
394     for (x = 0; x < HILDON_COLOR_SELECTOR_COLS; ++x) 
395     {
396         for (y = 0; y < HILDON_COLOR_SELECTOR_ROWS; ++y) 
397         {
398             color.pixel = color.red = color.green = color.blue = 0;
399             gdk_gc_set_rgb_fg_color(gc, &color);
400
401             /* focus around the selected color box */
402             if ( (y * HILDON_COLOR_SELECTOR_COLS + x) ==
403                  selector->priv->index) 
404             {
405                 /* focus box */
406                 gdk_draw_rectangle(widget->window, gc, TRUE,
407                                    (HILDON_COLOR_SELECTOR_BOX_BORDER * 2 +
408                                     HILDON_COLOR_SELECTOR_BOX_W) * x,
409                                    (HILDON_COLOR_SELECTOR_BOX_BORDER * 2 +
410                                     HILDON_COLOR_SELECTOR_BOX_H) * y,
411                                    HILDON_COLOR_SELECTOR_BOX_W +
412                                    HILDON_COLOR_SELECTOR_BOX_BORDER * 2,
413                                    HILDON_COLOR_SELECTOR_BOX_H +
414                                    HILDON_COLOR_SELECTOR_BOX_BORDER * 2); 
415             }
416             
417             /* frames on color box */
418             gdk_draw_rectangle(widget->window, gc, FALSE,
419                                (HILDON_COLOR_SELECTOR_BOX_BORDER * 2 +
420                                 HILDON_COLOR_SELECTOR_BOX_W) * x + 1,
421                                (HILDON_COLOR_SELECTOR_BOX_BORDER * 2 +
422                                 HILDON_COLOR_SELECTOR_BOX_H) * y + 1,
423                                HILDON_COLOR_SELECTOR_BOX_W + 1,
424                                HILDON_COLOR_SELECTOR_BOX_H + 1);
425             
426             gdk_gc_set_rgb_fg_color(gc, 
427               &(selector->priv->color[y * HILDON_COLOR_SELECTOR_COLS + x]));
428
429             /* color box */
430             gdk_draw_rectangle(widget->window, gc,
431                                TRUE,    /* filled */
432                                HILDON_COLOR_SELECTOR_BOX_BORDER +
433                                (HILDON_COLOR_SELECTOR_BOX_BORDER * 2 +
434                                 HILDON_COLOR_SELECTOR_BOX_W) * x,
435                                HILDON_COLOR_SELECTOR_BOX_BORDER +
436                                (HILDON_COLOR_SELECTOR_BOX_BORDER * 2 +
437                                 HILDON_COLOR_SELECTOR_BOX_H) * y,
438                                HILDON_COLOR_SELECTOR_BOX_W,
439                                HILDON_COLOR_SELECTOR_BOX_H);
440         }
441     }
442
443     g_object_unref(gc);
444     return TRUE;
445 }
446
447 /**
448  * hildon_color_selector_get_color:
449  * @selector: a #HildonColorSelector
450  * 
451  * Gets the currently selected base color as #GdkColor.
452  * 
453  * Returns: A copy of the currently selected #GdkColor.
454  */
455 GdkColor *hildon_color_selector_get_color(HildonColorSelector * selector)
456 {
457     g_return_val_if_fail(HILDON_IS_COLOR_SELECTOR(selector), NULL);    
458     return &(selector->priv->color[selector->priv->index]);
459 }
460
461 /**
462  * hildon_color_selector_set_color:
463  * @selector: #HildonColorSelector
464  * @color: #Gdkcolor to set.
465  * 
466  * Select the color specified. Does nothing if the color does not 
467  * exists among the standard colors.
468  */
469 void hildon_color_selector_set_color(HildonColorSelector * selector,
470                                      GdkColor * color)
471 {
472     gint i;
473
474     g_return_if_fail(HILDON_IS_COLOR_SELECTOR(selector));
475     g_return_if_fail(color);
476
477     for (i = 0; 
478          i < (HILDON_BASE_COLOR_NUM + HILDON_CUSTOM_COLOR_NUM);
479          ++i) 
480     {
481         if (selector->priv->color[i].red   == color->red &&
482             selector->priv->color[i].green == color->green &&
483             selector->priv->color[i].blue  == color->blue) 
484         {
485             selector->priv->index = i;
486             gtk_widget_set_sensitive(selector->priv->modify_button,
487                                      selector->priv->index >= HILDON_BASE_COLOR_NUM);
488             gtk_widget_queue_draw(selector->priv->drawing_area);
489             break;
490         }
491     }
492 }
493
494 static gboolean
495 color_pressed(GtkWidget * widget, GdkEventButton * event,
496               gpointer user_data)
497 {
498     select_color(HILDON_COLOR_SELECTOR(user_data), event->x, event->y, FALSE);
499     return TRUE;
500 }
501
502 static gboolean key_pressed(GtkWidget * widget,
503                             GdkEventKey * event)
504 {
505     HildonColorSelector *selector;
506     gint index;
507
508     g_return_val_if_fail(widget, FALSE);
509
510     selector = HILDON_COLOR_SELECTOR(widget);
511     index = selector->priv->index;
512
513     /* if dialog buttons has the focus */
514     if (GTK_WIDGET_HAS_FOCUS(selector->priv->drawing_area) == FALSE)
515         return GTK_WIDGET_CLASS(parent_class)->key_press_event(widget, event);
516
517     /* go for if available index otherwise stop keypress handler because
518        wrapping around is not allowed. */
519     switch (event->keyval) {
520     case GDK_KP_Right:
521     case GDK_Right:
522         if (index == (HILDON_BASE_COLOR_NUM + HILDON_CUSTOM_COLOR_NUM - 1)
523             || index == (HILDON_CUSTOM_COLOR_NUM - 1)
524             || index == (2*HILDON_CUSTOM_COLOR_NUM - 1)) 
525         {
526             return TRUE;
527         }
528         index++;
529         break;
530     case GDK_KP_Left:
531     case GDK_Left:
532         if (index == 0 
533             || index == (HILDON_CUSTOM_COLOR_NUM)
534             || index == (2*HILDON_CUSTOM_COLOR_NUM)) 
535         {
536             return TRUE;
537         }
538         index--;
539         break;
540     case GDK_KP_Up:
541     case GDK_Up:
542         if (index > (HILDON_COLOR_SELECTOR_COLS - 1)) 
543         {
544             index -= HILDON_COLOR_SELECTOR_COLS;
545         } 
546         else 
547         {
548             return GTK_WIDGET_CLASS(parent_class)->key_press_event(widget, event);
549         }
550         break;
551     case GDK_KP_Down:
552     case GDK_Down:
553         if (index < (HILDON_COLOR_SELECTOR_COLS + HILDON_CUSTOM_COLOR_NUM)) 
554         {
555             index += HILDON_COLOR_SELECTOR_COLS;  
556         } 
557         else 
558         {
559             return GTK_WIDGET_CLASS(parent_class)->key_press_event(widget, event);
560         }
561         break;
562     case GDK_KP_Enter:
563     case GDK_Return:
564         if (index < HILDON_BASE_COLOR_NUM)
565             return GTK_WIDGET_CLASS(parent_class)->key_press_event(widget, event);
566
567         modify_selected(selector);
568     default:
569         return GTK_WIDGET_CLASS(parent_class)->key_press_event(widget, event);
570     }
571
572     if (index < (HILDON_BASE_COLOR_NUM + HILDON_CUSTOM_COLOR_NUM)) 
573     {
574         selector->priv->index = index;
575     } 
576     else 
577     {
578         selector->priv->index = 
579             HILDON_BASE_COLOR_NUM + HILDON_CUSTOM_COLOR_NUM - 1;
580     }
581     gtk_widget_set_sensitive(selector->priv->modify_button,
582                              selector->priv->index >= HILDON_BASE_COLOR_NUM);
583
584     gtk_widget_queue_draw(selector->priv->drawing_area);
585     
586     return TRUE;
587 }
588
589 static void
590 select_color(HildonColorSelector * selector, int event_x, int event_y,
591              gboolean motion)
592 {
593     gint x, y;
594
595     g_return_if_fail(HILDON_IS_COLOR_SELECTOR(selector));
596
597     x = ( (event_x - HILDON_COLOR_SELECTOR_BOX_BORDER) /
598           (HILDON_COLOR_SELECTOR_BOX_BORDER * 2 +
599            HILDON_COLOR_SELECTOR_BOX_W)
600         );
601     y = ( (event_y -
602            HILDON_COLOR_SELECTOR_BOX_BORDER) /
603           (HILDON_COLOR_SELECTOR_BOX_BORDER * 2 +
604            HILDON_COLOR_SELECTOR_BOX_H)
605         );
606
607     if (x > (HILDON_COLOR_SELECTOR_COLS + HILDON_CUSTOM_COLOR_NUM - 1)) 
608     {
609         x = HILDON_COLOR_SELECTOR_COLS + HILDON_CUSTOM_COLOR_NUM - 1;
610     } 
611     else if (x < 0) 
612     {
613         x = 0;
614     }
615     if (y > (HILDON_COLOR_SELECTOR_ROWS - 1)) 
616     {
617         y = HILDON_COLOR_SELECTOR_ROWS - 1;
618     } 
619     else if (y < 0) 
620     {
621         y = 0;
622     }
623
624     if (!motion &&
625         selector->priv->index >= HILDON_BASE_COLOR_NUM &&
626         selector->priv->index == (x + y * HILDON_COLOR_SELECTOR_COLS))
627         modify_selected(selector);
628
629     selector->priv->index = (x + y * HILDON_COLOR_SELECTOR_COLS);
630     gtk_widget_set_sensitive(selector->priv->modify_button,
631                              selector->priv->index >= HILDON_BASE_COLOR_NUM);
632     
633     gtk_widget_queue_draw(selector->priv->drawing_area);
634 }
635
636 static gboolean
637 color_moved(GtkWidget * widget, GdkEventMotion * event, gpointer data)
638 {
639     if ( event->state &
640          (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK | GDK_BUTTON3_MASK) ) 
641     {
642         select_color(HILDON_COLOR_SELECTOR(data), event->x, event->y, TRUE);
643         return TRUE;
644     }
645     return FALSE;
646 }
647
648 static void
649 modify_button_clicked(GtkWidget * button, HildonColorSelector * selector)
650 {
651     modify_selected (selector);
652 }
653
654 static void
655 modify_selected(HildonColorSelector * colselector)
656 {
657     HildonColorPopup popupdata;
658     GtkWidget *popup;
659
660     popup = hildon_color_popup_new(GTK_WINDOW(GTK_WIDGET(colselector)->window), 
661                     hildon_color_selector_get_color(colselector), &popupdata);
662     
663     if ( gtk_dialog_run(GTK_DIALOG(popup) ) == GTK_RESPONSE_OK) 
664     {        
665       GdkColor *color;
666
667       /* We cannot modify a base color */
668       if (colselector->priv->index < HILDON_BASE_COLOR_NUM)
669       {
670         colselector->priv->color[HILDON_TOTAL_COLOR_NUM] = 
671           colselector->priv->color[colselector->priv->index];
672         colselector->priv->index = HILDON_TOTAL_COLOR_NUM;
673       }
674
675       color = hildon_color_selector_get_color(colselector);
676       hildon_color_popup_set_color_from_sliders(color, &popupdata);
677
678       /* If we modified a base color we just accept the dialog */      
679       if( colselector->priv->index >=  HILDON_TOTAL_COLOR_NUM)
680       {          
681         gtk_dialog_response(GTK_DIALOG(colselector), GTK_RESPONSE_OK); 
682       }
683       else /* If we mofied custom colors we have to save to gconf */
684       {
685         GConfValue *value;
686         GSList * list;
687         int i;  
688
689         value = gconf_value_new(GCONF_VALUE_LIST);
690         gconf_value_set_list_type(value, GCONF_VALUE_STRING);
691         list = NULL;
692
693         for ( i = HILDON_BASE_COLOR_NUM; i < HILDON_TOTAL_COLOR_NUM; i++) 
694         {
695             GConfValue *item;
696             char buffer[32];
697                   
698             g_snprintf(buffer, sizeof(buffer), "#%.2X%.2X%.2X",
699                             (colselector->priv->color[i].red>>8)&0xFF,
700                             (colselector->priv->color[i].green>>8)&0xFF,
701                             (colselector->priv->color[i].blue>>8)&0xFF ); 
702   
703             item = gconf_value_new(GCONF_VALUE_STRING);
704             gconf_value_set_string(item, buffer);
705             list = g_slist_append (list, item);
706         } 
707         
708         gconf_value_set_list_nocopy(value, list);
709
710         /* gconf client handles the possible error */
711         gconf_client_set(colselector->priv->client, 
712           HILDON_COLOR_GCONF_KEYS, value, NULL);
713     
714         gconf_value_free(value);
715       }  
716     }
717
718     gtk_widget_destroy (popup); 
719     gtk_window_present (GTK_WINDOW(colselector));
720 }