Fix gtk-doc packaging
[hildon] / src / 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: Michael Dominic Kostrzewa <michael.kostrzewa@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.
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 #ifdef                                          HAVE_CONFIG_H
42 #include                                        <config.h>
43 #endif
44
45 #include                                        <memory.h>
46 #include                                        <string.h>
47 #include                                        <libintl.h>
48 #include                                        <gdk/gdk.h>
49 #include                                        <gdk/gdkkeysyms.h>
50 #include                                        <gtk/gtk.h>
51 #include                                        <gconf/gconf-client.h>
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), _("ecdg_bd_colour_selector_ok"), GTK_RESPONSE_OK);
218     gtk_dialog_add_button (GTK_DIALOG (object), _("ecdg_bd_colour_selector_cancel"), GTK_RESPONSE_CANCEL);
219     gtk_dialog_set_default_response (GTK_DIALOG (object), GTK_RESPONSE_OK);
220
221     g_signal_connect (G_OBJECT (priv->chooser), 
222             "insensitive-press", G_CALLBACK (hildon_color_chooser_dialog_insensitive_press), object);
223
224     g_signal_connect (G_OBJECT (priv->area_custom), 
225             "expose-event", G_CALLBACK (hildon_color_chooser_dialog_area_expose), object);
226
227     g_signal_connect (G_OBJECT (priv->area_defined), 
228             "expose-event", G_CALLBACK (hildon_color_chooser_dialog_area_expose), object);
229
230     g_signal_connect (G_OBJECT (priv->area_custom), 
231             "button-press-event", G_CALLBACK (hildon_color_chooser_dialog_area_button_press), object);
232
233     g_signal_connect (G_OBJECT (priv->area_defined), 
234             "button-press-event", G_CALLBACK (hildon_color_chooser_dialog_area_button_press), object);
235
236     g_signal_connect (G_OBJECT (priv->chooser), 
237             "color-changed", G_CALLBACK (hildon_color_chooser_dialog_color_changed), object);
238
239     gtk_widget_add_events (priv->area_custom, GDK_BUTTON_PRESS_MASK);
240     gtk_widget_add_events (priv->area_defined, GDK_BUTTON_PRESS_MASK);
241
242     priv->selected = 0;
243     priv->gconf_client = gconf_client_get_default ();
244
245     memset (&priv->style_info, 0, sizeof (HildonColorChooserStyleInfo));
246     
247     priv->colors_custom = NULL;
248     priv->colors_defined = NULL;
249     priv->gc_array = NULL;
250
251     priv->has_style = 0;
252 }
253
254 static void
255 hildon_color_chooser_dialog_class_init          (HildonColorChooserDialogClass *klass)
256 {
257     GtkWidgetClass *widget_klass = GTK_WIDGET_CLASS (klass);
258     GtkObjectClass *object_klass = GTK_OBJECT_CLASS (klass);
259     gchar tmp[32];
260     gint i;
261
262     widget_klass->size_request      = hildon_color_chooser_dialog_size_request;
263     widget_klass->size_allocate     = hildon_color_chooser_dialog_size_allocate;
264     widget_klass->realize           = hildon_color_chooser_dialog_realize;
265     widget_klass->unrealize         = hildon_color_chooser_dialog_unrealize;
266     widget_klass->style_set         = hildon_color_chooser_dialog_style_set;
267     widget_klass->show              = hildon_color_chooser_dialog_show;
268     widget_klass->show_all          = hildon_color_chooser_dialog_show_all;
269     widget_klass->key_press_event   = hildon_color_chooser_dialog_key_press_event;
270     widget_klass->key_release_event = hildon_color_chooser_dialog_key_release_event;
271
272
273     object_klass->destroy           = hildon_color_chooser_dialog_destroy;
274
275     parent_class = g_type_class_peek_parent (klass);
276
277     gtk_widget_class_install_style_property (widget_klass,
278             g_param_spec_boxed ("container_sizes",
279                 "Container sizes",
280                 "Container specific sizes",
281                 GTK_TYPE_BORDER,
282                 G_PARAM_READABLE));
283
284     gtk_widget_class_install_style_property (widget_klass,
285             g_param_spec_boxed ("radio_sizes",
286                 "Color radio sizes",
287                 "Color radio specific sizes",
288                 GTK_TYPE_BORDER,
289                 G_PARAM_READABLE));
290
291     gtk_widget_class_install_style_property (widget_klass,
292             g_param_spec_boxed ("num_buttons",
293                 "Number of buttons",
294                 "Number of color store buttons",
295                 GTK_TYPE_BORDER,
296                 G_PARAM_READABLE));
297
298     gtk_widget_class_install_style_property (widget_klass,
299             g_param_spec_boxed ("default_color", "Default color",
300                 "Default color for nonpainted custom colors",
301                 GDK_TYPE_COLOR,
302                 G_PARAM_READABLE));
303
304     for (i = 0; i < 32; i++) {
305         memset (tmp, 0, 32);
306         g_snprintf (tmp, 32, "defined_color%d", i);
307
308         gtk_widget_class_install_style_property (widget_klass,
309                 g_param_spec_boxed (tmp, "Defined color",
310                     "Pre-defined colors for the dialog",
311                     GDK_TYPE_COLOR,
312                     G_PARAM_READABLE));
313     }
314
315     g_type_class_add_private (object_klass, sizeof (HildonColorChooserDialogPrivate));
316 }
317
318 static void 
319 hildon_color_chooser_dialog_size_request        (GtkWidget *widget, 
320                                                  GtkRequisition *req)
321 {
322     HildonColorChooserDialogPrivate *priv = HILDON_COLOR_CHOOSER_DIALOG_GET_PRIVATE (widget);
323
324     g_assert (priv);
325
326     gtk_container_set_border_width (GTK_CONTAINER (priv->hbox), priv->style_info.cont_sizes.left);
327
328     gtk_box_set_spacing (GTK_BOX (priv->hbox), priv->style_info.cont_sizes.right);
329     gtk_box_set_spacing (GTK_BOX (priv->vbox), priv->style_info.cont_sizes.top);
330     gtk_box_set_spacing (GTK_BOX (GTK_DIALOG (widget)->vbox), priv->style_info.cont_sizes.bottom);
331
332     gtk_widget_set_size_request (priv->area_custom,
333             (priv->style_info.radio_sizes.left + 
334              2 * priv->style_info.radio_sizes.bottom) * 
335             (priv->style_info.num_buttons.top) +
336             (priv->style_info.num_buttons.top-1) *
337             priv->style_info.radio_sizes.top,
338             (priv->style_info.radio_sizes.right + 
339              2 * priv->style_info.radio_sizes.bottom) * 
340             (priv->style_info.num_buttons.bottom) +
341             (priv->style_info.num_buttons.bottom-1) * 
342             priv->style_info.radio_sizes.top);
343
344     gtk_widget_set_size_request (priv->area_defined,
345             (priv->style_info.radio_sizes.left + 
346              2 * priv->style_info.radio_sizes.bottom) * 
347             (priv->style_info.num_buttons.left) +
348             (priv->style_info.num_buttons.left-1) * 
349             priv->style_info.radio_sizes.top,
350             (priv->style_info.radio_sizes.right +  
351              2 * priv->style_info.radio_sizes.bottom) * 
352             (priv->style_info.num_buttons.right) +
353             (priv->style_info.num_buttons.right-1) * 
354             priv->style_info.radio_sizes.top);
355
356     GTK_WIDGET_CLASS (parent_class)->size_request (widget, req);
357 }
358
359 static void 
360 hildon_color_chooser_dialog_size_allocate       (GtkWidget *widget,
361                                                  GtkAllocation *alloc)
362 {
363     HildonColorChooserDialogPrivate *priv = HILDON_COLOR_CHOOSER_DIALOG_GET_PRIVATE (widget);
364
365     GdkRectangle rect;
366     int i, tmp, tmp2;
367
368     g_assert (priv);
369
370     GTK_WIDGET_CLASS (parent_class)->size_allocate (widget, alloc);
371
372     if (GTK_WIDGET_REALIZED (widget)) {
373         tmp  = (priv->style_info.num_buttons.left * priv->style_info.num_buttons.right);
374         tmp2 = (priv->style_info.num_buttons.top * priv->style_info.num_buttons.bottom);
375
376         for (i = 0; i < tmp; i++) {
377             rect.x = ((i % priv->style_info.num_buttons.left) * 
378                     (priv->style_info.radio_sizes.left + 
379                      priv->style_info.radio_sizes.top + 
380                      2 * priv->style_info.radio_sizes.bottom)) + 
381                 priv->style_info.radio_sizes.bottom;
382
383             rect.y = ((i / priv->style_info.num_buttons.left) * 
384                     (priv->style_info.radio_sizes.right + 
385                      priv->style_info.radio_sizes.top +
386                      2 * priv->style_info.radio_sizes.bottom)) + 
387                 priv->style_info.radio_sizes.bottom;
388
389             rect.width = priv->style_info.radio_sizes.left;
390             rect.height = priv->style_info.radio_sizes.right;
391
392             gdk_gc_set_clip_rectangle (priv->gc_array[i], &rect);
393         }
394
395         for (i = 0; i < tmp2; i++) {
396             rect.x = ((i % priv->style_info.num_buttons.top) * 
397                     (priv->style_info.radio_sizes.left + 
398                      priv->style_info.radio_sizes.top +
399                      2 * priv->style_info.radio_sizes.bottom)) + 
400                 priv->style_info.radio_sizes.bottom;
401
402             rect.y = ((i / priv->style_info.num_buttons.top) * 
403                     (priv->style_info.radio_sizes.right + 
404                      priv->style_info.radio_sizes.top +
405                      2 * priv->style_info.radio_sizes.bottom)) + priv->style_info.radio_sizes.bottom;
406
407             rect.width = priv->style_info.radio_sizes.left;
408             rect.height = priv->style_info.radio_sizes.right;
409
410             gdk_gc_set_clip_rectangle (priv->gc_array[i + tmp], &rect);
411         }
412     }
413 }
414
415 static void 
416 hildon_color_chooser_dialog_realize             (GtkWidget *widget)
417 {
418     HildonColorChooserDialogPrivate *priv = HILDON_COLOR_CHOOSER_DIALOG_GET_PRIVATE (widget);
419
420     GdkRectangle rect;
421     int i, tmp, tmp2;
422
423     g_assert (priv);
424     
425     GTK_WIDGET_CLASS(parent_class)->realize (widget);
426
427     tmp = (priv->style_info.num_buttons.left * priv->style_info.num_buttons.right) +
428         (priv->style_info.num_buttons.top * priv->style_info.num_buttons.bottom);
429
430     for (i = 0; i < tmp; i++) {
431         priv->gc_array[i] = gdk_gc_new (widget->window);
432     }
433
434     tmp  = (priv->style_info.num_buttons.left * priv->style_info.num_buttons.right);
435     tmp2 = (priv->style_info.num_buttons.top * priv->style_info.num_buttons.bottom);
436
437     for (i = 0; i < tmp; i++) {
438         gdk_gc_set_rgb_fg_color (priv->gc_array[i], &priv->colors_defined[i]);
439
440         rect.x = ((i % priv->style_info.num_buttons.left) * 
441                 (priv->style_info.radio_sizes.left + 
442                  priv->style_info.radio_sizes.top +
443                  2 * priv->style_info.radio_sizes.bottom)) + 
444             priv->style_info.radio_sizes.bottom;
445
446         rect.y = ((i / priv->style_info.num_buttons.left) * 
447                 (priv->style_info.radio_sizes.right + 
448                  priv->style_info.radio_sizes.top +
449                  2 * priv->style_info.radio_sizes.bottom)) + 
450             priv->style_info.radio_sizes.bottom;
451
452         rect.width = priv->style_info.radio_sizes.left;
453         rect.height = priv->style_info.radio_sizes.right;
454
455         gdk_gc_set_clip_rectangle (priv->gc_array[i], &rect);
456     }
457
458     for (i = 0; i < tmp2; i++) {
459         gdk_gc_set_rgb_fg_color (priv->gc_array[i + tmp], &priv->colors_custom[i]);
460
461         rect.x = ((i % priv->style_info.num_buttons.top) * 
462                 (priv->style_info.radio_sizes.left + 
463                  priv->style_info.radio_sizes.top +
464                  2 * priv->style_info.radio_sizes.bottom)) + 
465             priv->style_info.radio_sizes.bottom;
466
467         rect.y = ((i / priv->style_info.num_buttons.top) * 
468                 (priv->style_info.radio_sizes.right + 
469                  priv->style_info.radio_sizes.top +
470                  2 * priv->style_info.radio_sizes.bottom)) + 
471             priv->style_info.radio_sizes.bottom;
472
473         rect.width = priv->style_info.radio_sizes.left;
474         rect.height = priv->style_info.radio_sizes.right;
475
476         gdk_gc_set_clip_rectangle (priv->gc_array[i + tmp], &rect);
477     }
478 }
479
480 static void 
481 hildon_color_chooser_dialog_unrealize           (GtkWidget *widget)
482 {
483     HildonColorChooserDialogPrivate *priv = HILDON_COLOR_CHOOSER_DIALOG_GET_PRIVATE (widget);
484
485     int i, tmp;
486
487     tmp = (priv->style_info.num_buttons.left * priv->style_info.num_buttons.right) +
488         (priv->style_info.num_buttons.top * priv->style_info.num_buttons.bottom);
489
490     for (i = 0; i < tmp; i++) {
491         g_object_unref (priv->gc_array[i]);
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     } else {
520         priv->style_info.default_color.red   = 0x0000;
521         priv->style_info.default_color.green = 0x0000;
522         priv->style_info.default_color.blue  = 0x0000;
523         priv->style_info.default_color.pixel = 0x00000000;
524     }
525
526     hildon_color_chooser_dialog_refresh_style_info (dialog);
527
528     if (memcmp (&priv->style_info.num_buttons, &priv->style_info.last_num_buttons, sizeof (GtkBorder))) {
529         if (priv->colors_custom) {
530             g_free (priv->colors_custom);
531         } if (priv->colors_defined) {
532             g_free (priv->colors_defined);
533         } if (priv->gc_array) {
534             if (GTK_WIDGET_REALIZED (widget)) {
535                 tmpn = (priv->style_info.last_num_buttons.left * priv->style_info.last_num_buttons.right) +
536                     (priv->style_info.last_num_buttons.top * priv->style_info.last_num_buttons.bottom);
537
538                 for (i = 0; i < tmpn; i++) {
539                     g_object_unref (priv->gc_array[i]);
540                 }
541             }
542
543             g_free (priv->gc_array);
544         }
545
546         priv->colors_custom = (GdkColor *)
547             g_malloc0 (sizeof (GdkColor) * (priv->style_info.num_buttons.top * 
548                         priv->style_info.num_buttons.bottom));
549
550         priv->colors_defined = (GdkColor *)
551             g_malloc0 (sizeof(GdkColor) * (priv->style_info.num_buttons.left * 
552                         priv->style_info.num_buttons.right));
553
554         tmpn = (priv->style_info.num_buttons.left * priv->style_info.num_buttons.right) +
555             (priv->style_info.num_buttons.top * priv->style_info.num_buttons.bottom);
556
557         priv->gc_array = (GdkGC **) g_malloc0 (sizeof (GdkGC *) * tmpn);
558
559         if (priv->gconf_client) {
560
561             for (i = 0; i < (priv->style_info.num_buttons.top * priv->style_info.num_buttons.bottom); i++) {
562                 memset (key, 0, 128);
563                 /* FIXME Extremally bad hardcoding */
564                 g_snprintf (key, 128, "/system/osso/af/color_chooser/custom_color%d", i);
565                 val = gconf_client_get_string (priv->gconf_client, key, NULL);
566
567                 if (val) {
568                     hildon_color_chooser_dialog_ascii_hex_to_color (val, &priv->colors_custom[i]);
569                     g_free (val);
570                 } else {
571                     priv->colors_custom[i] = priv->style_info.default_color;
572                 }
573             }
574         } else {
575             for (i = 0; i < (priv->style_info.num_buttons.top * priv->style_info.num_buttons.bottom); i++) {
576                 priv->colors_custom[i] = priv->style_info.default_color;
577             }
578         }
579     }
580
581     tmpn = (priv->style_info.num_buttons.left * priv->style_info.num_buttons.right);
582
583     hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (priv->chooser),
584             (priv->selected < tmpn) ? 
585             &priv->colors_defined[priv->selected] : 
586             &priv->colors_custom[priv->selected - tmpn]);
587
588     for (i = 0; i < (priv->style_info.num_buttons.left * priv->style_info.num_buttons.right); i++) {
589         memset (tmp, 0, 32);
590         g_snprintf (tmp, 32, "defined_color%d", i);
591
592         gtk_widget_style_get (widget, tmp, &tmpcolor, NULL);
593
594         if (tmpcolor) {
595             priv->colors_defined[i] = *tmpcolor;
596         } else {
597             if(i < 16) {
598                 priv->colors_defined[i] = hardcoded_colors[i];
599             } else { /* fallback to prevent segfault */
600                 priv->colors_defined[i].red = 0x0000;
601                 priv->colors_defined[i].green = 0x0000;
602                 priv->colors_defined[i].blue = 0x0000;
603                 priv->colors_defined[i].pixel = 0x00000000;
604             }
605         }
606     }
607
608     if (GTK_WIDGET_REALIZED (widget)) {
609         for (i = 0; i < (priv->style_info.num_buttons.left * 
610                     priv->style_info.num_buttons.right); i++) {
611             gdk_gc_set_rgb_fg_color (priv->gc_array[i], &priv->colors_defined[i]);
612         }
613     }
614
615     if (setcolor)
616         hildon_color_chooser_dialog_set_color (HILDON_COLOR_CHOOSER_DIALOG (dialog), 
617                 &priv->pending_color);
618
619     gtk_widget_queue_resize (widget);
620
621     GTK_WIDGET_CLASS (parent_class)->style_set (widget, previous_style);
622 }
623
624 static void 
625 hildon_color_chooser_dialog_show                (GtkWidget *widget)
626 {
627     HildonColorChooserDialogPrivate *priv = HILDON_COLOR_CHOOSER_DIALOG_GET_PRIVATE (widget);
628
629     g_assert (priv);
630
631     gtk_widget_show (priv->hbox);
632     gtk_widget_show (priv->vbox);
633
634     gtk_widget_show (priv->chooser);
635
636     gtk_widget_show (priv->align_custom);
637     gtk_widget_show (priv->align_defined);
638
639     gtk_widget_show (priv->separator);
640
641     gtk_widget_show (priv->area_custom);
642     gtk_widget_show (priv->area_defined);
643
644     GTK_WIDGET_CLASS (parent_class)->show (widget);
645 }
646
647 /* FIXME WTF this function is even needed here? */
648 static void 
649 hildon_color_chooser_dialog_show_all            (GtkWidget *widget)
650 {
651     hildon_color_chooser_dialog_show (widget);
652 }
653
654 static gboolean 
655 hildon_color_chooser_dialog_key_press_event     (GtkWidget *widget, 
656                                                  GdkEventKey *event)
657 {
658     HildonColorChooserDialog *dialog = HILDON_COLOR_CHOOSER_DIALOG (widget);
659     HildonColorChooserDialogPrivate *priv = HILDON_COLOR_CHOOSER_DIALOG_GET_PRIVATE (widget);
660     int tmp, tot, sel;
661
662     g_assert (priv);
663
664     if (event->keyval == HILDON_HARDKEY_UP || event->keyval == HILDON_HARDKEY_DOWN ||
665             event->keyval == HILDON_HARDKEY_LEFT || event->keyval == HILDON_HARDKEY_RIGHT) {
666         tmp = (priv->style_info.num_buttons.top * priv->style_info.num_buttons.bottom);
667         tot = (priv->style_info.num_buttons.left * priv->style_info.num_buttons.right) + tmp;
668
669         switch (event->keyval) {
670
671             case HILDON_HARDKEY_UP:
672                 if(priv->selected >= priv->style_info.num_buttons.top) {
673                     if(priv->selected - priv->style_info.num_buttons.left >= tmp) {
674                         sel = priv->selected - priv->style_info.num_buttons.left;
675                     } else {
676                         sel = priv->selected - priv->style_info.num_buttons.top;
677                     }
678
679                     hildon_color_chooser_dialog_set_color_num (dialog, sel);
680                 }
681                 break;
682
683             case HILDON_HARDKEY_DOWN:
684                 if(priv->selected < tot - priv->style_info.num_buttons.left) {
685                     if(priv->selected < tmp) {
686                         sel = priv->selected + priv->style_info.num_buttons.top;
687                     } else {
688                         sel = priv->selected + priv->style_info.num_buttons.left;
689                     }
690
691                     hildon_color_chooser_dialog_set_color_num (dialog, sel);
692                 }
693                 break;
694
695             case HILDON_HARDKEY_LEFT:
696                 if ((priv->selected < tmp ? 
697                             (priv->selected % priv->style_info.num_buttons.top) : 
698                             ((priv->selected - tmp) % priv->style_info.num_buttons.left)) > 0) {
699                     sel = priv->selected - 1;
700
701                     hildon_color_chooser_dialog_set_color_num (dialog, sel);
702                 }
703                 break;
704
705             case HILDON_HARDKEY_RIGHT:
706                 if ((priv->selected < tmp) ? 
707                         (priv->selected % priv->style_info.num_buttons.top < priv->style_info.num_buttons.top - 1) :
708                         ((priv->selected - tmp) % priv->style_info.num_buttons.left < priv->style_info.num_buttons.left - 1)) {
709                     sel = priv->selected + 1;
710
711                     hildon_color_chooser_dialog_set_color_num (dialog, sel);
712                 }
713                 break;
714
715             default:
716                 break;
717         }
718
719         return FALSE;
720     }
721
722     return GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, event);
723 }
724
725 static gboolean
726 hildon_color_chooser_dialog_key_release_event   (GtkWidget *widget, 
727                                                  GdkEventKey *event)
728 {
729     if (event->keyval == HILDON_HARDKEY_UP || 
730         event->keyval == HILDON_HARDKEY_DOWN ||
731         event->keyval == HILDON_HARDKEY_LEFT || 
732         event->keyval == HILDON_HARDKEY_RIGHT) 
733     {
734         return FALSE;
735     }
736
737     return GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, event);
738 }
739
740 static void 
741 hildon_color_chooser_dialog_destroy             (GtkObject *object)
742 {
743     HildonColorChooserDialogPrivate *priv = HILDON_COLOR_CHOOSER_DIALOG_GET_PRIVATE (object);
744
745     gchar key[128], color[13];
746     int i, tmp;
747
748     g_assert (priv);
749
750     if (priv->gconf_client) {
751         memset (color, 0, 13);
752
753         tmp = (priv->style_info.num_buttons.top * priv->style_info.num_buttons.bottom);
754
755         for (i = 0; i < tmp; i++) {
756             memset (key, 0, 128);
757             /* FIXME Extremally bad hardcoding */
758             g_snprintf (key, 128, "/system/osso/af/color_chooser/custom_color%d", i);
759             hildon_color_chooser_dialog_color_to_ascii_hex (color, &priv->colors_custom[i]);
760             gconf_client_set_string (priv->gconf_client, key, color, NULL);
761         }
762
763         g_object_unref (priv->gconf_client);
764         priv->gconf_client = NULL;
765     }
766
767     if (priv->gc_array) {
768         g_free (priv->gc_array);
769         priv->gc_array = NULL;
770     } if (priv->colors_defined) {
771         g_free (priv->colors_defined);
772         priv->colors_defined = NULL;
773     } if (priv->colors_custom) {
774         g_free (priv->colors_custom);
775         priv->colors_custom = NULL;
776     }
777
778     GTK_OBJECT_CLASS (parent_class)->destroy (object);
779 }
780
781 /**
782  * hildon_color_chooser_dialog_set_color:
783  * @dialog: a #HildonColorChooserDialog
784  * @color: a color to set on the #HildonColorChooserDialog
785  *
786  * Sets the dialog to point at the given color. It'll first try to
787  * search the palette of the existing colors to match the passed color. 
788  * If the color is not found in the pallette, the color in the currently 
789  * selected box will be modified.
790  *
791  */
792 void 
793 hildon_color_chooser_dialog_set_color           (HildonColorChooserDialog *dialog, 
794                                                  GdkColor *color)
795 {
796     HildonColorChooserDialogPrivate *priv = HILDON_COLOR_CHOOSER_DIALOG_GET_PRIVATE (dialog);
797
798     int i, found = -1, tmp, tmp2;
799
800     g_assert (priv);
801
802     if (! priv->has_style) {
803         priv->pending_color = *color;
804         return;
805     }
806
807     tmp  = (priv->style_info.num_buttons.left * priv->style_info.num_buttons.right);
808     tmp2 = (priv->style_info.num_buttons.top * priv->style_info.num_buttons.bottom);
809
810     for (i = 0; i < tmp; i++) {
811         if (priv->colors_defined[i].red == color->red &&
812                 priv->colors_defined[i].green == color->green &&
813                 priv->colors_defined[i].blue == color->blue) {
814             found = i;
815             break;
816         }
817     }
818
819     if (found == -1) {
820         for (i = 0; i < tmp2; i++) {
821             if (priv->colors_custom[i].red == color->red &&
822                     priv->colors_custom[i].green == color->green &&
823                     priv->colors_custom[i].blue == color->blue) {
824                 found = i + tmp;
825                 break;
826             }
827         }
828     }
829
830     if (found == -1) {
831         priv->colors_custom[tmp2-1] = *color;
832         if (GTK_WIDGET_REALIZED (GTK_WIDGET (dialog))) {
833             gdk_gc_set_rgb_fg_color (priv->gc_array[tmp2-1], color);
834         }
835         hildon_color_chooser_dialog_set_color_num (dialog, tmp2 - 1);
836     } else {
837         hildon_color_chooser_dialog_set_color_num (dialog, found);
838     }
839 }
840
841 static gboolean 
842 hildon_color_chooser_dialog_area_expose         (GtkWidget *widget, 
843                                                  GdkEventExpose *event, 
844                                                  gpointer data)
845 {
846     HildonColorChooserDialogPrivate *priv = HILDON_COLOR_CHOOSER_DIALOG_GET_PRIVATE (data);
847
848     int i, num_selected, tot_w, tot_h, spacing, brd, x, y;
849     GdkGC **start_gc;
850     int tmp, w, h;
851
852     g_assert (priv);
853
854     tmp = (priv->style_info.num_buttons.left * priv->style_info.num_buttons.right);
855
856     if (widget == priv->area_custom) {
857         num_selected = priv->selected - tmp;
858         start_gc = priv->gc_array + tmp;
859         tmp = (priv->style_info.num_buttons.top * priv->style_info.num_buttons.bottom);
860         w = priv->style_info.num_buttons.top; 
861         h = priv->style_info.num_buttons.bottom;
862     } else { /* widget == dialog->area_defined */
863         num_selected = priv->selected;
864         start_gc = priv->gc_array;
865         w = priv->style_info.num_buttons.left; 
866         h = priv->style_info.num_buttons.right;
867     }
868
869     spacing = priv->style_info.radio_sizes.top;
870     brd = priv->style_info.radio_sizes.bottom;
871     tot_w = priv->style_info.radio_sizes.left + 2 * brd;
872     tot_h = priv->style_info.radio_sizes.right + 2 * brd;
873
874     for (i = 0; i < tmp; i++) {
875         x = ((i % w) * (tot_w + spacing));
876         y = ((i / w) * (tot_h + spacing));
877
878         gdk_draw_rectangle (widget->window,
879                 widget->style->black_gc,
880                 TRUE,
881                 (i == num_selected) ? x : x + 2,  
882                 (i == num_selected) ? y : y + 2,
883                 (i == num_selected) ? tot_w : tot_w - 4,
884                 (i == num_selected) ? tot_h : tot_h - 4);
885
886         gdk_draw_rectangle(widget->window,
887                 widget->style->white_gc,
888                 TRUE,
889                 x + 3,  
890                 y + 3,
891                 tot_w - 6,
892                 tot_h - 6);
893
894         gdk_draw_rectangle(widget->window,
895                 start_gc [i],
896                 TRUE,
897                 x + 3 + 1,  
898                 y + 3 + 1,
899                 tot_w - 6 - 2,
900                 tot_h - 6 - 2);
901     }
902
903     return FALSE;
904 }
905
906 static gboolean 
907 hildon_color_chooser_dialog_area_button_press   (GtkWidget *widget, 
908                                                  GdkEventButton *event, 
909                                                  gpointer data)
910 {
911     HildonColorChooserDialog *dialog = HILDON_COLOR_CHOOSER_DIALOG (data);
912     HildonColorChooserDialogPrivate *priv = HILDON_COLOR_CHOOSER_DIALOG_GET_PRIVATE (data);
913
914     int i, hskip, vskip, brd, selection = -1;
915     int x, y, tmp, tmp2, w;
916
917     g_assert (priv);
918
919     x = event->x;
920     y = event->y;
921
922     brd = priv->style_info.radio_sizes.bottom;
923     hskip = priv->style_info.radio_sizes.left + 
924         priv->style_info.radio_sizes.top + 2 * brd;
925     vskip = priv->style_info.radio_sizes.right + 
926         priv->style_info.radio_sizes.top + 2 * brd;
927
928     tmp  = (priv->style_info.num_buttons.left * priv->style_info.num_buttons.right);
929     tmp2 = (priv->style_info.num_buttons.top * priv->style_info.num_buttons.bottom);
930
931     if (widget == priv->area_defined) {
932         w = priv->style_info.num_buttons.left;
933
934         for (i = 0; i < tmp; i++) {
935             if (x >= hskip * (i % w) + brd && x < hskip * (i % w) + brd + priv->style_info.radio_sizes.left &&
936                 y >= vskip * (i / w) + brd && y < hskip * (i / w) + brd + priv->style_info.radio_sizes.right) {
937                 selection = i;
938                 break;
939             }
940         }
941     } else {
942         w = priv->style_info.num_buttons.top;
943         for (i = 0; i < tmp2; i++) {
944             if (x >= hskip * (i % w) + brd && x < hskip * (i % w) + brd + priv->style_info.radio_sizes.left &&
945                 y >= vskip * (i / w) + brd && y < hskip * (i / w) + brd + priv->style_info.radio_sizes.right) {
946                 selection = i + tmp;
947                 break;
948             }
949         }
950     }
951
952     if (selection != -1) {
953         hildon_color_chooser_dialog_set_color_num (dialog, selection);
954     }
955
956     return FALSE;
957 }
958
959 static void 
960 hildon_color_chooser_dialog_color_changed       (HildonColorChooser *chooser, 
961                                                  gpointer data)
962 {
963     HildonColorChooserDialogPrivate *priv = HILDON_COLOR_CHOOSER_DIALOG_GET_PRIVATE (data);
964     char key[128], color_str[13];
965     int tmp;
966     GdkColor *color = g_new (GdkColor, 1);
967
968     g_assert (priv);
969
970     hildon_color_chooser_get_color (chooser, color);
971
972     tmp = (priv->style_info.num_buttons.left * priv->style_info.num_buttons.right);
973
974     if (priv->selected >= tmp) {
975         priv->colors_custom[priv->selected - tmp] = *color;
976
977         gdk_gc_set_rgb_fg_color (priv->gc_array[priv->selected], &priv->colors_custom[priv->selected - tmp]);
978         gtk_widget_queue_draw (priv->area_custom);
979
980         if (priv->gconf_client) {
981             memset (key, 0, 128);
982             memset (color_str, 0, 13);
983             /* FIXME Ugly hardcoded stuff! */
984             g_snprintf (key, 128, "/system/osso/af/color_chooser/custom_color%d", priv->selected - tmp);
985             hildon_color_chooser_dialog_color_to_ascii_hex (color_str, &priv->colors_custom[priv->selected - tmp]);
986             gconf_client_set_string (priv->gconf_client, key, color_str, NULL);
987         }
988     }
989 }
990
991 static void 
992 hildon_color_chooser_dialog_insensitive_press   (GtkWidget *widget, 
993                                                  gpointer data)
994 {
995     hildon_banner_show_information (widget, NULL, _("ecdg_ib_colour_selector_predefined"));
996 }
997
998 /* function has size defaults */
999 static void 
1000 hildon_color_chooser_dialog_refresh_style_info  (HildonColorChooserDialog *dialog)
1001 {
1002     GtkBorder *tmp1, *tmp2, *tmp3;
1003     HildonColorChooserDialogPrivate *priv = HILDON_COLOR_CHOOSER_DIALOG_GET_PRIVATE (dialog);
1004
1005     g_assert (priv);
1006
1007     gtk_widget_style_get (GTK_WIDGET (dialog), "container_sizes", &tmp1,
1008             "radio_sizes", &tmp2, "num_buttons", &tmp3, NULL);
1009
1010     priv->style_info.last_num_buttons = priv->style_info.num_buttons;
1011
1012     if (tmp1) {
1013         priv->style_info.cont_sizes = *tmp1;
1014         g_free (tmp1);
1015     } else {
1016         priv->style_info.cont_sizes.left = 0;
1017         priv->style_info.cont_sizes.right = 8;
1018         priv->style_info.cont_sizes.top = 4;
1019         priv->style_info.cont_sizes.bottom = 0;
1020     }
1021
1022     if (tmp2) {
1023         priv->style_info.radio_sizes = *tmp2;
1024         g_free (tmp2);
1025     } else {
1026         priv->style_info.radio_sizes.left = 16;
1027         priv->style_info.radio_sizes.right = 16;
1028         priv->style_info.radio_sizes.top = 4;
1029         priv->style_info.radio_sizes.bottom = 2;
1030     }
1031
1032     if (tmp3) {
1033         priv->style_info.num_buttons = *tmp3;
1034         g_free (tmp3);
1035     } else {
1036         priv->style_info.num_buttons.left = 8;
1037         priv->style_info.num_buttons.right = 2;
1038         priv->style_info.num_buttons.top = 8;
1039         priv->style_info.num_buttons.bottom = 2;
1040     }
1041 }
1042
1043 static void 
1044 hildon_color_chooser_dialog_set_color_num       (HildonColorChooserDialog *dialog, 
1045                                                  gint num)
1046 {
1047     HildonColorChooserDialogPrivate *priv = HILDON_COLOR_CHOOSER_DIALOG_GET_PRIVATE (dialog);
1048
1049     int tmp;
1050
1051     g_assert (priv);
1052
1053     tmp = (priv->style_info.num_buttons.left * priv->style_info.num_buttons.right);
1054
1055     if (num < tmp) {
1056         gtk_widget_set_sensitive (priv->chooser, FALSE);
1057     } else {
1058         gtk_widget_set_sensitive (priv->chooser, TRUE);
1059     }
1060
1061     priv->selected = num;
1062
1063     gtk_widget_queue_draw (priv->area_custom);
1064     gtk_widget_queue_draw (priv->area_defined);
1065
1066     priv->color = (num < tmp) ? priv->colors_defined[num] : priv->colors_custom[num - tmp];
1067
1068     hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (priv->chooser), 
1069             (num < tmp) ? &priv->colors_defined[num] : &priv->colors_custom[num - tmp]);
1070 }
1071
1072 static void 
1073 hildon_color_chooser_dialog_ascii_hex_to_color  (gchar *s, 
1074                                                  GdkColor *color)
1075 {
1076     int vals[12], i;
1077
1078     for (i = 0; i < 12; i++) {
1079         if (s[i] >= '0' && s[i] <= '9') {
1080             vals[i] = s[i] - 0x30;
1081         } else if (s[i] >= 'a' && s[i] <= 'f') {
1082             vals[i] = s[i] - 0x57;
1083         } else {
1084             vals[i] = 0;
1085         }
1086     }
1087
1088     color->red   = (vals[0] << 12) | (vals[1] <<  8) | (vals[2 ] <<  4) | (vals[3 ]);
1089     color->green = (vals[4] << 12) | (vals[5] <<  8) | (vals[6 ] <<  4) | (vals[7 ]);
1090     color->blue  = (vals[8] << 12) | (vals[9] <<  8) | (vals[10] <<  4) | (vals[11]);
1091 }
1092
1093 static void 
1094 hildon_color_chooser_dialog_color_to_ascii_hex  (gchar *s, 
1095                                                  GdkColor *color)
1096 {
1097     g_snprintf (s, 13, "%x%x%x%x%x%x%x%x%x%x%x%x",
1098          (color->red >> 12) & 0xf, (color->red >>  8) & 0xf,
1099          (color->red >>  4) & 0xf, (color->red      ) & 0xf,
1100          (color->green >> 12) & 0xf, (color->green >>  8) & 0xf,
1101          (color->green >>  4) & 0xf, (color->green      ) & 0xf,
1102          (color->blue >> 12) & 0xf, (color->blue >>  8) & 0xf,
1103          (color->blue >>  4) & 0xf, (color->blue      ) & 0xf);
1104 }
1105
1106 /**
1107  * hildon_color_chooser_dialog_new:
1108  *
1109  * Creates a new color chooser dialog.
1110  *
1111  * Returns: a new color chooser dialog.
1112  */
1113 GtkWidget*
1114 hildon_color_chooser_dialog_new                 (void)
1115 {
1116     return g_object_new (HILDON_TYPE_COLOR_CHOOSER_DIALOG, NULL);
1117 }
1118
1119 /**
1120  * hildon_color_chooser_dialog_get_color:
1121  * @dialog: a #HildonColorChooserDialog
1122  * @color: a color structure to fill with the currently selected color
1123  *
1124  * Retrives the currently selected color in the color chooser dialog.
1125  *
1126  */
1127 void
1128 hildon_color_chooser_dialog_get_color           (HildonColorChooserDialog *dialog, 
1129                                                  GdkColor *color)
1130 {
1131     /* FIXME Should return pending color? */
1132     HildonColorChooserDialogPrivate *priv;
1133
1134     g_return_if_fail (HILDON_IS_COLOR_CHOOSER_DIALOG (dialog));
1135     priv = HILDON_COLOR_CHOOSER_DIALOG_GET_PRIVATE (dialog);
1136     g_assert (priv);
1137
1138     hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER (priv->chooser), color);
1139 }
1140