Process the scrollbar window in the timeout
[hildon] / hildon / hildon-color-chooser-dialog.c
1 /*
2  * This file is a part of hildon
3  *
4  * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved.
5  *
6  * Author: Kuisma Salonen <kuisma.salonen@nokia.com>
7  * Contact: Rodrigo Novo <rodrigo.novo@nokia.com>
8  *
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.
13  *
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.
18  *
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
22  * 02110-1301 USA
23  *
24  */
25
26 /**
27  * SECTION:hildon-color-chooser-dialog
28  * @short_description: A dialog used to select a color from HSV colorspace.
29  * @see_also: #HildonColorButton
30  *
31  * HildonColorChooserDialog enables the user to 
32  * select an arbitrary color from a HSV colorspace.
33  * The color is stored in one of the predefined color 
34  * slots and can be reselected later on. 
35  *
36  * Additionally the user can choose one of the standard "factory"
37  * colors.
38  *
39  */
40
41 #undef                                          HILDON_DISABLE_DEPRECATED
42
43 #ifdef                                          HAVE_CONFIG_H
44 #include                                        <config.h>
45 #endif
46
47 #include                                        <memory.h>
48 #include                                        <string.h>
49 #include                                        <libintl.h>
50 #include                                        <gdk/gdkkeysyms.h>
51
52 #include                                        "hildon-color-chooser-dialog.h"
53 #include                                        "hildon-color-chooser.h"
54 #include                                        "hildon-defines.h"
55 #include                                        "hildon-banner.h"
56 #include                                        "hildon-color-chooser-dialog-private.h"
57
58 #define                                         _(String) dgettext("hildon-libs", String)
59
60 static HildonColorChooserDialogClass*           parent_class = NULL;
61
62 /* darkened EGA palette to be used as predefined colors if style doesn't
63    define anything else (darker colors are darkened 0x8000 -> 0x6666) */
64 static GdkColor hardcoded_colors[16] =          {{0, 0x0000, 0x0000, 0x0000},
65                                                  {0, 0x6666, 0x6666, 0x6666},
66                                                  {0, 0x6666, 0x0000, 0x0000},
67                                                  {0, 0x0000, 0x6666, 0x0000},
68                                                  {0, 0x0000, 0x0000, 0x6666},
69                                                  {0, 0x6666, 0x6666, 0x0000},
70                                                  {0, 0x6666, 0x0000, 0x6666},
71                                                  {0, 0x0000, 0x6666, 0x6666},
72                                                  {0, 0xffff, 0xffff, 0xffff},
73                                                  {0, 0xc000, 0xc000, 0xc000},
74                                                  {0, 0xffff, 0x0000, 0x0000},
75                                                  {0, 0x0000, 0xffff, 0x0000},
76                                                  {0, 0x0000, 0x0000, 0xffff},
77                                                  {0, 0xffff, 0xffff, 0x0000},
78                                                  {0, 0xffff, 0x0000, 0xffff},
79                                                  {0, 0x0000, 0xffff, 0xffff}};
80
81 static void
82 hildon_color_chooser_dialog_init                (HildonColorChooserDialog *object);
83
84 static void 
85 hildon_color_chooser_dialog_class_init          (HildonColorChooserDialogClass *klass);
86
87 static void 
88 hildon_color_chooser_dialog_size_request        (GtkWidget *widget, 
89                                                  GtkRequisition *req);
90
91 static void
92 hildon_color_chooser_dialog_size_allocate       (GtkWidget *widget, 
93                                                  GtkAllocation *alloc);
94
95 static void 
96 hildon_color_chooser_dialog_realize             (GtkWidget *widget);
97
98 static void
99 hildon_color_chooser_dialog_unrealize           (GtkWidget *widget);
100
101 static void 
102 hildon_color_chooser_dialog_style_set           (GtkWidget *widget, 
103                                                  GtkStyle *previous_style);
104
105 static void 
106 hildon_color_chooser_dialog_show                (GtkWidget *widget);
107
108 static void 
109 hildon_color_chooser_dialog_show_all            (GtkWidget *widget);
110
111 static gboolean 
112 hildon_color_chooser_dialog_key_press_event     (GtkWidget *widget, 
113                                                  GdkEventKey *event);
114
115 static gboolean 
116 hildon_color_chooser_dialog_key_release_event   (GtkWidget *widget, 
117                                                  GdkEventKey *event);
118
119 static void 
120 hildon_color_chooser_dialog_destroy             (GtkObject *object);
121
122 static gboolean 
123 hildon_color_chooser_dialog_area_expose         (GtkWidget *widget, 
124                                                  GdkEventExpose *event, 
125                                                  gpointer data);
126
127 static gboolean 
128 hildon_color_chooser_dialog_area_button_press   (GtkWidget *widget, 
129                                                  GdkEventButton *event, 
130                                                  gpointer data);
131
132 static void 
133 hildon_color_chooser_dialog_color_changed       (HildonColorChooser *chooser, 
134                                                  gpointer data);
135
136 static void 
137 hildon_color_chooser_dialog_insensitive_press   (GtkWidget *widget, 
138                                                  gpointer data);
139
140 static void 
141 hildon_color_chooser_dialog_refresh_style_info  (HildonColorChooserDialog *dialog);
142
143 static void 
144 hildon_color_chooser_dialog_set_color_num       (HildonColorChooserDialog *dialog, 
145                                                  gint num);
146
147 static void 
148 hildon_color_chooser_dialog_ascii_hex_to_color  (gchar *s, 
149                                                  GdkColor *color);
150
151 static void 
152 hildon_color_chooser_dialog_color_to_ascii_hex  (gchar *s, 
153                                                  GdkColor *color);
154
155 GType G_GNUC_CONST
156 hildon_color_chooser_dialog_get_type            (void)
157 {
158     static GType dialog_type = 0;
159
160     if (!dialog_type) {
161         static const GTypeInfo dialog_info =
162         {
163             sizeof (HildonColorChooserDialogClass),
164             NULL,
165             NULL,
166             (GClassInitFunc) hildon_color_chooser_dialog_class_init,
167             NULL,
168             NULL,
169             sizeof (HildonColorChooserDialog),
170             0,
171             (GInstanceInitFunc) hildon_color_chooser_dialog_init,
172             NULL
173         };
174
175         dialog_type = g_type_register_static (GTK_TYPE_DIALOG, 
176                 "HildonColorChooserDialog", &dialog_info, 0);
177     }
178
179     return dialog_type;
180 }
181
182 static void 
183 hildon_color_chooser_dialog_init                (HildonColorChooserDialog *object)
184 {
185     HildonColorChooserDialogPrivate *priv = HILDON_COLOR_CHOOSER_DIALOG_GET_PRIVATE (object);
186
187     gtk_dialog_set_has_separator (GTK_DIALOG (object), FALSE);
188     gtk_window_set_title (GTK_WINDOW (object), _("ecdg_ti_colour_selector"));
189
190     g_assert (priv);
191
192     priv->hbox = gtk_hbox_new (FALSE, 0);
193     priv->vbox = gtk_vbox_new (FALSE, 0);
194     priv->chooser = hildon_color_chooser_new ();
195
196     gtk_box_pack_start (GTK_BOX (priv->hbox), priv->chooser, TRUE, TRUE, 0);
197     gtk_box_pack_end (GTK_BOX (priv->hbox), priv->vbox, FALSE, FALSE, 0);
198
199     gtk_box_pack_start (GTK_BOX (GTK_DIALOG (object)->vbox), priv->hbox, TRUE, TRUE, 0);
200
201
202     priv->align_custom = gtk_alignment_new (0.5, 1.0, 0.0, 0.0);
203     priv->align_defined = gtk_alignment_new (0.5, 1.0, 0.0, 0.0);
204
205     priv->area_custom = gtk_drawing_area_new ();
206     priv->area_defined = gtk_drawing_area_new ();
207
208     gtk_container_add (GTK_CONTAINER (priv->align_custom), priv->area_custom);
209     gtk_container_add (GTK_CONTAINER (priv->align_defined), priv->area_defined);
210
211     priv->separator = gtk_hseparator_new ();
212
213     gtk_box_pack_start (GTK_BOX (priv->vbox), priv->align_defined, FALSE, FALSE, 0);
214     gtk_box_pack_start (GTK_BOX (priv->vbox), priv->separator, FALSE, FALSE, 0);
215     gtk_box_pack_start (GTK_BOX (priv->vbox), priv->align_custom, FALSE, FALSE, 0);
216
217     gtk_dialog_add_button (GTK_DIALOG (object), _("wdgt_bd_done"), GTK_RESPONSE_OK);
218     gtk_dialog_set_default_response (GTK_DIALOG (object), GTK_RESPONSE_OK);
219
220     g_signal_connect (G_OBJECT (priv->chooser), 
221             "query-tooltip", G_CALLBACK (hildon_color_chooser_dialog_insensitive_press), object);
222
223     g_signal_connect (G_OBJECT (priv->area_custom), 
224             "expose-event", G_CALLBACK (hildon_color_chooser_dialog_area_expose), object);
225
226     g_signal_connect (G_OBJECT (priv->area_defined), 
227             "expose-event", G_CALLBACK (hildon_color_chooser_dialog_area_expose), object);
228
229     g_signal_connect (G_OBJECT (priv->area_custom), 
230             "button-press-event", G_CALLBACK (hildon_color_chooser_dialog_area_button_press), object);
231
232     g_signal_connect (G_OBJECT (priv->area_defined), 
233             "button-press-event", G_CALLBACK (hildon_color_chooser_dialog_area_button_press), object);
234
235     g_signal_connect (G_OBJECT (priv->chooser), 
236             "color-changed", G_CALLBACK (hildon_color_chooser_dialog_color_changed), object);
237
238     gtk_widget_add_events (priv->area_custom, GDK_BUTTON_PRESS_MASK);
239     gtk_widget_add_events (priv->area_defined, GDK_BUTTON_PRESS_MASK);
240
241     priv->selected = 0;
242     priv->gconf_client = gconf_client_get_default ();
243
244     memset (&priv->style_info, 0, sizeof (HildonColorChooserStyleInfo));
245     
246     priv->colors_custom = NULL;
247     priv->colors_defined = NULL;
248     priv->gc_array = NULL;
249
250     priv->has_style = 0;
251 }
252
253 static void
254 hildon_color_chooser_dialog_class_init          (HildonColorChooserDialogClass *klass)
255 {
256     GtkWidgetClass *widget_klass = GTK_WIDGET_CLASS (klass);
257     GtkObjectClass *object_klass = GTK_OBJECT_CLASS (klass);
258     gchar tmp[32];
259     gint i;
260
261     widget_klass->size_request      = hildon_color_chooser_dialog_size_request;
262     widget_klass->size_allocate     = hildon_color_chooser_dialog_size_allocate;
263     widget_klass->realize           = hildon_color_chooser_dialog_realize;
264     widget_klass->unrealize         = hildon_color_chooser_dialog_unrealize;
265     widget_klass->style_set         = hildon_color_chooser_dialog_style_set;
266     widget_klass->show              = hildon_color_chooser_dialog_show;
267     widget_klass->show_all          = hildon_color_chooser_dialog_show_all;
268     widget_klass->key_press_event   = hildon_color_chooser_dialog_key_press_event;
269     widget_klass->key_release_event = hildon_color_chooser_dialog_key_release_event;
270
271
272     object_klass->destroy           = hildon_color_chooser_dialog_destroy;
273
274     parent_class = g_type_class_peek_parent (klass);
275
276     gtk_widget_class_install_style_property (widget_klass,
277             g_param_spec_boxed ("container_sizes",
278                 "Container sizes",
279                 "Container specific sizes",
280                 GTK_TYPE_BORDER,
281                 G_PARAM_READABLE));
282
283     gtk_widget_class_install_style_property (widget_klass,
284             g_param_spec_boxed ("radio_sizes",
285                 "Color radio sizes",
286                 "Color radio specific sizes",
287                 GTK_TYPE_BORDER,
288                 G_PARAM_READABLE));
289
290     gtk_widget_class_install_style_property (widget_klass,
291             g_param_spec_boxed ("num_buttons",
292                 "Number of buttons",
293                 "Number of color store buttons",
294                 GTK_TYPE_BORDER,
295                 G_PARAM_READABLE));
296
297     gtk_widget_class_install_style_property (widget_klass,
298             g_param_spec_boxed ("default_color", "Default color",
299                 "Default color for nonpainted custom colors",
300                 GDK_TYPE_COLOR,
301                 G_PARAM_READABLE));
302
303     for (i = 0; i < 32; i++) {
304         memset (tmp, 0, 32);
305         g_snprintf (tmp, 32, "defined_color%d", i);
306
307         gtk_widget_class_install_style_property (widget_klass,
308                 g_param_spec_boxed (tmp, "Defined color",
309                     "Pre-defined colors for the dialog",
310                     GDK_TYPE_COLOR,
311                     G_PARAM_READABLE));
312     }
313
314     g_type_class_add_private (object_klass, sizeof (HildonColorChooserDialogPrivate));
315 }
316
317 static void 
318 hildon_color_chooser_dialog_size_request        (GtkWidget *widget, 
319                                                  GtkRequisition *req)
320 {
321     HildonColorChooserDialogPrivate *priv = HILDON_COLOR_CHOOSER_DIALOG_GET_PRIVATE (widget);
322
323     g_assert (priv);
324
325     gtk_container_set_border_width (GTK_CONTAINER (priv->hbox), priv->style_info.cont_sizes.left);
326
327     gtk_box_set_spacing (GTK_BOX (priv->hbox), priv->style_info.cont_sizes.right);
328     gtk_box_set_spacing (GTK_BOX (priv->vbox), priv->style_info.cont_sizes.top);
329     gtk_box_set_spacing (GTK_BOX (GTK_DIALOG (widget)->vbox), priv->style_info.cont_sizes.bottom);
330
331     gtk_widget_set_size_request (priv->area_custom,
332             (priv->style_info.radio_sizes.left + 
333              2 * priv->style_info.radio_sizes.bottom) * 
334             (priv->style_info.num_buttons.top) +
335             (priv->style_info.num_buttons.top-1) *
336             priv->style_info.radio_sizes.top,
337             (priv->style_info.radio_sizes.right + 
338              2 * priv->style_info.radio_sizes.bottom) * 
339             (priv->style_info.num_buttons.bottom) +
340             (priv->style_info.num_buttons.bottom-1) * 
341             priv->style_info.radio_sizes.top);
342
343     gtk_widget_set_size_request (priv->area_defined,
344             (priv->style_info.radio_sizes.left + 
345              2 * priv->style_info.radio_sizes.bottom) * 
346             (priv->style_info.num_buttons.left) +
347             (priv->style_info.num_buttons.left-1) * 
348             priv->style_info.radio_sizes.top,
349             (priv->style_info.radio_sizes.right +  
350              2 * priv->style_info.radio_sizes.bottom) * 
351             (priv->style_info.num_buttons.right) +
352             (priv->style_info.num_buttons.right-1) * 
353             priv->style_info.radio_sizes.top);
354
355     GTK_WIDGET_CLASS (parent_class)->size_request (widget, req);
356 }
357
358 static void 
359 hildon_color_chooser_dialog_size_allocate       (GtkWidget *widget,
360                                                  GtkAllocation *alloc)
361 {
362     HildonColorChooserDialogPrivate *priv = HILDON_COLOR_CHOOSER_DIALOG_GET_PRIVATE (widget);
363
364     GdkRectangle rect;
365     int i, tmp, tmp2;
366
367     g_assert (priv);
368
369     GTK_WIDGET_CLASS (parent_class)->size_allocate (widget, alloc);
370
371     if (GTK_WIDGET_REALIZED (widget)) {
372         tmp  = (priv->style_info.num_buttons.left * priv->style_info.num_buttons.right);
373         tmp2 = (priv->style_info.num_buttons.top * priv->style_info.num_buttons.bottom);
374
375         for (i = 0; i < tmp; i++) {
376             rect.x = ((i % priv->style_info.num_buttons.left) * 
377                     (priv->style_info.radio_sizes.left + 
378                      priv->style_info.radio_sizes.top + 
379                      2 * priv->style_info.radio_sizes.bottom)) + 
380                 priv->style_info.radio_sizes.bottom;
381
382             rect.y = ((i / priv->style_info.num_buttons.left) * 
383                     (priv->style_info.radio_sizes.right + 
384                      priv->style_info.radio_sizes.top +
385                      2 * priv->style_info.radio_sizes.bottom)) + 
386                 priv->style_info.radio_sizes.bottom;
387
388             rect.width = priv->style_info.radio_sizes.left;
389             rect.height = priv->style_info.radio_sizes.right;
390
391             gdk_gc_set_clip_rectangle (priv->gc_array[i], &rect);
392         }
393
394         for (i = 0; i < tmp2; i++) {
395             rect.x = ((i % priv->style_info.num_buttons.top) * 
396                     (priv->style_info.radio_sizes.left + 
397                      priv->style_info.radio_sizes.top +
398                      2 * priv->style_info.radio_sizes.bottom)) + 
399                 priv->style_info.radio_sizes.bottom;
400
401             rect.y = ((i / priv->style_info.num_buttons.top) * 
402                     (priv->style_info.radio_sizes.right + 
403                      priv->style_info.radio_sizes.top +
404                      2 * priv->style_info.radio_sizes.bottom)) + priv->style_info.radio_sizes.bottom;
405
406             rect.width = priv->style_info.radio_sizes.left;
407             rect.height = priv->style_info.radio_sizes.right;
408
409             gdk_gc_set_clip_rectangle (priv->gc_array[i + tmp], &rect);
410         }
411     }
412 }
413
414 static void 
415 hildon_color_chooser_dialog_realize             (GtkWidget *widget)
416 {
417     HildonColorChooserDialogPrivate *priv = HILDON_COLOR_CHOOSER_DIALOG_GET_PRIVATE (widget);
418
419     GdkRectangle rect;
420     int i, tmp, tmp2;
421
422     g_assert (priv);
423     
424     GTK_WIDGET_CLASS(parent_class)->realize (widget);
425
426     tmp = (priv->style_info.num_buttons.left * priv->style_info.num_buttons.right) +
427         (priv->style_info.num_buttons.top * priv->style_info.num_buttons.bottom);
428
429     for (i = 0; i < tmp; i++) {
430         priv->gc_array[i] = gdk_gc_new (widget->window);
431     }
432
433     tmp  = (priv->style_info.num_buttons.left * priv->style_info.num_buttons.right);
434     tmp2 = (priv->style_info.num_buttons.top * priv->style_info.num_buttons.bottom);
435
436     for (i = 0; i < tmp; i++) {
437         gdk_gc_set_rgb_fg_color (priv->gc_array[i], &priv->colors_defined[i]);
438
439         rect.x = ((i % priv->style_info.num_buttons.left) * 
440                 (priv->style_info.radio_sizes.left + 
441                  priv->style_info.radio_sizes.top +
442                  2 * priv->style_info.radio_sizes.bottom)) + 
443             priv->style_info.radio_sizes.bottom;
444
445         rect.y = ((i / priv->style_info.num_buttons.left) * 
446                 (priv->style_info.radio_sizes.right + 
447                  priv->style_info.radio_sizes.top +
448                  2 * priv->style_info.radio_sizes.bottom)) + 
449             priv->style_info.radio_sizes.bottom;
450
451         rect.width = priv->style_info.radio_sizes.left;
452         rect.height = priv->style_info.radio_sizes.right;
453
454         gdk_gc_set_clip_rectangle (priv->gc_array[i], &rect);
455     }
456
457     for (i = 0; i < tmp2; i++) {
458         gdk_gc_set_rgb_fg_color (priv->gc_array[i + tmp], &priv->colors_custom[i]);
459
460         rect.x = ((i % priv->style_info.num_buttons.top) * 
461                 (priv->style_info.radio_sizes.left + 
462                  priv->style_info.radio_sizes.top +
463                  2 * priv->style_info.radio_sizes.bottom)) + 
464             priv->style_info.radio_sizes.bottom;
465
466         rect.y = ((i / priv->style_info.num_buttons.top) * 
467                 (priv->style_info.radio_sizes.right + 
468                  priv->style_info.radio_sizes.top +
469                  2 * priv->style_info.radio_sizes.bottom)) + 
470             priv->style_info.radio_sizes.bottom;
471
472         rect.width = priv->style_info.radio_sizes.left;
473         rect.height = priv->style_info.radio_sizes.right;
474
475         gdk_gc_set_clip_rectangle (priv->gc_array[i + tmp], &rect);
476     }
477 }
478
479 static void 
480 hildon_color_chooser_dialog_unrealize           (GtkWidget *widget)
481 {
482     HildonColorChooserDialogPrivate *priv = HILDON_COLOR_CHOOSER_DIALOG_GET_PRIVATE (widget);
483
484     int i, tmp;
485
486     tmp = (priv->style_info.num_buttons.left * priv->style_info.num_buttons.right) +
487         (priv->style_info.num_buttons.top * priv->style_info.num_buttons.bottom);
488
489     for (i = 0; i < tmp; i++) {
490         g_object_unref (priv->gc_array[i]);
491         priv->gc_array[i] = NULL;
492     }
493
494     GTK_WIDGET_CLASS (parent_class)->unrealize (widget);
495 }
496
497 static void 
498 hildon_color_chooser_dialog_style_set           (GtkWidget *widget, 
499                                                  GtkStyle *previous_style)
500 {
501     HildonColorChooserDialog *dialog = HILDON_COLOR_CHOOSER_DIALOG (widget);
502     HildonColorChooserDialogPrivate *priv = HILDON_COLOR_CHOOSER_DIALOG_GET_PRIVATE (widget);
503
504     GdkColor *tmpcolor;
505     gchar tmp[32], key[128], *val;
506     int i, tmpn, setcolor = 0;
507
508     g_assert (priv);
509
510     if (! priv->has_style)
511         setcolor = 1;
512
513     priv->has_style = 1;
514
515     gtk_widget_style_get (widget, "default_color", &tmpcolor, NULL);
516
517     if (tmpcolor) {
518         priv->style_info.default_color = *tmpcolor;
519         gdk_color_free (tmpcolor);
520     } else {
521         priv->style_info.default_color.red   = 0x0000;
522         priv->style_info.default_color.green = 0x0000;
523         priv->style_info.default_color.blue  = 0x0000;
524         priv->style_info.default_color.pixel = 0x00000000;
525     }
526
527     hildon_color_chooser_dialog_refresh_style_info (dialog);
528
529     if (memcmp (&priv->style_info.num_buttons, &priv->style_info.last_num_buttons, sizeof (GtkBorder))) {
530         if (priv->colors_custom) {
531             g_free (priv->colors_custom);
532         } if (priv->colors_defined) {
533             g_free (priv->colors_defined);
534         } if (priv->gc_array) {
535             if (GTK_WIDGET_REALIZED (widget)) {
536                 tmpn = (priv->style_info.last_num_buttons.left * priv->style_info.last_num_buttons.right) +
537                     (priv->style_info.last_num_buttons.top * priv->style_info.last_num_buttons.bottom);
538
539                 for (i = 0; i < tmpn; i++) {
540                     g_object_unref (priv->gc_array[i]);
541                     priv->gc_array[i] = NULL;
542                 }
543             }
544
545             g_free (priv->gc_array);
546         }
547
548         priv->colors_custom = (GdkColor *)
549             g_malloc0 (sizeof (GdkColor) * (priv->style_info.num_buttons.top * 
550                         priv->style_info.num_buttons.bottom));
551
552         priv->colors_defined = (GdkColor *)
553             g_malloc0 (sizeof(GdkColor) * (priv->style_info.num_buttons.left * 
554                         priv->style_info.num_buttons.right));
555
556         tmpn = (priv->style_info.num_buttons.left * priv->style_info.num_buttons.right) +
557             (priv->style_info.num_buttons.top * priv->style_info.num_buttons.bottom);
558
559         priv->gc_array = (GdkGC **) g_malloc0 (sizeof (GdkGC *) * tmpn);
560         if (GTK_WIDGET_REALIZED (widget)) {
561                 for (i = 0; i < tmpn; i++) {
562                     priv->gc_array[i] = gdk_gc_new (widget->window);
563                 }
564         }
565
566         if (priv->gconf_client) {
567
568             for (i = 0; i < (priv->style_info.num_buttons.top * priv->style_info.num_buttons.bottom); i++) {
569                 memset (key, 0, 128);
570                 /* FIXME Extremally bad hardcoding */
571                 g_snprintf (key, 128, "/system/osso/af/color_chooser/custom_color%d", i);
572                 val = gconf_client_get_string (priv->gconf_client, key, NULL);
573
574                 if (val) {
575                     hildon_color_chooser_dialog_ascii_hex_to_color (val, &priv->colors_custom[i]);
576                     g_free (val);
577                 } else {
578                     priv->colors_custom[i] = priv->style_info.default_color;
579                 }
580             }
581         } else {
582             for (i = 0; i < (priv->style_info.num_buttons.top * priv->style_info.num_buttons.bottom); i++) {
583                 priv->colors_custom[i] = priv->style_info.default_color;
584             }
585         }
586     }
587
588     tmpn = (priv->style_info.num_buttons.left * priv->style_info.num_buttons.right);
589
590     hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (priv->chooser),
591             (priv->selected < tmpn) ? 
592             &priv->colors_defined[priv->selected] : 
593             &priv->colors_custom[priv->selected - tmpn]);
594
595     for (i = 0; i < (priv->style_info.num_buttons.left * priv->style_info.num_buttons.right); i++) {
596         memset (tmp, 0, 32);
597         g_snprintf (tmp, 32, "defined_color%d", i);
598
599         gtk_widget_style_get (widget, tmp, &tmpcolor, NULL);
600
601         if (tmpcolor) {
602             priv->colors_defined[i] = *tmpcolor;
603             gdk_color_free (tmpcolor);
604         } else {
605             if(i < 16) {
606                 priv->colors_defined[i] = hardcoded_colors[i];
607             } else { /* fallback to prevent segfault */
608                 priv->colors_defined[i].red = 0x0000;
609                 priv->colors_defined[i].green = 0x0000;
610                 priv->colors_defined[i].blue = 0x0000;
611                 priv->colors_defined[i].pixel = 0x00000000;
612             }
613         }
614     }
615
616     if (GTK_WIDGET_REALIZED (widget)) {
617         for (i = 0; i < (priv->style_info.num_buttons.left * 
618                     priv->style_info.num_buttons.right); i++) {
619             gdk_gc_set_rgb_fg_color (priv->gc_array[i], &priv->colors_defined[i]);
620         }
621     }
622
623     if (setcolor)
624         hildon_color_chooser_dialog_set_color (HILDON_COLOR_CHOOSER_DIALOG (dialog), 
625                 &priv->pending_color);
626
627     gtk_widget_queue_resize (widget);
628
629     GTK_WIDGET_CLASS (parent_class)->style_set (widget, previous_style);
630 }
631
632 static void 
633 hildon_color_chooser_dialog_show                (GtkWidget *widget)
634 {
635     HildonColorChooserDialogPrivate *priv = HILDON_COLOR_CHOOSER_DIALOG_GET_PRIVATE (widget);
636
637     g_assert (priv);
638
639     gtk_widget_show (priv->hbox);
640     gtk_widget_show (priv->vbox);
641
642     gtk_widget_show (priv->chooser);
643
644     gtk_widget_show (priv->align_custom);
645     gtk_widget_show (priv->align_defined);
646
647     gtk_widget_show (priv->separator);
648
649     gtk_widget_show (priv->area_custom);
650     gtk_widget_show (priv->area_defined);
651
652     GTK_WIDGET_CLASS (parent_class)->show (widget);
653 }
654
655 /* FIXME WTF this function is even needed here? */
656 static void 
657 hildon_color_chooser_dialog_show_all            (GtkWidget *widget)
658 {
659     hildon_color_chooser_dialog_show (widget);
660 }
661
662 static gboolean 
663 hildon_color_chooser_dialog_key_press_event     (GtkWidget *widget, 
664                                                  GdkEventKey *event)
665 {
666     HildonColorChooserDialog *dialog = HILDON_COLOR_CHOOSER_DIALOG (widget);
667     HildonColorChooserDialogPrivate *priv = HILDON_COLOR_CHOOSER_DIALOG_GET_PRIVATE (widget);
668     int tmp, tot, sel;
669
670     g_assert (priv);
671
672     if (event->keyval == HILDON_HARDKEY_UP || event->keyval == HILDON_HARDKEY_DOWN ||
673             event->keyval == HILDON_HARDKEY_LEFT || event->keyval == HILDON_HARDKEY_RIGHT) {
674         tmp = (priv->style_info.num_buttons.top * priv->style_info.num_buttons.bottom);
675         tot = (priv->style_info.num_buttons.left * priv->style_info.num_buttons.right) + tmp;
676
677         switch (event->keyval) {
678
679             case HILDON_HARDKEY_UP:
680                 if(priv->selected >= priv->style_info.num_buttons.top) {
681                     if(priv->selected - priv->style_info.num_buttons.left >= tmp) {
682                         sel = priv->selected - priv->style_info.num_buttons.left;
683                     } else {
684                         sel = priv->selected - priv->style_info.num_buttons.top;
685                     }
686
687                     hildon_color_chooser_dialog_set_color_num (dialog, sel);
688                 }
689                 break;
690
691             case HILDON_HARDKEY_DOWN:
692                 if(priv->selected < tot - priv->style_info.num_buttons.left) {
693                     if(priv->selected < tmp) {
694                         sel = priv->selected + priv->style_info.num_buttons.top;
695                     } else {
696                         sel = priv->selected + priv->style_info.num_buttons.left;
697                     }
698
699                     hildon_color_chooser_dialog_set_color_num (dialog, sel);
700                 }
701                 break;
702
703             case HILDON_HARDKEY_LEFT:
704                 if ((priv->selected < tmp ? 
705                             (priv->selected % priv->style_info.num_buttons.top) : 
706                             ((priv->selected - tmp) % priv->style_info.num_buttons.left)) > 0) {
707                     sel = priv->selected - 1;
708
709                     hildon_color_chooser_dialog_set_color_num (dialog, sel);
710                 }
711                 break;
712
713             case HILDON_HARDKEY_RIGHT:
714                 if ((priv->selected < tmp) ? 
715                         (priv->selected % priv->style_info.num_buttons.top < priv->style_info.num_buttons.top - 1) :
716                         ((priv->selected - tmp) % priv->style_info.num_buttons.left < priv->style_info.num_buttons.left - 1)) {
717                     sel = priv->selected + 1;
718
719                     hildon_color_chooser_dialog_set_color_num (dialog, sel);
720                 }
721                 break;
722
723             default:
724                 break;
725         }
726
727         return FALSE;
728     }
729
730     return GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, event);
731 }
732
733 static gboolean
734 hildon_color_chooser_dialog_key_release_event   (GtkWidget *widget, 
735                                                  GdkEventKey *event)
736 {
737     if (event->keyval == HILDON_HARDKEY_UP || 
738         event->keyval == HILDON_HARDKEY_DOWN ||
739         event->keyval == HILDON_HARDKEY_LEFT || 
740         event->keyval == HILDON_HARDKEY_RIGHT) 
741     {
742         return FALSE;
743     }
744
745     return GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, event);
746 }
747
748 static void 
749 hildon_color_chooser_dialog_destroy             (GtkObject *object)
750 {
751     HildonColorChooserDialogPrivate *priv = HILDON_COLOR_CHOOSER_DIALOG_GET_PRIVATE (object);
752
753     gchar key[128], color[13];
754     int i, tmp;
755
756     g_assert (priv);
757
758     if (priv->gconf_client) {
759         memset (color, 0, 13);
760
761         tmp = (priv->style_info.num_buttons.top * priv->style_info.num_buttons.bottom);
762
763         for (i = 0; i < tmp; i++) {
764             memset (key, 0, 128);
765             /* FIXME Extremally bad hardcoding */
766             g_snprintf (key, 128, "/system/osso/af/color_chooser/custom_color%d", i);
767             hildon_color_chooser_dialog_color_to_ascii_hex (color, &priv->colors_custom[i]);
768             gconf_client_set_string (priv->gconf_client, key, color, NULL);
769         }
770
771         g_object_unref (priv->gconf_client);
772         priv->gconf_client = NULL;
773     }
774
775     if (priv->gc_array) {
776         g_free (priv->gc_array);
777         priv->gc_array = NULL;
778     } if (priv->colors_defined) {
779         g_free (priv->colors_defined);
780         priv->colors_defined = NULL;
781     } if (priv->colors_custom) {
782         g_free (priv->colors_custom);
783         priv->colors_custom = NULL;
784     }
785
786     GTK_OBJECT_CLASS (parent_class)->destroy (object);
787 }
788
789 /**
790  * hildon_color_chooser_dialog_set_color:
791  * @dialog: a #HildonColorChooserDialog
792  * @color: a color to set on the #HildonColorChooserDialog
793  *
794  * Sets the dialog to point at the given color. It'll first try to
795  * search the palette of the existing colors to match the passed color. 
796  * If the color is not found in the pallette, the color in the currently 
797  * selected box will be modified.
798  *
799  */
800 void 
801 hildon_color_chooser_dialog_set_color           (HildonColorChooserDialog *dialog, 
802                                                  GdkColor *color)
803 {
804     HildonColorChooserDialogPrivate *priv = HILDON_COLOR_CHOOSER_DIALOG_GET_PRIVATE (dialog);
805
806     int i, found = -1, tmp, tmp2;
807
808     g_assert (priv);
809
810     if (! priv->has_style) {
811         priv->pending_color = *color;
812         return;
813     }
814
815     tmp  = (priv->style_info.num_buttons.left * priv->style_info.num_buttons.right);
816     tmp2 = (priv->style_info.num_buttons.top * priv->style_info.num_buttons.bottom);
817
818     for (i = 0; i < tmp; i++) {
819         if (priv->colors_defined[i].red == color->red &&
820                 priv->colors_defined[i].green == color->green &&
821                 priv->colors_defined[i].blue == color->blue) {
822             found = i;
823             break;
824         }
825     }
826
827     if (found == -1) {
828         for (i = 0; i < tmp2; i++) {
829             if (priv->colors_custom[i].red == color->red &&
830                     priv->colors_custom[i].green == color->green &&
831                     priv->colors_custom[i].blue == color->blue) {
832                 found = i + tmp;
833                 break;
834             }
835         }
836     }
837
838     if (found == -1) {
839         priv->colors_custom[tmp2-1] = *color;
840         if (GTK_WIDGET_REALIZED (GTK_WIDGET (dialog))) {
841             gdk_gc_set_rgb_fg_color (priv->gc_array[tmp2-1], color);
842         }
843         hildon_color_chooser_dialog_set_color_num (dialog, tmp2 - 1);
844     } else {
845         hildon_color_chooser_dialog_set_color_num (dialog, found);
846     }
847 }
848
849 static gboolean 
850 hildon_color_chooser_dialog_area_expose         (GtkWidget *widget, 
851                                                  GdkEventExpose *event, 
852                                                  gpointer data)
853 {
854     HildonColorChooserDialogPrivate *priv = HILDON_COLOR_CHOOSER_DIALOG_GET_PRIVATE (data);
855
856     int i, num_selected, tot_w, tot_h, spacing, brd, x, y;
857     GdkGC **start_gc;
858     int tmp, w, h;
859
860     g_assert (priv);
861
862     tmp = (priv->style_info.num_buttons.left * priv->style_info.num_buttons.right);
863
864     if (widget == priv->area_custom) {
865         num_selected = priv->selected - tmp;
866         start_gc = priv->gc_array + tmp;
867         tmp = (priv->style_info.num_buttons.top * priv->style_info.num_buttons.bottom);
868         w = priv->style_info.num_buttons.top; 
869         h = priv->style_info.num_buttons.bottom;
870     } else { /* widget == dialog->area_defined */
871         num_selected = priv->selected;
872         start_gc = priv->gc_array;
873         w = priv->style_info.num_buttons.left; 
874         h = priv->style_info.num_buttons.right;
875     }
876
877     spacing = priv->style_info.radio_sizes.top;
878     brd = priv->style_info.radio_sizes.bottom;
879     tot_w = priv->style_info.radio_sizes.left + 2 * brd;
880     tot_h = priv->style_info.radio_sizes.right + 2 * brd;
881
882     for (i = 0; i < tmp; i++) {
883         x = ((i % w) * (tot_w + spacing));
884         y = ((i / w) * (tot_h + spacing));
885
886         gdk_draw_rectangle (widget->window,
887                 (i == num_selected) ? widget->style->bg_gc[GTK_STATE_SELECTED] : widget->style->bg_gc[GTK_STATE_NORMAL],
888                 TRUE,
889                 (i == num_selected) ? x : x + 2,  
890                 (i == num_selected) ? y : y + 2,
891                 (i == num_selected) ? tot_w : tot_w - 4,
892                 (i == num_selected) ? tot_h : tot_h - 4);
893
894         gdk_draw_rectangle(widget->window,
895                 (i == num_selected) ? widget->style->bg_gc[GTK_STATE_NORMAL] : widget->style->white_gc,
896                 TRUE,
897                 x + 3,  
898                 y + 3,
899                 tot_w - 6,
900                 tot_h - 6);
901
902         gdk_draw_rectangle(widget->window,
903                 start_gc [i],
904                 TRUE,
905                 x + 3 + 1,  
906                 y + 3 + 1,
907                 tot_w - 6 - 2,
908                 tot_h - 6 - 2);
909     }
910
911     return FALSE;
912 }
913
914 static gboolean 
915 hildon_color_chooser_dialog_area_button_press   (GtkWidget *widget, 
916                                                  GdkEventButton *event, 
917                                                  gpointer data)
918 {
919     HildonColorChooserDialog *dialog = HILDON_COLOR_CHOOSER_DIALOG (data);
920     HildonColorChooserDialogPrivate *priv = HILDON_COLOR_CHOOSER_DIALOG_GET_PRIVATE (data);
921
922     int i, hskip, vskip, brd, selection = -1;
923     int x, y, tmp, tmp2, w;
924
925     g_assert (priv);
926
927     x = event->x;
928     y = event->y;
929
930     brd = priv->style_info.radio_sizes.bottom;
931     hskip = priv->style_info.radio_sizes.left + 
932         priv->style_info.radio_sizes.top + 2 * brd;
933     vskip = priv->style_info.radio_sizes.right + 
934         priv->style_info.radio_sizes.top + 2 * brd;
935
936     tmp  = (priv->style_info.num_buttons.left * priv->style_info.num_buttons.right);
937     tmp2 = (priv->style_info.num_buttons.top * priv->style_info.num_buttons.bottom);
938
939     if (widget == priv->area_defined) {
940         w = priv->style_info.num_buttons.left;
941
942         for (i = 0; i < tmp; i++) {
943             if (x >= hskip * (i % w) + brd && x < hskip * (i % w) + brd + priv->style_info.radio_sizes.left &&
944                 y >= vskip * (i / w) + brd && y < hskip * (i / w) + brd + priv->style_info.radio_sizes.right) {
945                 selection = i;
946                 break;
947             }
948         }
949     } else {
950         w = priv->style_info.num_buttons.top;
951         for (i = 0; i < tmp2; i++) {
952             if (x >= hskip * (i % w) + brd && x < hskip * (i % w) + brd + priv->style_info.radio_sizes.left &&
953                 y >= vskip * (i / w) + brd && y < hskip * (i / w) + brd + priv->style_info.radio_sizes.right) {
954                 selection = i + tmp;
955                 break;
956             }
957         }
958     }
959
960     if (selection != -1) {
961         hildon_color_chooser_dialog_set_color_num (dialog, selection);
962     }
963
964     return FALSE;
965 }
966
967 static void 
968 hildon_color_chooser_dialog_color_changed       (HildonColorChooser *chooser, 
969                                                  gpointer data)
970 {
971     HildonColorChooserDialogPrivate *priv = HILDON_COLOR_CHOOSER_DIALOG_GET_PRIVATE (data);
972     char key[128], color_str[13];
973     int tmp;
974     GdkColor color;
975
976     g_assert (priv);
977
978     hildon_color_chooser_get_color (chooser, &color);
979
980     tmp = (priv->style_info.num_buttons.left * priv->style_info.num_buttons.right);
981
982     if (priv->selected >= tmp) {
983         priv->colors_custom[priv->selected - tmp] = color;
984
985         gdk_gc_set_rgb_fg_color (priv->gc_array[priv->selected], &priv->colors_custom[priv->selected - tmp]);
986         gtk_widget_queue_draw (priv->area_custom);
987
988         if (priv->gconf_client) {
989             memset (key, 0, 128);
990             memset (color_str, 0, 13);
991             /* FIXME Ugly hardcoded stuff! */
992             g_snprintf (key, 128, "/system/osso/af/color_chooser/custom_color%d", priv->selected - tmp);
993             hildon_color_chooser_dialog_color_to_ascii_hex (color_str, &priv->colors_custom[priv->selected - tmp]);
994             gconf_client_set_string (priv->gconf_client, key, color_str, NULL);
995         }
996     }
997 }
998
999 static void 
1000 hildon_color_chooser_dialog_insensitive_press   (GtkWidget *widget, 
1001                                                  gpointer data)
1002 {
1003     hildon_banner_show_information (widget, NULL, _("ecdg_ib_colour_selector_predefined"));
1004 }
1005
1006 /* function has size defaults */
1007 static void 
1008 hildon_color_chooser_dialog_refresh_style_info  (HildonColorChooserDialog *dialog)
1009 {
1010     GtkBorder *tmp1, *tmp2, *tmp3;
1011     HildonColorChooserDialogPrivate *priv = HILDON_COLOR_CHOOSER_DIALOG_GET_PRIVATE (dialog);
1012
1013     g_assert (priv);
1014
1015     gtk_widget_style_get (GTK_WIDGET (dialog), "container_sizes", &tmp1,
1016             "radio_sizes", &tmp2, "num_buttons", &tmp3, NULL);
1017
1018     priv->style_info.last_num_buttons = priv->style_info.num_buttons;
1019
1020     if (tmp1) {
1021         priv->style_info.cont_sizes = *tmp1;
1022         gtk_border_free (tmp1);
1023     } else {
1024         priv->style_info.cont_sizes.left = 0;
1025         priv->style_info.cont_sizes.right = 8;
1026         priv->style_info.cont_sizes.top = 4;
1027         priv->style_info.cont_sizes.bottom = 0;
1028     }
1029
1030     if (tmp2) {
1031         priv->style_info.radio_sizes = *tmp2;
1032         gtk_border_free (tmp2);
1033     } else {
1034         priv->style_info.radio_sizes.left = 16;
1035         priv->style_info.radio_sizes.right = 16;
1036         priv->style_info.radio_sizes.top = 4;
1037         priv->style_info.radio_sizes.bottom = 2;
1038     }
1039
1040     if (tmp3) {
1041         priv->style_info.num_buttons = *tmp3;
1042         gtk_border_free (tmp3);
1043     } else {
1044         priv->style_info.num_buttons.left = 8;
1045         priv->style_info.num_buttons.right = 2;
1046         priv->style_info.num_buttons.top = 8;
1047         priv->style_info.num_buttons.bottom = 2;
1048     }
1049 }
1050
1051 static void 
1052 hildon_color_chooser_dialog_set_color_num       (HildonColorChooserDialog *dialog, 
1053                                                  gint num)
1054 {
1055     HildonColorChooserDialogPrivate *priv = HILDON_COLOR_CHOOSER_DIALOG_GET_PRIVATE (dialog);
1056
1057     int tmp;
1058
1059     g_assert (priv);
1060
1061     tmp = (priv->style_info.num_buttons.left * priv->style_info.num_buttons.right);
1062
1063     if (num < tmp) {
1064         gtk_widget_set_sensitive (priv->chooser, FALSE);
1065     } else {
1066         gtk_widget_set_sensitive (priv->chooser, TRUE);
1067     }
1068
1069     priv->selected = num;
1070
1071     gtk_widget_queue_draw (priv->area_custom);
1072     gtk_widget_queue_draw (priv->area_defined);
1073
1074     priv->color = (num < tmp) ? priv->colors_defined[num] : priv->colors_custom[num - tmp];
1075
1076     hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (priv->chooser), 
1077             (num < tmp) ? &priv->colors_defined[num] : &priv->colors_custom[num - tmp]);
1078 }
1079
1080 static void 
1081 hildon_color_chooser_dialog_ascii_hex_to_color  (gchar *s, 
1082                                                  GdkColor *color)
1083 {
1084     int vals[12], i;
1085
1086     for (i = 0; i < 12; i++) {
1087         if (s[i] >= '0' && s[i] <= '9') {
1088             vals[i] = s[i] - 0x30;
1089         } else if (s[i] >= 'a' && s[i] <= 'f') {
1090             vals[i] = s[i] - 0x57;
1091         } else {
1092             vals[i] = 0;
1093         }
1094     }
1095
1096     color->red   = (vals[0] << 12) | (vals[1] <<  8) | (vals[2 ] <<  4) | (vals[3 ]);
1097     color->green = (vals[4] << 12) | (vals[5] <<  8) | (vals[6 ] <<  4) | (vals[7 ]);
1098     color->blue  = (vals[8] << 12) | (vals[9] <<  8) | (vals[10] <<  4) | (vals[11]);
1099 }
1100
1101 static void 
1102 hildon_color_chooser_dialog_color_to_ascii_hex  (gchar *s, 
1103                                                  GdkColor *color)
1104 {
1105     g_snprintf (s, 13, "%x%x%x%x%x%x%x%x%x%x%x%x",
1106          (color->red >> 12) & 0xf, (color->red >>  8) & 0xf,
1107          (color->red >>  4) & 0xf, (color->red      ) & 0xf,
1108          (color->green >> 12) & 0xf, (color->green >>  8) & 0xf,
1109          (color->green >>  4) & 0xf, (color->green      ) & 0xf,
1110          (color->blue >> 12) & 0xf, (color->blue >>  8) & 0xf,
1111          (color->blue >>  4) & 0xf, (color->blue      ) & 0xf);
1112 }
1113
1114 /**
1115  * hildon_color_chooser_dialog_new:
1116  *
1117  * Creates a new color chooser dialog.
1118  *
1119  * Returns: a new color chooser dialog.
1120  */
1121 GtkWidget*
1122 hildon_color_chooser_dialog_new                 (void)
1123 {
1124     return g_object_new (HILDON_TYPE_COLOR_CHOOSER_DIALOG, NULL);
1125 }
1126
1127 /**
1128  * hildon_color_chooser_dialog_get_color:
1129  * @dialog: a #HildonColorChooserDialog
1130  * @color: a color structure to fill with the currently selected color
1131  *
1132  * Retrives the currently selected color in the color chooser dialog.
1133  *
1134  */
1135 void
1136 hildon_color_chooser_dialog_get_color           (HildonColorChooserDialog *dialog, 
1137                                                  GdkColor *color)
1138 {
1139     /* FIXME Should return pending color? */
1140     HildonColorChooserDialogPrivate *priv;
1141
1142     g_return_if_fail (HILDON_IS_COLOR_CHOOSER_DIALOG (dialog));
1143     priv = HILDON_COLOR_CHOOSER_DIALOG_GET_PRIVATE (dialog);
1144     g_assert (priv);
1145
1146     hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER (priv->chooser), color);
1147 }
1148