Merge branch 'upstream'
[framework/uifw/elementary.git] / src / lib / elm_colorselector.c
1 #include <Elementary.h>
2 #include "elm_priv.h"
3
4 /**
5  * @defgroup Colorselector Colorselector
6  * @ingroup Elementary
7  *
8  * By using colorselector, you can select a color.
9  * Colorselector made a color using HSV/HSB mode.
10  *
11  * Signals that you can add callbacks for are:
12  *
13  * "changed" - when the color value changes
14  */
15
16 #define BASE_STEP 360.0
17 #define HUE_STEP 360.0
18 #define SAT_STEP 128.0
19 #define LIG_STEP 256.0
20 #define ALP_STEP 256.0
21
22 typedef enum _Button_State
23 {
24    BUTTON_RELEASED,
25    L_BUTTON_PRESSED,
26    R_BUTTON_PRESSED
27 } Button_State;
28
29 typedef enum _Color_Type
30 {
31    HUE,
32    SATURATION,
33    LIGHTNESS,
34    ALPHA
35 } Color_Type;
36
37 typedef struct _Colorselector_Data Colorselector_Data;
38 struct _Colorselector_Data
39 {
40    Evas_Object *parent;
41    Evas_Object *colorbar;
42    Evas_Object *bar;
43    Evas_Object *lbt;
44    Evas_Object *rbt;
45    Evas_Object *bg_rect;
46    Evas_Object *arrow;
47    Evas_Object *touch_area;
48    Color_Type color_type;
49    Button_State button_state;
50 };
51
52 typedef struct _Widget_Data Widget_Data;
53 struct _Widget_Data
54 {
55    Evas_Object *base;
56    Colorselector_Data *cp[4];
57    Evas_Coord _x, _y, _w, _h;
58    int r, g, b, a;
59    int er, eg, eb;
60    int sr, sg, sb;
61    int lr, lg, lb;
62    double h, s, l;
63    Ecore_Timer *lp_timer;
64    Ecore_Timer *mv_timer;
65 };
66
67 static const char *widtype = NULL;
68
69 static void _del_hook(Evas_Object *obj);
70 static void _theme_hook(Evas_Object *obj);
71 static void _sizing_eval(Evas_Object *obj);
72 static void _rgb_to_hsl(void *data);
73 static void _hsl_to_rgb(void *data);
74 static void _color_with_saturation(void *data);
75 static void _color_with_lightness(void *data);
76 static void _draw_rects(void *data, double x);
77 static void _arrow_cb(void *data, Evas_Object *obj, const char *emission, const char *source);
78 static void _colorbar_cb(void *data, Evas *e, Evas_Object *obj, void *event_info);
79 static Eina_Bool _mv_timer(void *data);
80 static Eina_Bool _long_press_timer(void *data);
81 static void _left_button_down_cb(void *data, Evas *e, Evas_Object *obj, void *event_info);
82 static void _right_button_down_cb(void *data, Evas *e, Evas_Object *obj, void *event_info);
83 static void _left_button_up_cb(void *data, Evas *e, Evas_Object *obj, void *event_info);
84 static void _right_button_up_cb(void *data, Evas *e, Evas_Object *obj, void *event_info);
85 static void _add_colorbar(Evas_Object *obj);
86 static void _set_color(Evas_Object *obj, int r, int g, int b, int a);
87
88 static const char SIG_CHANGED[] = "changed";
89
90 static const Evas_Smart_Cb_Description _signals[] =
91 {
92      {SIG_CHANGED, ""},
93      {NULL, NULL}
94 };
95
96 static void
97 _del_hook(Evas_Object *obj)
98 {
99    Widget_Data *wd = elm_widget_data_get(obj);
100    int i = 0;
101
102    if (!wd) return;
103    if (wd->lp_timer) ecore_timer_del(wd->lp_timer);
104    if (wd->mv_timer) ecore_timer_del(wd->mv_timer);
105    for (i = 0; i < 4; i++) free(wd->cp[i]);
106    free(wd);
107 }
108
109 static void
110 _theme_hook(Evas_Object *obj)
111 {
112    Widget_Data *wd = elm_widget_data_get(obj);
113    int i;
114
115    if ((!wd) || (!wd->base)) return;
116
117    _elm_theme_object_set(obj, wd->base, "colorselector", "bg",
118                          elm_widget_style_get(obj));
119
120    for (i = 0; i < 4; i++)
121      {
122         evas_object_del(wd->cp[i]->colorbar);
123         wd->cp[i]->colorbar = NULL;
124         evas_object_del(wd->cp[i]->bar);
125         wd->cp[i]->bar = NULL;
126         evas_object_del(wd->cp[i]->lbt);
127         wd->cp[i]->lbt = NULL;
128         evas_object_del(wd->cp[i]->rbt);
129         wd->cp[i]->rbt = NULL;
130         if (i != 0)
131           {
132              evas_object_del(wd->cp[i]->bg_rect);
133              wd->cp[i]->bg_rect = NULL;
134           }
135         evas_object_del(wd->cp[i]->arrow);
136         wd->cp[i]->arrow = NULL;
137         evas_object_del(wd->cp[i]->touch_area);
138         wd->cp[i]->touch_area = NULL;
139      }
140
141    _add_colorbar(obj);
142    _sizing_eval(obj);
143 }
144
145 static void
146 _colorselector_set_size_hints(Evas_Object *obj, int timesw, int timesh)
147 {
148    Evas_Coord minw = -1, minh = -1;
149
150    elm_coords_finger_size_adjust(timesw, &minw, timesh, &minh);
151    edje_object_size_min_restricted_calc(obj, &minw, &minh,
152                                         minw, minh);
153    evas_object_size_hint_min_set(obj, minw, minh);
154    evas_object_size_hint_max_set(obj, -1, -1);
155 }
156
157 static void
158 _sizing_eval(Evas_Object *obj)
159 {
160    Widget_Data *wd = elm_widget_data_get(obj);
161    Evas_Coord minw = -1, minh = -1;
162    int i;
163
164    if (!wd) return;
165    elm_coords_finger_size_adjust(1, &minw, 1, &minh);
166    for (i = 0; i < 4; i++)
167      {
168         if (wd->cp[i]->bg_rect)
169           _colorselector_set_size_hints(wd->cp[i]->bg_rect, 1, 1);
170         _colorselector_set_size_hints(wd->cp[i]->bar, 1, 1);
171         _colorselector_set_size_hints(wd->cp[i]->rbt, 1, 1);
172         _colorselector_set_size_hints(wd->cp[i]->lbt, 1, 1);
173
174         _colorselector_set_size_hints(wd->cp[i]->colorbar, 4, 1);
175      }
176
177    elm_coords_finger_size_adjust(4, &minw, 4, &minh);
178    edje_object_size_min_restricted_calc(wd->base, &minw, &minh, minw, minh);
179    evas_object_size_hint_min_set(obj, minw, minh);
180    evas_object_size_hint_max_set(obj, -1, -1);
181 }
182
183 static void
184 _rgb_to_hsl(void *data)
185 {
186    Widget_Data *wd = data;
187    double r, g, b;
188    double v, m, vm;
189    double r2, g2, b2;
190
191    r = wd->r;
192    g = wd->g;
193    b = wd->b;
194
195    r /= 255.0;
196    g /= 255.0;
197    b /= 255.0;
198
199    v = (r > g) ? r : g;
200    v = (v > b) ? v : b;
201
202    m = (r < g) ? r : g;
203    m = (m < b) ? m : b;
204
205    wd->h = 0.0;
206    wd->s = 0.0;
207    wd->l = 0.0;
208
209    wd->l = (m + v) / 2.0;
210
211    if (wd->l <= 0.0) return;
212
213    vm = v - m;
214    wd->s = vm;
215
216    if (wd->s > 0.0) wd->s /= (wd->l <= 0.5) ? (v + m) : (2.0 - v - m);
217    else return;
218
219    r2 = (v - r) / vm;
220    g2 = (v - g) / vm;
221    b2 = (v - b) / vm;
222
223    if (r == v) wd->h = (g == m ? 5.0 + b2 : 1.0 - g2);
224    else if (g == v) wd->h = (b == m ? 1.0 + r2 : 3.0 - b2);
225    else wd->h = (r == m ? 3.0 + g2 : 5.0 - r2);
226
227    wd->h *= 60.0;
228 }
229
230 static void
231 _hsl_to_rgb(void *data)
232 {
233    Widget_Data *wd = data;
234    double r = 0, g = 0, b = 0;
235    double _h, _s, _l;
236    int i = 0;
237    double sv, vsf, f, p, q, t, v;
238
239    _h = wd->h;
240    _s = wd->s;
241    _l = wd->l;
242
243    if (_s == 0.0) r = g = b = _l;
244    else
245      {
246         if (_h == 360.0) _h = 0.0;
247         _h /= 60.0;
248
249         v = (_l <= 0.5) ? (_l * (1.0 + _s)) : (_l + _s - (_l * _s));
250         p = _l + _l - v;
251
252         if (v) sv = (v - p) / v;
253         else sv = 0;
254
255         i = (int)_h;
256         f = _h - i;
257
258         vsf = v * sv * f;
259
260         t = p + vsf;
261         q = v - vsf;
262
263         switch (i)
264           {
265            case 0:
266               r = v;
267               g = t;
268               b = p;
269               break;
270            case 1:
271               r = q;
272               g = v;
273               b = p;
274               break;
275            case 2:
276               r = p;
277               g = v;
278               b = t;
279               break;
280            case 3:
281               r = p;
282               g = q;
283               b = v;
284               break;
285            case 4:
286               r = t;
287               g = p;
288               b = v;
289               break;
290            case 5:
291               r = v;
292               g = p;
293               b = q;
294               break;
295           }
296      }
297    i = (int)(r * 255.0);
298    f = (r * 255.0) - i;
299    wd->r = (f <= 0.5) ? i : (i + 1);
300
301    i = (int)(g * 255.0);
302    f = (g * 255.0) - i;
303    wd->g = (f <= 0.5) ? i : (i + 1);
304
305    i = (int)(b * 255.0);
306    f = (b * 255.0) - i;
307    wd->b = (f <= 0.5) ? i : (i + 1);
308 }
309
310 static void
311 _color_with_saturation(void *data)
312 {
313    Widget_Data *wd = data;
314
315    if (wd->er > 127)
316      wd->sr = 127 + (int)((double)(wd->er - 127) * wd->s);
317    else
318      wd->sr = 127 - (int)((double)(127 - wd->er) * wd->s);
319
320    if (wd->eg > 127)
321      wd->sg = 127 + (int)((double)(wd->eg - 127) * wd->s);
322    else
323      wd->sg = 127 - (int)((double)(127 - wd->eg) * wd->s);
324
325    if (wd->eb > 127)
326      wd->sb = 127 + (int)((double)(wd->eb - 127) * wd->s);
327    else
328      wd->sb = 127 - (int)((double)(127 - wd->eb) * wd->s);
329 }
330
331 static void
332 _color_with_lightness(void *data)
333 {
334    Widget_Data *wd = data;
335
336    if (wd->l > 0.5)
337      {
338         wd->lr = wd->er + (int)((double)(255 - wd->er) * (wd->l - 0.5) * 2.0);
339         wd->lg = wd->eg + (int)((double)(255 - wd->eg) * (wd->l - 0.5) * 2.0);
340         wd->lb = wd->eb + (int)((double)(255 - wd->eb) * (wd->l - 0.5) * 2.0);
341      }
342    else if (wd->l < 0.5)
343      {
344         wd->lr = (double)wd->er * wd->l * 2.0;
345         wd->lg = (double)wd->eg * wd->l * 2.0;
346         wd->lb = (double)wd->eb * wd->l * 2.0;
347      }
348    else
349      {
350         wd->lr = wd->er;
351         wd->lg = wd->eg;
352         wd->lb = wd->eb;
353      }
354 }
355
356 static void
357 _draw_rects(void *data, double x)
358 {
359    Colorselector_Data *cp = data;
360    Widget_Data *wd = elm_widget_data_get(cp->parent);
361    double one_six = 1.0 / 6.0;
362
363    switch (cp->color_type)
364      {
365       case HUE:
366          wd->h = 360.0 * x;
367
368          if (x < one_six)
369            {
370               wd->er = 255;
371               wd->eg = (255.0 * x * 6.0);
372               wd->eb = 0;
373            }
374          else if (x < 2 * one_six)
375            {
376               wd->er = 255 - (int)(255.0 * (x - one_six) * 6.0);
377               wd->eg = 255;
378               wd->eb = 0;
379            }
380          else if (x < 3 * one_six)
381            {
382               wd->er = 0;
383               wd->eg = 255;
384               wd->eb = (int)(255.0 * (x - (2.0 * one_six)) * 6.0);
385            }
386          else if (x < 4 * one_six)
387            {
388               wd->er = 0;
389               wd->eg = 255 - (int)(255.0 * (x - (3.0 * one_six)) * 6.0);
390               wd->eb = 255;
391            }
392          else if (x < 5 * one_six)
393            {
394               wd->er = 255.0 * (x - (4.0 * one_six)) * 6.0;
395               wd->eg = 0;
396               wd->eb = 255;
397            }
398          else
399            {
400               wd->er = 255;
401               wd->eg = 0;
402               wd->eb = 255 - (int)(255.0 * (x - (5.0 * one_six)) * 6.0);
403            }
404
405          evas_object_color_set(wd->cp[0]->arrow, wd->er, wd->eg, wd->eb, 255);
406          evas_object_color_set(wd->cp[1]->bg_rect, wd->er, wd->eg, wd->eb, 255);
407          evas_object_color_set(wd->cp[2]->bg_rect, wd->er, wd->eg, wd->eb, 255);
408          evas_object_color_set(wd->cp[3]->bar, wd->er, wd->eg, wd->eb, 255);
409
410          _color_with_saturation(wd);
411          evas_object_color_set(wd->cp[1]->arrow, wd->sr, wd->sg, wd->sb, 255);
412
413          _color_with_lightness(wd);
414          evas_object_color_set(wd->cp[2]->arrow, wd->lr, wd->lg, wd->lb, 255);
415
416          evas_object_color_set(wd->cp[3]->arrow,
417                                (wd->er * wd->a) / 255,
418                                (wd->eg * wd->a) / 255,
419                                (wd->eb * wd->a) / 255,
420                                wd->a);
421          break;
422       case SATURATION:
423          wd->s = 1.0 - x;
424          _color_with_saturation(wd);
425          evas_object_color_set(wd->cp[1]->arrow, wd->sr, wd->sg, wd->sb, 255);
426          break;
427       case LIGHTNESS:
428          wd->l = x;
429          _color_with_lightness(wd);
430          evas_object_color_set(wd->cp[2]->arrow, wd->lr, wd->lg, wd->lb, 255);
431          break;
432       case ALPHA:
433          wd->a = 255.0 * x;
434          evas_object_color_set(wd->cp[3]->arrow, wd->er, wd->eg, wd->eb, wd->a);
435          break;
436       default:
437          break;
438      }
439    _hsl_to_rgb(wd);
440 }
441
442 static void
443 _arrow_cb(void *data, Evas_Object *obj, const char *emission __UNUSED__, const char *source __UNUSED__)
444 {
445    Colorselector_Data *cp = data;
446    double x, y;
447
448    edje_object_part_drag_value_get(obj, "elm.arrow", &x, &y);
449    _draw_rects(data, x);
450    evas_object_smart_callback_call(cp->parent, SIG_CHANGED, NULL);
451 }
452
453 static void
454 _colorbar_cb(void *data, Evas *e, Evas_Object *obj __UNUSED__, void *event_info)
455 {
456    Colorselector_Data *cp = data;
457    Evas_Event_Mouse_Down *ev = event_info;
458    Evas_Coord x, y, w, h;
459    double arrow_x = 0, arrow_y;
460
461    evas_object_geometry_get(cp->bar, &x, &y, &w, &h);
462    edje_object_part_drag_value_get(cp->colorbar, "elm.arrow",
463                                    &arrow_x, &arrow_y);
464    if (w > 0) arrow_x = (double)(ev->canvas.x - x) / (double)w;
465    if (arrow_x > 1) arrow_x = 1;
466    if (arrow_x < 0) arrow_x = 0;
467    edje_object_part_drag_value_set(cp->colorbar, "elm.arrow", arrow_x, arrow_y);
468    _draw_rects(data, arrow_x);
469    evas_object_smart_callback_call(cp->parent, SIG_CHANGED, NULL);
470    evas_event_feed_mouse_cancel(e, 0, NULL);
471    evas_event_feed_mouse_down(e, 1, EVAS_BUTTON_NONE, 0, NULL);
472 }
473
474 static Eina_Bool
475 _mv_timer(void *data)
476 {
477    Colorselector_Data *cp = data;
478    Widget_Data *wd = elm_widget_data_get(cp->parent);
479    double x, y;
480
481    if (!wd) return EINA_FALSE;
482
483    edje_object_part_drag_value_get(cp->colorbar, "elm.arrow", &x, &y);
484    if (cp->button_state == L_BUTTON_PRESSED)
485      {
486         x -= 1.0 / BASE_STEP;
487         if (x < 0.0) x = 0.0;
488         edje_object_part_drag_value_set(cp->colorbar, "elm.arrow", x, y);
489         _draw_rects(data, x);
490         evas_object_smart_callback_call(cp->parent, SIG_CHANGED, NULL);
491         return EINA_TRUE;
492      }
493    else if (cp->button_state == R_BUTTON_PRESSED)
494      {
495         x += 1.0 / BASE_STEP;
496         if (x > 1.0) x = 1.0;
497         edje_object_part_drag_value_set(cp->colorbar, "elm.arrow", x, y);
498         _draw_rects(data, x);
499         evas_object_smart_callback_call(cp->parent, SIG_CHANGED, NULL);
500         return EINA_TRUE;
501      }
502    wd->mv_timer = NULL;
503    return EINA_FALSE;
504 }
505
506 static Eina_Bool
507 _long_press_timer(void *data)
508 {
509    Colorselector_Data *cp = data;
510    Widget_Data *wd = elm_widget_data_get(cp->parent);
511
512    if (wd->mv_timer) ecore_timer_del(wd->mv_timer);
513    wd->mv_timer = ecore_timer_add(0.01, _mv_timer, cp);
514
515    wd->lp_timer = NULL;
516    return EINA_FALSE;
517 }
518
519 static void
520 _left_button_down_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
521 {
522    Colorselector_Data *cp = data;
523    Widget_Data *wd = elm_widget_data_get(cp->parent);
524    double x, y;
525
526    edje_object_signal_emit(cp->lbt, "elm,state,left,button,down",
527                            "left_button");
528    edje_object_part_drag_value_get(cp->colorbar, "elm.arrow", &x, &y);
529
530    switch(cp->color_type)
531      {
532       case HUE :
533          x -= 1.0 / HUE_STEP;
534          break;
535       case SATURATION :
536          x -= 1.0 / SAT_STEP;
537          break;
538       case LIGHTNESS :
539          x -= 1.0 / LIG_STEP;
540          break;
541       case ALPHA :
542          x -= 1.0 / ALP_STEP;
543          break;
544       default :
545          break;
546      }
547
548    if (x < 0.0) x = 0.0;
549
550    edje_object_part_drag_value_set(cp->colorbar, "elm.arrow", x, y);
551    _draw_rects(data, x);
552    evas_object_smart_callback_call(cp->parent, SIG_CHANGED, NULL);
553    cp->button_state = L_BUTTON_PRESSED;
554    if (wd->lp_timer) ecore_timer_del(wd->lp_timer);
555    wd->lp_timer = ecore_timer_add(_elm_config->longpress_timeout, _long_press_timer, cp);
556 }
557
558 static void
559 _right_button_down_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
560 {
561    Colorselector_Data *cp = data;
562    Widget_Data *wd = elm_widget_data_get(cp->parent);
563    double x, y;
564
565    edje_object_signal_emit(cp->rbt, "elm,state,right,button,down",
566                            "right_button");
567    edje_object_part_drag_value_get(cp->colorbar, "elm.arrow", &x, &y);
568
569    switch(cp->color_type)
570      {
571       case HUE :
572          x += 1.0 / HUE_STEP;
573          break;
574       case SATURATION :
575          x += 1.0 / SAT_STEP;
576          break;
577       case LIGHTNESS :
578          x += 1.0 / LIG_STEP;
579          break;
580       case ALPHA :
581          x += 1.0 / ALP_STEP;
582          break;
583       default :
584          break;
585      }
586
587    if (x > 1.0) x = 1.0;
588
589    edje_object_part_drag_value_set(cp->colorbar, "elm.arrow", x, y);
590    _draw_rects(data, x);
591    evas_object_smart_callback_call(cp->parent, SIG_CHANGED, NULL);
592    cp->button_state = R_BUTTON_PRESSED;
593    wd->lp_timer = ecore_timer_add(_elm_config->longpress_timeout, _long_press_timer, cp);
594 }
595
596 static void
597 _left_button_up_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
598 {
599    Colorselector_Data *cp = data;
600    Widget_Data *wd = elm_widget_data_get(cp->parent);
601
602    if (wd->lp_timer)
603      {
604         ecore_timer_del(wd->lp_timer);
605         wd->lp_timer = NULL;
606      }
607    if (wd->mv_timer)
608      {
609         ecore_timer_del(wd->mv_timer);
610         wd->mv_timer = NULL;
611      }
612
613    cp->button_state = BUTTON_RELEASED;
614    edje_object_signal_emit(cp->lbt, "elm,state,left,button,up", "left_button");
615 }
616
617 static void
618 _right_button_up_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
619 {
620    Colorselector_Data *cp = data;
621    Widget_Data *wd = elm_widget_data_get(cp->parent);
622
623    if (wd->lp_timer)
624      {
625         ecore_timer_del(wd->lp_timer);
626         wd->lp_timer = NULL;
627      }
628    if (wd->mv_timer)
629      {
630         ecore_timer_del(wd->mv_timer);
631         wd->mv_timer = NULL;
632      }
633
634    cp->button_state = BUTTON_RELEASED;
635    edje_object_signal_emit(cp->rbt, "elm,state,right,button,up",
636                            "right_button");
637 }
638
639 static void
640 _add_colorbar(Evas_Object *obj)
641 {
642    char colorbar_name[128];
643    char colorbar_s[128];
644    Widget_Data *wd;
645    Evas *e;
646    int i = 0;
647
648    wd = elm_widget_data_get(obj);
649    if (!wd) return;
650
651    e = evas_object_evas_get(obj);
652
653    for (i = 0; i < 4; i++)
654      {
655         wd->cp[i] = ELM_NEW(Colorselector_Data);
656         wd->cp[i]->parent = obj;
657         switch(i)
658           {
659            case 0 :
660               wd->cp[i]->color_type = HUE;
661               break;
662            case 1 :
663               wd->cp[i]->color_type = SATURATION;
664               break;
665            case 2 :
666               wd->cp[i]->color_type = LIGHTNESS;
667               break;
668            case 3 :
669               wd->cp[i]->color_type = ALPHA;
670               break;
671            default :
672               break;
673           }
674         /* load colorbar area */
675         wd->cp[i]->colorbar = edje_object_add(e);
676         _elm_theme_object_set(obj, wd->cp[i]->colorbar, "colorselector", "base",
677                               "default");
678         snprintf(colorbar_name, sizeof(colorbar_name), "colorbar_%d", i);
679         snprintf(colorbar_s, sizeof(colorbar_s), "elm.colorbar_%d", i);
680         edje_object_signal_callback_add(wd->cp[i]->colorbar, "drag", "*",
681                                         _arrow_cb, wd->cp[i]);
682         edje_object_part_swallow(wd->base, colorbar_s, wd->cp[i]->colorbar);
683         elm_widget_sub_object_add(obj, wd->cp[i]->colorbar);
684
685         /* load colorbar image */
686         wd->cp[i]->bar = edje_object_add(e);
687         _elm_theme_object_set(obj, wd->cp[i]->bar, "colorselector", "image",
688                               colorbar_name);
689         edje_object_part_swallow(wd->cp[i]->colorbar, "elm.bar",
690                                  wd->cp[i]->bar);
691         elm_widget_sub_object_add(obj, wd->cp[i]->bar);
692
693         /* provide expanded touch area */
694         wd->cp[i]->touch_area = evas_object_rectangle_add(e);
695         evas_object_color_set(wd->cp[i]->touch_area, 0, 0, 0, 0);
696         edje_object_part_swallow(wd->cp[i]->colorbar, "elm.arrow_bg",
697                                  wd->cp[i]->touch_area);
698         evas_object_event_callback_add(wd->cp[i]->touch_area,
699                                        EVAS_CALLBACK_MOUSE_DOWN, _colorbar_cb,
700                                        wd->cp[i]);
701         elm_widget_sub_object_add(obj, wd->cp[i]->touch_area);
702
703         /* load background rectangle of the colorbar. used for
704            changing color of the opacity bar */
705         if ((i == 1) || (i == 2))
706           {
707              wd->cp[i]->bg_rect = evas_object_rectangle_add(e);
708              evas_object_color_set(wd->cp[i]->bg_rect, wd->er, wd->eg, wd->eb,
709                                    255);
710              edje_object_part_swallow(wd->cp[i]->colorbar, "elm.bar_bg",
711                                       wd->cp[i]->bg_rect);
712
713              elm_widget_sub_object_add(obj, wd->cp[i]->bg_rect);
714           }
715         if (i == 3)
716           {
717              wd->cp[i]->bg_rect = edje_object_add(e);
718              _elm_theme_object_set(obj, wd->cp[i]->bg_rect, "colorselector",
719                                    "bg_image", colorbar_name);
720              edje_object_part_swallow(wd->cp[i]->colorbar, "elm.bar_bg",
721                                       wd->cp[i]->bg_rect);
722              elm_widget_sub_object_add(obj, wd->cp[i]->bg_rect);
723              evas_object_color_set(wd->cp[i]->bar, wd->er, wd->eg, wd->eb, 255);
724           }
725         /* load arrow image, pointing the colorbar */
726         wd->cp[i]->arrow = edje_object_add(e);
727         _elm_theme_object_set(obj, wd->cp[i]->arrow, "colorselector", "image",
728                               "updown");
729         edje_object_part_swallow(wd->cp[i]->colorbar, "elm.arrow_icon",
730                                  wd->cp[i]->arrow);
731         elm_widget_sub_object_add(obj, wd->cp[i]->arrow);
732         if (i == 2)
733           evas_object_color_set(wd->cp[i]->arrow, 0, 0, 0, 255);
734         else
735           evas_object_color_set(wd->cp[i]->arrow, wd->er, wd->eg, wd->eb, 255);
736
737         /* load left button */
738         wd->cp[i]->lbt = edje_object_add(e);
739         _elm_theme_object_set(obj, wd->cp[i]->lbt, "colorselector", "button",
740                               "left");
741         evas_object_event_callback_add(wd->cp[i]->lbt, EVAS_CALLBACK_MOUSE_DOWN,
742                                        _left_button_down_cb, wd->cp[i]);
743         evas_object_event_callback_add(wd->cp[i]->lbt, EVAS_CALLBACK_MOUSE_UP,
744                                        _left_button_up_cb, wd->cp[i]);
745         edje_object_part_swallow(wd->cp[i]->colorbar, "elm.l_button",
746                                  wd->cp[i]->lbt);
747         elm_widget_sub_object_add(obj, wd->cp[i]->lbt);
748
749         /* load right button */
750         wd->cp[i]->rbt = edje_object_add(e);
751         _elm_theme_object_set(obj, wd->cp[i]->rbt, "colorselector", "button",
752                               "right");
753         evas_object_event_callback_add(wd->cp[i]->rbt, EVAS_CALLBACK_MOUSE_DOWN,
754                                        _right_button_down_cb, wd->cp[i]);
755         evas_object_event_callback_add(wd->cp[i]->rbt, EVAS_CALLBACK_MOUSE_UP,
756                                        _right_button_up_cb, wd->cp[i]);
757         edje_object_part_swallow(wd->cp[i]->colorbar, "elm.r_button",
758                                  wd->cp[i]->rbt);
759         elm_widget_sub_object_add(obj, wd->cp[i]->rbt);
760      }
761 }
762
763 static void
764 _set_color(Evas_Object *obj, int r, int g, int b, int a)
765 {
766    Widget_Data *wd = elm_widget_data_get(obj);
767    double x, y;
768
769    wd->r = r;
770    wd->g = g;
771    wd->b = b;
772    wd->a = a;
773
774    _rgb_to_hsl(wd);
775
776    edje_object_part_drag_value_get(wd->cp[0]->colorbar, "elm.arrow", &x, &y);
777    x = wd->h / 360.0;
778    edje_object_part_drag_value_set(wd->cp[0]->colorbar, "elm.arrow", x, y);
779    _draw_rects(wd->cp[0], x);
780
781    edje_object_part_drag_value_get(wd->cp[1]->colorbar, "elm.arrow", &x, &y);
782    x = 1.0 - wd->s;
783    edje_object_part_drag_value_set(wd->cp[1]->colorbar, "elm.arrow", x, y);
784    _draw_rects(wd->cp[1], x);
785
786    edje_object_part_drag_value_get(wd->cp[2]->colorbar, "elm.arrow", &x, &y);
787    x = wd->l;
788    edje_object_part_drag_value_set(wd->cp[2]->colorbar, "elm.arrow", x, y);
789    _draw_rects(wd->cp[2], x);
790
791    edje_object_part_drag_value_get(wd->cp[3]->colorbar, "elm.arrow", &x, &y);
792    x = wd->a / 255.0;
793    edje_object_part_drag_value_set(wd->cp[3]->colorbar, "elm.arrow", x, y);
794    _draw_rects(wd->cp[3], x);
795 }
796
797 /**
798  * Add a new colorselector to the parent
799  *
800  * @param parent The parent object
801  * @return The new object or NULL if it cannot be created
802  *
803  * @ingroup Colorselector
804  */
805 EAPI Evas_Object *
806 elm_colorselector_add(Evas_Object *parent)
807 {
808    Evas_Object *obj = NULL;
809    Widget_Data *wd = NULL;
810    Evas *e;
811
812    ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
813
814    ELM_SET_WIDTYPE(widtype, "colorselector");
815    elm_widget_type_set(obj, "colorselector");
816    elm_widget_sub_object_add(parent, obj);
817    elm_widget_data_set(obj, wd);
818    elm_widget_del_hook_set(obj, _del_hook);
819    elm_widget_theme_hook_set(obj, _theme_hook);
820
821    /* load background edj */
822    wd->base = edje_object_add(e);
823    _elm_theme_object_set(obj, wd->base, "colorselector", "bg", "default");
824    elm_widget_resize_object_set(obj, wd->base);
825
826    wd->er = 255;
827    wd->eg = 0;
828    wd->eb = 0;
829    wd->h = 0.0;
830    wd->s = 1.0;
831    wd->l = 0.0;
832    wd->a = 255;
833
834    _hsl_to_rgb(wd);
835    _add_colorbar(obj);
836    _sizing_eval(obj);
837
838    evas_object_smart_callbacks_descriptions_set(obj, _signals);
839    return obj;
840 }
841
842 /**
843  * Set a color for the colorselector
844  *
845  * @param obj   Colorselector object
846  * @param r     r-value of color
847  * @param g     g-value of color
848  * @param b     b-value of color
849  * @param a     a-value of color
850  *
851  * @ingroup Colorselector
852  */
853 EAPI void
854 elm_colorselector_color_set(Evas_Object *obj, int r, int g, int b, int a)
855 {
856    ELM_CHECK_WIDTYPE(obj, widtype);
857    _set_color(obj, r, g, b, a);
858 }
859
860 /**
861  * Get a color from the colorselector
862  *
863  * @param obj   Colorselector object
864  * @param r     integer pointer for r-value of color
865  * @param g     integer pointer for g-value of color
866  * @param b     integer pointer for b-value of color
867  * @param a     integer pointer for a-value of color
868  *
869  * @ingroup Colorselector
870  */
871 EAPI void
872 elm_colorselector_color_get(const Evas_Object *obj, int *r, int *g, int *b, int*a)
873 {
874    Widget_Data *wd = elm_widget_data_get(obj);
875    ELM_CHECK_WIDTYPE(obj, widtype);
876
877    if (r) *r = wd->r;
878    if (g) *g = wd->g;
879    if (b) *b = wd->b;
880    if (a) *a = wd->a;
881 }