Merge branch 'master' of 165.213.180.234:/git/slp/pkgs/elementary
[framework/uifw/elementary.git] / src / lib / elm_segment_control.c
1 #include <Elementary.h>
2 #include "elm_priv.h"
3
4 /**
5  * @defgroup SegmentControl SegmentControl
6  * @ingroup Elementary
7  *
8  * SegmentControl object is a horizontal control made of multiple segments,
9  * each segment item functioning as a discrete button. A segmented control affords a compact means to group together a number of controls.
10  * A segmented control can display a title or an image. The UISegmentedControl object automatically resizes segment items to fit proportionally
11  * within their superview unless they have a specific width set. When you add and remove segments,
12  * you can request that the action be animated with sliding and fading effects.
13  */
14 typedef struct _Widget_Data Widget_Data;
15 struct _Widget_Data
16 {
17    Evas_Object *box;
18    Evas_Object *base;
19    Eina_List *seg_ctrl;
20    Elm_Segment_Item *ani_it;
21    Ecore_Animator *ani;
22    int width, height;
23    int id;
24    int item_width;
25    int cur_fontsize;
26    int max_height, w_pad, h_pad;
27    unsigned int count;
28    unsigned int insert_index;
29    unsigned int del_index;
30    unsigned int cur_seg_id;
31    unsigned int def_r;
32    unsigned int def_g;
33    unsigned int def_b;
34    unsigned int def_a;
35    unsigned int press_r;
36    unsigned int press_g;
37    unsigned int press_b;
38    unsigned int press_a;
39    unsigned int sel_r;
40    unsigned int sel_g;
41    unsigned int sel_b;
42    unsigned int sel_a;
43    double scale_factor;
44 };
45
46 struct _Elm_Segment_Item
47 {
48    Evas_Object *obj;
49    Evas_Object *base;
50    Evas_Object *icon;
51    Evas_Object *label_wd;
52    const char *label;
53    int segment_id;
54    int selected_id;
55    Eina_Bool delete_me : 1;
56    Eina_Bool sel : 1;
57 };
58
59 static void _mouse_down(void *data, Evas *evas, Evas_Object *obj, void *event_info);
60 static void _mouse_up(void *data, Evas *e, Evas_Object *obj, void *event_info);
61 static void _signal_segment_selected(void *data);
62 static void _signal_segment_on(void *data);
63 static void _signal_segment_off(void *data);
64 static void _theme_hook(Evas_Object *obj);
65 static void _item_free(Evas_Object *obj, Elm_Segment_Item *it);
66 static void _del_hook(Evas_Object *obj);
67 static void _layout(Evas_Object *o, Evas_Object_Box_Data *priv, void *data);
68 static void _segment_resizing(void *data);
69 static void _object_resize(void *data, Evas *e, Evas_Object *obj, void *event_info);
70 static void _update_list(Evas_Object *obj);
71 static void _refresh_segment_ids(Evas_Object *obj);
72 static void _state_value_set(Evas_Object *obj);
73 static void _color_value_get(Evas_Object *obj);
74
75 static Elm_Segment_Item* _item_new(Evas_Object *obj, const char *label, Evas_Object *icon);
76 static Elm_Segment_Item *_item_find(Evas_Object *obj, unsigned int index);
77
78 static int * _animator_animate_add_cb(Evas_Object *obj);
79 static int * _animator_animate_del_cb(Evas_Object *obj);
80
81 static void
82 _signal_segment_off(void *data)
83 {
84     Elm_Segment_Item *item = (Elm_Segment_Item *) data;
85     Widget_Data *wd = elm_widget_data_get(item->obj);
86     if (!wd) return;
87     
88     edje_object_signal_emit(item->base, "elm,action,unfocus", "elm");
89     edje_object_signal_emit(item->base, "elm,state,segment,release", "elm");
90     if(!item->label_wd && item->label)
91       edje_object_signal_emit(item->base, "elm,state,text,visible", "elm");
92     if(item->label_wd)
93       elm_label_text_color_set(item->label_wd, wd->def_r, wd->def_g, wd->def_b, wd->def_a);
94
95     return;
96 }
97
98 static void
99 _signal_segment_selected(void *data)
100 {
101    Elm_Segment_Item *item = (Elm_Segment_Item *) data;
102    Elm_Segment_Item *it;
103    Eina_List *l;
104
105    Widget_Data *wd = elm_widget_data_get(item->obj);
106    if (!wd) return;
107    item->sel = EINA_TRUE;
108    if (item->segment_id == wd->cur_seg_id && item->segment_id) return;
109    EINA_LIST_FOREACH(wd->seg_ctrl, l, it)
110      {
111         if (it->segment_id == wd->cur_seg_id)
112           {
113              _signal_segment_off (it);
114           }
115         if (it->segment_id == item->selected_id)
116           {
117              _signal_segment_off (it);
118           }
119         it->selected_id = -1;
120      }
121    edje_object_signal_emit(item->base, "elm,action,focus", "elm");
122    if(!item->label_wd)
123      edje_object_signal_emit(item->base, "elm,state,text,change", "elm");
124    if(item->label_wd)
125      elm_label_text_color_set(item->label_wd, wd->sel_r, wd->sel_g, wd->sel_b, wd->sel_a);
126    item->selected_id = item->segment_id;
127    evas_object_smart_callback_call(item->obj, "changed", (void*)item->selected_id);
128
129    return;
130 }
131
132 static void
133 _signal_segment_on(void *data)
134 {
135    Elm_Segment_Item *item = (Elm_Segment_Item *) data;
136    Elm_Segment_Item *it;
137    Eina_List *l;
138
139    Widget_Data *wd = elm_widget_data_get(item->obj);
140    if (!wd) return;
141
142    item->sel = EINA_TRUE;
143
144    if (item->segment_id == wd->cur_seg_id && item->segment_id) return;
145
146    EINA_LIST_FOREACH(wd->seg_ctrl, l, it)
147      {
148         if (it->segment_id == wd->cur_seg_id)
149           {
150              _signal_segment_off (it);
151           }
152         if (it->segment_id == item->selected_id)
153           {
154              _signal_segment_off (it);
155           }
156         it->selected_id = -1;
157      }
158    edje_object_signal_emit(item->base, "elm,action,focus", "elm");
159    if(!item->label_wd)
160      edje_object_signal_emit(item->base, "elm,state,text,change", "elm");
161    if(item->label_wd)
162      elm_label_text_color_set(item->label_wd, wd->sel_r,wd->sel_g, wd->sel_g, wd->sel_a);
163
164    wd->cur_seg_id = item->segment_id;
165    evas_object_smart_callback_call(item->obj, "changed", (void*)wd->cur_seg_id);
166
167    return;
168 }
169
170 static void
171 _mouse_up(void *data, Evas *e, Evas_Object *obj, void *event_info)
172 {
173    Elm_Segment_Item *item = (Elm_Segment_Item *) data;
174    Widget_Data *wd = elm_widget_data_get(item->obj);
175    if (!wd) return;
176    if (item->segment_id == wd->cur_seg_id)
177      {
178         if(!item->label_wd)
179           edje_object_signal_emit(item->base, "elm,state,text,change", "elm");
180         item->sel = EINA_TRUE;
181         return;
182      }
183     _signal_segment_on((void*)item);
184
185     return;
186 }
187
188 static void
189 _mouse_down(void *data, Evas *evas, Evas_Object *obj, void *event_info)
190 {
191    Elm_Segment_Item *item = (Elm_Segment_Item *) data;
192    Widget_Data *wd = elm_widget_data_get(item->obj);
193
194    if (!wd) return;
195    
196    if(!item->label_wd && wd->cur_seg_id != item->segment_id)
197      {
198         edje_object_signal_emit(item->base, "elm,state,text,pressed", "elm");
199      }
200    if(item->label_wd && wd->cur_seg_id != item->segment_id)
201      elm_label_text_color_set(item->label_wd, wd->press_r, wd->press_g, wd->press_b, wd->press_a);
202
203    edje_object_signal_emit(item->base, "elm,state,segment,press", "elm");
204    return;
205 }
206
207 static void
208 _theme_hook(Evas_Object *obj)
209 {
210    _elm_theme_object_set(obj, obj, "segmented-control", "base", elm_widget_style_get(obj));
211
212    return;
213 }
214
215 static void
216 _item_free(Evas_Object *obj, Elm_Segment_Item *it)
217 {
218    Widget_Data *wd = elm_widget_data_get(obj);
219    if (!wd) return;
220
221    if(wd->seg_ctrl)
222      wd->seg_ctrl = eina_list_remove(wd->seg_ctrl, it);
223
224    if(it->icon) evas_object_del(it->icon);
225    if(it->label_wd) 
226      {
227         evas_object_del(it->label_wd);
228         it->label_wd = NULL;
229         if (edje_object_part_swallow_get(it->base, "elm.swallow.label.content") == NULL) 
230           {
231              edje_object_part_unswallow(it->base, it->label_wd);
232           }
233      }
234    if(it->base) evas_object_del(it->base);
235    if(it->label) eina_stringshare_del(it->label);
236
237    if(it)
238      free(it);
239    it = NULL;
240    
241    return;
242 }
243
244 static void
245 _del_hook(Evas_Object *obj)
246 {
247    Widget_Data *wd = elm_widget_data_get(obj);
248    Elm_Segment_Item *it;
249    Eina_List *l, *clear = NULL;
250
251    EINA_LIST_FOREACH(wd->seg_ctrl, l, it) clear = eina_list_append(clear, it);
252    EINA_LIST_FREE(clear, it) _item_free(obj, it);
253
254    if(wd) free(wd);
255    wd = NULL;
256
257    return;
258 }
259
260
261 static void
262 _layout(Evas_Object *o, Evas_Object_Box_Data *priv, void *data)
263 {
264    Widget_Data *wd = data;
265    if (!wd) return;
266    _els_box_layout(o, priv, 1, 0); /* making box layout non homogenous */
267
268    return;
269 }
270
271 static void
272 _segment_resizing(void *data)
273 {
274    Widget_Data *wd = elm_widget_data_get((Evas_Object *)data);
275    if (!wd) return;
276    Evas_Coord w = 0, h = 0;
277
278    evas_object_geometry_get(wd->base, NULL, NULL, &w, &h);
279    wd->item_width = wd->width = w;
280    wd->height = h;
281
282    _state_value_set((Evas_Object *)data);
283 }
284
285 static void 
286 _object_resize(void *data, Evas *e, Evas_Object *obj, void *event_info)
287 {
288    Widget_Data *wd;
289    if(!data) return;
290    wd = elm_widget_data_get((Evas_Object *)data);
291    if(!wd) return;
292
293    ecore_job_add(_segment_resizing, (Evas_Object *)data);
294 }
295
296 static void
297 _segment_item_resizing(void *data)
298 {
299    Widget_Data *wd;
300    Elm_Segment_Item *it = (Elm_Segment_Item *)data; 
301    wd = elm_widget_data_get(it->obj);
302
303    if(!wd) return;
304    Evas_Coord w = 0, h = 0;
305    _update_list(it->obj);
306
307    evas_object_geometry_get(it->base, NULL, NULL, &w, &h);
308
309    if(wd->max_height == 1) wd->max_height = h;
310
311    if(it->label_wd) 
312      {
313         elm_label_wrap_width_set(it->label_wd, w-wd->w_pad);
314         elm_label_wrap_height_set(it->label_wd, wd->max_height-wd->h_pad);
315
316         if (edje_object_part_swallow_get(it->base, "elm.swallow.label.content") == NULL)
317           {
318              edje_object_part_unswallow(it->base, it->label_wd);
319           }
320         edje_object_part_swallow(it->base, "elm.swallow.label.content", it->label_wd);
321         edje_object_signal_emit(it->base, "elm,state,label,visible", "elm");
322         if (it->segment_id == wd->cur_seg_id && it->sel)
323           {
324             elm_label_text_color_set(it->label_wd, wd->sel_r, wd->sel_g, wd->sel_b, wd->sel_a);
325           }
326         else
327           elm_label_text_color_set(it->label_wd, wd->def_r, wd->def_g, wd->def_b, wd->def_a);
328      }
329 }
330
331 static void 
332 _object_item_resize(void *data, Evas *e, Evas_Object *obj, void *event_info)
333 {
334    ecore_job_add(_segment_item_resizing, (Evas_Object *)data);
335 }
336
337 static Elm_Segment_Item*
338 _item_new(Evas_Object *obj, const char *label, Evas_Object *icon)
339 {
340    Elm_Segment_Item *it; 
341    Evas_Coord mw, mh; 
342    Widget_Data *wd = elm_widget_data_get(obj);
343    if (!wd) return NULL;
344
345    it = calloc(1, sizeof(   Elm_Segment_Item));
346    if (!it) return NULL;
347
348    if(obj) it->obj = obj;
349    it->delete_me = EINA_FALSE;
350    it->segment_id = wd->id;
351    it->label_wd = NULL;
352    it->sel = EINA_FALSE;
353    it->selected_id = -1;
354
355    it->base = edje_object_add(evas_object_evas_get(obj));
356    _elm_theme_object_set(obj, it->obj, "segment", "base/default", elm_object_style_get(it->obj));
357
358    if (it->label) eina_stringshare_del(it->label);
359    if (label)
360      {
361         it->label = eina_stringshare_add(label);
362      }
363
364    if ((it->icon != icon) && (it->icon))
365      elm_widget_sub_object_del(obj, it->icon);
366    it->icon = icon;
367    if (it->icon)
368      {
369         elm_widget_sub_object_add(obj, icon);
370         Evas_Coord minw = -1, minh = -1, maxw = -1, maxh = -1;
371         elm_coords_finger_size_adjust(1, &minw, 1, &minh);
372         elm_coords_finger_size_adjust(1, &minw, 1, &minh);
373
374         evas_object_size_hint_weight_set(it->base, 1.0, -1.0);
375         evas_object_size_hint_align_set(it->base, 1.0, -1.0);
376         evas_object_size_hint_min_set(it->base, -1, -1);
377         evas_object_size_hint_max_set(it->base, maxw, maxh);
378      }
379
380    edje_object_size_min_restricted_calc(obj, &mw, &mh, 0, 0);
381    evas_object_size_hint_weight_set(obj, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
382    evas_object_size_hint_align_set(obj, EVAS_HINT_FILL, EVAS_HINT_FILL);
383
384    return it;
385 }
386
387
388 static void 
389 _update_list(Evas_Object *obj)
390 {
391    Elm_Segment_Item *it = NULL;
392    Elm_Segment_Item *del_it = NULL;
393    Elm_Segment_Item *next_sel_it = NULL;
394    Elm_Segment_Item *seg_it;
395    Eina_List *l;
396    int i = 0;
397  
398    Widget_Data *wd = elm_widget_data_get(obj);
399    if (!wd) return;
400
401    wd->count = eina_list_count(wd->seg_ctrl);
402    if(wd->count == 1)
403      {
404         it = _item_find(obj, 0);
405         _elm_theme_object_set(obj, it->base, "segment", "base/single", elm_object_style_get(it->obj));\r
406         edje_object_signal_emit(it->base, "elm,state,segment,on", "elm");
407         if(it->label && !it->label_wd)
408           {
409              edje_object_signal_emit(it->base, "elm,state,text,change", "elm");
410              edje_object_part_text_set(it->base, "elm.text", it->label);
411           }
412         else
413        edje_object_signal_emit(it->base, "elm,state,text,hidden", "elm");
414
415         if (it->icon && edje_object_part_swallow_get(it->base, "elm.swallow.content") == NULL)
416           {
417              if(it->icon)
418                {
419                   edje_object_part_swallow(it->base, "elm.swallow.content", it->icon);
420                   edje_object_signal_emit(it->base, "elm,state,icon,visible", "elm");
421                }
422              else
423                edje_object_signal_emit(it->base, "elm,state,icon,hidden", "elm");
424           }
425         if(it->label_wd)
426           {
427              edje_object_signal_emit(it->base, "elm,state,label,visible", "elm");
428              elm_label_text_color_set(it->label_wd, wd->sel_r, wd->sel_g, wd->sel_b, wd->sel_a);
429           }
430
431         return;
432      }
433
434    EINA_LIST_FOREACH(wd->seg_ctrl, l, it)
435      {
436         if(i==0)
437           {
438              _elm_theme_object_set(obj, it->base, "segment", "base/first", elm_object_style_get(it->obj));
439           }
440         else if(i==wd->count-1)
441           {
442              _elm_theme_object_set(obj, it->base, "segment", "base/last", elm_object_style_get(it->obj));
443           }
444         else
445           {
446              _elm_theme_object_set(obj, it->base, "segment", "base/default", elm_object_style_get(it->obj));
447
448           }
449           
450         if(it->label && !it->label_wd)
451           {
452              edje_object_signal_emit(it->base, "elm,state,text,visible", "elm");
453              edje_object_part_text_set(it->base, "elm.text", it->label);
454           }
455         else
456           edje_object_signal_emit(it->base, "elm,state,text,hidden", "elm");
457
458         if (it->icon && edje_object_part_swallow_get(it->base, "elm.swallow.content") == NULL)
459           {
460              if(it->icon)
461                {
462                   edje_object_part_swallow(it->base, "elm.swallow.content", it->icon);
463                   edje_object_signal_emit(it->base, "elm,state,icon,visible", "elm");
464                }
465              else
466                edje_object_signal_emit(it->base, "elm,state,icon,hidden", "elm");
467           }
468         if(it->label_wd)
469           {
470              edje_object_signal_emit(it->base, "elm,state,label,visible", "elm");
471           }
472         if(it->sel)
473           _signal_segment_on((void*)it);
474
475         i++;
476      }
477
478      i = 0;
479      EINA_LIST_FOREACH(wd->seg_ctrl, l, seg_it)
480        {
481           if(wd->del_index == 0)
482             {
483               if (i == 0)
484                 {
485                    next_sel_it = seg_it;
486                    _signal_segment_on((void*)next_sel_it);
487                    break;
488                 }
489             }
490           else
491             {
492                if (i == wd->del_index-1)
493                  next_sel_it = seg_it;
494                if (i == wd->del_index)
495                  {
496                     del_it = seg_it;
497                     break;
498                  }
499              }
500           i++;
501        }
502      if(next_sel_it && del_it && del_it->sel)
503        _signal_segment_on((void*)next_sel_it);
504 }
505
506
507 static void 
508 _refresh_segment_ids(Evas_Object *obj)
509 {
510    Elm_Segment_Item *it;
511    Eina_List *l;
512    int i = 0;
513    Widget_Data *wd = elm_widget_data_get(obj);
514    if (!wd) return;
515
516    if ((wd->insert_index > 0) && wd->cur_seg_id >= wd->insert_index)
517      {
518         ++wd->cur_seg_id;
519         wd->insert_index = 0;
520      }
521    if (wd->del_index > 0)
522      {
523         if (wd->cur_seg_id >= wd->del_index)
524           --wd->cur_seg_id;
525         wd->del_index = -1;
526      }
527
528    EINA_LIST_FOREACH(wd->seg_ctrl, l, it)
529      {
530         it->segment_id = i;
531         i++;
532      }
533 }
534
535 static void 
536 _state_value_set(Evas_Object *obj)
537 {
538    Elm_Segment_Item *it;
539    Eina_List *l;
540    Evas_Coord mw, mh, x, y;
541
542    int w1=0, w2, i=0;
543    unsigned int count ;
544    Widget_Data *wd = elm_widget_data_get(obj);
545    if (!wd) return;
546    
547    count = eina_list_count(wd->seg_ctrl);
548    if (count > 0)
549      wd->item_width = wd->width/count;
550    if (wd->ani_it)
551      {
552         evas_object_geometry_get(wd->ani_it->base, &x, &y, &w1, NULL);
553         if (wd->ani_it->delete_me)
554           {
555              w1-=(wd->item_width/5);
556              if( w1< 0) w1 = 0;
557           }
558         else
559         {
560            w1+=(wd->item_width/5);
561            if( w1 > wd->item_width )
562              w1 = wd->item_width;
563         }
564         w2 = (wd->width-w1)/(count -1);
565      }
566    else
567       w2 = wd->item_width;
568           
569    EINA_LIST_FOREACH(wd->seg_ctrl, l, it)
570     {
571        edje_object_size_min_restricted_calc(it->base, &mw, &mh, 0, 0);
572        evas_object_size_hint_weight_set(it->base, 1.0, 1.0);
573        evas_object_size_hint_align_set(it->base, -1.0, -1.0);
574         
575                 
576        if(wd->ani_it  && it == wd->ani_it)
577          {
578             evas_object_resize(it->base, w1, wd->height);
579             evas_object_size_hint_min_set(it->base, w1, wd->height);
580             evas_object_size_hint_max_set(it->base, w1, wd->height);
581          }
582        else
583          {
584             evas_object_resize(it->base, w2, wd->height);
585             evas_object_size_hint_min_set(it->base, w2, wd->height);
586             evas_object_size_hint_max_set(it->base, w2, wd->height);
587         }
588        ++i;
589     }
590
591     return;
592 }
593
594 static void _color_value_get(Evas_Object *obj)
595 {
596    Widget_Data *wd = (Widget_Data *)obj;
597    if (!wd) return;
598
599    const char *def_r, *def_g, *def_b, *def_a;
600    const char *press_r, *press_g, *press_b, *press_a;
601    const char *sel_r, *sel_g, *sel_b, *sel_a;
602
603    def_r = edje_object_data_get(wd->base, "def_r");
604    if (def_r) wd->def_r = atoi(def_r);
605    else wd->def_r = 0x1B;
606    def_g = edje_object_data_get(wd->base, "def_g");
607    if (def_g) wd->def_g = atoi(def_g);
608    else wd->def_g = 0x1A;
609    def_b = edje_object_data_get(wd->base, "def_b");
610    if (def_b) wd->def_b = atoi(def_b);
611    else wd->def_b = 0x18;
612    def_a = edje_object_data_get(wd->base, "def_a");
613    if (def_a) wd->def_a = atoi(def_a);
614    else wd->def_a = 0xFF;
615
616    press_r = edje_object_data_get(wd->base, "press_r");
617    if (press_r) wd->press_r = atoi(press_r);
618    else wd->press_r = 0xFF;
619    press_g = edje_object_data_get(wd->base, "press_g");
620    if (press_g) wd->press_g = atoi(press_g);
621    else wd->press_g = 0xFF;
622    press_b = edje_object_data_get(wd->base, "press_b");
623    if (press_b) wd->press_b = atoi(press_b);
624    else wd->press_b = 0xFF;
625    press_a = edje_object_data_get(wd->base, "press_a");
626    if (press_a) wd->press_a = atoi(press_a);
627    else wd->press_a = 0xFF;
628
629    sel_r = edje_object_data_get(wd->base, "sel_r");
630    if (sel_r) wd->sel_r = atoi(sel_r);
631    else  wd->sel_r = 0x00;
632    sel_g = edje_object_data_get(wd->base, "sel_g");
633    if (sel_g) wd->sel_g = atoi(sel_g);
634    else wd->sel_g = 0x00;
635    sel_b = edje_object_data_get(wd->base, "sel_b");
636    if (sel_b) wd->sel_b = atoi(sel_b);
637    else wd->sel_b = 0x00;
638    sel_a = edje_object_data_get(wd->base, "sel_a");
639    if (sel_a) wd->sel_a = atoi(sel_a);
640    else wd->sel_a = 0xFF;
641 }
642
643 static int *
644 _animator_animate_add_cb(Evas_Object *obj)
645 {
646    int w;
647    Widget_Data *wd = elm_widget_data_get(obj);
648    if (!wd) return 0;
649
650    evas_object_geometry_get(wd->ani_it->base, NULL, NULL, &w, NULL);
651    if( w <  wd->item_width )
652      {
653          _state_value_set(obj);
654          evas_object_geometry_get(wd->ani_it->base, NULL, NULL, &w, NULL);
655          return (int*) ECORE_CALLBACK_RENEW;
656      }
657    else
658      {
659         ecore_animator_del(wd->ani);
660         wd->ani = NULL;
661         wd->ani_it = NULL;
662         return (int*) ECORE_CALLBACK_CANCEL;
663      }
664 }
665
666
667 static int *
668 _animator_animate_del_cb(Evas_Object *obj)
669 {
670    int w;
671    Widget_Data *wd = elm_widget_data_get(obj);
672    if (!wd) return 0;\r
673
674    evas_object_geometry_get(wd->ani_it->base, NULL, NULL, &w, NULL);
675    if( w >  0 )
676      {
677         _state_value_set(obj);
678         evas_object_geometry_get(wd->ani_it->base, NULL, NULL, &w, NULL);
679         return (int*) ECORE_CALLBACK_RENEW;
680      }
681    else
682      {
683         _item_free(obj, wd->ani_it );
684         _refresh_segment_ids(obj);
685         ecore_animator_del(wd->ani);
686         wd->ani = NULL;
687         wd->ani_it = NULL;
688         _update_list(obj);
689         wd->id = eina_list_count(wd->seg_ctrl);
690         return (int*) ECORE_CALLBACK_CANCEL;
691      }
692 }
693
694 static Elm_Segment_Item *
695 _item_find(Evas_Object *obj, unsigned int index)
696 {
697    Elm_Segment_Item *it;
698    Eina_List *l;
699    int i = 0;
700    Widget_Data *wd = elm_widget_data_get(obj);
701    if (!wd) return NULL;
702
703    EINA_LIST_FOREACH(wd->seg_ctrl, l, it)
704      {
705         if (i == index) return it;
706         i++;
707      }
708      return NULL;
709 }
710
711 /**
712  * Add a new segmentcontrol to the parent
713  * @param parent The parent object
714  * @return The new object or NULL if it cannot be created
715  *
716  * @ingroup SegmentControl SegmentControl
717  */
718 EAPI Evas_Object *
719 elm_segment_control_add(Evas_Object *parent)
720 {
721    Evas_Object *obj;
722    Evas *e;
723    Widget_Data *wd;
724
725    const char *deffont, *maxheight, *wpad, *hpad;
726
727    wd = ELM_NEW(Widget_Data);
728    e = evas_object_evas_get(parent);
729    if(!e) return NULL;
730    obj = elm_widget_add(e);
731    elm_widget_type_set(obj, "segmented-control");
732    elm_widget_sub_object_add(parent, obj);
733    elm_widget_data_set(obj, wd);
734    elm_widget_del_hook_set(obj, _del_hook);
735    elm_widget_theme_hook_set(obj, _theme_hook);
736
737    wd->base = edje_object_add(e);
738    _elm_theme_object_set(obj, wd->base, "segmented-control", "base", "default");
739    elm_widget_resize_object_set(obj, wd->base);
740    wd->box = evas_object_box_add(e);
741    evas_object_box_layout_set(wd->box, _layout, wd, NULL);
742    elm_widget_sub_object_add(obj, wd->box);
743    edje_object_part_swallow(wd->base, "elm.swallow.content", wd->box);
744    evas_object_show(wd->box);
745
746    evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE, _object_resize, obj);
747    wd->id = 0;
748    wd->del_index = -1;
749    wd->insert_index = -1;
750    wd->cur_seg_id = -1;
751
752    deffont = edje_object_data_get(wd->base, "default_font_size");
753    if (deffont) wd->cur_fontsize = atoi(deffont);
754    else wd->cur_fontsize = 1;
755
756    maxheight = edje_object_data_get(wd->base, "max_height");
757    if (maxheight) wd->max_height = atoi(maxheight);
758    else wd->max_height = 1;
759
760    wpad = edje_object_data_get(wd->base, "w_pad");
761    if (wpad) wd->w_pad = atoi(wpad);
762    else wd->w_pad = 1;
763
764    hpad = edje_object_data_get(wd->base, "h_pad");
765    if (hpad) wd->h_pad = atoi(hpad);
766    else wd->h_pad = 1;
767
768    return obj;
769 }
770
771 EAPI Elm_Segment_Item *
772 elm_segment_control_item_add(Evas_Object *obj, Evas_Object *icon, const char *label, Eina_Bool animate)
773 {
774    Elm_Segment_Item *it;
775    Widget_Data *wd = elm_widget_data_get(obj);
776    if(!wd) return NULL;
777
778    it = _item_new(obj, label, icon);
779    if(!it) return NULL;
780
781    wd->seg_ctrl = eina_list_append(wd->seg_ctrl, it);
782    wd->id = eina_list_count(wd->seg_ctrl);
783    
784    evas_object_event_callback_add(it->base, EVAS_CALLBACK_MOUSE_DOWN, _mouse_down, it);
785    evas_object_event_callback_add(it->base, EVAS_CALLBACK_MOUSE_UP, _mouse_up, it);
786    evas_object_event_callback_add(it->base, EVAS_CALLBACK_RESIZE, _object_item_resize, it);
787    wd->insert_index = -1;
788    wd->del_index = -1;
789    _refresh_segment_ids(obj);
790
791    if(animate && it->segment_id && wd->ani_it == NULL)
792      {
793         evas_object_resize(it->base, 1, wd->height);
794         wd->ani_it = it;
795         wd->ani = ecore_animator_add( _animator_animate_add_cb, obj );
796      }
797    else
798      _state_value_set(obj);
799    evas_object_show( it->base);
800
801    evas_object_box_append(wd->box, it->base);
802    evas_object_smart_calculate(wd->box);
803
804    return it;
805 }
806
807 /**
808  * Add a new segment item to segmentcontrol
809  * @param obj The SegmentControl object
810  * @param icon The icon object for added segment item
811  * @param label The label for added segment item
812  * @param animate If 1 the action be animated with sliding effects default 0.
813  * @return The new segment item or NULL if it cannot be created
814  *
815  * @ingroup SegmentControl SegmentControl
816  */
817 EAPI Elm_Segment_Item *
818 elm_segment_control_add_segment(Evas_Object *obj, Evas_Object *icon, const char *label, Eina_Bool animate)
819 {
820    Elm_Segment_Item * it;
821    it = elm_segment_control_item_add(obj, icon, label, animate);
822 \r
823     return it;\r
824 }
825
826 EAPI Elm_Segment_Item *
827 elm_segment_control_item_insert_at(Evas_Object *obj, Evas_Object *icon, const char *label, unsigned int index, Eina_Bool animate)
828 {
829    Elm_Segment_Item *it, *it_rel;
830    Widget_Data *wd = elm_widget_data_get(obj);
831    if(!wd) return NULL;
832
833    it = _item_new(obj, label, icon);
834    it_rel = _item_find(obj, index);
835    if (!it_rel)
836      {
837         wd->seg_ctrl = eina_list_append(wd->seg_ctrl, it);
838      }
839    else
840      {
841         if (!it) return NULL;
842         wd->seg_ctrl = eina_list_prepend_relative(wd->seg_ctrl, it, it_rel);
843      }
844    evas_object_event_callback_add(it->base, EVAS_CALLBACK_MOUSE_DOWN, _mouse_down, it);
845    evas_object_event_callback_add(it->base, EVAS_CALLBACK_MOUSE_UP, _mouse_up, it);
846    evas_object_event_callback_add(it->base, EVAS_CALLBACK_RESIZE, _object_item_resize, it);
847    wd->insert_index = index;
848    wd->id = eina_list_count(wd->seg_ctrl);
849    _refresh_segment_ids(obj);
850
851    if(animate && it->segment_id && wd->ani_it == NULL)
852      {
853         wd->ani_it = it;
854         evas_object_resize(it->base, 1, wd->height);
855         wd->ani = ecore_animator_add( _animator_animate_add_cb, obj );
856      }
857    else
858       _state_value_set(obj);
859
860    evas_object_show( it->base);
861
862    if(index >= wd->id-1)
863      {
864         evas_object_box_append(wd->box,  it->base);
865      }
866    else
867      {
868         evas_object_box_insert_at(wd->box,  it->base, index);
869      }
870
871    evas_object_smart_calculate(wd->box);
872
873    return it ;
874 }
875 /**
876  * Insert a new segment item to segmentcontrol
877  * @param obj The SegmentControl object
878  * @param icon The icon object for added segment item
879  * @param label The label for added segment item
880  * @param index The position at which segment item to be inserted
881  * @param animate If 1 the action be animated with sliding effects default 0.
882  * @return The new segment item or NULL if it cannot be created
883  *
884  * @ingroup SegmentControl SegmentControl
885  */
886 EAPI void
887 elm_segment_control_insert_segment_at(Evas_Object *obj, Evas_Object *icon, const char *label, unsigned int index, Eina_Bool animate)
888 {
889    Elm_Segment_Item *it;
890    it = elm_segment_control_item_insert_at(obj, icon, label, index, animate);
891
892    return;
893 }
894
895 EAPI void
896 elm_segment_control_item_del(Evas_Object *obj, Elm_Segment_Item *item, Eina_Bool animate)
897 {
898    Elm_Segment_Item *it;
899    Widget_Data *wd = elm_widget_data_get(obj);
900    if(!wd) return;
901
902
903    it = item;
904    if(!it) return;
905
906    wd->del_index = it->segment_id;
907    if(animate && it->segment_id && wd->ani_it == NULL)
908      {
909         it->delete_me = EINA_TRUE;
910         wd->ani_it = it;
911         wd->ani = ecore_animator_add( _animator_animate_del_cb, obj );
912      }
913    else
914      {
915         evas_object_box_remove(wd->box, it->base);
916         evas_object_smart_calculate(wd->box);
917
918         _item_free(obj, it);
919         _refresh_segment_ids(obj);
920         _state_value_set(obj);
921      }
922    wd->id = eina_list_count(wd->seg_ctrl);
923    return;
924 }
925
926 /**
927  * Delete a segment item to segmentcontrol
928  * @param obj The SegmentControl object
929  * @param item The  segment item to be deleted
930  * @param animate If 1 the action be animated with sliding effects default 0.
931  *
932  * @ingroup SegmentControl SegmentControl
933  */
934 EAPI void
935 elm_segment_control_delete_segment(Evas_Object *obj, Elm_Segment_Item *item, Eina_Bool animate)
936 {
937    elm_segment_control_item_del(obj, item, animate);
938
939    return;
940 }
941
942 EAPI void
943 elm_segment_control_item_del_at(Evas_Object *obj,  unsigned int index, Eina_Bool animate)
944 {
945    Elm_Segment_Item *it;
946    Widget_Data *wd = elm_widget_data_get(obj);
947    if(!wd) return;
948
949    it = _item_find(obj, index);
950
951    if(!it) return;
952
953    wd->del_index = index;
954    if(animate && it->segment_id)
955      {
956         if(wd->ani_it == NULL)
957         {
958            wd->ani_it = it;
959            it->delete_me = EINA_TRUE;
960            wd->ani = ecore_animator_add( _animator_animate_del_cb, obj );
961         }
962      }
963    else
964      {
965         evas_object_box_remove(wd->box, it->base);
966         evas_object_smart_calculate(wd->box);
967         _item_free(obj, it);
968         _refresh_segment_ids(obj);
969         _state_value_set(obj);
970      }
971    wd->id = eina_list_count(wd->seg_ctrl);
972    return;
973 }
974
975 /**
976  * Delete a segment item of given index to segmentcontrol
977  * @param obj The SegmentControl object
978  * @param index The position at which segment item to be deleted
979  * @param animate If 1 the action be animated with sliding effects default 0.
980  *
981  * @ingroup SegmentControl SegmentControl
982  */
983 EAPI void
984 elm_segment_control_delete_segment_at(Evas_Object *obj,  unsigned int index, Eina_Bool animate)
985 {
986    elm_segment_control_item_del_at( obj, index, animate);
987
988    return;
989 }
990
991
992 EAPI const char *
993 elm_segment_control_item_label_get(Evas_Object *obj, unsigned int index)
994 {
995    Elm_Segment_Item *it_rel;
996    Widget_Data *wd = elm_widget_data_get(obj);
997    if(!wd) return NULL;
998
999    it_rel = _item_find(obj, index);
1000
1001    if(it_rel) return it_rel->label;
1002
1003    return NULL;
1004 }
1005
1006 /**
1007  * Get the label of a segment item of segmentcontrol
1008  * @param obj The SegmentControl object
1009  * @param index The index of the segment item
1010  * @return The label of the segment item
1011  *
1012  * @ingroup SegmentControl SegmentControl
1013  */
1014 EAPI const char *
1015 elm_segment_control_get_segment_label_at(Evas_Object *obj, unsigned int index)
1016 {
1017    char *label;
1018    label = elm_segment_control_item_label_get( obj, index);
1019   
1020    return label;
1021 }
1022
1023 EAPI Evas_Object *
1024 elm_segment_control_item_icon_get(Evas_Object *obj, unsigned int index)
1025 {
1026    Elm_Segment_Item *seg_rel;
1027    Widget_Data *wd = elm_widget_data_get(obj);
1028    if(!wd) return NULL;
1029
1030    seg_rel = _item_find(obj, index);
1031
1032    if(seg_rel) return seg_rel->icon;
1033
1034    return NULL;
1035 }
1036
1037 /**
1038  * Get the icon of a segment item of segmentcontrol
1039  * @param obj The SegmentControl object
1040  * @param index The index of the segment item
1041  * @return The icon object or NULL if it is not found.
1042  *
1043  * @ingroup SegmentControl SegmentControl
1044  */
1045 EAPI Evas_Object *
1046 elm_segment_control_get_segment_icon_at(Evas_Object *obj, unsigned int index)
1047 {
1048    Evas_Object *icon;
1049    icon = elm_segment_control_item_icon_get( obj, index);
1050
1051    return icon;
1052 }
1053
1054 EAPI Elm_Segment_Item *
1055 elm_segment_control_item_selected_get(const Evas_Object *obj)
1056 {
1057    Elm_Segment_Item *it;
1058    Eina_List *l;
1059    Widget_Data *wd = elm_widget_data_get(obj);
1060    if(!wd || !wd->seg_ctrl) return NULL;
1061
1062    EINA_LIST_FOREACH(wd->seg_ctrl, l, it)
1063      {
1064         if(it->selected_id!=-1 && it->segment_id == it->selected_id)
1065           {
1066              wd->cur_seg_id = it->selected_id;
1067           }
1068         if(it->segment_id == wd->cur_seg_id && it->sel)
1069           return it;
1070      }
1071     return NULL;
1072  }
1073
1074 /**
1075  * Get the currently selected segment item of segmentcontrol
1076  * @param obj The SegmentControl object
1077  * @param value The Selected Segment id.
1078  * @return The selected Segment item
1079  *
1080  * @ingroup SegmentControl SegmentControl
1081  */
1082 EAPI Elm_Segment_Item *
1083 elm_segment_control_selected_segment_get(const Evas_Object *obj, int *value)
1084 {
1085    Elm_Segment_Item *it;
1086    it = elm_segment_control_item_selected_get(obj);
1087    if(!it) return NULL;
1088    if(it->sel)
1089      *value = it->segment_id;
1090    else
1091      *value = -1;
1092     return it;
1093  }
1094
1095
1096 EAPI int
1097 elm_segment_control_item_count_get(Evas_Object *obj)
1098 {
1099    Widget_Data *wd = elm_widget_data_get(obj);
1100    if(!wd) return 0;
1101
1102    return wd->id;
1103 }
1104
1105 /**
1106  * Get the count of segments of segmentcontrol
1107  * @param obj The SegmentControl object
1108  * @return The count of Segment items
1109  *
1110  * @ingroup SegmentControl SegmentControl
1111  */
1112 EAPI int
1113 elm_segment_control_get_segment_count(Evas_Object *obj)
1114 {
1115    int id;
1116    id = elm_segment_control_item_count_get( obj);
1117
1118    return id;
1119 }
1120
1121 /**
1122  * Get the base object of segment item in segmentcontrol
1123  * @param it The Segment item
1124  * @return obj The base object of the segment item.
1125  *
1126  * @ingroup SegmentControl SegmentControl
1127  */
1128 EAPI Evas_Object *
1129 elm_segment_control_item_object_get(Elm_Segment_Item *it)
1130 {
1131    if (!it) return NULL;
1132    
1133    return it->obj;
1134 }
1135
1136 /**
1137  * Select/unselect a particular segment item of segmentcontrol
1138  * @param item The Segment item that is to be selected or unselected.
1139  * @param select If 1 the segment item is selected and if 0 it will be unselected.
1140  *
1141  * @ingroup SegmentControl SegmentControl
1142  */
1143 EAPI void
1144 elm_segment_control_item_selected_set( Elm_Segment_Item *item, Eina_Bool select)
1145 {
1146    if(!item) return;
1147    Widget_Data *wd = elm_widget_data_get(item->obj);
1148    if(!wd) return;
1149
1150    if(select)
1151      {
1152         if(item->segment_id == wd->cur_seg_id && wd->cur_seg_id) return;
1153         item->sel = EINA_TRUE;
1154         _signal_segment_selected(item);
1155      }
1156    else if(item->segment_id == wd->cur_seg_id)
1157      {
1158         item->sel = EINA_FALSE;
1159         wd->cur_seg_id = -1;
1160         _signal_segment_off(item);
1161      } 
1162
1163    return;
1164 }
1165
1166 /**
1167  * Get a particular indexed segment item of segmentcontrol
1168  * @param obj The Segment control object.
1169  * @param index The index of the segment item.
1170  * @return The corresponding Segment item.
1171  *
1172  * @ingroup SegmentControl SegmentControl
1173  */
1174 EAPI Elm_Segment_Item *
1175 elm_segment_control_item_get_at(Evas_Object *obj, unsigned int index)
1176 {
1177    Elm_Segment_Item *it;
1178    it = _item_find(obj, index);
1179
1180    return it;
1181 }
1182 \r
1183 /**
1184  * Get the index of a Segment item of Segmentcontrol
1185  * @param item The Segment item.
1186  * @return The corresponding index of the Segment item.
1187  *
1188  * @ingroup SegmentControl SegmentControl
1189  */
1190 EAPI int
1191 elm_segment_control_item_index_get(Elm_Segment_Item *item)
1192 {
1193    if(!item) return -1;
1194    Widget_Data *wd = elm_widget_data_get(item->obj);
1195    if(!wd) return -1;
1196
1197    return item->segment_id;
1198 }
1199
1200 /**
1201  * Set The Label widget to a Segment item of Segmentcontrol
1202  * @param item The Segment item.
1203  * @param label The Label.
1204  * @return Evas_Object The Label widget.
1205  *
1206  * @ingroup SegmentControl SegmentControl
1207  */
1208 EAPI Evas_Object *
1209 elm_segment_control_item_label_object_set(Elm_Segment_Item *item, char *label)
1210 {
1211    if(!item) return NULL;
1212    Widget_Data *wd = elm_widget_data_get(item->obj);
1213    if(!wd) return NULL;
1214    if(!label) return NULL;
1215
1216    _color_value_get(wd);
1217    item->label_wd = elm_label_add(item->obj);
1218    elm_object_style_set(item->label_wd, "segment");
1219    elm_label_label_set(item->label_wd, label);
1220    elm_label_text_align_set(item->label_wd, "middle");
1221    elm_label_ellipsis_set(item->label_wd, 1);
1222    eina_stringshare_replace(&item->label, label);
1223
1224    return item->label_wd;
1225 }
1226