Git init
[platform/core/uifw/e17.git] / src / bin / e_widget_cslider.c
1 #include "e.h"
2
3 typedef struct _E_Widget_Data E_Widget_Data;
4
5 struct _E_Widget_Data
6 {
7    Evas_Object *o_cslider;
8    Evas_Object *o_grad;
9    Evas_Object *o_event;
10
11    Eina_List *o_hgrad;
12
13    Evas_Coord x, y, w, h;
14
15    int vertical;
16    int fixed;
17    E_Color_Component mode;
18    int valnum;
19    E_Color *color;
20    E_Color *prev;
21
22    int dragging;
23 };
24
25 static void _e_wid_del_hook(Evas_Object *obj);
26 static void _e_wid_focus_hook(Evas_Object *obj);
27 static void _e_wid_disable_hook(Evas_Object *obj);
28 static void _e_wid_focus_steal(void *data, Evas *e, Evas_Object *obj, void *event_info);
29 static void _e_wid_value_set(Evas_Object *obj, double vx);
30 static void _e_wid_update(E_Widget_Data *wd);
31 static void _e_wid_update_standard(E_Widget_Data *wd);
32 static void _e_wid_update_fixed(E_Widget_Data *wd);
33
34 static void _e_wid_move(void *data, Evas *e, Evas_Object *obj, void *event_info);
35 static void _e_wid_resize(void *data, Evas *e, Evas_Object *obj, void *event_info);
36 static void _e_wid_cb_down(void *data, Evas *e, Evas_Object *obj, void *event_info);
37 static void _e_wid_cb_move(void *data, Evas *e, Evas_Object *obj, void *event_info);
38 static void _e_wid_cb_up(void *data, Evas *e, Evas_Object *obj, void *event_info);
39
40 Evas_Object *
41 e_widget_cslider_add(Evas *evas, E_Color_Component mode, E_Color *color, int vertical, int fixed)
42 {
43    Evas_Object *obj, *o;
44    E_Widget_Data *wd;
45    Evas_Coord mw, mh;
46    
47    obj = e_widget_add(evas);
48    
49    e_widget_del_hook_set(obj, _e_wid_del_hook);
50    e_widget_focus_hook_set(obj, _e_wid_focus_hook);
51    e_widget_disable_hook_set(obj, _e_wid_disable_hook);
52    wd = calloc(1, sizeof(E_Widget_Data));
53    e_widget_data_set(obj, wd);
54
55    wd->vertical = vertical;
56    wd->fixed = fixed;
57    wd->mode = mode;
58    wd->color = color;
59    wd->prev = calloc(1, sizeof (E_Color));
60    wd->o_hgrad = NULL;
61    
62    o = edje_object_add(evas);
63    wd->o_cslider = o;
64    e_theme_edje_object_set(o, "base/theme/widgets",
65                            "e/widgets/cslider");
66    if (wd->vertical)
67      edje_object_signal_emit(o, "e,state,direction,v", "e");
68    else
69      edje_object_signal_emit(o, "e,state,direction,h", "e");
70    evas_object_show(o);
71    edje_object_size_min_calc(o, &mw, &mh);
72    e_widget_size_min_set(obj, mw, mh);
73
74    e_widget_sub_object_add(obj, o);
75    evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_DOWN, _e_wid_focus_steal, obj);
76    e_widget_resize_object_set(obj, o);
77
78    /* add gradient obj */
79    o = evas_object_rectangle_add(evas);
80    e_widget_sub_object_add(obj, o);
81    evas_object_event_callback_add(o, EVAS_CALLBACK_MOVE, _e_wid_move, wd);
82    evas_object_event_callback_add(o, EVAS_CALLBACK_RESIZE, _e_wid_resize, wd);
83    evas_object_show(o);
84    evas_object_color_set(o, 0, 0, 0, 0);
85    wd->o_event = o;
86
87    edje_object_part_swallow(wd->o_cslider, "e.swallow.content", o);
88
89    o = evas_object_rectangle_add(evas);
90    e_widget_sub_object_add(obj, o);
91    evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_DOWN, _e_wid_cb_down, obj);
92    evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_MOVE, _e_wid_cb_move, obj);
93    evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_UP, _e_wid_cb_up, obj);
94    evas_object_show(o);
95    evas_object_color_set(o, 255, 255, 255, 255);
96    wd->o_grad = o;
97
98    _e_wid_update(wd);
99
100    return obj;
101 }
102
103 static void
104 _e_wid_move(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
105 {
106    E_Widget_Data *wd;
107    Evas_Coord x, y;
108
109    wd = data;
110    evas_object_geometry_get(obj, &x, &y, NULL, NULL);
111    evas_object_move(wd->o_grad, x, y);
112    _e_wid_update(wd);
113 }
114
115 static void
116 _e_wid_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
117 {
118    E_Widget_Data *wd;
119    Evas_Coord w, h;
120
121    wd = data;
122    evas_object_geometry_get(obj, NULL, NULL, &w, &h);
123    evas_object_resize(wd->o_grad, w, h);
124    _e_wid_update(wd);
125 }
126
127 static void
128 _e_wid_value_set(Evas_Object *o, double vx)
129 {
130    E_Widget_Data *wd;
131
132    wd = e_widget_data_get(o);
133    switch (wd->mode)
134      {
135       case E_COLOR_COMPONENT_R:
136          wd->color->r = 255 * vx;
137          e_color_update_rgb(wd->color);
138          break;
139       case E_COLOR_COMPONENT_G:
140          wd->color->g = 255 * vx;
141          e_color_update_rgb(wd->color);
142          break;
143       case E_COLOR_COMPONENT_B:
144          wd->color->b = 255 * vx;
145          e_color_update_rgb(wd->color);
146          break;
147       case E_COLOR_COMPONENT_H:
148          wd->color->h = 360 * vx;
149          e_color_update_hsv(wd->color);
150          break;
151       case E_COLOR_COMPONENT_S:
152          wd->color->s = vx;
153          e_color_update_hsv(wd->color);
154          break;
155       case E_COLOR_COMPONENT_V:
156          wd->color->v = vx;
157          e_color_update_hsv(wd->color);
158          break;
159       case E_COLOR_COMPONENT_MAX:
160          break;
161      }
162
163    _e_wid_update(wd);
164    e_widget_change(o);
165 }
166
167 void
168 e_widget_cslider_color_value_set(Evas_Object *obj, E_Color *val)
169 {
170    E_Widget_Data *wd;
171    
172    wd = e_widget_data_get(obj);
173    wd->color = val;
174    _e_wid_update(wd);
175 }
176
177 void
178 e_widget_cslider_update(Evas_Object *obj)
179 {
180    E_Widget_Data *wd;
181
182    wd = e_widget_data_get(obj);
183    _e_wid_update(wd);
184 }
185
186 void
187 e_widget_cslider_mode_set(Evas_Object *obj, E_Color_Component mode)
188 {
189    E_Widget_Data *wd;
190
191    wd = e_widget_data_get(obj);
192    if (wd->mode == mode) return;
193    wd->mode = mode;
194    _e_wid_update(wd);
195 }
196
197 static void
198 _e_wid_update(E_Widget_Data *wd)
199 {
200    Evas_Coord x, y, w, h;
201    Eina_Bool changed = EINA_FALSE;
202
203    evas_object_geometry_get(wd->o_event, &x, &y, &w, &h);
204    if (x != wd->x || y != wd->y || w != wd->w || h != wd->h)
205      changed = EINA_TRUE;
206
207    if (memcmp(wd->color, wd->prev, sizeof (E_Color)))
208      changed = EINA_TRUE;
209
210    if (changed)
211      {
212         Evas_Object *o;
213
214         if (wd->fixed)
215           _e_wid_update_fixed(wd);
216         else
217           _e_wid_update_standard(wd);
218
219         wd->x = x; wd->y = y;
220         wd->w = w; wd->h = h;
221         memcpy(wd->prev, wd->color, sizeof (E_Color));
222
223         if (wd->mode != E_COLOR_COMPONENT_H)
224           {
225              EINA_LIST_FREE(wd->o_hgrad, o)
226                evas_object_del(o);
227              evas_object_show(wd->o_grad);
228           }
229         else
230           {
231              evas_object_hide(wd->o_grad);
232           }
233      }
234 }
235
236 static void
237 _e_wid_gradient_set(Evas_Object *o, Eina_Bool orientation,
238                     int rf, int gf, int bf,
239                     int rt, int gt, int bt)
240 {
241    Evas_Map *m;
242
243    m = evas_map_new(4);
244    evas_map_util_points_populate_from_object(m, o);
245
246    if (orientation)
247      {
248         evas_map_point_color_set(m, 0, rf, gf, bf, 255);
249         evas_map_point_color_set(m, 1, rf, gf, bf, 255);
250         evas_map_point_color_set(m, 2, rt, gt, bt, 255);
251         evas_map_point_color_set(m, 3, rt, gt, bt, 255);
252      }
253    else
254      {
255         /* Rotate by 270° */
256         evas_map_point_color_set(m, 0, rf, gf, bf, 255);
257         evas_map_point_color_set(m, 1, rt, gt, bt, 255);
258         evas_map_point_color_set(m, 2, rt, gt, bt, 255);
259         evas_map_point_color_set(m, 3, rf, gf, bf, 255);
260      }
261
262    evas_object_map_enable_set(o, 1);
263    evas_object_map_set(o, m);
264    evas_map_free(m);
265 }
266
267 static void
268 _e_wid_update_standard(E_Widget_Data *wd)
269 {
270    Evas_Object *o;
271    Eina_List *l;
272    Evas_Coord x, y, w, h;
273    int r, g, b;
274    int rd, gd, bd;
275    int max, min;
276    unsigned int i;
277    float vx = 0;
278    int *grad[7][3] = {
279      { &max, &min, &min },
280      { &max, &max, &min },
281      { &min, &max, &min },
282      { &min, &max, &max },
283      { &min, &min, &max },
284      { &max, &min, &max },
285      { &max, &min, &min }
286    };
287
288    if (!wd->color) return;
289
290    switch (wd->mode)
291      {
292       case E_COLOR_COMPONENT_R:
293          _e_wid_gradient_set(wd->o_grad, wd->vertical,
294                              0, wd->color->g, wd->color->b,
295                              255, wd->color->g, wd->color->b);
296          vx = wd->color->r / 255.0;
297          break;
298       case E_COLOR_COMPONENT_G:
299          _e_wid_gradient_set(wd->o_grad, wd->vertical,
300                              wd->color->r, 0, wd->color->b,
301                              wd->color->r, 255, wd->color->b);
302          vx = wd->color->g / 255.0;
303          break;
304       case E_COLOR_COMPONENT_B:
305          _e_wid_gradient_set(wd->o_grad, wd->vertical,
306                              wd->color->r, wd->color->g, 0,
307                              wd->color->r, wd->color->g, 255);
308          vx = wd->color->b / 255.0;
309          break;
310       case E_COLOR_COMPONENT_H:
311          evas_color_hsv_to_rgb(0, wd->color->s, wd->color->v, &max, &min, NULL);
312
313          if (!wd->o_hgrad)
314            {
315               Evas *e;
316
317               e = evas_object_evas_get(wd->o_grad);
318               for (i = 0; i < 6; ++i)
319                 wd->o_hgrad = eina_list_append(wd->o_hgrad,
320                                                evas_object_rectangle_add(e));
321            }
322
323          evas_object_geometry_get(wd->o_grad, &x, &y, &w, &h);
324          evas_object_hide(wd->o_grad);
325
326          i = 0;
327          EINA_LIST_FOREACH(wd->o_hgrad, l, o)
328            {
329               if (wd->vertical)
330                 {
331                    evas_object_move(o, x, y + (i * h) / 6);
332                    evas_object_resize(o, w, h / 6);
333                 }
334               else
335                 {
336                    evas_object_move(o, x + (i * w) / 6, y);
337                    evas_object_resize(o, w / 6, h);
338                 }
339
340               _e_wid_gradient_set(o, wd->vertical,
341                                   *grad[i][0], *grad[i][1], *grad[i][2],
342                                   *grad[i + 1][0], *grad[i + 1][1], *grad[i + 1][2]);
343               evas_object_show(o);
344               i++;
345            }
346          vx = wd->color->h / 360.0;
347          break;
348       case E_COLOR_COMPONENT_S:
349          evas_color_hsv_to_rgb(wd->color->h, 0, wd->color->v, &r, &g, &b);
350          evas_color_hsv_to_rgb(wd->color->h, 1, wd->color->v, &rd, &gd, &bd);
351
352          _e_wid_gradient_set(wd->o_grad, wd->vertical,
353                              r, g, b,
354                              rd, gd, bd);
355          vx = wd->color->s;
356          break;
357       case E_COLOR_COMPONENT_V:
358          evas_color_hsv_to_rgb(wd->color->h, wd->color->s, 0, &r, &g, &b);
359          evas_color_hsv_to_rgb(wd->color->h, wd->color->s, 1, &rd, &gd, &bd);
360
361          _e_wid_gradient_set(wd->o_grad, wd->vertical,
362                              r, g, b,
363                              rd, gd, bd);
364          vx = wd->color->v;
365          break;
366       case E_COLOR_COMPONENT_MAX:
367          break;
368      }
369
370    edje_object_part_drag_value_set(wd->o_cslider, "e.dragable.cursor", vx, vx);
371 }
372
373 void
374 _e_wid_update_fixed(E_Widget_Data *wd)
375 {
376 #define GMAX 255
377 #define GMIN 0
378
379    Evas_Object *o;
380    Eina_List *l;
381    Evas_Coord x, y, w, h;
382    unsigned int i;
383    float vx = 0;
384    int grad[7][3] = {
385      { GMAX, GMIN, GMIN },
386      { GMAX, GMIN, GMAX },
387      { GMIN, GMIN, GMAX },
388      { GMIN, GMAX, GMAX },
389      { GMIN, GMAX, GMIN },
390      { GMAX, GMAX, GMIN },
391      { GMAX, GMIN, GMIN }
392    };
393
394    if (!wd) return;
395
396    switch (wd->mode)
397     {
398      case E_COLOR_COMPONENT_R:
399         _e_wid_gradient_set(wd->o_grad, wd->vertical,
400                             255, 0, 0,
401                             0, 0, 0);
402         vx = wd->color->r / 255.0;
403         break;
404      case E_COLOR_COMPONENT_G:
405         _e_wid_gradient_set(wd->o_grad, wd->vertical,
406                             0, 255, 0,
407                             0, 0, 0);
408         vx = wd->color->g / 255.0;
409         break;
410      case E_COLOR_COMPONENT_B:
411         _e_wid_gradient_set(wd->o_grad, wd->vertical,
412                             0, 0, 255,
413                             0, 0, 0);
414         vx = wd->color->b / 255.0;
415         break;
416      case E_COLOR_COMPONENT_H:
417         /*
418          * Color Stops:
419          *   0 x n n
420          *  60 x x n
421          * 120 n x n
422          * 180 n x x
423          * 240 n n x
424          * 300 x n x
425          * 360 x n n
426          */
427
428         if (!wd->o_hgrad)
429           {
430              Evas *e;
431
432              e = evas_object_evas_get(wd->o_grad);
433              for (i = 0; i < 6; ++i)
434                wd->o_hgrad = eina_list_append(wd->o_hgrad,
435                                               evas_object_rectangle_add(e));
436           }
437
438         evas_object_geometry_get(wd->o_grad, &x, &y, &w, &h);
439         evas_object_hide(wd->o_grad);
440
441         i = 0;
442         EINA_LIST_FOREACH(wd->o_hgrad, l, o)
443           {
444              if (wd->vertical)
445                {
446                   evas_object_move(o, x, y + (i * h) / 6);
447                   evas_object_resize(o, w, h / 6);
448                }
449              else
450                {
451                   evas_object_move(o, x + (i * w) / 6, y);
452                   evas_object_resize(o, w / 6, h);
453                }
454
455              _e_wid_gradient_set(o, wd->vertical,
456                                  grad[i][0], grad[i][1], grad[i][2],
457                                  grad[i + 1][0], grad[i + 1][1], grad[i + 1][2]);
458              evas_object_show(o);
459              i++;
460           }
461         vx = wd->color->h / 360.0;
462         break;
463      case E_COLOR_COMPONENT_S:
464         _e_wid_gradient_set(wd->o_grad, wd->vertical,
465                             255, 255, 255,
466                             0, 0, 0);
467         vx = wd->color->s;
468         break;
469      case E_COLOR_COMPONENT_V:
470         _e_wid_gradient_set(wd->o_grad, wd->vertical,
471                             255, 255, 255,
472                             0, 0, 0);
473         vx = wd->color->v;
474         break;
475      case E_COLOR_COMPONENT_MAX:
476         break;
477     }
478
479    edje_object_part_drag_value_set(wd->o_cslider, "e.dragable.cursor", vx, vx);
480
481 #undef GMAX
482 #undef GMIN
483 }
484
485 static void
486 _e_wid_del_hook(Evas_Object *obj)
487 {
488    E_Widget_Data *wd;
489    
490    wd = e_widget_data_get(obj);
491    free(wd);
492 }
493
494 static void
495 _e_wid_focus_hook(Evas_Object *obj)
496 {
497    E_Widget_Data *wd;
498    
499    wd = e_widget_data_get(obj);
500    if (e_widget_focus_get(obj))
501      {
502         edje_object_signal_emit(wd->o_cslider, "e,state,focused", "e");
503         evas_object_focus_set(wd->o_cslider, 1);
504      }
505    else
506      {
507         edje_object_signal_emit(wd->o_cslider, "e,state,unfocused", "e");
508         evas_object_focus_set(wd->o_cslider, 0);
509      }
510 }
511
512 static void
513 _e_wid_disable_hook(Evas_Object *obj)
514 {
515    E_Widget_Data *wd;
516    
517    wd = e_widget_data_get(obj);
518    if (e_widget_disabled_get(obj))
519      edje_object_signal_emit(wd->o_cslider, "e,state,disabled", "e");
520    else
521      edje_object_signal_emit(wd->o_cslider, "e,state,enabled", "e");
522 }
523
524 static void
525 _e_wid_focus_steal(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
526 {
527    e_widget_focus_steal(data);
528 }
529
530 static void
531 _e_wid_cb_down(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
532 {
533    Evas_Event_Mouse_Down *ev;
534    Evas_Object *o_wid;
535    E_Widget_Data *wd;
536    Evas_Coord ox, oy, ow, oh;
537    double val;
538
539    ev = event_info;
540
541    o_wid = data;
542    wd = e_widget_data_get(o_wid);
543    wd->dragging = 1;
544
545    evas_object_geometry_get(wd->o_grad, &ox, &oy, &ow, &oh);
546
547    if (wd->vertical) 
548      val = 1 - ((ev->canvas.y - oy) / (double)oh);
549    else
550      val = (ev->canvas.x - ox) / (double)ow;
551    if (val > 1) val = 1;
552    if (val < 0) val = 0;
553    _e_wid_value_set(o_wid, val);
554 }
555
556 static void
557 _e_wid_cb_up(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
558 {
559    Evas_Object *o_wid;
560    E_Widget_Data *wd;
561    
562    o_wid = data;
563    wd = e_widget_data_get(o_wid);
564    wd->dragging = 0;
565 }
566
567 static void
568 _e_wid_cb_move(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
569 {
570    Evas_Event_Mouse_Move *ev;
571    Evas_Object *o_wid;
572    E_Widget_Data *wd;
573    
574    o_wid = data;
575    wd = e_widget_data_get(o_wid);
576    ev = event_info;
577   
578    if (wd->dragging == 1)
579      {
580         Evas_Coord ox, oy, ow, oh;
581         double val;
582         evas_object_geometry_get(wd->o_grad, &ox, &oy, &ow, &oh);
583
584         if (wd->vertical) 
585           val = 1 - ((ev->cur.canvas.y - oy) / (double)oh);
586         else
587           val = (ev->cur.canvas.x - ox) / (double)ow;
588         if (val > 1) val = 1;
589         if (val < 0) val = 0;
590         _e_wid_value_set(o_wid, val);
591      }
592 }