Merge "[SegmentControl] Border issue fixed. Unnecessary if check is removed."
[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 Widget is a horizontal control made of multiple segment items,
9  * each segment item functioning similar to discrete two state button. A segment
10  * control groups the the items together and provides compact single button with
11  * multiple equal size segments. Segment item size is determined by base widget
12  * size and the number of items added.
13  * Only one Segment item can be at selected state. A segment item can display
14  * combination of Text and any Evas_Object like Images or other widget.
15  *
16  * Signals that you can add callbacks for are:
17  *
18  * "changed" -when the user clicks on a segment item which is not previously
19  *            selected and get selected. The event_info parameter is the
20  *            segment item index.
21  */
22 typedef struct _Widget_Data Widget_Data;
23
24 struct _Widget_Data
25 {
26    Evas_Object *obj;
27    Evas_Object *base;
28    Eina_List *seg_items;
29    int item_count;
30    Elm_Segment_Item *selected_item;
31    int item_width;
32 };
33
34 struct _Elm_Segment_Item
35 {
36    Elm_Widget_Item base;
37    Evas_Object *icon;
38    const char *label;
39    int seg_index;
40 };
41
42 static const char *widtype = NULL;
43 static void _sizing_eval(Evas_Object *obj);
44 static void _del_hook(Evas_Object *obj);
45 static void _theme_hook(Evas_Object *obj);
46 static void _disable_hook(Evas_Object *obj);
47 static void _item_free(Elm_Segment_Item *it);
48 static void _segment_off(Elm_Segment_Item *it);
49 static void _segment_on(Elm_Segment_Item *it);
50 static void _position_items(Widget_Data *wd);
51 static void _on_move_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj
52                             __UNUSED__, void *event_info __UNUSED__);
53 static void _mouse_up(void *data, Evas *e __UNUSED__, Evas_Object *obj
54                       __UNUSED__, void *event_info __UNUSED__);
55 static void _mouse_down(void *data, Evas *e __UNUSED__, Evas_Object *obj
56                         __UNUSED__, void *event_info __UNUSED__);
57 static void _swallow_item_objects(Elm_Segment_Item *it);
58 static void _update_list(Widget_Data *wd);
59 static Elm_Segment_Item * _item_find(const Evas_Object *obj, int index);
60 static Elm_Segment_Item* _item_new(Evas_Object *obj, Evas_Object *icon,
61                                    const char *label);
62
63 static const char SIG_CHANGED[] = "changed";
64
65 static const Evas_Smart_Cb_Description _signals[] = {
66    {SIG_CHANGED, ""},
67    {NULL, NULL}
68 };
69
70 static void
71 _sizing_eval(Evas_Object *obj)
72 {
73    Widget_Data *wd;
74    Evas_Coord minw = -1, minh = -1;
75    Evas_Coord w, h;
76
77    wd = elm_widget_data_get(obj);
78    if (!wd) return;
79
80    elm_coords_finger_size_adjust(wd->item_count, &minw, 1, &minh);
81    edje_object_size_min_restricted_calc(wd->base, &minw, &minh, minw, minh);
82    elm_coords_finger_size_adjust(wd->item_count, &minw, 1, &minh);
83
84    evas_object_size_hint_min_get(obj, &w, &h);
85    if (w > minw) minw = w;
86    if (h > minh) minh = h;
87    evas_object_size_hint_min_set(obj, minw, minh);
88 }
89
90 static void
91 _del_hook(Evas_Object *obj)
92 {
93    Elm_Segment_Item *it;
94    Widget_Data *wd;
95
96    wd = elm_widget_data_get(obj);
97    if (!wd) return;
98
99    EINA_LIST_FREE(wd->seg_items, it) _item_free(it);
100
101    free(wd);
102 }
103
104 static void
105 _theme_hook(Evas_Object *obj)
106 {
107    Eina_List *l;
108    Eina_Bool rtl;
109    Elm_Segment_Item *it;
110    Widget_Data *wd;
111
112    wd = elm_widget_data_get(obj);
113    if (!wd) return;
114
115    _elm_widget_mirrored_reload(obj);
116    rtl = elm_widget_mirrored_get(obj);
117    edje_object_mirrored_set(wd->base, rtl);
118
119    _elm_theme_object_set(obj, wd->base, "segment_control", "base",
120                          elm_widget_style_get(obj));
121    edje_object_scale_set(wd->base, elm_widget_scale_get(wd->base)
122                          *_elm_config->scale);
123
124    EINA_LIST_FOREACH(wd->seg_items, l, it)
125      {
126         _elm_theme_object_set(obj, it->base.view, "segment_control",
127                               "item", elm_widget_style_get(obj));
128         edje_object_scale_set(it->base.view, elm_widget_scale_get(it->base.view)
129                               *_elm_config->scale);
130         edje_object_mirrored_set(it->base.view, rtl);
131      }
132
133    _update_list(wd);
134 }
135
136 static void
137 _disable_hook(Evas_Object *obj)
138 {
139    Widget_Data *wd;
140
141    wd = elm_widget_data_get(obj);
142    if (!wd) return;
143    _update_list(wd);
144 }
145
146 // TODO:  Elm_widget elm_widget_focus_list_next_get  supports only Elm_widget list,
147 // Not the Elm_Widget_item. Focus switching with in widget not supported until
148 // it is supported in elm_widget
149 #if 0
150 static void *
151 _elm_list_data_get(const Eina_List *list)
152 {
153    Elm_Segment_Item *it = eina_list_data_get(list);
154
155    if (it) return NULL;
156
157    edje_object_signal_emit(it->base.view, "elm,state,segment,selected", "elm");
158    return it->base.view;
159 }
160
161 static Eina_Bool
162 _focus_next_hook(const Evas_Object *obj, Elm_Focus_Direction dir,
163                  Evas_Object **next)
164 {
165    static int count=0;
166    Widget_Data *;
167    const Eina_List *items;
168    void *(*list_data_get) (const Eina_List *list);
169
170    wd = elm_widget_data_get(obj);
171    if ((!wd)) return EINA_FALSE;
172
173    /* Focus chain */
174    /* TODO: Change this to use other chain */
175    if ((items = elm_widget_focus_custom_chain_get(obj)))
176      list_data_get = eina_list_data_get;
177    else
178      {
179         items = wd->seg_items;
180         list_data_get = _elm_list_data_get;
181         if (!items) return EINA_FALSE;
182      }
183    return elm_widget_focus_list_next_get(obj, items, list_data_get, dir, next);
184 }
185 #endif
186
187 static void
188 _item_free(Elm_Segment_Item *it)
189 {
190    Widget_Data *wd;
191
192    if (!it) return;
193
194    wd = elm_widget_item_data_get(it);
195    if (!wd) return;
196
197    if (wd->selected_item == it) wd->selected_item = NULL;
198    if (wd->seg_items) wd->seg_items = eina_list_remove(wd->seg_items, it);
199
200    elm_widget_item_pre_notify_del(it);
201
202    if (it->icon) evas_object_del(it->icon);
203    if (it->label) eina_stringshare_del(it->label);
204
205    elm_widget_item_del(it);
206 }
207
208 static void
209 _segment_off(Elm_Segment_Item *it)
210 {
211    Widget_Data *wd;
212
213    if (!it) return;
214
215    wd = elm_widget_item_data_get(it);
216    if (!wd) return;
217
218    edje_object_signal_emit(it->base.view, "elm,state,segment,normal", "elm");
219
220    if (wd->selected_item == it) wd->selected_item = NULL;
221 }
222
223 static void
224 _segment_on(Elm_Segment_Item *it)
225 {
226    Widget_Data *wd;
227
228    if (!it) return;
229
230    wd = elm_widget_item_data_get(it);
231    if (!wd) return;
232    if (it == wd->selected_item) return;
233
234    if (wd->selected_item) _segment_off(wd->selected_item);
235
236    edje_object_signal_emit(it->base.view, "elm,state,segment,selected", "elm");
237
238    wd->selected_item = it;
239    evas_object_smart_callback_call(wd->obj, SIG_CHANGED,
240                                    (void *)(unsigned long)it->seg_index);
241 }
242
243 static void
244 _position_items(Widget_Data *wd)
245 {
246    Eina_List *l, *ll;
247    Elm_Segment_Item *it;
248    Eina_Bool rtl;
249    int bx, by, bw, bh, pos;
250
251    wd->item_count = eina_list_count(wd->seg_items);
252    if (wd->item_count <= 0) return;
253
254    evas_object_geometry_get(wd->base, &bx, &by, &bw, &bh);
255    wd->item_width = bw / wd->item_count;
256
257    rtl = elm_widget_mirrored_get(wd->obj);
258
259    if (rtl)
260      pos = bx + bw - wd->item_width;
261    else
262      pos = bx;
263
264    EINA_LIST_FOREACH(wd->seg_items, l, it)
265      {
266         evas_object_move(it->base.view, pos, by);
267         evas_object_resize(it->base.view, wd->item_width, bh);
268         if (rtl)
269           pos -= wd->item_width;
270         else
271           pos += wd->item_width;
272      }
273    ll = eina_list_last(wd->seg_items);
274    it = ll->data;
275    evas_object_resize(it->base.view,
276                         (bw - ((wd->item_count - 1) * wd->item_width)),
277                         bh);
278    _sizing_eval(wd->obj);
279 }
280
281 static void
282 _on_move_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__,
283                 void *event_info __UNUSED__)
284 {
285    Widget_Data *wd;
286
287    wd = elm_widget_data_get(data);
288    if (!wd) return;
289
290    _position_items(wd);
291
292 }
293
294 static void
295 _mouse_up(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__,
296           void *event_info)
297 {
298    Widget_Data *wd;
299    Elm_Segment_Item *it;
300    Evas_Event_Mouse_Up *ev;
301    Evas_Coord x, y, w, h;
302
303    it = data;
304    if (!it) return;
305
306    wd = elm_widget_item_data_get(it);
307    if (!wd) return;
308
309    if (elm_widget_disabled_get(wd->obj)) return;
310
311    if (it == wd->selected_item) return;
312
313    ev = event_info;
314    evas_object_geometry_get(it->base.view, &x, &y, &w, &h);
315
316    if ((ev->canvas.x >= x) && (ev->output.x <= (x + w)) && (ev->canvas.y >= y)
317        && (ev->canvas.y <= (y + h)))
318      _segment_on(it);
319    else
320      edje_object_signal_emit(it->base.view, "elm,state,segment,normal", "elm");
321 }
322
323 static void
324 _mouse_down(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__,
325             void *event_info __UNUSED__)
326 {
327    Widget_Data *wd;
328    Elm_Segment_Item *it;
329
330    it = data;
331    if (!it) return;
332
333    wd = elm_widget_item_data_get(it);
334    if (!wd) return;
335
336    if (elm_widget_disabled_get(wd->obj)) return;
337
338    if (it == wd->selected_item) return;
339
340    edje_object_signal_emit(it->base.view, "elm,state,segment,pressed", "elm");
341 }
342
343 static void
344 _swallow_item_objects(Elm_Segment_Item *it)
345 {
346    if (!it) return;
347
348    if (it->icon)
349      {
350         edje_object_part_swallow(it->base.view, "elm.swallow.icon", it->icon);
351         edje_object_signal_emit(it->base.view, "elm,state,icon,visible", "elm");
352      }
353    else
354      edje_object_signal_emit(it->base.view, "elm,state,icon,hidden", "elm");
355
356    if (it->label)
357      {
358         edje_object_part_text_set(it->base.view, "elm.text", it->label);
359         edje_object_signal_emit(it->base.view, "elm,state,text,visible", "elm");
360      }
361    else
362      edje_object_signal_emit(it->base.view, "elm,state,text,hidden", "elm");
363    edje_object_message_signal_process(it->base.view);
364 }
365
366 static void
367 _update_list(Widget_Data *wd)
368 {
369    Eina_List *l;
370    Elm_Segment_Item *it;
371    Eina_Bool rtl;
372    int idx = 0;
373
374    _position_items(wd);
375
376    if (wd->item_count == 1)
377      {
378         it = eina_list_nth(wd->seg_items, 0);
379         it->seg_index = 0;
380
381         //Set the segment type
382         edje_object_signal_emit(it->base.view,
383                                 "elm,type,segment,single", "elm");
384
385         //Set the segment state
386         if (wd->selected_item == it)
387           edje_object_signal_emit(it->base.view,
388                                   "elm,state,segment,selected", "elm");
389         else
390           edje_object_signal_emit(it->base.view,
391                                   "elm,state,segment,normal", "elm");
392
393         if (elm_widget_disabled_get(wd->obj))
394           edje_object_signal_emit(it->base.view, "elm,state,disabled", "elm");
395         else
396           edje_object_signal_emit(it->base.view, "elm,state,enabled", "elm");
397
398         _swallow_item_objects(it);
399         return;
400      }
401
402    rtl = elm_widget_mirrored_get(wd->obj);
403    EINA_LIST_FOREACH(wd->seg_items, l, it)
404      {
405         it->seg_index = idx;
406
407         //Set the segment type
408         if (idx == 0)
409           {
410              if (rtl)
411                edje_object_signal_emit(it->base.view,
412                                        "elm,type,segment,right", "elm");
413              else
414                edje_object_signal_emit(it->base.view,
415                                        "elm,type,segment,left", "elm");
416           }
417         else if (idx == (wd->item_count - 1))
418           {
419              if (rtl)
420                edje_object_signal_emit(it->base.view,
421                                        "elm,type,segment,left", "elm");
422              else
423                edje_object_signal_emit(it->base.view,
424                                        "elm,type,segment,right", "elm");
425           }
426         else
427           edje_object_signal_emit(it->base.view,
428                                   "elm,type,segment,middle", "elm");
429
430         //Set the segment state
431         if (wd->selected_item == it)
432           edje_object_signal_emit(it->base.view,
433                                   "elm,state,segment,selected", "elm");
434         else
435           edje_object_signal_emit(it->base.view,
436                                   "elm,state,segment,normal", "elm");
437
438         if (elm_widget_disabled_get(wd->obj))
439           edje_object_signal_emit(it->base.view, "elm,state,disabled", "elm");
440         else
441           edje_object_signal_emit(it->base.view, "elm,state,enabled", "elm");
442
443         _swallow_item_objects(it);
444         idx++;
445      }
446 }
447
448 static Elm_Segment_Item *
449 _item_find(const Evas_Object *obj, int idx)
450 {
451    Widget_Data *wd;
452    Elm_Segment_Item *it;
453
454    wd = elm_widget_data_get(obj);
455    if (!wd) return NULL;
456
457    it = eina_list_nth(wd->seg_items, idx);
458    return it;
459 }
460
461 static Elm_Segment_Item*
462 _item_new(Evas_Object *obj, Evas_Object *icon, const char *label)
463 {
464    Elm_Segment_Item *it;
465    Widget_Data *wd;
466
467    wd = elm_widget_data_get(obj);
468    if (!wd) return NULL;
469
470    it = elm_widget_item_new(obj, Elm_Segment_Item);
471    if (!it) return NULL;
472    elm_widget_item_data_set(it, wd);
473
474    it->base.view = edje_object_add(evas_object_evas_get(obj));
475    edje_object_scale_set(it->base.view, elm_widget_scale_get(it->base.view)
476                          *_elm_config->scale);
477    evas_object_smart_member_add(it->base.view, obj);
478    elm_widget_sub_object_add(obj, it->base.view);
479    evas_object_clip_set(it->base.view, evas_object_clip_get(obj));
480
481    _elm_theme_object_set(obj, it->base.view, "segment_control", "item",
482                          elm_object_style_get(obj));
483    edje_object_mirrored_set(it->base.view,
484                             elm_widget_mirrored_get(it->base.widget));
485
486    if (label)
487      eina_stringshare_replace(&it->label, label);
488    if (it->label)
489      edje_object_signal_emit(it->base.view, "elm,state,text,visible", "elm");
490    else
491      edje_object_signal_emit(it->base.view, "elm,state,text,hidden", "elm");
492    edje_object_message_signal_process(it->base.view);
493    edje_object_part_text_set(it->base.view, "elm.text", label);
494
495    it->icon = icon;
496    if (it->icon) elm_widget_sub_object_add(it->base.view, it->icon);
497    evas_object_event_callback_add(it->base.view, EVAS_CALLBACK_MOUSE_DOWN,
498                                   _mouse_down, it);
499    evas_object_event_callback_add(it->base.view, EVAS_CALLBACK_MOUSE_UP,
500                                   _mouse_up, it);
501    evas_object_show(it->base.view);
502
503    return it;
504 }
505
506 /**
507  * Create new SegmentControl.
508  * @param [in] parent The parent object
509  * @return The new object or NULL if it cannot be created
510  *
511  * @ingroup SegmentControl
512  */
513 EAPI Evas_Object *
514 elm_segment_control_add(Evas_Object *parent)
515 {
516    Evas_Object *obj;
517    Evas *e;
518    Widget_Data *wd;
519
520    ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
521
522    ELM_SET_WIDTYPE(widtype, "segment_control");
523    elm_widget_type_set(obj, "segment_control");
524    elm_widget_sub_object_add(parent, obj);
525    elm_widget_data_set(obj, wd);
526    elm_widget_del_hook_set(obj, _del_hook);
527    elm_widget_theme_hook_set(obj, _theme_hook);
528    elm_widget_disable_hook_set(obj, _disable_hook);
529
530    // TODO: Focus switch support to Elm_widget_Item not supported yet.
531 #if 0
532    elm_widget_focus_next_hook_set(obj, _focus_next_hook);
533 #endif
534
535    wd->obj = obj;
536
537    wd->base = edje_object_add(e);
538    edje_object_scale_set(wd->base, elm_widget_scale_get(wd->base)
539                          *_elm_config->scale);
540    _elm_theme_object_set(obj, wd->base, "segment_control", "base", "default");
541    elm_widget_resize_object_set(obj, wd->base);
542
543    evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE,
544                                   _on_move_resize, obj);
545    evas_object_event_callback_add(obj, EVAS_CALLBACK_MOVE,
546                                   _on_move_resize, obj);
547
548    evas_object_smart_callbacks_descriptions_set(obj, _signals);
549
550    return obj;
551 }
552
553 /**
554  * Add new segment item to SegmentControl.
555  * @param [in] obj The SegmentControl object
556  * @param [in] icon Any Objects like icon, Label, layout etc
557  * @param [in] label The label for added segment item.
558  *             Note that, NULL is different from empty string "".
559  * @return The new segment item or NULL if it cannot be created
560  *
561  * @ingroup SegmentControl
562  */
563 EAPI Elm_Segment_Item *
564 elm_segment_control_item_add(Evas_Object *obj, Evas_Object *icon,
565                              const char *label)
566 {
567    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
568    Elm_Segment_Item *it;
569    Widget_Data *wd;
570
571    wd = elm_widget_data_get(obj);
572    if (!wd) return NULL;
573
574    it = _item_new(obj, icon, label);
575    if (!it) return NULL;
576
577    wd->seg_items = eina_list_append(wd->seg_items, it);
578    _update_list(wd);
579
580    return it;
581 }
582
583 /**
584  * Insert a new segment item to SegmentControl.
585  * @param [in] obj The SegmentControl object
586  * @param [in] icon Any Objects like icon, Label, layout etc
587  * @param [in] label The label for added segment item.
588  *        Note that, NULL is different from empty string "".
589  * @param [in] index Segment item location. Value should be between 0 and
590  *        Existing total item count( @see elm_segment_control_item_count_get() )
591  * @return The new segment item or NULL if it cannot be created
592  *
593  * @ingroup SegmentControl
594  */
595 EAPI Elm_Segment_Item *
596 elm_segment_control_item_insert_at(Evas_Object *obj, Evas_Object *icon,
597                                    const char *label, int idx)
598 {
599    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
600    Elm_Segment_Item *it, *it_rel;
601    Widget_Data *wd;
602
603    wd = elm_widget_data_get(obj);
604    if (!wd) return NULL;
605    if (idx < 0) idx = 0;
606
607    it = _item_new(obj, icon, label);
608    if (!it) return NULL;
609
610    it_rel = _item_find(obj, idx);
611
612    if (it_rel)
613      wd->seg_items = eina_list_prepend_relative(wd->seg_items, it, it_rel);
614    else
615      wd->seg_items = eina_list_append(wd->seg_items, it);
616
617    _update_list(wd);
618    return it;
619 }
620
621 /**
622  * Delete a segment item from SegmentControl
623  * @param [in] obj The SegmentControl object
624  * @param [in] it The segment item to be deleted
625  *
626  * @ingroup SegmentControl
627  */
628 EAPI void
629 elm_segment_control_item_del(Elm_Segment_Item *it)
630 {
631    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
632    Widget_Data *wd;
633
634    wd = elm_widget_item_data_get(it);
635    if (!wd) return;
636
637    _item_free(it);
638    _update_list(wd);
639 }
640
641 /**
642  * Delete a segment item of given index from SegmentControl
643  * @param [in] obj The SegmentControl object
644  * @param [in] index The position at which segment item to be deleted.
645  *
646  * @ingroup SegmentControl
647  */
648 EAPI void
649 elm_segment_control_item_del_at(Evas_Object *obj, int idx)
650 {
651    ELM_CHECK_WIDTYPE(obj, widtype);
652    Elm_Segment_Item *it;
653    Widget_Data *wd;
654
655    wd = elm_widget_data_get(obj);
656    if (!wd) return;
657
658    it = _item_find(obj, idx);
659
660    if (!it) return;
661    _item_free(it);
662    _update_list(wd);
663 }
664
665 /**
666  * Get the label of a segment item.
667  * @param [in] obj The SegmentControl object
668  * @param [in] index The index of the segment item
669  * @return The label of the segment item
670  *
671  * @ingroup SegmentControl
672  */
673 EAPI const char*
674 elm_segment_control_item_label_get(const Evas_Object *obj, int idx)
675 {
676    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
677    Elm_Segment_Item *it;
678
679    it = _item_find(obj, idx);
680
681    if (it) return it->label;
682
683    return NULL;
684 }
685
686 /**
687  * Set the label of a segment item.
688  * @param [in] it The SegmentControl Item
689  * @param [in] label New label text.
690  *
691  * @ingroup SegmentControl
692  */
693 EAPI void
694 elm_segment_control_item_label_set(Elm_Segment_Item* it, const char* label)
695 {
696    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
697    Widget_Data *wd;
698
699    wd = elm_widget_item_data_get(it);
700    if (!wd) return;
701
702    eina_stringshare_replace(&it->label, label);
703    if (it->label)
704      edje_object_signal_emit(it->base.view, "elm,state,text,visible", "elm");
705    else
706      edje_object_signal_emit(it->base.view, "elm,state,text,hidden", "elm");
707    edje_object_message_signal_process(it->base.view);
708    //label can be NULL also.
709    edje_object_part_text_set(it->base.view, "elm.text", it->label);
710 }
711
712 /**
713  * Get the icon of a segment item of SegmentControl
714  * @param [in] obj The SegmentControl object
715  * @param [in] index The index of the segment item
716  * @return The icon object.
717  *
718  * @ingroup SegmentControl
719  */
720 EAPI Evas_Object *
721 elm_segment_control_item_icon_get(const Evas_Object *obj, int idx)
722 {
723    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
724    Elm_Segment_Item *it;
725
726    it = _item_find(obj, idx);
727
728    if (it) return it->icon;
729
730    return NULL;
731 }
732
733 /**
734  * Set the Icon to the segment item
735  * @param [in] it The SegmentControl Item
736  * @param [in] icon Objects like Layout, Icon, Label etc...
737  *
738  * @ingroup SegmentControl
739  */
740 EAPI void
741 elm_segment_control_item_icon_set(Elm_Segment_Item *it, Evas_Object *icon)
742 {
743    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
744
745    //Remove the existing icon
746    if (it->icon)
747      {
748         edje_object_part_unswallow(it->base.view, it->icon);
749         evas_object_del(it->icon);
750         it->icon = NULL;
751      }
752
753    it->icon = icon;
754    if (it->icon)
755      {
756         elm_widget_sub_object_add(it->base.view, it->icon);
757         edje_object_part_swallow(it->base.view, "elm.swallow.icon", it->icon);
758         edje_object_signal_emit(it->base.view, "elm,state,icon,visible", "elm");
759      }
760    else
761      edje_object_signal_emit(it->base.view, "elm,state,icon,hidden", "elm");
762 }
763
764 /**
765  * Get the Segment items count from SegmentControl
766  * @param [in] obj The SegmentControl object
767  * @return Segment items count.
768  *
769  * @ingroup SegmentControl
770  */
771 EAPI int
772 elm_segment_control_item_count_get(const Evas_Object *obj)
773 {
774    ELM_CHECK_WIDTYPE(obj, widtype) 0;
775    Widget_Data *wd;
776
777    wd = elm_widget_data_get(obj);
778    if (!wd) return 0;
779
780    return eina_list_count(wd->seg_items);
781 }
782
783 /**
784  * Get the base object of segment item.
785  * @param [in] it The Segment item
786  * @return obj The base object of the segment item.
787  *
788  * @ingroup SegmentControl
789  */
790 EAPI Evas_Object*
791 elm_segment_control_item_object_get(const Elm_Segment_Item *it)
792 {
793    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, NULL);
794
795    return it->base.view;
796 }
797
798 /**
799  * Get the selected segment item in the SegmentControl
800  * @param [in] obj The SegmentControl object
801  * @return Selected Segment Item. NULL if none of segment item is selected.
802  *
803  * @ingroup SegmentControl
804  */
805 EAPI Elm_Segment_Item*
806 elm_segment_control_item_selected_get(const Evas_Object *obj)
807 {
808    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
809    Widget_Data *wd;
810
811    wd = elm_widget_data_get(obj);
812    if (!wd) return NULL;
813
814    return wd->selected_item;
815 }
816
817 /**
818  * Select/unselect a particular segment item of SegmentControl
819  * @param [in] it The Segment item that is to be selected or unselected.
820  * @param [in] select Passing EINA_TRUE will select the segment item and
821  *             EINA_FALSE will unselect.
822  *
823  * @ingroup SegmentControl
824  */
825 EAPI void
826 elm_segment_control_item_selected_set(Elm_Segment_Item *it, Eina_Bool selected)
827 {
828    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
829    Widget_Data *wd;
830
831    wd = elm_widget_item_data_get(it);
832    if (!wd) return;
833
834    if (it == wd->selected_item)
835      {
836         //already in selected state.
837         if (selected) return;
838
839         //unselect case
840         _segment_off(it);
841      }
842    else if (selected)
843      _segment_on(it);
844
845    return;
846 }
847
848 /**
849  * Get the Segment Item from the specified Index.
850  * @param [in] obj The Segment Control object.
851  * @param [in] index The index of the segment item.
852  * @return The Segment item.
853  *
854  * @ingroup SegmentControl
855  */
856 EAPI Elm_Segment_Item *
857 elm_segment_control_item_get(const Evas_Object *obj, int idx)
858 {
859    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
860    Elm_Segment_Item *it;
861
862    it = _item_find(obj, idx);
863
864    return it;
865 }
866
867 /**
868  * Get the index of a Segment item in the SegmentControl
869  * @param [in] it The Segment Item.
870  * @return Segment Item index.
871  *
872  * @ingroup SegmentControl
873  */
874 EAPI int
875 elm_segment_control_item_index_get(const Elm_Segment_Item *it)
876 {
877    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, -1);
878
879    return it->seg_index;
880 }