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