1 #include <Elementary.h>
4 typedef struct _Widget_Data Widget_Data;
5 typedef struct _Elm_Menu_Item Elm_Menu_Item;
10 Elm_Menu_Item *parent;
18 Evas_Object *hv, *bx, *location;
23 Eina_Bool separator : 1;
24 Eina_Bool selected : 1;
25 Eina_Bool object_item : 1;
30 Evas_Object *hv, *bx, *location, *parent, *obj;
32 Evas_Coord xloc, yloc;
35 static const char *widtype = NULL;
36 static void _del_hook(Evas_Object *obj);
37 static void _theme_hook(Evas_Object *obj);
38 static void _item_disable_set_hook(Elm_Object_Item *it);
39 static void _sizing_eval(Evas_Object *obj);
40 static void _submenu_sizing_eval(Elm_Menu_Item *parent);
41 static void _item_sizing_eval(Elm_Menu_Item *item);
42 static void _submenu_hide(Elm_Menu_Item *item);
43 static void _submenu_open(void *data, Evas_Object *obj, const char *emission, const char *source);
44 static void _parent_resize(void *data, Evas *e, Evas_Object *obj, void *event_info);
45 static void _parent_del(void *data, Evas *e, Evas_Object *obj, void *event_info);
46 static void _menu_hide(void *data, Evas_Object *obj, void *event_info);
48 static const char SIG_CLICKED[] = "clicked";
50 static const Evas_Smart_Cb_Description _signals[] = {
57 _del_item(Elm_Menu_Item *item)
61 elm_widget_item_pre_notify_del(item);
63 EINA_LIST_FREE(item->submenu.items, child)
66 if (item->label) eina_stringshare_del(item->label);
67 if (item->submenu.hv) evas_object_del(item->submenu.hv);
68 if (item->submenu.location) evas_object_del(item->submenu.location);
69 if (item->icon_str) eina_stringshare_del(item->icon_str);
70 elm_widget_item_del(item);
74 _del_pre_hook(Evas_Object *obj)
77 Widget_Data *wd = elm_widget_data_get(obj);
80 evas_object_event_callback_del_full(wd->parent, EVAS_CALLBACK_RESIZE, _parent_resize, obj);
81 evas_object_event_callback_del_full(wd->parent, EVAS_CALLBACK_DEL, _parent_del, wd);
83 EINA_LIST_FREE(wd->items, item)
86 if (wd->hv) evas_object_del(wd->hv);
87 if (wd->location) evas_object_del(wd->location);
91 _del_hook(Evas_Object *obj)
93 Widget_Data *wd = elm_widget_data_get(obj);
98 _theme_hook(Evas_Object *obj)
100 Eina_List *l, *_l, *_ll, *ll = NULL;
102 Widget_Data *wd = elm_widget_data_get(obj);
104 _elm_widget_mirrored_reload(obj);
105 ll = eina_list_append(ll, wd->items);
106 EINA_LIST_FOREACH(ll, _ll, l)
108 EINA_LIST_FOREACH(l, _l, item)
110 edje_object_mirrored_set(VIEW(item), elm_widget_mirrored_get(obj));
111 ll = eina_list_append(ll, item->submenu.items);
113 _elm_theme_object_set(obj, VIEW(item), "menu", "separator",
114 elm_widget_style_get(obj));
115 else if (item->submenu.bx)
117 _elm_theme_object_set
118 (obj, VIEW(item), "menu", "item_with_submenu",
119 elm_widget_style_get(obj));
120 elm_object_item_text_set((Elm_Object_Item *) item,
122 elm_menu_item_object_icon_name_set((Elm_Object_Item *) item,
127 _elm_theme_object_set(obj, VIEW(item), "menu", "item",
128 elm_widget_style_get(obj));
129 elm_object_item_text_set((Elm_Object_Item *) item,
131 elm_menu_item_object_icon_name_set((Elm_Object_Item *) item,
134 _item_disable_set_hook((Elm_Object_Item *) item);
135 edje_object_scale_set(VIEW(item), elm_widget_scale_get(obj) *
143 _item_text_set_hook(Elm_Object_Item *it,
147 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
150 if (part && strcmp(part, "default")) return;
152 item = (Elm_Menu_Item *) it;
154 eina_stringshare_replace(&item->label, label);
157 edje_object_signal_emit(VIEW(item), "elm,state,text,visible", "elm");
159 edje_object_signal_emit(VIEW(item), "elm,state,text,hidden", "elm");
161 edje_object_message_signal_process(VIEW(item));
162 edje_object_part_text_set(VIEW(item), "elm.text", label);
163 _sizing_eval(WIDGET(item));
167 _item_text_get_hook(const Elm_Object_Item *it, const char *part)
169 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
170 if (part && strcmp(part, "default")) return NULL;
171 return ((Elm_Menu_Item *) it)->label;
175 _item_content_set_hook(Elm_Object_Item *it,
177 Evas_Object *content)
179 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
182 if (part && strcmp(part, "default")) return;
184 item = (Elm_Menu_Item *) it;
188 elm_widget_sub_object_del(WIDGET(item), item->content);
189 evas_object_del(item->content);
192 item->content = content;
194 elm_widget_sub_object_add(WIDGET(item), item->content);
195 edje_object_part_swallow(VIEW(item), "elm.swallow.content", item->content);
196 _sizing_eval(WIDGET(item));
200 _item_content_get_hook(const Elm_Object_Item *it, const char *part)
202 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
203 if (part && strcmp(part, "default")) return NULL;
204 return ((Elm_Menu_Item *) it)->content;
208 _item_disable_set_hook(Elm_Object_Item *it)
210 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
211 Elm_Menu_Item *item = (Elm_Menu_Item *) it;
213 if (elm_widget_item_disabled_get(item))
215 edje_object_signal_emit(VIEW(item), "elm,state,disabled", "elm");
216 if (item->submenu.open) _submenu_hide(item);
219 edje_object_signal_emit(VIEW(item), "elm,state,enabled", "elm");
221 edje_object_message_signal_process(VIEW(item));
225 _sizing_eval(Evas_Object *obj)
229 Evas_Coord x_p, y_p, w_p, h_p, x2, y2, w2, h2, bx, by, bw, bh;
230 Widget_Data *wd = elm_widget_data_get(obj);
231 if ((!wd) || (!wd->parent)) return;
232 EINA_LIST_FOREACH(wd->items,l,item) _item_sizing_eval(item);
233 evas_object_geometry_get(wd->location, &x_p, &y_p, &w_p, &h_p);
234 evas_object_geometry_get(wd->parent, &x2, &y2, &w2, &h2);
235 evas_object_geometry_get(wd->bx, &bx, &by, &bw, &bh);
240 if (elm_widget_mirrored_get(obj))
243 if (x_p+bw > x2+w2) x_p -= x_p+bw - (x2+w2);
244 if (x_p < x2) x_p += x2 - x_p;
246 if (y_p+h_p+bh > y2+h2) y_p -= y_p+h_p+bh - (y2+h2);
247 if (y_p < y2) y_p += y2 - y_p;
250 evas_object_move(wd->location, x_p, y_p);
251 evas_object_resize(wd->location, bw, h_p);
252 evas_object_size_hint_min_set(wd->location, bw, h_p);
253 evas_object_size_hint_max_set(wd->location, bw, h_p);
254 elm_hover_target_set(wd->hv, wd->location);
256 EINA_LIST_FOREACH(wd->items,l,item)
258 if (item->submenu.open) _submenu_sizing_eval(item);
263 _submenu_sizing_eval(Elm_Menu_Item *parent)
267 Evas_Coord x_p, y_p, w_p, h_p, x2, y2, w2, h2, bx, by, bw, bh, px, py, pw, ph;
268 Widget_Data *wd = elm_widget_data_get(WIDGET(parent));
270 EINA_LIST_FOREACH(parent->submenu.items, l, item) _item_sizing_eval(item);
271 evas_object_geometry_get(parent->submenu.location, &x_p, &y_p, &w_p, &h_p);
272 evas_object_geometry_get(VIEW(parent), &x2, &y2, &w2, &h2);
273 evas_object_geometry_get(parent->submenu.bx, &bx, &by, &bw, &bh);
274 evas_object_geometry_get(wd->parent, &px, &py, &pw, &ph);
279 /* If it overflows on the right, adjust the x */
280 if ((x_p + bw > px + pw) || elm_widget_mirrored_get(WIDGET(parent)))
283 /* If it overflows on the left, adjust the x - usually only happens
284 * with an RTL interface */
288 /* If after all the adjustments it still overflows, fix it */
289 if (x_p + bw > px + pw)
293 y_p -= y_p+bh - (py+ph);
297 evas_object_move(parent->submenu.location, x_p, y_p);
298 evas_object_resize(parent->submenu.location, bw, h_p);
299 evas_object_size_hint_min_set(parent->submenu.location, bw, h_p);
300 evas_object_size_hint_max_set(parent->submenu.location, bw, h_p);
301 elm_hover_target_set(parent->submenu.hv, parent->submenu.location);
303 EINA_LIST_FOREACH(parent->submenu.items, l, item)
305 if (item->submenu.open)
306 _submenu_sizing_eval(item);
311 _item_sizing_eval(Elm_Menu_Item *item)
313 Evas_Coord minw = -1, minh = -1, maxw = -1, maxh = -1;
314 if (!item->separator)
315 elm_coords_finger_size_adjust(1, &minw, 1, &minh);
316 edje_object_size_min_restricted_calc(VIEW(item), &minw, &minh, minw, minh);
317 if (!item->separator)
318 elm_coords_finger_size_adjust(1, &minw, 1, &minh);
319 evas_object_size_hint_min_set(VIEW(item), minw, minh);
320 evas_object_size_hint_max_set(VIEW(item), maxw, maxh);
324 _menu_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
330 _parent_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
336 _parent_del(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
338 Widget_Data *wd = data;
339 evas_object_event_callback_del_full(obj, EVAS_CALLBACK_RESIZE, _parent_resize, wd->obj);
344 _item_move_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
346 Elm_Menu_Item *item = data;
347 if (item->submenu.open) _submenu_sizing_eval(item);
351 _hover_clicked_cb(void *data, Evas_Object *obj, void *event_info)
353 _menu_hide(data, obj, event_info);
354 evas_object_smart_callback_call(data, SIG_CLICKED, NULL);
358 _menu_hide(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
361 Elm_Menu_Item *item2;
362 Widget_Data *wd = elm_widget_data_get(data);
364 evas_object_hide(wd->hv);
365 evas_object_hide(data);
367 EINA_LIST_FOREACH(wd->items, l, item2)
369 if (item2->submenu.open) _submenu_hide(item2);
374 _submenu_hide(Elm_Menu_Item *item)
377 Elm_Menu_Item *item2;
378 evas_object_hide(item->submenu.hv);
379 item->submenu.open = EINA_FALSE;
380 EINA_LIST_FOREACH(item->submenu.items, l, item2)
382 if (item2->submenu.open) _submenu_hide(item2);
387 _menu_item_select(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
389 Elm_Menu_Item *item = data;
390 if (item->submenu.items)
392 if (!item->submenu.open) _submenu_open(item, NULL, NULL, NULL);
393 else _submenu_hide(item);
396 _menu_hide(WIDGET(item), NULL, NULL);
398 if (item->func) item->func((void *)(item->base.data), WIDGET(item), item);
402 _menu_item_activate(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
405 Elm_Menu_Item *item2;
406 Elm_Menu_Item *item = data;
410 EINA_LIST_FOREACH(item->parent->submenu.items, l, item2)
413 elm_menu_item_selected_set((Elm_Object_Item *) item2, 0);
418 Widget_Data *wd = elm_widget_data_get(WIDGET(item));
419 EINA_LIST_FOREACH(wd->items, l, item2)
422 elm_menu_item_selected_set((Elm_Object_Item *) item2, 0);
428 _menu_item_inactivate(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
430 Elm_Menu_Item *item = data;
432 if (item->submenu.open) _submenu_hide(item);
436 _submenu_open(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
438 Elm_Menu_Item *item = data;
439 item->submenu.open = EINA_TRUE;
440 evas_object_show(item->submenu.hv);
441 _sizing_eval(WIDGET(item));
445 _show(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
447 Widget_Data *wd = elm_widget_data_get(data);
449 evas_object_show(wd->hv);
453 _item_obj_create(Elm_Menu_Item *item)
455 Widget_Data *wd = elm_widget_data_get(WIDGET(item));
457 VIEW(item) = edje_object_add(evas_object_evas_get(wd->bx));
458 edje_object_mirrored_set(VIEW(item), elm_widget_mirrored_get(WIDGET(item)));
459 evas_object_size_hint_weight_set(VIEW(item), EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
460 evas_object_size_hint_fill_set(VIEW(item), EVAS_HINT_FILL, EVAS_HINT_FILL);
461 _elm_theme_object_set(WIDGET(item), VIEW(item), "menu", "item", elm_widget_style_get(WIDGET(item)));
462 edje_object_signal_callback_add(VIEW(item), "elm,action,click", "",
463 _menu_item_select, item);
464 edje_object_signal_callback_add(VIEW(item), "elm,action,activate", "",
465 _menu_item_activate, item);
466 edje_object_signal_callback_add(VIEW(item), "elm,action,inactivate", "",
467 _menu_item_inactivate, item);
468 evas_object_show(VIEW(item));
472 _item_separator_obj_create(Elm_Menu_Item *item)
474 Widget_Data *wd = elm_widget_data_get(WIDGET(item));
476 VIEW(item) = edje_object_add(evas_object_evas_get(wd->bx));
477 evas_object_size_hint_weight_set(VIEW(item), EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
478 evas_object_size_hint_fill_set(VIEW(item), EVAS_HINT_FILL, EVAS_HINT_FILL);
479 _elm_theme_object_set(WIDGET(item), VIEW(item), "menu", "separator", elm_widget_style_get(WIDGET(item)));
480 edje_object_signal_callback_add(VIEW(item), "elm,action,activate", "",
481 _menu_item_activate, item);
482 evas_object_show(VIEW(item));
486 _item_submenu_obj_create(Elm_Menu_Item *item)
488 Widget_Data *wd = elm_widget_data_get(WIDGET(item));
490 item->submenu.location = elm_icon_add(wd->bx);
491 item->submenu.hv = elm_hover_add(wd->bx);
492 elm_widget_mirrored_set(item->submenu.hv, EINA_FALSE);
493 elm_hover_target_set(item->submenu.hv, item->submenu.location);
494 elm_hover_parent_set(item->submenu.hv, wd->parent);
495 elm_object_style_set(item->submenu.hv, "submenu");
497 item->submenu.bx = elm_box_add(wd->bx);
498 elm_widget_mirrored_set(item->submenu.bx, EINA_FALSE);
499 evas_object_size_hint_weight_set(item->submenu.bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
500 evas_object_show(item->submenu.bx);
501 elm_hover_content_set(item->submenu.hv, elm_hover_best_content_location_get(item->submenu.hv, ELM_HOVER_AXIS_VERTICAL), item->submenu.bx);
503 edje_object_mirrored_set(VIEW(item), elm_widget_mirrored_get(WIDGET(item)));
504 _elm_theme_object_set(WIDGET(item), VIEW(item), "menu", "item_with_submenu", elm_widget_style_get(WIDGET(item)));
505 elm_object_item_text_set((Elm_Object_Item *) item,
508 elm_menu_item_object_icon_name_set((Elm_Object_Item *) item,
510 edje_object_signal_callback_add(VIEW(item), "elm,action,open", "",
511 _submenu_open, item);
512 evas_object_event_callback_add(VIEW(item), EVAS_CALLBACK_MOVE, _item_move_resize, item);
513 evas_object_event_callback_add(VIEW(item), EVAS_CALLBACK_RESIZE, _item_move_resize, item);
515 evas_object_event_callback_add(item->submenu.bx, EVAS_CALLBACK_RESIZE, _menu_resize, WIDGET(item));
519 elm_menu_add(Evas_Object *parent)
525 ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
527 ELM_SET_WIDTYPE(widtype, "menu");
528 elm_widget_type_set(obj, "menu");
529 elm_widget_sub_object_add(parent, obj);
530 elm_widget_data_set(obj, wd);
531 elm_widget_del_pre_hook_set(obj, _del_pre_hook);
532 elm_widget_del_hook_set(obj, _del_hook);
533 elm_widget_theme_hook_set(obj, _theme_hook);
534 elm_widget_can_focus_set(obj, EINA_FALSE);
536 wd->location = elm_icon_add(obj);
540 wd->hv = elm_hover_add(obj);
541 elm_widget_mirrored_set(wd->hv, EINA_FALSE);
542 elm_hover_parent_set(wd->hv, parent);
543 elm_hover_target_set(wd->hv, wd->location);
544 elm_object_style_set(wd->hv, "menu");
545 evas_object_smart_callback_add(wd->hv, "clicked", _hover_clicked_cb, obj);
547 wd->bx = elm_box_add(obj);
548 elm_widget_mirrored_set(wd->bx, EINA_FALSE);
549 evas_object_size_hint_weight_set(wd->bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
550 evas_object_show(wd->bx);
551 elm_hover_content_set(wd->hv, elm_hover_best_content_location_get(wd->hv, ELM_HOVER_AXIS_VERTICAL), wd->bx);
553 evas_object_event_callback_add(wd->parent, EVAS_CALLBACK_RESIZE, _parent_resize, wd->obj);
554 evas_object_event_callback_add(wd->parent, EVAS_CALLBACK_DEL, _parent_del, wd);
556 evas_object_event_callback_add(obj, EVAS_CALLBACK_SHOW, _show, obj);
558 evas_object_event_callback_add(wd->bx, EVAS_CALLBACK_RESIZE, _menu_resize, obj);
560 evas_object_smart_callbacks_descriptions_set(obj, _signals);
567 elm_menu_parent_set(Evas_Object *obj, Evas_Object *parent)
569 Eina_List *l, *_l, *_ll, *ll = NULL;
571 ELM_CHECK_WIDTYPE(obj, widtype);
572 Widget_Data *wd = elm_widget_data_get(obj);
575 if (wd->parent == parent) return;
578 evas_object_event_callback_del_full(wd->parent, EVAS_CALLBACK_RESIZE, _parent_resize, wd->obj);
579 evas_object_event_callback_del_full(wd->parent, EVAS_CALLBACK_DEL, _parent_del, wd);
584 evas_object_event_callback_add(wd->parent, EVAS_CALLBACK_RESIZE, _parent_resize, wd->obj);
585 evas_object_event_callback_add(wd->parent, EVAS_CALLBACK_DEL, _parent_del, wd);
587 elm_hover_parent_set(wd->hv, parent);
589 ll = eina_list_append(ll, wd->items);
590 EINA_LIST_FOREACH(ll, _ll, l)
592 EINA_LIST_FOREACH(l, _l, item)
594 if (item->submenu.hv)
596 elm_hover_parent_set(item->submenu.hv, parent);
597 ll = eina_list_append(ll, item->submenu.items);
605 elm_menu_parent_get(const Evas_Object *obj)
607 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
608 Widget_Data *wd = elm_widget_data_get(obj);
609 if (!wd) return NULL;
614 elm_menu_move(Evas_Object *obj, Evas_Coord x, Evas_Coord y)
616 ELM_CHECK_WIDTYPE(obj, widtype);
617 Widget_Data *wd = elm_widget_data_get(obj);
625 elm_menu_close(Evas_Object *obj)
627 ELM_CHECK_WIDTYPE(obj, widtype);
628 Widget_Data *wd = elm_widget_data_get(obj);
629 _menu_hide(obj, wd->hv, NULL);
633 elm_menu_item_object_get(const Elm_Object_Item *it)
635 return VIEW(((Elm_Menu_Item *) it));
639 _item_clone(Evas_Object *obj, Elm_Menu_Item *parent, Elm_Menu_Item *item)
641 Elm_Object_Item *new_item;
642 Elm_Menu_Item *subitem;
646 new_item = elm_menu_item_separator_add(obj, (Elm_Object_Item *) parent);
648 new_item = elm_menu_item_add(obj,
649 (Elm_Object_Item *) parent,
654 elm_object_item_disabled_set(new_item,
655 elm_widget_item_disabled_get(item));
657 EINA_LIST_FOREACH(item->submenu.items, iter, subitem)
658 _item_clone(obj, (Elm_Menu_Item *) new_item, subitem);
662 elm_menu_clone(Evas_Object *from_menu, Evas_Object *to_menu, Elm_Object_Item *parent)
664 ELM_CHECK_WIDTYPE(from_menu, widtype);
665 ELM_CHECK_WIDTYPE(to_menu, widtype);
666 Widget_Data *from_wd = elm_widget_data_get(from_menu);
670 if (!from_wd) return;
671 EINA_LIST_FOREACH(from_wd->items, iter, item)
672 _item_clone(to_menu, (Elm_Menu_Item *) parent, item);
676 _elm_menu_item_add_helper(Evas_Object *obj, Elm_Menu_Item *parent, Elm_Menu_Item *subitem, Widget_Data *wd)
680 if (!parent->submenu.bx) _item_submenu_obj_create(parent);
681 elm_box_pack_end(parent->submenu.bx, VIEW(subitem));
682 parent->submenu.items = eina_list_append(parent->submenu.items, subitem);
683 subitem->idx = eina_list_count(parent->submenu.items) - 1;
687 elm_box_pack_end(wd->bx, VIEW(subitem));
688 wd->items = eina_list_append(wd->items, subitem);
689 subitem->idx = eina_list_count(wd->items) - 1;
695 EAPI Elm_Object_Item *
696 elm_menu_item_add(Evas_Object *obj, Elm_Object_Item *parent, const char *icon, const char *label, Evas_Smart_Cb func, const void *data)
698 Elm_Menu_Item *subitem;
699 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
700 Widget_Data *wd = elm_widget_data_get(obj);
701 Evas_Object *icon_obj;
703 if (!wd) return NULL;
704 icon_obj = elm_icon_add(obj);
705 if (!icon_obj) return NULL;
706 subitem = elm_widget_item_new(obj, Elm_Menu_Item);
709 evas_object_del(icon_obj);
713 elm_widget_item_disable_set_hook_set(subitem, _item_disable_set_hook);
714 elm_widget_item_text_set_hook_set(subitem, _item_text_set_hook);
715 elm_widget_item_text_get_hook_set(subitem, _item_text_get_hook);
716 elm_widget_item_content_set_hook_set(subitem, _item_content_set_hook);
717 elm_widget_item_content_get_hook_set(subitem, _item_content_get_hook);
719 subitem->base.data = data;
720 subitem->func = func;
721 subitem->parent = (Elm_Menu_Item *) parent;
722 subitem->content = icon_obj;
724 _item_obj_create(subitem);
725 elm_object_item_text_set((Elm_Object_Item *) subitem, label);
727 elm_widget_sub_object_add(WIDGET(subitem), subitem->content);
728 edje_object_part_swallow(VIEW(subitem), "elm.swallow.content", subitem->content);
730 elm_menu_item_object_icon_name_set((Elm_Object_Item *) subitem, icon);
732 _elm_menu_item_add_helper(obj, (Elm_Menu_Item *) parent, subitem, wd);
734 return (Elm_Object_Item *) subitem;
737 EAPI Elm_Object_Item *
738 elm_menu_item_add_object(Evas_Object *obj, Elm_Object_Item *parent, Evas_Object *subobj, Evas_Smart_Cb func, const void *data)
740 Elm_Menu_Item *subitem;
741 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
742 Widget_Data *wd = elm_widget_data_get(obj);
744 if (!wd) return NULL;
745 subitem = elm_widget_item_new(obj, Elm_Menu_Item);
746 if (!subitem) return NULL;
748 elm_widget_item_disable_set_hook_set(subitem, _item_disable_set_hook);
749 elm_widget_item_text_set_hook_set(subitem, _item_text_set_hook);
750 elm_widget_item_text_get_hook_set(subitem, _item_text_get_hook);
751 elm_widget_item_content_set_hook_set(subitem, _item_content_set_hook);
752 elm_widget_item_content_get_hook_set(subitem, _item_content_get_hook);
754 subitem->base.data = data;
755 subitem->func = func;
756 subitem->parent = (Elm_Menu_Item *) parent;
757 subitem->object_item = EINA_TRUE;
758 subitem->content = subobj;
760 _item_obj_create(subitem);
762 elm_widget_sub_object_add(WIDGET(subitem), subitem->content);
763 edje_object_part_swallow(VIEW(subitem), "elm.swallow.content", subobj);
764 _sizing_eval(WIDGET(subitem));
766 _elm_menu_item_add_helper(obj, (Elm_Menu_Item *) parent, subitem, wd);
768 return (Elm_Object_Item *) subitem;
772 elm_menu_item_index_get(const Elm_Object_Item *it)
774 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, 0);
775 return ((Elm_Menu_Item *) it)->idx;
779 elm_menu_item_label_set(Elm_Object_Item *it, const char *label)
781 _item_text_set_hook(it, NULL, label);
785 elm_menu_item_label_get(const Elm_Object_Item *it)
787 return _item_text_get_hook(it, NULL);
791 elm_menu_item_object_icon_name_set(Elm_Object_Item *it, const char *icon)
793 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
794 EINA_SAFETY_ON_NULL_RETURN(icon);
796 Elm_Menu_Item *item = (Elm_Menu_Item *) it;
799 if ((item->icon_str) && (!strcmp(item->icon_str, icon))) return;
800 if ((snprintf(icon_tmp, sizeof(icon_tmp), "menu/%s", icon) > 0) &&
801 (elm_icon_standard_set(item->content, icon_tmp) ||
802 elm_icon_standard_set(item->content, icon)))
804 eina_stringshare_replace(&item->icon_str, icon);
805 edje_object_signal_emit(VIEW(item), "elm,state,icon,visible", "elm");
808 edje_object_signal_emit(VIEW(item), "elm,state,icon,hidden", "elm");
809 edje_object_message_signal_process(VIEW(item));
810 _sizing_eval(WIDGET(item));
814 elm_menu_item_disabled_set(Elm_Object_Item *it, Eina_Bool disabled)
816 elm_object_item_disabled_set(it, disabled);
820 elm_menu_item_disabled_get(const Elm_Object_Item *it)
822 return elm_object_item_disabled_get(it);
825 EAPI Elm_Object_Item *
826 elm_menu_item_separator_add(Evas_Object *obj, Elm_Object_Item *parent)
828 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
829 Elm_Menu_Item *subitem;
830 Widget_Data *wd = elm_widget_data_get(obj);
831 Elm_Menu_Item *p_item = (Elm_Menu_Item *) parent;
832 if (!wd) return NULL;
833 /* don't add a separator as the first item */
834 if (!wd->items) return NULL;
835 /* don't allow adding more than one separator in a row */
836 if (p_item) subitem = eina_list_last(p_item->submenu.items)->data;
837 else subitem = eina_list_last(wd->items)->data;
838 if (subitem->separator) return NULL;
840 subitem = elm_widget_item_new(obj, Elm_Menu_Item);
841 if (!subitem) return NULL;
843 elm_widget_item_disable_set_hook_set(subitem, _item_disable_set_hook);
844 elm_widget_item_text_set_hook_set(subitem, _item_text_set_hook);
845 elm_widget_item_text_get_hook_set(subitem, _item_text_get_hook);
846 elm_widget_item_content_set_hook_set(subitem, _item_content_set_hook);
847 elm_widget_item_content_get_hook_set(subitem, _item_content_get_hook);
849 subitem->separator = EINA_TRUE;
850 _item_separator_obj_create(subitem);
853 elm_box_pack_end(wd->bx, VIEW(subitem));
854 wd->items = eina_list_append(wd->items, subitem);
858 if (!p_item->submenu.bx) _item_submenu_obj_create(p_item);
859 elm_box_pack_end(p_item->submenu.bx, VIEW(subitem));
860 p_item->submenu.items = eina_list_append(p_item->submenu.items,
864 return (Elm_Object_Item *) subitem;
868 elm_menu_item_object_content_set(Elm_Object_Item *it, Evas_Object *obj)
870 _item_content_set_hook(it, NULL, obj);
875 elm_menu_item_object_content_get(const Elm_Object_Item *it)
877 return _item_content_get_hook(it, NULL);
881 elm_menu_item_object_icon_name_get(const Elm_Object_Item *it)
883 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
884 return ((Elm_Menu_Item *) it)->icon_str;
888 elm_menu_item_is_separator(Elm_Object_Item *it)
890 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
891 return ((Elm_Menu_Item *) it)->separator;
895 elm_menu_item_del(Elm_Object_Item *it)
897 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
898 Elm_Menu_Item *item = (Elm_Menu_Item *) it;
899 Elm_Object_Item *_item;
901 elm_widget_item_pre_notify_del(item);
903 EINA_LIST_FREE(item->submenu.items, _item) elm_menu_item_del(_item);
904 if (item->label) eina_stringshare_del(item->label);
905 if (item->content) evas_object_del(item->content);
906 if (item->submenu.hv) evas_object_del(item->submenu.hv);
907 if (item->submenu.location) evas_object_del(item->submenu.location);
910 item->parent->submenu.items = eina_list_remove(item->parent->submenu.items, item);
913 Widget_Data *wd = elm_widget_data_get(WIDGET(item));
914 wd->items = eina_list_remove(wd->items, item);
917 elm_widget_item_del(item);
921 elm_menu_item_del_cb_set(Elm_Object_Item *it, Evas_Smart_Cb func)
923 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
924 elm_widget_item_del_cb_set(it, func);
928 elm_menu_item_data_get(const Elm_Object_Item *it)
930 return elm_object_item_data_get(it);
934 elm_menu_item_data_set(Elm_Object_Item *it, const void *data)
936 elm_object_item_data_set(it, (void *) data);
939 EAPI const Eina_List *
940 elm_menu_item_subitems_get(const Elm_Object_Item *it)
942 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
943 return ((Elm_Menu_Item *) it)->submenu.items;
946 EAPI const Eina_List *
947 elm_menu_items_get(const Evas_Object * obj)
949 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
950 Widget_Data *wd = elm_widget_data_get(obj);
955 elm_menu_item_selected_set(Elm_Object_Item *it, Eina_Bool selected)
957 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
958 Elm_Menu_Item *item = (Elm_Menu_Item *) it;
960 if (selected == item->selected) return;
961 item->selected = selected;
964 edje_object_signal_emit(VIEW(item), "elm,state,selected", "elm");
965 _menu_item_activate(item, NULL, NULL, NULL);
969 edje_object_signal_emit(VIEW(item), "elm,state,unselected", "elm");
970 _menu_item_inactivate(item, NULL, NULL, NULL);
972 edje_object_message_signal_process(VIEW(item));
976 elm_menu_item_selected_get(const Elm_Object_Item *it)
978 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
979 return ((Elm_Menu_Item *) it)->selected;
982 EAPI Elm_Object_Item *
983 elm_menu_item_prev_get(const Elm_Object_Item *it)
985 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
986 Elm_Menu_Item *item = (Elm_Menu_Item *) it;
990 Eina_List *l = eina_list_data_find_list(item->parent->submenu.items,
992 l = eina_list_prev(l);
998 Widget_Data *wd = elm_widget_data_get(WIDGET(item));
999 if (!wd || !wd->items) return NULL;
1000 Eina_List *l = eina_list_data_find_list(wd->items, item);
1001 l = eina_list_prev(l);
1002 if (!l) return NULL;
1008 EAPI Elm_Object_Item *
1009 elm_menu_item_next_get(const Elm_Object_Item *it)
1011 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
1012 Elm_Menu_Item *item = (Elm_Menu_Item *) it;
1016 Eina_List *l = eina_list_data_find_list(item->parent->submenu.items,
1018 l = eina_list_next(l);
1019 if (!l) return NULL;
1024 Widget_Data *wd = elm_widget_data_get(WIDGET(item));
1025 if (!wd || !wd->items) return NULL;
1026 Eina_List *l = eina_list_data_find_list(wd->items, item);
1027 l = eina_list_next(l);
1028 if (!l) return NULL;
1035 elm_menu_item_menu_get(const Elm_Object_Item *it)
1037 return elm_object_item_object_get(it);
1040 EAPI Elm_Object_Item *
1041 elm_menu_first_item_get(const Evas_Object * obj)
1043 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1044 Widget_Data *wd = elm_widget_data_get(obj);
1045 if (!wd) return NULL;
1046 if (wd->items) return wd->items->data;
1050 EAPI Elm_Object_Item *
1051 elm_menu_last_item_get(const Evas_Object * obj)
1053 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1054 Widget_Data *wd = elm_widget_data_get(obj);
1055 if (!wd) return NULL;
1056 Eina_List *l = eina_list_last(wd->items);
1057 if (l) return l->data;
1061 EAPI Elm_Object_Item *
1062 elm_menu_selected_item_get(const Evas_Object * obj)
1064 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1065 Widget_Data *wd = elm_widget_data_get(obj);
1066 if (!wd) return NULL;
1068 Elm_Menu_Item *item;
1069 EINA_LIST_FOREACH(wd->items, l, item)
1071 if (item->selected) return ((Elm_Object_Item *) item);