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