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