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