1 #include <Elementary.h>
5 * @defgroup SegmentControl SegmentControl
8 * SegmentControl Widget is a horizontal control made of multiple segments, each segment item
9 * functioning as a discrete two state button. A segmented control affords a compact means to group together a number of controls.
10 * Only one Segment item can be at selected state. A segmented control item can display combination of Text and Icon.
12 typedef struct _Widget_Data Widget_Data;
19 unsigned int item_count;
20 Elm_Segment_Item *selected_item;
24 struct _Elm_Segment_Item
33 static void _item_free(Evas_Object *obj, Elm_Segment_Item *it);
34 static void _del_hook(Evas_Object *obj);
35 static void _update_list(Evas_Object *obj);
38 _sizing_eval(Evas_Object *obj)
40 Widget_Data *wd = elm_widget_data_get(obj);
41 Evas_Coord minw = -1, minh = -1;
45 elm_coords_finger_size_adjust(1, &minw, 1, &minh);
46 edje_object_size_min_restricted_calc(wd->base, &minw, &minh, minw, minh);
47 elm_coords_finger_size_adjust(1, &minw, 1, &minh);
49 evas_object_size_hint_min_get(obj, &w, &h);
50 if (w > minw) minw = w;
51 if (h > minh) minh = h;
52 evas_object_size_hint_min_set(obj, minw, minh);
56 _del_hook(Evas_Object *obj)
59 Widget_Data *wd = elm_widget_data_get(obj);
61 EINA_LIST_FREE(wd->seg_items, it) _item_free(obj, it);
68 _theme_hook(Evas_Object *obj)
72 Widget_Data *wd = elm_widget_data_get(obj);
73 _elm_theme_object_set(obj, wd->base, "segment_control", "base",
74 elm_widget_style_get(obj));
76 EINA_LIST_FOREACH(wd->seg_items, l, it)
77 _elm_theme_object_set(obj, it->base, "segment_control", "item", elm_widget_style_get(obj));
85 _item_free(Evas_Object *obj, Elm_Segment_Item *it)
87 Widget_Data *wd = elm_widget_data_get(obj);
88 if (!it || !wd) return;
90 if (wd->selected_item == it) wd->selected_item = NULL;
91 if (wd->seg_items) wd->seg_items = eina_list_remove(wd->seg_items, it);
93 if (it->icon) evas_object_del(it->icon);
94 if (it->label) evas_object_del(it->label);
95 if (it->base) evas_object_del(it->base);
103 _segment_off(Elm_Segment_Item *it)
107 edje_object_signal_emit(it->base, "elm,state,segment,normal", "elm");
108 if (it->label) elm_object_style_set(it->label, "segment_normal");
110 if (it->wd->selected_item == it) it->wd->selected_item = NULL;
116 _segment_on(Elm_Segment_Item *it)
118 if (!it || (it == it->wd->selected_item)) return;
120 if (it->wd->selected_item) _segment_off(it->wd->selected_item);
122 edje_object_signal_emit(it->base, "elm,state,segment,selected", "elm");
124 if (it->label) elm_object_style_set(it->label, "segment_selected");
126 it->wd->selected_item = it;
127 evas_object_smart_callback_call(it->wd->obj, "changed", (void*) it->seg_index);
133 _position_items(Evas_Object *obj)
136 Elm_Segment_Item *it;
137 int bx, by, bw, bh, position;
139 Widget_Data *wd = elm_widget_data_get(obj);
142 wd->item_count = eina_list_count(wd->seg_items);
143 if (wd->item_count <= 0) return;
145 evas_object_geometry_get(wd->base, &bx, &by, &bw, &bh);
146 wd->item_width = bw / wd->item_count;
149 EINA_LIST_FOREACH(wd->seg_items, l, it)
151 evas_object_move(it->base, bx, by );
152 evas_object_resize(it->base, wd->item_width, bh );
153 bx += wd->item_width;
159 _on_move_resize(void *data, Evas *e, Evas_Object *obj, void *event_info)
161 Evas_Coord law = 0, lah = 0;
163 Elm_Segment_Item *it = NULL;
166 Widget_Data *wd = elm_widget_data_get((Evas_Object *) data);
168 _position_items((Evas_Object *) data);
170 EINA_LIST_FOREACH(wd->seg_items, l, it)
172 lbl_area = edje_object_data_get(it->base, "label.wrap.part");
173 if( it->label && lbl_area)
175 edje_object_part_geometry_get(it->base, lbl_area, NULL, NULL, &law, &lah);
176 elm_label_wrap_width_set(it->label, law);
177 //elm_label_wrap_height_set(it->label, lah); // not supported by elm_label yet
183 _mouse_up(void *data, Evas *e, Evas_Object *obj, void *event_info)
185 Elm_Segment_Item *it = (Elm_Segment_Item *) data;
187 if (it == it->wd->selected_item) return;
194 _mouse_down(void *data, Evas *evas, Evas_Object *obj, void *event_info)
196 Elm_Segment_Item *it = (Elm_Segment_Item *) data;
198 if (it == it->wd->selected_item) return;
200 edje_object_signal_emit(it->base, "elm,state,segment,pressed", "elm");
201 if (it->label) elm_object_style_set(it->label, "segment_pressed");
207 _swallow_item_objects(Elm_Segment_Item *it)
209 Evas_Coord law = 0, lah = 0;
216 edje_object_part_swallow(it->base, "elm.swallow.icon", it->icon);
217 edje_object_signal_emit(it->base, "elm,state,icon,visible", "elm");
220 edje_object_signal_emit(it->base, "elm,state,icon,hidden", "elm");
224 edje_object_part_swallow(it->base, "elm.swallow.label", it->label);
225 edje_object_signal_emit(it->base, "elm,state,text,visible", "elm");
227 lbl_area = edje_object_data_get(it->base, "label.wrap.part");
230 edje_object_part_geometry_get(it->base, lbl_area, NULL, NULL, &law, &lah );
231 elm_label_wrap_width_set(it->label, law);
232 //elm_label_wrap_height_set(it->label, lah); // not supported by elm_label yet
236 edje_object_signal_emit(it->base, "elm,state,text,hidden", "elm");
240 _update_list(Evas_Object *obj)
243 Elm_Segment_Item *it = NULL;
246 Widget_Data *wd = elm_widget_data_get(obj);
249 _position_items(obj);
251 if (wd->item_count == 1)
253 it = (Elm_Segment_Item *) eina_list_nth(wd->seg_items, 0);
256 //Set the segment type
257 edje_object_signal_emit(it->base, "elm,type,segment,single", "elm");
259 //Set the segment state
260 if (wd->selected_item == it)
262 edje_object_signal_emit(it->base, "elm,state,segment,selected", "elm");
263 if (it->label) elm_object_style_set(it->label, "segment_selected");
266 edje_object_signal_emit(it->base, "elm,state,segment,normal", "elm");
268 _swallow_item_objects(it);
273 EINA_LIST_FOREACH(wd->seg_items, l, it)
275 it->seg_index = index;
277 //Set the segment type
279 edje_object_signal_emit(it->base, "elm,type,segment,left", "elm");
280 else if(index == wd->item_count-1)
281 edje_object_signal_emit(it->base, "elm,type,segment,right", "elm");
283 edje_object_signal_emit(it->base, "elm,type,segment,middle", "elm");
285 //Set the segment state
286 if(wd->selected_item == it )
288 edje_object_signal_emit(it->base, "elm,state,segment,selected", "elm");
289 if(it->label) elm_object_style_set(it->label, "segment_selected");
292 edje_object_signal_emit(it->base, "elm,state,segment,normal", "elm");
294 _swallow_item_objects(it);
299 static Elm_Segment_Item *
300 _item_find(Evas_Object *obj, unsigned int index)
302 Elm_Segment_Item *it;
303 Widget_Data *wd = elm_widget_data_get(obj);
304 if (!wd) return NULL;
\r
306 it = (Elm_Segment_Item *) eina_list_nth(wd->seg_items, index);
310 static Elm_Segment_Item*
311 _item_new(Evas_Object *obj, Evas_Object *icon, const char *label )
313 Elm_Segment_Item *it;
314 Widget_Data *wd = elm_widget_data_get(obj);
315 if (!wd) return NULL;
317 it = calloc(1, sizeof(Elm_Segment_Item));
318 if (!it) return NULL;
321 it->base = edje_object_add(evas_object_evas_get(obj));
322 elm_widget_sub_object_add(obj, it->base);
323 _elm_theme_object_set(obj, it->base, "segment_control", "item",
324 elm_object_style_get(obj));
328 it->label = elm_label_add(obj);
329 elm_widget_sub_object_add(it->base, it->label);
330 elm_object_style_set(it->label, "segment_normal");
331 elm_label_label_set(it->label, label);
332 elm_label_ellipsis_set(it->label, EINA_TRUE);
333 evas_object_show(it->label);
337 if (it->icon) elm_widget_sub_object_add(it->base, it->icon);
339 evas_object_event_callback_add(it->base, EVAS_CALLBACK_MOUSE_DOWN, _mouse_down, it);
340 evas_object_event_callback_add(it->base, EVAS_CALLBACK_MOUSE_UP, _mouse_up,
342 evas_object_show(it->base);
348 * Create new SegmentControl.
349 * @param [in] parent The parent object
350 * @return The new object or NULL if it cannot be created
352 * @ingroup SegmentControl SegmentControl
355 elm_segment_control_add(Evas_Object *parent)
361 wd = ELM_NEW(Widget_Data);
362 e = evas_object_evas_get(parent);
364 obj = elm_widget_add(e);
365 elm_widget_type_set(obj, "segmented-control");
366 elm_widget_sub_object_add(parent, obj);
367 elm_widget_data_set(obj, wd);
368 elm_widget_del_hook_set(obj, _del_hook);
369 elm_widget_theme_hook_set(obj, _theme_hook);
372 wd->base = edje_object_add(e);
373 _elm_theme_object_set(obj, wd->base, "segment_control", "base", "default");
374 elm_widget_resize_object_set(obj, wd->base);
376 evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE, _on_move_resize,
378 evas_object_event_callback_add(obj, EVAS_CALLBACK_MOVE, _on_move_resize, obj);
380 wd->selected_item = NULL;
388 * Add new segment item to SegmentControl item.
389 * @param [in] obj The SegmentControl object
390 * @param [in] icon Any Objects like icon, Label, layout etc
391 * @param [in] label The label for added segment item
392 * @return The new segment item or NULL if it cannot be created
394 * @ingroup SegmentControl SegmentControl
396 EAPI Elm_Segment_Item *
397 elm_segment_control_item_add(Evas_Object *obj, Evas_Object *icon,
400 Elm_Segment_Item *it;
401 Widget_Data *wd = elm_widget_data_get(obj);
402 if (!wd) return NULL;
404 it = _item_new(obj, icon, label);
405 if (!it) return NULL;
407 wd->seg_items = eina_list_append(wd->seg_items, it);
414 * Insert a new segment item to SegmentControl item.
415 * @param [in] obj The SegmentControl object
416 * @param [in] icon Any Objects like icon, Label, layout etc
417 * @param [in] label The label for added segment item
418 * @param [in] index Segment item location. Value should be between 0 and
419 * Existing total item count( @see elm_segment_control_item_count_get() )
420 * @return The new segment item or NULL if it cannot be created
422 * @ingroup SegmentControl SegmentControl
424 EAPI Elm_Segment_Item *
425 elm_segment_control_item_insert_at(Evas_Object *obj, Evas_Object *icon,
426 const char *label, unsigned int index)
428 Elm_Segment_Item *it, *it_rel;
429 Widget_Data *wd = elm_widget_data_get(obj);
430 if (!wd) return NULL;
431 if (index < 0 || index > wd->item_count) return NULL;
433 it = _item_new(obj, icon, label);
434 if (!it) return NULL;
436 it_rel = _item_find(obj, index);
438 wd->seg_items = eina_list_append(wd->seg_items, it);
440 wd->seg_items = eina_list_prepend_relative(wd->seg_items, it, it_rel);
446 * Delete a segment item from SegmentControl
447 * @param [in] obj The SegmentControl object
448 * @param [in] it The segment item to be deleted
450 * @ingroup SegmentControl SegmentControl
454 elm_segment_control_item_del(Evas_Object *obj, Elm_Segment_Item *it)
456 Widget_Data *wd = elm_widget_data_get(obj);
457 if (!wd || !it) return;
466 * Delete a segment item of given index from SegmentControl
467 * @param [in] obj The SegmentControl object
468 * @param [in] index The position at which segment item to be deleted
470 * @ingroup SegmentControl SegmentControl
473 elm_segment_control_item_del_at(Evas_Object *obj, unsigned int index)
475 Elm_Segment_Item *it;
476 Widget_Data *wd = elm_widget_data_get(obj);
479 it = _item_find(obj, index);
488 * Get the label of a segment item.
489 * @param [in] obj The SegmentControl object
490 * @param [in] index The index of the segment item
491 * @return The label of the segment item
493 * @ingroup SegmentControl SegmentControl
496 elm_segment_control_item_label_get(Evas_Object *obj, unsigned int index)
498 Elm_Segment_Item *it;
499 Widget_Data *wd = elm_widget_data_get(obj);
500 if (!wd) return NULL;
502 it = _item_find(obj, index);
503 if (it && it->label) return elm_label_label_get(it->label);
509 * Set the label of a segment item.
510 * @param [in] it The SegmentControl Item
511 * @param [in] label New label text.
513 * @ingroup SegmentControl SegmentControl
516 elm_segment_control_item_label_set(Elm_Segment_Item* it, const char* label)
520 if( !label && !it->label ) return; //No label, return
522 if( label && !it->label ) // Create Label Object
524 it->label = elm_label_add(it->base);
525 elm_widget_sub_object_add(it->base, it->label);
526 elm_label_label_set(it->label, label);
527 elm_label_ellipsis_set(it->label, EINA_TRUE);
528 evas_object_show(it->label);
530 if(it->wd->selected_item == it )
531 elm_object_style_set(it->label, "segment_selected");
533 elm_object_style_set(it->label, "segment_normal");
535 else if( !label && it->label ) // Delete Label Object
537 evas_object_del(it->label);
540 else // Update the text
541 elm_label_label_set(it->label, label);
543 _swallow_item_objects( it );
548 * Get the icon of a segment item of SegmentControl
549 * @param [in] obj The SegmentControl object
550 * @param [in] index The index of the segment item
551 * @return The icon object.
553 * @ingroup SegmentControl SegmentControl
556 elm_segment_control_item_icon_get(Evas_Object *obj, unsigned int index)
558 Elm_Segment_Item *it;
559 Widget_Data *wd = elm_widget_data_get(obj);
560 if (!wd) return NULL;
562 it = _item_find(obj, index);
563 if (it) return it->icon;
569 * Set the Icon to the segment item
570 * @param [in] it The SegmentControl Item
571 * @param [in] icon Objects like Layout, Icon, Label etc...
573 * @ingroup SegmentControl SegmentControl
576 elm_segment_control_item_icon_set(Elm_Segment_Item *it, Evas_Object *icon)
580 //Remove the existing icon
583 edje_object_part_unswallow(it->base, it->icon);
584 evas_object_del(it->icon);
588 if (it->icon) elm_widget_sub_object_add(it->base, it->icon);
589 _swallow_item_objects( it );
593 * Get the Segment items count from SegmentControl
594 * @param [in] obj The SegmentControl object
595 * @return Segment items count.
597 * @ingroup SegmentControl SegmentControl
600 elm_segment_control_item_count_get(Evas_Object *obj)
602 Widget_Data *wd = elm_widget_data_get(obj);
605 return wd->item_count;
609 * Get the base object of segment item.
610 * @param [in] it The Segment item
611 * @return obj The base object of the segment item.
613 * @ingroup SegmentControl SegmentControl
616 elm_segment_control_item_object_get(Elm_Segment_Item *it)
618 if (!it) return NULL;
623 * Get the selected segment item in the SegmentControl
624 * @param [in] obj The SegmentControl object
625 * @return Selected Segment Item. NULL if none of segment item is selected.
627 * @ingroup SegmentControl SegmentControl
629 EAPI Elm_Segment_Item*
630 elm_segment_control_item_selected_get(const Evas_Object *obj)
632 Widget_Data *wd = elm_widget_data_get(obj);
633 if (!wd) return NULL;
634 return wd->selected_item;
638 * Select/unselect a particular segment item of SegmentControl
639 * @param [in] it The Segment item that is to be selected or unselected.
640 * @param [in] select Passing EINA_TRUE will select the segment item and EINA_FALSE will unselect.
642 * @ingroup SegmentControl SegmentControl
645 elm_segment_control_item_selected_set(Elm_Segment_Item *it, Eina_Bool select)
649 if (it == it->wd->selected_item)
651 if (select) return; //already in selected selected state.
663 * Get the Segment Item from the specified Index.
664 * @param [in] obj The Segment Control object.
665 * @param [in] index The index of the segment item.
666 * @return The Segment item.
668 * @ingroup SegmentControl SegmentControl
670 EAPI Elm_Segment_Item *
671 elm_segment_control_item_get_at(Evas_Object *obj, unsigned int index)
673 Elm_Segment_Item *it;
674 it = _item_find(obj, index);
680 * Get the index of a Segment item in the SegmentControl
681 * @param [in] it The Segment Item.
682 * @return Segment Item.
684 * @ingroup SegmentControl SegmentControl
687 elm_segment_control_item_index_get(Elm_Segment_Item *it)
690 return it->seg_index;
693 ////////////////////////////////// BEGIN //////////////////////////////////////////////
694 /////////////////////////// OLD SLP APIs - TO BE DEPRECATED /////////////////////////////
695 /////////////////////////////////////////////////////////////////////////////////////////
698 elm_segment_control_get_segment_count(Evas_Object *obj)
701 "#####\nWARNING: Use elm_segment_control_item_count_get()\ninstead of elm_segment_control_get_segment_count()\n#####\n");
702 return elm_segment_control_item_count_get(obj);
705 EAPI Elm_Segment_Item *
706 elm_segment_control_selected_segment_get(const Evas_Object *obj, int *value)
708 Elm_Segment_Item *it;
709 it = elm_segment_control_item_selected_get(obj);
710 if (!it) return NULL;
711 *value = it->seg_index;
714 "#####\nWARNING: Use elm_segment_control_item_selected_get() &\nelm_segment_control_item_index_get()\n instead of elm_segment_control_selected_segment_get()\n#####\n");
719 elm_segment_control_get_segment_icon_at(Evas_Object *obj, unsigned int index)
722 "#####\nWARNING: Use elm_segment_control_item_icon_get()\ninstead of elm_segment_control_get_segment_icon_at()\n#####\n");
723 return elm_segment_control_item_icon_get(obj, index);
727 elm_segment_control_get_segment_label_at(Evas_Object *obj, unsigned int index)
730 "#####\nWARNING: Use elm_segment_control_item_label_get()\n instead of elm_segment_control_get_segment_label_at() \n#####\n");
731 return elm_segment_control_item_label_get(obj, index);
735 elm_segment_control_delete_segment_at(Evas_Object *obj, unsigned int index,
739 "#####\nWARNING: Use elm_segment_control_item_del_at()\ninstead of elm_segment_control_delete_segment_at() \n#####\n");
740 elm_segment_control_item_del_at(obj, index);
744 elm_segment_control_delete_segment(Evas_Object *obj, Elm_Segment_Item *item,
748 "#####\nWARNING: Use elm_segment_control_item_del()\ninstead of elm_segment_control_delete_segment()\n#####\n");
749 elm_segment_control_item_del(obj, item);
753 elm_segment_control_insert_segment_at(Evas_Object *obj, Evas_Object *icon,
754 const char *label, unsigned int index,
758 "#####\nWARNING: Use elm_segment_control_item_insert_at()\ninstead of elm_segment_control_insert_segment_at()\n#####\n");
759 elm_segment_control_item_insert_at(obj, icon, label, index);
762 EAPI Elm_Segment_Item *
763 elm_segment_control_add_segment(Evas_Object *obj, Evas_Object *icon,
764 const char *label, Eina_Bool animate)
767 "#####\nWARNING: Use elm_segment_control_item_add()\n instead of elm_segment_control_add_segment()\n#####\n");
768 return elm_segment_control_item_add(obj, icon, label);
772 elm_segment_control_item_label_object_set(Elm_Segment_Item *item, char *label)
775 "#####\nWARNING: Use elm_segment_control_item_label_set()\n instead of elm_segment_control_item_label_object_set()\n#####\n");
776 elm_segment_control_item_label_set(item, label);
778 /////////////////////////////////////////////////////////////////////////////////////////
779 /////////////////////////// OLD SLP APIs - TO BE DEPRECATED /////////////////////////////
780 /////////////////////////////////// END ////////////////////////////////////////////////