[SegmentControl] String handling for getting text color of label object from .edc
[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    unsigned int def_color[4];
33    unsigned int press_color[4];
34    unsigned int sel_color[4];
35 };
36
37 struct _Elm_Segment_Item
38 {
39    Evas_Object *obj;
40    Evas_Object *base;
41    Evas_Object *icon;
42    Evas_Object *label_wd;
43    const char *label;
44    int segment_id;
45    int selected_id;
46    Eina_Bool delete_me : 1;
47    Eina_Bool sel : 1;
48 };
49
50 #define MAXTOKENS 5
51
52 char **_split(char *string, char *delim);
53 static void _mouse_down(void *data, Evas *evas, Evas_Object *obj, void *event_info);
54 static void _mouse_up(void *data, Evas *e, Evas_Object *obj, void *event_info);
55 static void _signal_segment_selected(void *data);
56 static void _signal_segment_on(void *data);
57 static void _signal_segment_off(void *data);
58 static void _theme_hook(Evas_Object *obj);
59 static void _item_free(Evas_Object *obj, Elm_Segment_Item *it);
60 static void _del_hook(Evas_Object *obj);
61 static void _layout(Evas_Object *o, Evas_Object_Box_Data *priv, void *data);
62 static void _segment_resizing(void *data, Evas *e, Evas_Object *obj, void *event_info);
63 static void _segment_item_resizing(void *data, Evas *e, Evas_Object *obj, void *event_info);
64 #if 0
65 static void _object_resize(void *data, Evas *e, Evas_Object *obj, void *event_info);
66 #endif
67 static void _update_list(Evas_Object *obj);
68 static void _refresh_segment_ids(Evas_Object *obj);
69 static void _state_value_set(Evas_Object *obj);
70 static void _color_value_get(Evas_Object *obj);
71
72 static Elm_Segment_Item* _item_new(Evas_Object *obj, const char *label, Evas_Object *icon);
73 static Elm_Segment_Item *_item_find(Evas_Object *obj, unsigned int index);
74
75 static int * _animator_animate_add_cb(Evas_Object *obj);
76 static int * _animator_animate_del_cb(Evas_Object *obj);
77
78 static void
79 _signal_segment_off(void *data)
80 {
81     Elm_Segment_Item *item = (Elm_Segment_Item *) data;
82     Widget_Data *wd = elm_widget_data_get(item->obj);
83     if (!wd) return;
84     
85     item->sel = EINA_FALSE;
86     edje_object_signal_emit(item->base, "elm,action,unfocus", "elm");
87     edje_object_signal_emit(item->base, "elm,state,segment,release", "elm");
88     if(!item->label_wd && item->label)
89       edje_object_signal_emit(item->base, "elm,state,text,visible", "elm");
90     if(item->label_wd)
91       elm_label_text_color_set(item->label_wd, wd->def_color[0], wd->def_color[1], wd->def_color[2], wd->def_color[3]);
92
93     return;
94 }
95
96 static void
97 _signal_segment_selected(void *data)
98 {
99    Elm_Segment_Item *item = (Elm_Segment_Item *) data;
100    Elm_Segment_Item *it;
101    Eina_List *l;
102
103    Widget_Data *wd = elm_widget_data_get(item->obj);
104    if (!wd) return;
105    item->sel = EINA_TRUE;
106    if (item->segment_id == wd->cur_seg_id && item->segment_id) return;
107    EINA_LIST_FOREACH(wd->seg_ctrl, l, it)
108      {
109         if (it->segment_id == wd->cur_seg_id)
110           {
111              _signal_segment_off (it);
112           }
113         if (it->segment_id == item->selected_id)
114           {
115              _signal_segment_off (it);
116           }
117         it->selected_id = -1;
118      }
119    edje_object_signal_emit(item->base, "elm,action,focus", "elm");
120    if(!item->label_wd)
121      edje_object_signal_emit(item->base, "elm,state,text,change", "elm");
122    if(item->label_wd)
123      elm_label_text_color_set(item->label_wd, wd->sel_color[0], wd->sel_color[1], wd->sel_color[2], wd->sel_color[3]);
124    item->selected_id = item->segment_id;
125    evas_object_smart_callback_call(item->obj, "changed", (void*)item->selected_id);
126
127    return;
128 }
129
130 static void
131 _signal_segment_on(void *data)
132 {
133    Elm_Segment_Item *item = (Elm_Segment_Item *) data;
134    Elm_Segment_Item *it;
135    Eina_List *l;
136
137    Widget_Data *wd = elm_widget_data_get(item->obj);
138    if (!wd) return;
139
140    item->sel = EINA_TRUE;
141
142    if (item->segment_id == wd->cur_seg_id && item->segment_id) return;
143
144    EINA_LIST_FOREACH(wd->seg_ctrl, l, it)
145      {
146         if (it->segment_id == wd->cur_seg_id)
147           {
148              _signal_segment_off (it);
149           }
150         if (it->segment_id == item->selected_id)
151           {
152              _signal_segment_off (it);
153           }
154         it->selected_id = -1;
155      }
156    edje_object_signal_emit(item->base, "elm,action,focus", "elm");
157    if(!item->label_wd)
158      edje_object_signal_emit(item->base, "elm,state,text,change", "elm");
159    if(item->label_wd)
160      elm_label_text_color_set(item->label_wd, wd->sel_color[0],wd->sel_color[1], wd->sel_color[1], wd->sel_color[3]);
161
162    wd->cur_seg_id = item->segment_id;
163    evas_object_smart_callback_call(item->obj, "changed", (void*)wd->cur_seg_id);
164
165    return;
166 }
167
168 static void
169 _mouse_up(void *data, Evas *e, Evas_Object *obj, void *event_info)
170 {
171    Elm_Segment_Item *item = (Elm_Segment_Item *) data;
172    Widget_Data *wd = elm_widget_data_get(item->obj);
173    if (!wd) return;
174    if (item->segment_id == wd->cur_seg_id)
175      {
176         if(!item->label_wd)
177           edje_object_signal_emit(item->base, "elm,state,text,change", "elm");
178         item->sel = EINA_TRUE;
179         return;
180      }
181     _signal_segment_on((void*)item);
182
183     return;
184 }
185
186 static void
187 _mouse_down(void *data, Evas *evas, Evas_Object *obj, void *event_info)
188 {
189    Elm_Segment_Item *item = (Elm_Segment_Item *) data;
190    Widget_Data *wd = elm_widget_data_get(item->obj);
191
192    if (!wd) return;
193    
194    if(!item->label_wd && wd->cur_seg_id != item->segment_id)
195      {
196         edje_object_signal_emit(item->base, "elm,state,text,pressed", "elm");
197      }
198    if(item->label_wd && wd->cur_seg_id != item->segment_id)
199      elm_label_text_color_set(item->label_wd, wd->press_color[0], wd->press_color[1], wd->press_color[2], wd->press_color[3]);
200
201    edje_object_signal_emit(item->base, "elm,state,segment,press", "elm");
202    return;
203 }
204
205 static void
206 _theme_hook(Evas_Object *obj)
207 {
208    _elm_theme_object_set(obj, obj, "segmented-control", "base", elm_widget_style_get(obj));
209
210    return;
211 }
212
213 static void
214 _item_free(Evas_Object *obj, Elm_Segment_Item *it)
215 {
216    Widget_Data *wd = elm_widget_data_get(obj);
217    if (!wd) return;
218
219    if(wd->seg_ctrl)
220      wd->seg_ctrl = eina_list_remove(wd->seg_ctrl, it);
221
222    if(it->icon) evas_object_del(it->icon);
223    if(it->label_wd) 
224      {
225         evas_object_del(it->label_wd);
226         it->label_wd = NULL;
227         if (edje_object_part_swallow_get(it->base, "elm.swallow.label.content") == NULL) 
228           {
229              edje_object_part_unswallow(it->base, it->label_wd);
230           }
231      }
232    if(it->base) evas_object_del(it->base);
233    if(it->label) eina_stringshare_del(it->label);
234
235    if(it)
236      free(it);
237    it = NULL;
238    
239    return;
240 }
241
242 static void
243 _del_hook(Evas_Object *obj)
244 {
245    Widget_Data *wd = elm_widget_data_get(obj);
246    Elm_Segment_Item *it;
247    Eina_List *l, *clear = NULL;
248
249    EINA_LIST_FOREACH(wd->seg_ctrl, l, it) clear = eina_list_append(clear, it);
250    EINA_LIST_FREE(clear, it) _item_free(obj, it);
251
252    if(wd) free(wd);
253    wd = NULL;
254
255    return;
256 }
257
258
259 static void
260 _layout(Evas_Object *o, Evas_Object_Box_Data *priv, void *data)
261 {
262    Widget_Data *wd = data;
263    if (!wd) return;
264    _els_box_layout(o, priv, 1, 0); /* making box layout non homogenous */
265
266    return;
267 }
268
269 static void
270 _segment_resizing(void *data, Evas *e, Evas_Object *obj, void *event_info)
271 {
272    Widget_Data *wd = elm_widget_data_get((Evas_Object *)data);
273    if (!wd) return;
274    Evas_Coord w = 0, h = 0;
275
276    evas_object_geometry_get(wd->base, NULL, NULL, &w, &h);
277    wd->item_width = wd->width = w;
278    wd->height = h;
279
280    _state_value_set((Evas_Object *)data);
281 }
282 #if 0
283 static void 
284 _object_resize(void *data, Evas *e, Evas_Object *obj, void *event_info)
285 {
286    Widget_Data *wd;
287    if(!data) return;
288    wd = elm_widget_data_get((Evas_Object *)data);
289    if(!wd) return;
290
291    ecore_job_add(_segment_resizing, (Evas_Object *)data);
292 }
293 #endif
294
295 static void
296 _segment_item_resizing(void *data, Evas *e, Evas_Object *obj, void *event_info)
297 {
298    Widget_Data *wd;
299    Elm_Segment_Item *it = (Elm_Segment_Item *)data; 
300    wd = elm_widget_data_get(it->obj);
301
302    if(!wd) return;
303    Evas_Coord w = 0, h = 0;
304    _update_list(it->obj);
305
306    evas_object_geometry_get(it->base, NULL, NULL, &w, &h);
307
308    if(wd->max_height == 1) wd->max_height = h;
309
310    if(it->label_wd) 
311      {
312         elm_label_wrap_width_set(it->label_wd, w-wd->w_pad);
313         elm_label_wrap_height_set(it->label_wd, wd->max_height-wd->h_pad);
314
315         if (edje_object_part_swallow_get(it->base, "elm.swallow.label.content") == NULL)
316           {
317              edje_object_part_unswallow(it->base, it->label_wd);
318           }
319         edje_object_part_swallow(it->base, "elm.swallow.label.content", it->label_wd);
320         edje_object_signal_emit(it->base, "elm,state,label,visible", "elm");
321         if (it->segment_id == wd->cur_seg_id && it->sel)
322           {
323             elm_label_text_color_set(it->label_wd, wd->sel_color[0], wd->sel_color[1], wd->sel_color[2], wd->sel_color[3]);
324           }
325         else
326           elm_label_text_color_set(it->label_wd, wd->def_color[0], wd->def_color[1], wd->def_color[2], wd->def_color[3]);
327      }
328 }
329 #if 0
330 static void 
331 _object_item_resize(void *data, Evas *e, Evas_Object *obj, void *event_info)
332 {
333    ecore_job_add(_segment_item_resizing, (Evas_Object *)data);
334 }
335 #endif
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_color[0], wd->sel_color[1], wd->sel_color[2], wd->sel_color[3]);
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 /* split string into tokens, return token array */
595 char **
596 _split(char *string, char *delim) 
597 {
598    char **tokens = NULL;
599    char *working = NULL;
600    char *token = NULL;
601    int idx = 0;
602
603    tokens  = malloc(sizeof(char *) * MAXTOKENS);
604    if(tokens == NULL)
605      return NULL;
606    working = malloc(sizeof(char) * strlen(string) + 1);
607    if(working == NULL)
608      return NULL;
609
610  /* to make sure, copy string to a safe place */
611    strcpy(working, string);
612    for(idx = 0; idx < MAXTOKENS; idx++)
613      tokens[idx] = NULL;
614
615    token = strtok(working, delim);
616    idx = 0;
617
618  /* always keep the last entry NULL termindated */
619    while((idx < (MAXTOKENS - 1)) && (token != NULL)) {
620      tokens[idx] = malloc(sizeof(char) * strlen(token) + 1);
621      if(tokens[idx] != NULL) {
622        strcpy(tokens[idx], token);
623        idx++;
624        token = strtok(NULL, delim);
625      }
626    }
627
628  free(working);
629  return tokens;
630 }
631
632 static void _color_value_get(Evas_Object *obj)
633 {
634    Widget_Data *wd = (Widget_Data *)obj;
635    if (!wd) return;
636
637    const char *def_color;
638    const char *press_color;
639    const char *sel_color;
640
641    char *delim = " ";
642    char **tokens = NULL;
643    int i = 0;
644
645    def_color = edje_object_data_get(wd->base, "def_rgb");
646    if(def_color)
647      {
648         tokens = _split(def_color, delim);
649         for(i = 0; tokens[i] != NULL; i++)
650           {
651              if (tokens[i]) wd->def_color[i] = atoi(tokens[i]);
652              else wd->def_color[i] = 0xFF;
653           }
654         for(i = 0; tokens[i] != NULL; i++)
655           free(tokens[i]);
656         free(tokens);
657         tokens = NULL;
658      }
659    else
660      {
661         for(i = 0; i<(MAXTOKENS - 1); i++)
662           wd->def_color[i] = 0xFF;
663      }
664    press_color = edje_object_data_get(wd->base, "press_rgb");
665    if(press_color)
666      {
667         tokens = _split(press_color, delim);
668         for(i = 0; tokens[i] != NULL; i++)
669           {
670              if (tokens[i]) wd->press_color[i] = atoi(tokens[i]);
671              else wd->press_color[i] = 0xFF;
672           }
673         for(i = 0; tokens[i] != NULL; i++)
674           free(tokens[i]);
675         free(tokens);
676         tokens = NULL;
677      }
678    else
679      {
680         for(i = 0; i<(MAXTOKENS - 1); i++)
681           wd->press_color[i] = 0xFF;
682      }
683
684    sel_color = edje_object_data_get(wd->base, "sel_rgb");
685    if(sel_color)
686      {
687        tokens = _split(sel_color, delim);
688        for(i = 0; tokens[i] != NULL; i++)
689          {
690             if (tokens[i]) wd->sel_color[i] = atoi(tokens[i]);
691             else wd->sel_color[i] = 0xFF;
692          }
693        for(i = 0; tokens[i] != NULL; i++)
694          free(tokens[i]);
695        
696        free(tokens);
697        tokens = NULL;
698      }
699    else
700      {
701         for(i = 0; i<(MAXTOKENS - 1); i++)
702           wd->sel_color[i] = 0xFF;
703      }
704 }
705
706 static int *
707 _animator_animate_add_cb(Evas_Object *obj)
708 {
709    int w;
710    Widget_Data *wd = elm_widget_data_get(obj);
711    if (!wd) return 0;
712
713    evas_object_geometry_get(wd->ani_it->base, NULL, NULL, &w, NULL);
714    if( w <  wd->item_width )
715      {
716          _state_value_set(obj);
717          evas_object_geometry_get(wd->ani_it->base, NULL, NULL, &w, NULL);
718          return (int*) ECORE_CALLBACK_RENEW;
719      }
720    else
721      {
722         ecore_animator_del(wd->ani);
723         wd->ani = NULL;
724         wd->ani_it = NULL;
725         return (int*) ECORE_CALLBACK_CANCEL;
726      }
727 }
728
729
730 static int *
731 _animator_animate_del_cb(Evas_Object *obj)
732 {
733    int w;
734    Widget_Data *wd = elm_widget_data_get(obj);
735    if (!wd) return 0;\r
736
737    evas_object_geometry_get(wd->ani_it->base, NULL, NULL, &w, NULL);
738    if( w >  0 )
739      {
740         _state_value_set(obj);
741         evas_object_geometry_get(wd->ani_it->base, NULL, NULL, &w, NULL);
742         return (int*) ECORE_CALLBACK_RENEW;
743      }
744    else
745      {
746         _item_free(obj, wd->ani_it );
747         _refresh_segment_ids(obj);
748         ecore_animator_del(wd->ani);
749         wd->ani = NULL;
750         wd->ani_it = NULL;
751         _update_list(obj);
752         wd->id = eina_list_count(wd->seg_ctrl);
753         return (int*) ECORE_CALLBACK_CANCEL;
754      }
755 }
756
757 static Elm_Segment_Item *
758 _item_find(Evas_Object *obj, unsigned int index)
759 {
760    Elm_Segment_Item *it;
761    Eina_List *l;
762    int i = 0;
763    Widget_Data *wd = elm_widget_data_get(obj);
764    if (!wd) return NULL;
765
766    EINA_LIST_FOREACH(wd->seg_ctrl, l, it)
767      {
768         if (i == index) return it;
769         i++;
770      }
771      return NULL;
772 }
773
774 /**
775  * Add a new segmentcontrol to the parent
776  * @param parent The parent object
777  * @return The new object or NULL if it cannot be created
778  *
779  * @ingroup SegmentControl SegmentControl
780  */
781 EAPI Evas_Object *
782 elm_segment_control_add(Evas_Object *parent)
783 {
784    Evas_Object *obj;
785    Evas *e;
786    Widget_Data *wd;
787
788    const char *deffont, *maxheight, *wpad, *hpad;
789
790    wd = ELM_NEW(Widget_Data);
791    e = evas_object_evas_get(parent);
792    if(!e) return NULL;
793    obj = elm_widget_add(e);
794    elm_widget_type_set(obj, "segmented-control");
795    elm_widget_sub_object_add(parent, obj);
796    elm_widget_data_set(obj, wd);
797    elm_widget_del_hook_set(obj, _del_hook);
798    elm_widget_theme_hook_set(obj, _theme_hook);
799
800    wd->base = edje_object_add(e);
801    _elm_theme_object_set(obj, wd->base, "segmented-control", "base", "default");
802    elm_widget_resize_object_set(obj, wd->base);
803    wd->box = evas_object_box_add(e);
804    evas_object_box_layout_set(wd->box, _layout, wd, NULL);
805    elm_widget_sub_object_add(obj, wd->box);
806    edje_object_part_swallow(wd->base, "elm.swallow.content", wd->box);
807    evas_object_show(wd->box);
808
809    evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE, _segment_resizing, obj);
810    wd->id = 0;
811    wd->del_index = -1;
812    wd->insert_index = -1;
813    wd->cur_seg_id = -1;
814
815    deffont = edje_object_data_get(wd->base, "default_font_size");
816    if (deffont) wd->cur_fontsize = atoi(deffont);
817    else wd->cur_fontsize = 1;
818
819    maxheight = edje_object_data_get(wd->base, "max_height");
820    if (maxheight) wd->max_height = atoi(maxheight);
821    else wd->max_height = 1;
822
823    wpad = edje_object_data_get(wd->base, "w_pad");
824    if (wpad) wd->w_pad = atoi(wpad);
825    else wd->w_pad = 1;
826
827    hpad = edje_object_data_get(wd->base, "h_pad");
828    if (hpad) wd->h_pad = atoi(hpad);
829    else wd->h_pad = 1;
830
831    _color_value_get((Evas_Object *)wd);
832
833    return obj;
834 }
835
836 EAPI Elm_Segment_Item *
837 elm_segment_control_item_add(Evas_Object *obj, Evas_Object *icon, const char *label, Eina_Bool animate)
838 {
839    Elm_Segment_Item *it;
840    Widget_Data *wd = elm_widget_data_get(obj);
841    if(!wd) return NULL;
842
843    it = _item_new(obj, label, icon);
844    if(!it) return NULL;
845
846    wd->seg_ctrl = eina_list_append(wd->seg_ctrl, it);
847    wd->id = eina_list_count(wd->seg_ctrl);
848    
849    evas_object_event_callback_add(it->base, EVAS_CALLBACK_MOUSE_DOWN, _mouse_down, it);
850    evas_object_event_callback_add(it->base, EVAS_CALLBACK_MOUSE_UP, _mouse_up, it);
851    evas_object_event_callback_add(it->base, EVAS_CALLBACK_RESIZE, _segment_item_resizing, it);
852    wd->insert_index = -1;
853    wd->del_index = -1;
854    _refresh_segment_ids(obj);
855
856    if(animate && it->segment_id && wd->ani_it == NULL)
857      {
858         evas_object_resize(it->base, 1, wd->height);
859         wd->ani_it = it;
860         wd->ani = ecore_animator_add( _animator_animate_add_cb, obj );
861      }
862    else
863    {
864      _state_value_set(obj);
865      _update_list(obj);
866    }
867    evas_object_show( it->base);
868
869    evas_object_box_append(wd->box, it->base);
870    evas_object_smart_calculate(wd->box);
871
872    return it;
873 }
874
875 /**
876  * Add 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 animate If EINA_TRUE the action be animated with sliding effects default EINA_FALSE.
881  * @return The new segment item or NULL if it cannot be created
882  *
883  * @ingroup SegmentControl SegmentControl
884  */
885 EAPI Elm_Segment_Item *
886 elm_segment_control_add_segment(Evas_Object *obj, Evas_Object *icon, const char *label, Eina_Bool animate)
887 {
888    Elm_Segment_Item * it;
889    it = elm_segment_control_item_add(obj, icon, label, animate);
890 \r
891     return it;\r
892 }
893
894 EAPI Elm_Segment_Item *
895 elm_segment_control_item_insert_at(Evas_Object *obj, Evas_Object *icon, const char *label, unsigned int index, Eina_Bool animate)
896 {
897    Elm_Segment_Item *it, *it_rel;
898    Widget_Data *wd = elm_widget_data_get(obj);
899    if(!wd) return NULL;
900
901    it = _item_new(obj, label, icon);
902    it_rel = _item_find(obj, index);
903    if (!it_rel)
904      {
905         wd->seg_ctrl = eina_list_append(wd->seg_ctrl, it);
906      }
907    else
908      {
909         if (!it) return NULL;
910         wd->seg_ctrl = eina_list_prepend_relative(wd->seg_ctrl, it, it_rel);
911      }
912    evas_object_event_callback_add(it->base, EVAS_CALLBACK_MOUSE_DOWN, _mouse_down, it);
913    evas_object_event_callback_add(it->base, EVAS_CALLBACK_MOUSE_UP, _mouse_up, it);
914    evas_object_event_callback_add(it->base, EVAS_CALLBACK_RESIZE, _segment_item_resizing, it);
915    wd->insert_index = index;
916    wd->id = eina_list_count(wd->seg_ctrl);
917    _refresh_segment_ids(obj);
918
919    if(animate && it->segment_id && wd->ani_it == NULL)
920      {
921         wd->ani_it = it;
922         evas_object_resize(it->base, 1, wd->height);
923         wd->ani = ecore_animator_add( _animator_animate_add_cb, obj );
924      }
925    else
926    {
927      _state_value_set(obj);
928      _update_list(obj);
929    }
930
931    evas_object_show( it->base);
932
933    if(index >= wd->id-1)
934      {
935         evas_object_box_append(wd->box,  it->base);
936      }
937    else
938      {
939         evas_object_box_insert_at(wd->box,  it->base, index);
940      }
941
942    evas_object_smart_calculate(wd->box);
943
944    return it ;
945 }
946 /**
947  * Insert a new segment item to segmentcontrol
948  * @param obj The SegmentControl object
949  * @param icon The icon object for added segment item
950  * @param label The label for added segment item
951  * @param index The position at which segment item to be inserted
952  * @param animate If 1EINA_TRUE the action be animated with sliding effects default EINA_FALSE.
953  * @return The new segment item or NULL if it cannot be created
954  *
955  * @ingroup SegmentControl SegmentControl
956  */
957 EAPI void
958 elm_segment_control_insert_segment_at(Evas_Object *obj, Evas_Object *icon, const char *label, unsigned int index, Eina_Bool animate)
959 {
960    Elm_Segment_Item *it;
961    it = elm_segment_control_item_insert_at(obj, icon, label, index, animate);
962
963    return;
964 }
965
966 EAPI void
967 elm_segment_control_item_del(Evas_Object *obj, Elm_Segment_Item *item, Eina_Bool animate)
968 {
969    Elm_Segment_Item *it;
970    Widget_Data *wd = elm_widget_data_get(obj);
971    if(!wd) return;
972
973
974    it = item;
975    if(!it) return;
976
977    wd->del_index = it->segment_id;
978    if(animate && it->segment_id && wd->ani_it == NULL)
979      {
980         it->delete_me = EINA_TRUE;
981         wd->ani_it = it;
982         wd->ani = ecore_animator_add( _animator_animate_del_cb, obj );
983      }
984    else
985      {
986         evas_object_box_remove(wd->box, it->base);
987         evas_object_smart_calculate(wd->box);
988
989         _item_free(obj, it);
990         _refresh_segment_ids(obj);
991         _state_value_set(obj);
992      }
993    wd->id = eina_list_count(wd->seg_ctrl);
994    return;
995 }
996
997 /**
998  * Delete a segment item to segmentcontrol
999  * @param obj The SegmentControl object
1000  * @param item The  segment item to be deleted
1001  * @param animate If EINA_TRUE the action be animated with sliding effects default EINA_FALSE.
1002  *
1003  * @ingroup SegmentControl SegmentControl
1004  */
1005 EAPI void
1006 elm_segment_control_delete_segment(Evas_Object *obj, Elm_Segment_Item *item, Eina_Bool animate)
1007 {
1008    elm_segment_control_item_del(obj, item, animate);
1009
1010    return;
1011 }
1012
1013 EAPI void
1014 elm_segment_control_item_del_at(Evas_Object *obj,  unsigned int index, Eina_Bool animate)
1015 {
1016    Elm_Segment_Item *it;
1017    Widget_Data *wd = elm_widget_data_get(obj);
1018    if(!wd) return;
1019
1020    it = _item_find(obj, index);
1021
1022    if(!it) return;
1023
1024    wd->del_index = index;
1025    if(animate && it->segment_id)
1026      {
1027         if(wd->ani_it == NULL)
1028         {
1029            wd->ani_it = it;
1030            it->delete_me = EINA_TRUE;
1031            wd->ani = ecore_animator_add( _animator_animate_del_cb, obj );
1032         }
1033      }
1034    else
1035      {
1036         evas_object_box_remove(wd->box, it->base);
1037         evas_object_smart_calculate(wd->box);
1038         _item_free(obj, it);
1039         _refresh_segment_ids(obj);
1040         _state_value_set(obj);
1041      }
1042    wd->id = eina_list_count(wd->seg_ctrl);
1043    return;
1044 }
1045
1046 /**
1047  * Delete a segment item of given index to segmentcontrol
1048  * @param obj The SegmentControl object
1049  * @param index The position at which segment item to be deleted
1050  * @param animate If EINA_TRUE the action be animated with sliding effects default EINA_FALSE.
1051  *
1052  * @ingroup SegmentControl SegmentControl
1053  */
1054 EAPI void
1055 elm_segment_control_delete_segment_at(Evas_Object *obj,  unsigned int index, Eina_Bool animate)
1056 {
1057    elm_segment_control_item_del_at( obj, index, animate);
1058
1059    return;
1060 }
1061
1062
1063 EAPI const char *
1064 elm_segment_control_item_label_get(Evas_Object *obj, unsigned int index)
1065 {
1066    Elm_Segment_Item *it_rel;
1067    Widget_Data *wd = elm_widget_data_get(obj);
1068    if(!wd) return NULL;
1069
1070    it_rel = _item_find(obj, index);
1071
1072    if(it_rel) return it_rel->label;
1073
1074    return NULL;
1075 }
1076
1077 /**
1078  * Get the label of a segment item of segmentcontrol
1079  * @param obj The SegmentControl object
1080  * @param index The index of the segment item
1081  * @return The label of the segment item
1082  *
1083  * @ingroup SegmentControl SegmentControl
1084  */
1085 EAPI const char *
1086 elm_segment_control_get_segment_label_at(Evas_Object *obj, unsigned int index)
1087 {
1088    char *label;
1089    label = elm_segment_control_item_label_get( obj, index);
1090   
1091    return label;
1092 }
1093
1094 EAPI Evas_Object *
1095 elm_segment_control_item_icon_get(Evas_Object *obj, unsigned int index)
1096 {
1097    Elm_Segment_Item *seg_rel;
1098    Widget_Data *wd = elm_widget_data_get(obj);
1099    if(!wd) return NULL;
1100
1101    seg_rel = _item_find(obj, index);
1102
1103    if(seg_rel) return seg_rel->icon;
1104
1105    return NULL;
1106 }
1107
1108 /**
1109  * Get the icon of a segment item of segmentcontrol
1110  * @param obj The SegmentControl object
1111  * @param index The index of the segment item
1112  * @return The icon object or NULL if it is not found.
1113  *
1114  * @ingroup SegmentControl SegmentControl
1115  */
1116 EAPI Evas_Object *
1117 elm_segment_control_get_segment_icon_at(Evas_Object *obj, unsigned int index)
1118 {
1119    Evas_Object *icon;
1120    icon = elm_segment_control_item_icon_get( obj, index);
1121
1122    return icon;
1123 }
1124
1125 EAPI Elm_Segment_Item *
1126 elm_segment_control_item_selected_get(const Evas_Object *obj)
1127 {
1128    Elm_Segment_Item *it;
1129    Eina_List *l;
1130    Widget_Data *wd = elm_widget_data_get(obj);
1131    if(!wd || !wd->seg_ctrl) return NULL;
1132
1133    EINA_LIST_FOREACH(wd->seg_ctrl, l, it)
1134      {
1135         if(it->selected_id!=-1 && it->segment_id == it->selected_id)
1136           {
1137              wd->cur_seg_id = it->selected_id;
1138           }
1139         if(it->segment_id == wd->cur_seg_id && it->sel)
1140           return it;
1141      }
1142     return NULL;
1143  }
1144
1145 /**
1146  * Get the currently selected segment item of segmentcontrol
1147  * @param obj The SegmentControl object
1148  * @param value The Selected Segment id.
1149  * @return The selected Segment item
1150  *
1151  * @ingroup SegmentControl SegmentControl
1152  */
1153 EAPI Elm_Segment_Item *
1154 elm_segment_control_selected_segment_get(const Evas_Object *obj, int *value)
1155 {
1156    Elm_Segment_Item *it;
1157    it = elm_segment_control_item_selected_get(obj);
1158    if(!it) return NULL;
1159    if(it->sel)
1160      *value = it->segment_id;
1161    else
1162      *value = -1;
1163     return it;
1164  }
1165
1166
1167 EAPI int
1168 elm_segment_control_item_count_get(Evas_Object *obj)
1169 {
1170    Widget_Data *wd = elm_widget_data_get(obj);
1171    if(!wd) return 0;
1172
1173    return wd->id;
1174 }
1175
1176 /**
1177  * Get the count of segments of segmentcontrol
1178  * @param obj The SegmentControl object
1179  * @return The count of Segment items
1180  *
1181  * @ingroup SegmentControl SegmentControl
1182  */
1183 EAPI int
1184 elm_segment_control_get_segment_count(Evas_Object *obj)
1185 {
1186    int id;
1187    id = elm_segment_control_item_count_get( obj);
1188
1189    return id;
1190 }
1191
1192 /**
1193  * Get the base object of segment item in segmentcontrol
1194  * @param it The Segment item
1195  * @return obj The base object of the segment item.
1196  *
1197  * @ingroup SegmentControl SegmentControl
1198  */
1199 EAPI Evas_Object *
1200 elm_segment_control_item_object_get(Elm_Segment_Item *it)
1201 {
1202    if (!it) return NULL;
1203    
1204    return it->obj;
1205 }
1206
1207 /**
1208  * Select/unselect a particular segment item of segmentcontrol
1209  * @param item The Segment item that is to be selected or unselected.
1210  * @param select If 1 the segment item is selected and if 0 it will be unselected.
1211  *
1212  * @ingroup SegmentControl SegmentControl
1213  */
1214 EAPI void
1215 elm_segment_control_item_selected_set( Elm_Segment_Item *item, Eina_Bool select)
1216 {
1217    if(!item) return;
1218    Widget_Data *wd = elm_widget_data_get(item->obj);
1219    if(!wd) return;
1220
1221    if(select)
1222      {
1223         if(item->segment_id == wd->cur_seg_id && wd->cur_seg_id) return;
1224         item->sel = EINA_TRUE;
1225         _signal_segment_selected(item);
1226      }
1227    else if(item->segment_id == wd->cur_seg_id)
1228      {
1229         item->sel = EINA_FALSE;
1230         wd->cur_seg_id = -1;
1231         _signal_segment_off(item);
1232      } 
1233
1234    return;
1235 }
1236
1237 /**
1238  * Get a particular indexed segment item of segmentcontrol
1239  * @param obj The Segment control object.
1240  * @param index The index of the segment item.
1241  * @return The corresponding Segment item.
1242  *
1243  * @ingroup SegmentControl SegmentControl
1244  */
1245 EAPI Elm_Segment_Item *
1246 elm_segment_control_item_get_at(Evas_Object *obj, unsigned int index)
1247 {
1248    Elm_Segment_Item *it;
1249    it = _item_find(obj, index);
1250
1251    return it;
1252 }
1253 \r
1254 /**
1255  * Get the index of a Segment item of Segmentcontrol
1256  * @param item The Segment item.
1257  * @return The corresponding index of the Segment item.
1258  *
1259  * @ingroup SegmentControl SegmentControl
1260  */
1261 EAPI int
1262 elm_segment_control_item_index_get(Elm_Segment_Item *item)
1263 {
1264    if(!item) return -1;
1265    Widget_Data *wd = elm_widget_data_get(item->obj);
1266    if(!wd) return -1;
1267
1268    return item->segment_id;
1269 }
1270
1271 /**
1272  * Set The Label widget to a Segment item of Segmentcontrol
1273  * @param item The Segment item.
1274  * @param label The Label.
1275  * @return Evas_Object The Label widget.
1276  *
1277  * @ingroup SegmentControl SegmentControl
1278  */
1279 EAPI Evas_Object *
1280 elm_segment_control_item_label_object_set(Elm_Segment_Item *item, char *label)
1281 {
1282    if(!item) return NULL;
1283    Widget_Data *wd = elm_widget_data_get(item->obj);
1284    if(!wd) return NULL;
1285    if(!label) return NULL;
1286
1287    item->label_wd = elm_label_add(item->obj);
1288    elm_object_style_set(item->label_wd, "segment");
1289    elm_label_label_set(item->label_wd, label);
1290    elm_label_text_align_set(item->label_wd, "middle");
1291    elm_label_ellipsis_set(item->label_wd, 1);
1292    eina_stringshare_replace(&item->label, label);
1293
1294    return item->label_wd;
1295 }
1296