2006-08-30 Michael Dominic Kostrzewa <michael.kostrzewa@nokia.com>
[hildon] / hildon-widgets-plugins / hildon-color-chooser-dialog-hsv.c
1 /*
2  * This file is part of hildon-libs
3  *
4  * Copyright (C) 2005, 2006 Nokia Corporation.
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
254
255   g_signal_connect(G_OBJECT(object->chooser), "insensitive-press", G_CALLBACK(hildon_color_chooser_dialog_hsv_chooser_insensitive_press), object);
256
257
258   g_signal_connect(G_OBJECT(object->area_custom), "expose-event", G_CALLBACK(hildon_color_chooser_dialog_hsv_area_expose), object);
259   g_signal_connect(G_OBJECT(object->area_defined), "expose-event", G_CALLBACK(hildon_color_chooser_dialog_hsv_area_expose), object);
260
261   g_signal_connect(G_OBJECT(object->area_custom), "button-press-event", G_CALLBACK(hildon_color_chooser_dialog_hsv_area_button_press), object);
262   g_signal_connect(G_OBJECT(object->area_defined), "button-press-event", G_CALLBACK(hildon_color_chooser_dialog_hsv_area_button_press), object);
263
264   gtk_widget_add_events(object->area_custom, GDK_BUTTON_PRESS_MASK);
265   gtk_widget_add_events(object->area_defined, GDK_BUTTON_PRESS_MASK);
266
267
268   object->selected = 0;
269
270
271   g_signal_connect(G_OBJECT(object->chooser), "color-changed", G_CALLBACK(hildon_color_chooser_dialog_hsv_chooser_color_changed), object);
272
273
274   object->gconf_data.client = gconf_client_get_default();
275
276
277   memset(&object->style_info, 0, sizeof(HildonColorChooserStyleInfo));
278
279
280   object->colors_custom = NULL;
281   object->colors_defined = NULL;
282
283   object->gc_array = NULL;
284
285
286   object->has_style = 0;
287 }
288
289 static void hildon_color_chooser_dialog_hsv_class_init(HildonColorChooserDialogHSVClass *klass)
290 {
291   GtkWidgetClass *widget_klass = GTK_WIDGET_CLASS(klass);
292   GtkObjectClass *object_klass = GTK_OBJECT_CLASS(klass);
293   HildonColorChooserDialogClass *dialog_klass = HILDON_COLOR_CHOOSER_DIALOG_CLASS(klass);
294   gchar tmp[32];
295   gint i;
296
297
298   widget_klass->size_request = hildon_color_chooser_dialog_hsv_size_request;
299   widget_klass->size_allocate = hildon_color_chooser_dialog_hsv_size_allocate;
300
301   widget_klass->realize = hildon_color_chooser_dialog_hsv_realize;
302   widget_klass->unrealize = hildon_color_chooser_dialog_hsv_unrealize;
303
304   widget_klass->style_set = hildon_color_chooser_dialog_hsv_style_set;
305
306   widget_klass->show = hildon_color_chooser_dialog_hsv_show;
307   widget_klass->show_all = hildon_color_chooser_dialog_hsv_show_all;
308
309   widget_klass->key_press_event = hildon_color_chooser_dialog_hsv_key_press_event;
310   widget_klass->key_release_event = hildon_color_chooser_dialog_hsv_key_release_event;
311
312
313   object_klass->destroy = hildon_color_chooser_dialog_hsv_destroy;
314
315
316   dialog_klass->set_color = hildon_color_chooser_dialog_hsv_set_color;
317
318
319   parent_klass = g_type_class_peek_parent(klass);
320
321
322   gtk_widget_class_install_style_property(widget_klass,
323                                           g_param_spec_boxed("container_sizes",
324                                                              "Container sizes",
325                                                              "Container specific sizes",
326                                                              GTK_TYPE_BORDER,
327                                                              G_PARAM_READABLE));
328
329   gtk_widget_class_install_style_property(widget_klass,
330                                           g_param_spec_boxed("radio_sizes",
331                                                              "Color radio sizes",
332                                                              "Color radio specific sizes",
333                                                              GTK_TYPE_BORDER,
334                                                              G_PARAM_READABLE));
335
336   gtk_widget_class_install_style_property(widget_klass,
337                                           g_param_spec_boxed("num_buttons",
338                                                              "Number of buttons",
339                                                              "Number of color store buttons",
340                                                              GTK_TYPE_BORDER,
341                                                              G_PARAM_READABLE));
342
343
344   gtk_widget_class_install_style_property(widget_klass,
345                                           g_param_spec_boxed("default_color", "Default color",
346                                                              "Default color for nonpainted custom colors",
347                                                              GDK_TYPE_COLOR,
348                                                              G_PARAM_READABLE));
349
350
351   for(i = 0; i < 32; i++) {
352     memset(tmp, 0, 32);
353     g_snprintf(tmp, 32, "defined_color%d", i);
354
355     gtk_widget_class_install_style_property(widget_klass,
356                                             g_param_spec_boxed(tmp, "Defined color",
357                                                                "Pre-defined colors for the dialog",
358                                                                GDK_TYPE_COLOR,
359                                                                G_PARAM_READABLE));
360   }
361 }
362
363
364 static void hildon_color_chooser_dialog_hsv_size_request(GtkWidget *widget, GtkRequisition *req)
365 {
366   HildonColorChooserDialogHSV *dialog = HILDON_COLOR_CHOOSER_DIALOG_HSV(widget);
367
368
369   gtk_container_set_border_width(GTK_CONTAINER(dialog->hbox), dialog->style_info.cont_sizes.left);
370
371   gtk_box_set_spacing(GTK_BOX(dialog->hbox), dialog->style_info.cont_sizes.right);
372   gtk_box_set_spacing(GTK_BOX(dialog->vbox), dialog->style_info.cont_sizes.top);
373   gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(widget)->vbox), dialog->style_info.cont_sizes.bottom);
374
375
376   gtk_widget_set_size_request(dialog->area_custom,
377                               (dialog->style_info.radio_sizes.left + 2*dialog->style_info.radio_sizes.bottom)*(dialog->style_info.num_buttons.top) +
378                               (dialog->style_info.num_buttons.top-1)*dialog->style_info.radio_sizes.top,
379                               (dialog->style_info.radio_sizes.right + 2*dialog->style_info.radio_sizes.bottom)*(dialog->style_info.num_buttons.bottom) +
380                               (dialog->style_info.num_buttons.bottom-1)*dialog->style_info.radio_sizes.top);
381   gtk_widget_set_size_request(dialog->area_defined,
382                               (dialog->style_info.radio_sizes.left + 2*dialog->style_info.radio_sizes.bottom)*(dialog->style_info.num_buttons.left) +
383                               (dialog->style_info.num_buttons.left-1)*dialog->style_info.radio_sizes.top,
384                               (dialog->style_info.radio_sizes.right + 2*dialog->style_info.radio_sizes.bottom)*(dialog->style_info.num_buttons.right) +
385                               (dialog->style_info.num_buttons.right-1)*dialog->style_info.radio_sizes.top);
386
387
388   GTK_WIDGET_CLASS(parent_klass)->size_request(widget, req);
389 }
390
391 static void hildon_color_chooser_dialog_hsv_size_allocate(GtkWidget *widget, GtkAllocation *alloc)
392 {
393   HildonColorChooserDialogHSV *dialog = HILDON_COLOR_CHOOSER_DIALOG_HSV(widget);
394   GdkRectangle rect;
395   int i, tmp, tmp2;
396
397
398   GTK_WIDGET_CLASS(parent_klass)->size_allocate(widget, alloc);
399
400
401   if(GTK_WIDGET_REALIZED(widget)) {
402     tmp  = (dialog->style_info.num_buttons.left * dialog->style_info.num_buttons.right);
403     tmp2 = (dialog->style_info.num_buttons.top * dialog->style_info.num_buttons.bottom);
404
405     for(i = 0; i < tmp; i++) {
406       rect.x = ((i % dialog->style_info.num_buttons.left) * (dialog->style_info.radio_sizes.left + dialog->style_info.radio_sizes.top +
407                2*dialog->style_info.radio_sizes.bottom)) + dialog->style_info.radio_sizes.bottom;
408       rect.y = ((i / dialog->style_info.num_buttons.left) * (dialog->style_info.radio_sizes.right + dialog->style_info.radio_sizes.top +
409                2*dialog->style_info.radio_sizes.bottom)) + dialog->style_info.radio_sizes.bottom;
410       rect.width = dialog->style_info.radio_sizes.left;
411       rect.height = dialog->style_info.radio_sizes.right;
412
413       gdk_gc_set_clip_rectangle(dialog->gc_array[i], &rect);
414     }
415
416     for(i = 0; i < tmp2; i++) {
417       rect.x = ((i % dialog->style_info.num_buttons.top) * (dialog->style_info.radio_sizes.left + dialog->style_info.radio_sizes.top +
418                2*dialog->style_info.radio_sizes.bottom)) + dialog->style_info.radio_sizes.bottom;
419       rect.y = ((i / dialog->style_info.num_buttons.top) * (dialog->style_info.radio_sizes.right + dialog->style_info.radio_sizes.top +
420                2*dialog->style_info.radio_sizes.bottom)) + dialog->style_info.radio_sizes.bottom;
421       rect.width = dialog->style_info.radio_sizes.left;
422       rect.height = dialog->style_info.radio_sizes.right;
423
424       gdk_gc_set_clip_rectangle(dialog->gc_array[i + tmp], &rect);
425     }
426   }
427 }
428
429
430 static void hildon_color_chooser_dialog_hsv_realize(GtkWidget *widget)
431 {
432   HildonColorChooserDialogHSV *dialog = HILDON_COLOR_CHOOSER_DIALOG_HSV(widget);
433   GdkRectangle rect;
434   int i, tmp, tmp2;
435
436
437   GTK_WIDGET_CLASS(parent_klass)->realize(widget);
438
439
440   tmp = (dialog->style_info.num_buttons.left * dialog->style_info.num_buttons.right) +
441         (dialog->style_info.num_buttons.top * dialog->style_info.num_buttons.bottom);
442
443   for(i = 0; i < tmp; i++) {
444     dialog->gc_array[i] = gdk_gc_new(widget->window);
445   }
446
447
448
449   tmp  = (dialog->style_info.num_buttons.left * dialog->style_info.num_buttons.right);
450   tmp2 = (dialog->style_info.num_buttons.top * dialog->style_info.num_buttons.bottom);
451
452   for(i = 0; i < tmp; i++) {
453     gdk_gc_set_rgb_fg_color(dialog->gc_array[i], &dialog->colors_defined[i]);
454
455     rect.x = ((i % dialog->style_info.num_buttons.left) * (dialog->style_info.radio_sizes.left + dialog->style_info.radio_sizes.top +
456              2*dialog->style_info.radio_sizes.bottom)) + dialog->style_info.radio_sizes.bottom;
457     rect.y = ((i / dialog->style_info.num_buttons.left) * (dialog->style_info.radio_sizes.right + dialog->style_info.radio_sizes.top +
458              2*dialog->style_info.radio_sizes.bottom)) + dialog->style_info.radio_sizes.bottom;
459     rect.width = dialog->style_info.radio_sizes.left;
460     rect.height = dialog->style_info.radio_sizes.right;
461
462     gdk_gc_set_clip_rectangle(dialog->gc_array[i], &rect);
463   }
464
465   for(i = 0; i < tmp2; i++) {
466     gdk_gc_set_rgb_fg_color(dialog->gc_array[i + tmp], &dialog->colors_custom[i]);
467
468     rect.x = ((i % dialog->style_info.num_buttons.top) * (dialog->style_info.radio_sizes.left + dialog->style_info.radio_sizes.top +
469              2*dialog->style_info.radio_sizes.bottom)) + dialog->style_info.radio_sizes.bottom;
470     rect.y = ((i / dialog->style_info.num_buttons.top) * (dialog->style_info.radio_sizes.right + dialog->style_info.radio_sizes.top +
471              2*dialog->style_info.radio_sizes.bottom)) + dialog->style_info.radio_sizes.bottom;
472     rect.width = dialog->style_info.radio_sizes.left;
473     rect.height = dialog->style_info.radio_sizes.right;
474
475     gdk_gc_set_clip_rectangle(dialog->gc_array[i + tmp], &rect);
476   }
477 }
478
479 static void hildon_color_chooser_dialog_hsv_unrealize(GtkWidget *widget)
480 {
481   HildonColorChooserDialogHSV *dialog = HILDON_COLOR_CHOOSER_DIALOG_HSV(widget);
482   int i, tmp;
483
484
485   tmp = (dialog->style_info.num_buttons.left * dialog->style_info.num_buttons.right) +
486         (dialog->style_info.num_buttons.top * dialog->style_info.num_buttons.bottom);
487
488   for(i = 0; i < tmp; i++) {
489     g_object_unref(dialog->gc_array[i]);
490   }
491
492
493   GTK_WIDGET_CLASS(parent_klass)->unrealize(widget);
494 }
495
496
497 static void hildon_color_chooser_dialog_hsv_style_set(GtkWidget *widget, GtkStyle *previous_style)
498 {
499   HildonColorChooserDialogHSV *dialog = HILDON_COLOR_CHOOSER_DIALOG_HSV(widget);
500   GdkColor *tmpcolor;
501   gchar tmp[32], key[128], *val;
502   int i, tmpn, setcolor = 0;
503
504
505   if(!dialog->has_style)
506     setcolor = 1;
507
508   dialog->has_style = 1;
509
510
511   gtk_widget_style_get(widget, "default_color", &tmpcolor, NULL);
512   if(tmpcolor) {
513     dialog->style_info.default_color = *tmpcolor;
514   } else {
515     dialog->style_info.default_color.red   = 0x0000;
516     dialog->style_info.default_color.green = 0x0000;
517     dialog->style_info.default_color.blue  = 0x0000;
518     dialog->style_info.default_color.pixel = 0x00000000;
519   }
520
521
522   hildon_color_chooser_dialog_hsv_refresh_style_info(dialog);
523
524
525   if(memcmp(&dialog->style_info.num_buttons, &dialog->style_info.last_num_buttons, sizeof(GtkBorder))) {
526     if(dialog->colors_custom) {
527       g_free(dialog->colors_custom);
528     } if(dialog->colors_defined) {
529       g_free(dialog->colors_defined);
530     } if(dialog->gc_array) {
531       if(GTK_WIDGET_REALIZED(widget)) {
532         tmpn = (dialog->style_info.last_num_buttons.left * dialog->style_info.last_num_buttons.right) +
533                (dialog->style_info.last_num_buttons.top * dialog->style_info.last_num_buttons.bottom);
534
535         for(i = 0; i < tmpn; i++) {
536           g_object_unref(dialog->gc_array[i]);
537         }
538       }
539
540       g_free(dialog->gc_array);
541     }
542
543     dialog->colors_custom  = (GdkColor *)g_malloc0(sizeof(GdkColor) * (dialog->style_info.num_buttons.top * dialog->style_info.num_buttons.bottom));
544     dialog->colors_defined = (GdkColor *)g_malloc0(sizeof(GdkColor) * (dialog->style_info.num_buttons.left * dialog->style_info.num_buttons.right));
545
546
547     tmpn = (dialog->style_info.num_buttons.left * dialog->style_info.num_buttons.right) +
548            (dialog->style_info.num_buttons.top * dialog->style_info.num_buttons.bottom);
549     dialog->gc_array = (GdkGC **)g_malloc0(sizeof(GdkGC *) * tmpn);
550
551
552     if(dialog->gconf_data.client) {
553       for(i = 0; i < (dialog->style_info.num_buttons.top * dialog->style_info.num_buttons.bottom); i++) {
554         memset(key, 0, 128);
555         g_snprintf(key, 128, "/system/osso/af/color_chooser/custom_color%d", i);
556         val = gconf_client_get_string(dialog->gconf_data.client, key, NULL);
557         if(val) {
558           hildon_color_chooser_dialog_hsv_ascii_hex_to_color(val, &dialog->colors_custom[i]);
559           g_free(val);
560         } else {
561           dialog->colors_custom[i] = dialog->style_info.default_color;
562         }
563       }
564     } else {
565       for(i = 0; i < (dialog->style_info.num_buttons.top * dialog->style_info.num_buttons.bottom); i++) {
566         dialog->colors_custom[i] = dialog->style_info.default_color;
567       }
568     }
569   }
570
571
572   tmpn = (dialog->style_info.num_buttons.left * dialog->style_info.num_buttons.right);
573
574   hildon_color_chooser_set_color(HILDON_COLOR_CHOOSER(dialog->chooser),
575                                  (dialog->selected < tmpn) ? &dialog->colors_defined[dialog->selected] : &dialog->colors_custom[dialog->selected - tmpn]);
576
577
578   for(i = 0; i < (dialog->style_info.num_buttons.left * dialog->style_info.num_buttons.right); i++) {
579     memset(tmp, 0, 32);
580     g_snprintf(tmp, 32, "defined_color%d", i);
581
582     gtk_widget_style_get(widget, tmp, &tmpcolor, NULL);
583
584     if(tmpcolor) {
585       dialog->colors_defined[i] = *tmpcolor;
586     } else {
587       if(i < 16) {
588         dialog->colors_defined[i] = hardcoded_colors[i];
589       } else { /* fallback to prevent segfault */
590         dialog->colors_defined[i].red = 0x0000;
591         dialog->colors_defined[i].green = 0x0000;
592         dialog->colors_defined[i].blue = 0x0000;
593         dialog->colors_defined[i].pixel = 0x00000000;
594       }
595     }
596   }
597
598
599   if(GTK_WIDGET_REALIZED(widget)) {
600     for(i = 0; i < (dialog->style_info.num_buttons.left * dialog->style_info.num_buttons.right); i++) {
601       gdk_gc_set_rgb_fg_color(dialog->gc_array[i], &dialog->colors_defined[i]);
602     }
603   }
604
605
606   if(setcolor)
607     hildon_color_chooser_dialog_hsv_set_color(HILDON_COLOR_CHOOSER_DIALOG(dialog), &dialog->pending_color);
608
609
610   gtk_widget_queue_resize(widget);
611
612
613   GTK_WIDGET_CLASS(parent_klass)->style_set(widget, previous_style);
614 }
615
616
617 static void hildon_color_chooser_dialog_hsv_show(GtkWidget *widget)
618 {
619   HildonColorChooserDialogHSV *dialog = HILDON_COLOR_CHOOSER_DIALOG_HSV(widget);
620
621
622   gtk_widget_show(dialog->hbox);
623   gtk_widget_show(dialog->vbox);
624
625   gtk_widget_show(dialog->chooser);
626
627   gtk_widget_show(dialog->align_custom);
628   gtk_widget_show(dialog->align_defined);
629
630   gtk_widget_show(dialog->separator);
631
632   gtk_widget_show(dialog->area_custom);
633   gtk_widget_show(dialog->area_defined);
634
635
636   GTK_WIDGET_CLASS(parent_klass)->show(widget);
637 }
638
639 static void hildon_color_chooser_dialog_hsv_show_all(GtkWidget *widget)
640 {
641   hildon_color_chooser_dialog_hsv_show(widget);
642 }
643
644
645 static gboolean hildon_color_chooser_dialog_hsv_key_press_event(GtkWidget *widget, GdkEventKey *event)
646 {
647   HildonColorChooserDialogHSV *dialog = HILDON_COLOR_CHOOSER_DIALOG_HSV(widget);
648   int tmp, tot, sel;
649
650
651   if(event->keyval == HILDON_HARDKEY_UP || event->keyval == HILDON_HARDKEY_DOWN ||
652      event->keyval == HILDON_HARDKEY_LEFT || event->keyval == HILDON_HARDKEY_RIGHT) {
653     tmp = (dialog->style_info.num_buttons.top * dialog->style_info.num_buttons.bottom);
654     tot = (dialog->style_info.num_buttons.left * dialog->style_info.num_buttons.right) + tmp;
655
656     switch(event->keyval) {
657     case HILDON_HARDKEY_UP:
658       if(dialog->selected >= dialog->style_info.num_buttons.top) {
659         if(dialog->selected - dialog->style_info.num_buttons.left >= tmp) {
660           sel = dialog->selected - dialog->style_info.num_buttons.left;
661         } else {
662           sel = dialog->selected - dialog->style_info.num_buttons.top;
663         }
664
665         hildon_color_chooser_dialog_hsv_set_color_num(dialog, sel);
666       }
667       break;
668     case HILDON_HARDKEY_DOWN:
669       if(dialog->selected < tot - dialog->style_info.num_buttons.left) {
670         if(dialog->selected < tmp) {
671           sel = dialog->selected + dialog->style_info.num_buttons.top;
672         } else {
673           sel = dialog->selected + dialog->style_info.num_buttons.left;
674         }
675
676         hildon_color_chooser_dialog_hsv_set_color_num(dialog, sel);
677       }
678       break;
679     case HILDON_HARDKEY_LEFT:
680       if((dialog->selected < tmp ? (dialog->selected % dialog->style_info.num_buttons.top) : ((dialog->selected - tmp) % dialog->style_info.num_buttons.left)) > 0) {
681         sel = dialog->selected - 1;
682
683         hildon_color_chooser_dialog_hsv_set_color_num(dialog, sel);
684       }
685       break;
686     case HILDON_HARDKEY_RIGHT:
687       if((dialog->selected < tmp) ? (dialog->selected % dialog->style_info.num_buttons.top < dialog->style_info.num_buttons.top - 1) :
688          ((dialog->selected - tmp) % dialog->style_info.num_buttons.left < dialog->style_info.num_buttons.left - 1)) {
689         sel = dialog->selected + 1;
690
691         hildon_color_chooser_dialog_hsv_set_color_num(dialog, sel);
692       }
693       break;
694     default:
695       break;
696     }
697
698     return FALSE;
699   }
700
701   return GTK_WIDGET_CLASS(parent_klass)->key_press_event(widget, event);
702 }
703
704 static gboolean hildon_color_chooser_dialog_hsv_key_release_event(GtkWidget *widget, GdkEventKey *event)
705 {
706   if(event->keyval == HILDON_HARDKEY_UP || event->keyval == HILDON_HARDKEY_DOWN ||
707      event->keyval == HILDON_HARDKEY_LEFT || event->keyval == HILDON_HARDKEY_RIGHT) {
708     return FALSE;
709   }
710
711   return GTK_WIDGET_CLASS(parent_klass)->key_press_event(widget, event);
712 }
713
714
715 static void hildon_color_chooser_dialog_hsv_destroy(GtkObject *object)
716 {
717   HildonColorChooserDialogHSV *dialog = HILDON_COLOR_CHOOSER_DIALOG_HSV(object);
718   gchar key[128], color[13];
719   int i, tmp;
720
721
722   if(dialog->gconf_data.client) {
723     memset(color, 0, 13);
724
725     tmp = (dialog->style_info.num_buttons.top * dialog->style_info.num_buttons.bottom);
726
727     for(i = 0; i < tmp; i++) {
728       memset(key, 0, 128);
729       g_snprintf(key, 128, "/system/osso/af/color_chooser/custom_color%d", i);
730       hildon_color_chooser_dialog_hsv_color_to_ascii_hex(color, &dialog->colors_custom[i]);
731       gconf_client_set_string(dialog->gconf_data.client, key, color, NULL);
732     }
733
734     g_object_unref(dialog->gconf_data.client);
735     dialog->gconf_data.client = NULL;
736   }
737
738
739   if(dialog->gc_array) {
740     g_free(dialog->gc_array);
741     dialog->gc_array = NULL;
742   } if(dialog->colors_defined) {
743     g_free(dialog->colors_defined);
744     dialog->colors_defined = NULL;
745   } if(dialog->colors_custom) {
746     g_free(dialog->colors_custom);
747     dialog->colors_custom = NULL;
748   }
749
750
751   GTK_OBJECT_CLASS(parent_klass)->destroy(object);
752 }
753
754
755 static void hildon_color_chooser_dialog_hsv_set_color(HildonColorChooserDialog *dialog, GdkColor *color)
756 {
757   HildonColorChooserDialogHSV *dialog_hsv = HILDON_COLOR_CHOOSER_DIALOG_HSV(dialog);
758   int i, found = -1, tmp, tmp2;
759
760
761   if(!dialog_hsv->has_style) {
762     dialog_hsv->pending_color = *color;
763     return;
764   }
765
766
767   tmp  = (dialog_hsv->style_info.num_buttons.left * dialog_hsv->style_info.num_buttons.right);
768   tmp2 = (dialog_hsv->style_info.num_buttons.top * dialog_hsv->style_info.num_buttons.bottom);
769
770   for(i = 0; i < tmp; i++) {
771     if(dialog_hsv->colors_defined[i].red == color->red &&
772        dialog_hsv->colors_defined[i].green == color->green &&
773        dialog_hsv->colors_defined[i].blue == color->blue) {
774       found = i;
775       break;
776     }
777   }
778
779   if(found == -1) {
780     for(i = 0; i < tmp2; i++) {
781       if(dialog_hsv->colors_custom[i].red == color->red &&
782          dialog_hsv->colors_custom[i].green == color->green &&
783          dialog_hsv->colors_custom[i].blue == color->blue) {
784         found = i + tmp;
785         break;
786       }
787     }
788   }
789
790
791   if(found == -1) {
792     dialog_hsv->colors_custom[tmp2-1] = *color;
793     if(GTK_WIDGET_REALIZED(GTK_WIDGET(dialog))) {
794       gdk_gc_set_rgb_fg_color(dialog_hsv->gc_array[tmp2-1], color);
795     }
796     hildon_color_chooser_dialog_hsv_set_color_num(dialog_hsv, tmp2-1);
797   } else {
798     hildon_color_chooser_dialog_hsv_set_color_num(dialog_hsv, found);
799   }
800 }
801
802
803 static gboolean hildon_color_chooser_dialog_hsv_area_expose(GtkWidget *widget, GdkEventExpose *event, gpointer data)
804 {
805   HildonColorChooserDialogHSV *dialog = HILDON_COLOR_CHOOSER_DIALOG_HSV(data);
806   int i, num_selected, tot_w, tot_h, spacing, brd, x, y;
807   GdkGC **start_gc;
808   int tmp, w, h;
809
810
811   tmp = (dialog->style_info.num_buttons.left * dialog->style_info.num_buttons.right);
812
813   if(widget == dialog->area_custom) {
814     num_selected = dialog->selected - tmp;
815     start_gc = dialog->gc_array + tmp;
816     tmp = (dialog->style_info.num_buttons.top * dialog->style_info.num_buttons.bottom);
817     w = dialog->style_info.num_buttons.top; h = dialog->style_info.num_buttons.bottom;
818   } else { /* widget == dialog->area_defined */
819     num_selected = dialog->selected;
820     start_gc = dialog->gc_array;
821     w = dialog->style_info.num_buttons.left; h = dialog->style_info.num_buttons.right;
822   }
823
824   spacing = dialog->style_info.radio_sizes.top;
825   brd = dialog->style_info.radio_sizes.bottom;
826   tot_w = dialog->style_info.radio_sizes.left + 2*brd;
827   tot_h = dialog->style_info.radio_sizes.right + 2*brd;
828
829
830   for(i = 0; i < tmp; i++) {
831     x = ((i % w) * (tot_w + spacing));
832     y = ((i / w) * (tot_h + spacing));
833
834     if(brd) {
835       gtk_paint_box(gtk_widget_get_style(GTK_WIDGET(dialog)), widget->window, (i == num_selected) ? GTK_STATE_SELECTED : GTK_STATE_NORMAL,
836                     (i == num_selected) ? GTK_SHADOW_IN : GTK_SHADOW_OUT, &event->area, GTK_WIDGET(dialog), "color-radio", x, y, tot_w, tot_h);
837     }
838
839     gdk_draw_rectangle(widget->window, start_gc[i], TRUE, event->area.x, event->area.y, event->area.width, event->area.height);
840   }
841
842
843   return FALSE;
844 }
845
846
847 static gboolean hildon_color_chooser_dialog_hsv_area_button_press(GtkWidget *widget, GdkEventButton *event, gpointer data)
848 {
849   HildonColorChooserDialogHSV *dialog = HILDON_COLOR_CHOOSER_DIALOG_HSV(data);
850   int i, hskip, vskip, brd, selection = -1;
851   int x, y, tmp, tmp2, w;
852
853
854   x = event->x;
855   y = event->y;
856
857
858   brd = dialog->style_info.radio_sizes.bottom;
859   hskip = dialog->style_info.radio_sizes.left  + dialog->style_info.radio_sizes.top + 2*brd;
860   vskip = dialog->style_info.radio_sizes.right + dialog->style_info.radio_sizes.top + 2*brd;
861
862
863   tmp  = (dialog->style_info.num_buttons.left * dialog->style_info.num_buttons.right);
864   tmp2 = (dialog->style_info.num_buttons.top * dialog->style_info.num_buttons.bottom);
865
866
867   if(widget == dialog->area_defined) {
868     w = dialog->style_info.num_buttons.left;
869
870     for(i = 0; i < tmp; i++) {
871       if(x >= hskip*(i % w) + brd && x < hskip*(i % w) + brd + dialog->style_info.radio_sizes.left &&
872          y >= vskip*(i / w) + brd && y < hskip*(i / w) + brd + dialog->style_info.radio_sizes.right) {
873         selection = i;
874         break;
875       }
876     }
877   } else {
878     w = dialog->style_info.num_buttons.top;
879     for(i = 0; i < tmp2; i++) {
880       if(x >= hskip*(i % w) + brd && x < hskip*(i % w) + brd + dialog->style_info.radio_sizes.left &&
881          y >= vskip*(i / w) + brd && y < hskip*(i / w) + brd + dialog->style_info.radio_sizes.right) {
882          selection = i + tmp;
883          break;
884       }
885     }
886   }
887
888
889   if(selection != -1) {
890     hildon_color_chooser_dialog_hsv_set_color_num(dialog, selection);
891   }
892
893
894   return FALSE;
895 }
896
897
898 static void hildon_color_chooser_dialog_hsv_chooser_color_changed(HildonColorChooser *chooser, GdkColor *color, gpointer data)
899 {
900   HildonColorChooserDialogHSV *dialog = HILDON_COLOR_CHOOSER_DIALOG_HSV(data);
901   HildonColorChooserDialog *dia = HILDON_COLOR_CHOOSER_DIALOG(data);
902   char key[128], color_str[13];
903   int tmp;
904
905
906   dia->color = *color;
907
908
909   tmp = (dialog->style_info.num_buttons.left * dialog->style_info.num_buttons.right);
910
911
912   if(dialog->selected >= tmp) {
913     dialog->colors_custom[dialog->selected - tmp] = *color;
914
915     gdk_gc_set_rgb_fg_color(dialog->gc_array[dialog->selected], &dialog->colors_custom[dialog->selected - tmp]);
916
917     gtk_widget_queue_draw(dialog->area_custom);
918
919
920     if(dialog->gconf_data.client) {
921       memset(key, 0, 128);
922       memset(color_str, 0, 13);
923       g_snprintf(key, 128, "/system/osso/af/color_chooser/custom_color%d", dialog->selected - tmp);
924       hildon_color_chooser_dialog_hsv_color_to_ascii_hex(color_str, &dialog->colors_custom[dialog->selected - tmp]);
925       gconf_client_set_string(dialog->gconf_data.client, key, color_str, NULL);
926     }
927   }
928 }
929
930
931 static void hildon_color_chooser_dialog_hsv_chooser_insensitive_press(GtkWidget *widget, gpointer data)
932 {
933   hildon_banner_show_information(widget, NULL, _("ecdg_ib_colour_selector_predefined"));
934 }
935
936   /* function has size defaults */
937 static void hildon_color_chooser_dialog_hsv_refresh_style_info(HildonColorChooserDialogHSV *dialog)
938 {
939   GtkBorder *tmp1, *tmp2, *tmp3;
940
941
942   gtk_widget_style_get(GTK_WIDGET(dialog), "container_sizes", &tmp1,
943                        "radio_sizes", &tmp2, "num_buttons", &tmp3, NULL);
944
945
946   dialog->style_info.last_num_buttons = dialog->style_info.num_buttons;
947
948
949   if(tmp1) {
950     dialog->style_info.cont_sizes = *tmp1;
951     g_free(tmp1);
952   } else {
953     dialog->style_info.cont_sizes.left = 0;
954     dialog->style_info.cont_sizes.right = 8;
955     dialog->style_info.cont_sizes.top = 4;
956     dialog->style_info.cont_sizes.bottom = 0;
957   }
958
959   if(tmp2) {
960     dialog->style_info.radio_sizes = *tmp2;
961     g_free(tmp2);
962   } else {
963     dialog->style_info.radio_sizes.left = 16;
964     dialog->style_info.radio_sizes.right = 16;
965     dialog->style_info.radio_sizes.top = 4;
966     dialog->style_info.radio_sizes.bottom = 2;
967   }
968
969   if(tmp3) {
970     dialog->style_info.num_buttons = *tmp3;
971     g_free(tmp3);
972   } else {
973     dialog->style_info.num_buttons.left = 8;
974     dialog->style_info.num_buttons.right = 2;
975     dialog->style_info.num_buttons.top = 8;
976     dialog->style_info.num_buttons.bottom = 2;
977   }
978 }
979
980
981 static void hildon_color_chooser_dialog_hsv_set_color_num(HildonColorChooserDialogHSV *dialog, gint num)
982 {
983   HildonColorChooserDialog *dia = HILDON_COLOR_CHOOSER_DIALOG(dialog);
984   int tmp;
985
986
987   tmp = (dialog->style_info.num_buttons.left * dialog->style_info.num_buttons.right);
988
989
990   if(num < tmp) {
991     gtk_widget_set_sensitive(dialog->chooser, FALSE);
992   } else {
993     gtk_widget_set_sensitive(dialog->chooser, TRUE);
994   }
995
996
997   dialog->selected = num;
998
999   gtk_widget_queue_draw(dialog->area_custom);
1000   gtk_widget_queue_draw(dialog->area_defined);
1001
1002   dia->color = (num < tmp) ? dialog->colors_defined[num] : dialog->colors_custom[num - tmp];
1003
1004   hildon_color_chooser_set_color(HILDON_COLOR_CHOOSER(dialog->chooser), (num < tmp) ? &dialog->colors_defined[num] : &dialog->colors_custom[num - tmp]);
1005 }
1006
1007
1008 static void hildon_color_chooser_dialog_hsv_ascii_hex_to_color(gchar *s, GdkColor *color)
1009 {
1010   int vals[12], i;
1011
1012
1013   for(i = 0; i < 12; i++) {
1014     if(s[i] >= '0' && s[i] <= '9') {
1015       vals[i] = s[i] - 0x30;
1016     } else if(s[i] >= 'a' && s[i] <= 'f') {
1017       vals[i] = s[i] - 0x57;
1018     } else {
1019       vals[i] = 0;
1020     }
1021   }
1022
1023
1024   color->red   = (vals[0] << 12) | (vals[1] <<  8) | (vals[2 ] <<  4) | (vals[3 ]      );
1025   color->green = (vals[4] << 12) | (vals[5] <<  8) | (vals[6 ] <<  4) | (vals[7 ]      );
1026   color->blue  = (vals[8] << 12) | (vals[9] <<  8) | (vals[10] <<  4) | (vals[11]      );
1027 }
1028
1029 static void hildon_color_chooser_dialog_hsv_color_to_ascii_hex(gchar *s, GdkColor *color)
1030 {
1031   g_snprintf(s, 12, "%x%x%x%x%x%x%x%x%x%x%x%x",
1032              (color->red >> 12) & 0xf, (color->red >>  8) & 0xf,
1033              (color->red >>  4) & 0xf, (color->red      ) & 0xf,
1034              (color->green >> 12) & 0xf, (color->green >>  8) & 0xf,
1035              (color->green >>  4) & 0xf, (color->green      ) & 0xf,
1036              (color->blue >> 12) & 0xf, (color->blue >>  8) & 0xf,
1037              (color->blue >>  4) & 0xf, (color->blue      ) & 0xf);
1038 }