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