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_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 EINA_LIST_FREE(item->submenu.items, child)
64 if (item->label) eina_stringshare_del(item->label);
65 if (item->submenu.hv) evas_object_del(item->submenu.hv);
66 if (item->submenu.location) evas_object_del(item->submenu.location);
67 if (item->icon_str) eina_stringshare_del(item->icon_str);
68 elm_widget_item_free(item);
72 _del_pre_hook(Evas_Object *obj)
75 Widget_Data *wd = elm_widget_data_get(obj);
78 evas_object_event_callback_del_full(wd->parent, EVAS_CALLBACK_RESIZE, _parent_resize, obj);
79 evas_object_event_callback_del_full(wd->parent, EVAS_CALLBACK_DEL, _parent_del, wd);
81 EINA_LIST_FREE(wd->items, item)
84 if (wd->hv) evas_object_del(wd->hv);
85 if (wd->location) evas_object_del(wd->location);
89 _del_hook(Evas_Object *obj)
91 Widget_Data *wd = elm_widget_data_get(obj);
96 _theme_hook(Evas_Object *obj)
98 Eina_List *l, *_l, *_ll, *ll = NULL;
100 Widget_Data *wd = elm_widget_data_get(obj);
102 _elm_widget_mirrored_reload(obj);
103 ll = eina_list_append(ll, wd->items);
104 EINA_LIST_FOREACH(ll, _ll, l)
106 EINA_LIST_FOREACH(l, _l, item)
108 edje_object_mirrored_set(VIEW(item), elm_widget_mirrored_get(obj));
109 ll = eina_list_append(ll, item->submenu.items);
111 _elm_theme_object_set(obj, VIEW(item), "menu", "separator",
112 elm_widget_style_get(obj));
113 else if (item->submenu.bx)
115 _elm_theme_object_set
116 (obj, VIEW(item), "menu", "item_with_submenu",
117 elm_widget_style_get(obj));
118 elm_object_item_text_set((Elm_Object_Item *) item,
120 elm_menu_item_object_icon_name_set((Elm_Object_Item *) item,
125 _elm_theme_object_set(obj, VIEW(item), "menu", "item",
126 elm_widget_style_get(obj));
127 elm_object_item_text_set((Elm_Object_Item *) item,
129 elm_menu_item_object_icon_name_set((Elm_Object_Item *) item,
132 _item_disable_hook((Elm_Object_Item *) item);
133 edje_object_scale_set(VIEW(item), elm_widget_scale_get(obj) *
141 _item_text_set_hook(Elm_Object_Item *it,
145 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
148 if (part && strcmp(part, "default")) return;
150 item = (Elm_Menu_Item *) it;
152 eina_stringshare_replace(&item->label, label);
155 edje_object_signal_emit(VIEW(item), "elm,state,text,visible", "elm");
157 edje_object_signal_emit(VIEW(item), "elm,state,text,hidden", "elm");
159 edje_object_message_signal_process(VIEW(item));
160 edje_object_part_text_set(VIEW(item), "elm.text", label);
161 _sizing_eval(WIDGET(item));
165 _item_text_get_hook(const Elm_Object_Item *it, const char *part)
167 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
168 if (part && strcmp(part, "default")) return NULL;
169 return ((Elm_Menu_Item *) it)->label;
173 _item_content_set_hook(Elm_Object_Item *it,
175 Evas_Object *content)
177 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
180 if (part && strcmp(part, "default")) return;
182 item = (Elm_Menu_Item *) it;
186 elm_widget_sub_object_del(WIDGET(item), item->content);
187 evas_object_del(item->content);
190 item->content = content;
192 elm_widget_sub_object_add(WIDGET(item), item->content);
193 edje_object_part_swallow(VIEW(item), "elm.swallow.content", item->content);
194 _sizing_eval(WIDGET(item));
198 _item_content_get_hook(const Elm_Object_Item *it, const char *part)
200 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
201 if (part && strcmp(part, "default")) return NULL;
202 return ((Elm_Menu_Item *) it)->content;
206 _item_disable_hook(Elm_Object_Item *it)
208 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
209 Elm_Menu_Item *item = (Elm_Menu_Item *) it;
211 if (elm_widget_item_disabled_get(item))
213 edje_object_signal_emit(VIEW(item), "elm,state,disabled", "elm");
214 if (item->submenu.open) _submenu_hide(item);
217 edje_object_signal_emit(VIEW(item), "elm,state,enabled", "elm");
219 edje_object_message_signal_process(VIEW(item));
223 _sizing_eval(Evas_Object *obj)
227 Evas_Coord x_p, y_p, w_p, h_p, x2, y2, w2, h2, bx, by, bw, bh;
228 Widget_Data *wd = elm_widget_data_get(obj);
229 if ((!wd) || (!wd->parent)) return;
230 EINA_LIST_FOREACH(wd->items,l,item) _item_sizing_eval(item);
231 evas_object_geometry_get(wd->location, &x_p, &y_p, &w_p, &h_p);
232 evas_object_geometry_get(wd->parent, &x2, &y2, &w2, &h2);
233 evas_object_geometry_get(wd->bx, &bx, &by, &bw, &bh);
238 if (elm_widget_mirrored_get(obj))
241 if (x_p+bw > x2+w2) x_p -= x_p+bw - (x2+w2);
242 if (x_p < x2) x_p += x2 - x_p;
244 if (y_p+h_p+bh > y2+h2) y_p -= y_p+h_p+bh - (y2+h2);
245 if (y_p < y2) y_p += y2 - y_p;
248 evas_object_move(wd->location, x_p, y_p);
249 evas_object_resize(wd->location, bw, h_p);
250 evas_object_size_hint_min_set(wd->location, bw, h_p);
251 evas_object_size_hint_max_set(wd->location, bw, h_p);
252 elm_hover_target_set(wd->hv, wd->location);
254 EINA_LIST_FOREACH(wd->items,l,item)
256 if (item->submenu.open) _submenu_sizing_eval(item);
261 _submenu_sizing_eval(Elm_Menu_Item *parent)
265 Evas_Coord x_p, y_p, w_p, h_p, x2, y2, w2, h2, bx, by, bw, bh, px, py, pw, ph;
266 Widget_Data *wd = elm_widget_data_get(WIDGET(parent));
268 EINA_LIST_FOREACH(parent->submenu.items, l, item) _item_sizing_eval(item);
269 evas_object_geometry_get(parent->submenu.location, &x_p, &y_p, &w_p, &h_p);
270 evas_object_geometry_get(VIEW(parent), &x2, &y2, &w2, &h2);
271 evas_object_geometry_get(parent->submenu.bx, &bx, &by, &bw, &bh);
272 evas_object_geometry_get(wd->parent, &px, &py, &pw, &ph);
277 /* If it overflows on the right, adjust the x */
278 if ((x_p + bw > px + pw) || elm_widget_mirrored_get(WIDGET(parent)))
281 /* If it overflows on the left, adjust the x - usually only happens
282 * with an RTL interface */
286 /* If after all the adjustments it still overflows, fix it */
287 if (x_p + bw > px + pw)
291 y_p -= y_p+bh - (py+ph);
295 evas_object_move(parent->submenu.location, x_p, y_p);
296 evas_object_resize(parent->submenu.location, bw, h_p);
297 evas_object_size_hint_min_set(parent->submenu.location, bw, h_p);
298 evas_object_size_hint_max_set(parent->submenu.location, bw, h_p);
299 elm_hover_target_set(parent->submenu.hv, parent->submenu.location);
301 EINA_LIST_FOREACH(parent->submenu.items, l, item)
303 if (item->submenu.open)
304 _submenu_sizing_eval(item);
309 _item_sizing_eval(Elm_Menu_Item *item)
311 Evas_Coord minw = -1, minh = -1, maxw = -1, maxh = -1;
312 if (!item->separator)
313 elm_coords_finger_size_adjust(1, &minw, 1, &minh);
314 edje_object_size_min_restricted_calc(VIEW(item), &minw, &minh, minw, minh);
315 if (!item->separator)
316 elm_coords_finger_size_adjust(1, &minw, 1, &minh);
317 evas_object_size_hint_min_set(VIEW(item), minw, minh);
318 evas_object_size_hint_max_set(VIEW(item), maxw, maxh);
322 _menu_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
328 _parent_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
334 _parent_del(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
336 Widget_Data *wd = data;
337 evas_object_event_callback_del_full(obj, EVAS_CALLBACK_RESIZE, _parent_resize, wd->obj);
342 _item_move_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
344 Elm_Menu_Item *item = data;
345 if (item->submenu.open) _submenu_sizing_eval(item);
349 _hover_clicked_cb(void *data, Evas_Object *obj, void *event_info)
351 _menu_hide(data, obj, event_info);
352 evas_object_smart_callback_call(data, SIG_CLICKED, NULL);
356 _menu_hide(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
359 Elm_Menu_Item *item2;
360 Widget_Data *wd = elm_widget_data_get(data);
362 evas_object_hide(wd->hv);
363 evas_object_hide(data);
365 EINA_LIST_FOREACH(wd->items, l, item2)
367 if (item2->submenu.open) _submenu_hide(item2);
372 _submenu_hide(Elm_Menu_Item *item)
375 Elm_Menu_Item *item2;
376 evas_object_hide(item->submenu.hv);
377 item->submenu.open = EINA_FALSE;
378 EINA_LIST_FOREACH(item->submenu.items, l, item2)
380 if (item2->submenu.open) _submenu_hide(item2);
385 _menu_item_select(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
387 Elm_Menu_Item *item = data;
388 if (item->submenu.items)
390 if (!item->submenu.open) _submenu_open(item, NULL, NULL, NULL);
391 else _submenu_hide(item);
394 _menu_hide(WIDGET(item), NULL, NULL);
396 if (item->func) item->func((void *)(item->base.data), WIDGET(item), item);
400 _menu_item_activate(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
403 Elm_Menu_Item *item2;
404 Elm_Menu_Item *item = data;
408 EINA_LIST_FOREACH(item->parent->submenu.items, l, item2)
411 elm_menu_item_selected_set((Elm_Object_Item *) item2, 0);
416 Widget_Data *wd = elm_widget_data_get(WIDGET(item));
417 EINA_LIST_FOREACH(wd->items, l, item2)
420 elm_menu_item_selected_set((Elm_Object_Item *) item2, 0);
426 _menu_item_inactivate(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
428 Elm_Menu_Item *item = data;
430 if (item->submenu.open) _submenu_hide(item);
434 _submenu_open(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
436 Elm_Menu_Item *item = data;
437 item->submenu.open = EINA_TRUE;
438 evas_object_show(item->submenu.hv);
439 _sizing_eval(WIDGET(item));
443 _show(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
445 Widget_Data *wd = elm_widget_data_get(data);
447 evas_object_show(wd->hv);
451 _item_obj_create(Elm_Menu_Item *item)
453 Widget_Data *wd = elm_widget_data_get(WIDGET(item));
455 VIEW(item) = edje_object_add(evas_object_evas_get(wd->bx));
456 edje_object_mirrored_set(VIEW(item), elm_widget_mirrored_get(WIDGET(item)));
457 evas_object_size_hint_weight_set(VIEW(item), EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
458 evas_object_size_hint_fill_set(VIEW(item), EVAS_HINT_FILL, EVAS_HINT_FILL);
459 _elm_theme_object_set(WIDGET(item), VIEW(item), "menu", "item", elm_widget_style_get(WIDGET(item)));
460 edje_object_signal_callback_add(VIEW(item), "elm,action,click", "",
461 _menu_item_select, item);
462 edje_object_signal_callback_add(VIEW(item), "elm,action,activate", "",
463 _menu_item_activate, item);
464 edje_object_signal_callback_add(VIEW(item), "elm,action,inactivate", "",
465 _menu_item_inactivate, item);
466 evas_object_show(VIEW(item));
470 _item_separator_obj_create(Elm_Menu_Item *item)
472 Widget_Data *wd = elm_widget_data_get(WIDGET(item));
474 VIEW(item) = edje_object_add(evas_object_evas_get(wd->bx));
475 evas_object_size_hint_weight_set(VIEW(item), EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
476 evas_object_size_hint_fill_set(VIEW(item), EVAS_HINT_FILL, EVAS_HINT_FILL);
477 _elm_theme_object_set(WIDGET(item), VIEW(item), "menu", "separator", elm_widget_style_get(WIDGET(item)));
478 edje_object_signal_callback_add(VIEW(item), "elm,action,activate", "",
479 _menu_item_activate, item);
480 evas_object_show(VIEW(item));
484 _item_submenu_obj_create(Elm_Menu_Item *item)
486 Widget_Data *wd = elm_widget_data_get(WIDGET(item));
488 item->submenu.location = elm_icon_add(wd->bx);
489 item->submenu.hv = elm_hover_add(wd->bx);
490 elm_widget_mirrored_set(item->submenu.hv, EINA_FALSE);
491 elm_hover_target_set(item->submenu.hv, item->submenu.location);
492 elm_hover_parent_set(item->submenu.hv, wd->parent);
493 elm_object_style_set(item->submenu.hv, "submenu");
495 item->submenu.bx = elm_box_add(wd->bx);
496 elm_widget_mirrored_set(item->submenu.bx, EINA_FALSE);
497 evas_object_size_hint_weight_set(item->submenu.bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
498 evas_object_show(item->submenu.bx);
499 elm_object_part_content_set(item->submenu.hv, elm_hover_best_content_location_get(item->submenu.hv, ELM_HOVER_AXIS_VERTICAL), item->submenu.bx);
501 edje_object_mirrored_set(VIEW(item), elm_widget_mirrored_get(WIDGET(item)));
502 _elm_theme_object_set(WIDGET(item), VIEW(item), "menu", "item_with_submenu", elm_widget_style_get(WIDGET(item)));
503 elm_object_item_text_set((Elm_Object_Item *) item,
506 elm_menu_item_object_icon_name_set((Elm_Object_Item *) item,
508 edje_object_signal_callback_add(VIEW(item), "elm,action,open", "",
509 _submenu_open, item);
510 evas_object_event_callback_add(VIEW(item), EVAS_CALLBACK_MOVE, _item_move_resize, item);
511 evas_object_event_callback_add(VIEW(item), EVAS_CALLBACK_RESIZE, _item_move_resize, item);
513 evas_object_event_callback_add(item->submenu.bx, EVAS_CALLBACK_RESIZE, _menu_resize, WIDGET(item));
517 elm_menu_add(Evas_Object *parent)
523 ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
525 ELM_SET_WIDTYPE(widtype, "menu");
526 elm_widget_type_set(obj, "menu");
527 elm_widget_sub_object_add(parent, obj);
528 elm_widget_data_set(obj, wd);
529 elm_widget_del_pre_hook_set(obj, _del_pre_hook);
530 elm_widget_del_hook_set(obj, _del_hook);
531 elm_widget_theme_hook_set(obj, _theme_hook);
532 elm_widget_can_focus_set(obj, EINA_FALSE);
534 wd->location = elm_icon_add(obj);
538 wd->hv = elm_hover_add(obj);
539 elm_widget_mirrored_set(wd->hv, EINA_FALSE);
540 elm_hover_parent_set(wd->hv, parent);
541 elm_hover_target_set(wd->hv, wd->location);
542 elm_object_style_set(wd->hv, "menu");
543 evas_object_smart_callback_add(wd->hv, "clicked", _hover_clicked_cb, obj);
545 wd->bx = elm_box_add(obj);
546 elm_widget_mirrored_set(wd->bx, EINA_FALSE);
547 evas_object_size_hint_weight_set(wd->bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
548 evas_object_show(wd->bx);
549 elm_object_part_content_set(wd->hv, elm_hover_best_content_location_get(wd->hv, ELM_HOVER_AXIS_VERTICAL), wd->bx);
551 evas_object_event_callback_add(wd->parent, EVAS_CALLBACK_RESIZE, _parent_resize, wd->obj);
552 evas_object_event_callback_add(wd->parent, EVAS_CALLBACK_DEL, _parent_del, wd);
554 evas_object_event_callback_add(obj, EVAS_CALLBACK_SHOW, _show, obj);
556 evas_object_event_callback_add(wd->bx, EVAS_CALLBACK_RESIZE, _menu_resize, obj);
558 evas_object_smart_callbacks_descriptions_set(obj, _signals);
565 elm_menu_parent_set(Evas_Object *obj, Evas_Object *parent)
567 Eina_List *l, *_l, *_ll, *ll = NULL;
569 ELM_CHECK_WIDTYPE(obj, widtype);
570 Widget_Data *wd = elm_widget_data_get(obj);
573 if (wd->parent == parent) return;
576 evas_object_event_callback_del_full(wd->parent, EVAS_CALLBACK_RESIZE, _parent_resize, wd->obj);
577 evas_object_event_callback_del_full(wd->parent, EVAS_CALLBACK_DEL, _parent_del, wd);
582 evas_object_event_callback_add(wd->parent, EVAS_CALLBACK_RESIZE, _parent_resize, wd->obj);
583 evas_object_event_callback_add(wd->parent, EVAS_CALLBACK_DEL, _parent_del, wd);
585 elm_hover_parent_set(wd->hv, parent);
587 ll = eina_list_append(ll, wd->items);
588 EINA_LIST_FOREACH(ll, _ll, l)
590 EINA_LIST_FOREACH(l, _l, item)
592 if (item->submenu.hv)
594 elm_hover_parent_set(item->submenu.hv, parent);
595 ll = eina_list_append(ll, item->submenu.items);
603 elm_menu_parent_get(const Evas_Object *obj)
605 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
606 Widget_Data *wd = elm_widget_data_get(obj);
607 if (!wd) return NULL;
612 elm_menu_move(Evas_Object *obj, Evas_Coord x, Evas_Coord y)
614 ELM_CHECK_WIDTYPE(obj, widtype);
615 Widget_Data *wd = elm_widget_data_get(obj);
623 elm_menu_close(Evas_Object *obj)
625 ELM_CHECK_WIDTYPE(obj, widtype);
626 Widget_Data *wd = elm_widget_data_get(obj);
627 _menu_hide(obj, wd->hv, NULL);
631 elm_menu_item_object_get(const Elm_Object_Item *it)
633 return VIEW(((Elm_Menu_Item *) it));
637 _item_clone(Evas_Object *obj, Elm_Menu_Item *parent, Elm_Menu_Item *item)
639 Elm_Object_Item *new_item;
640 Elm_Menu_Item *subitem;
644 new_item = elm_menu_item_separator_add(obj, (Elm_Object_Item *) parent);
646 new_item = elm_menu_item_add(obj,
647 (Elm_Object_Item *) parent,
652 elm_object_item_disabled_set(new_item,
653 elm_widget_item_disabled_get(item));
655 EINA_LIST_FOREACH(item->submenu.items, iter, subitem)
656 _item_clone(obj, (Elm_Menu_Item *) new_item, subitem);
660 elm_menu_clone(Evas_Object *from_menu, Evas_Object *to_menu, Elm_Object_Item *parent)
662 ELM_CHECK_WIDTYPE(from_menu, widtype);
663 ELM_CHECK_WIDTYPE(to_menu, widtype);
664 Widget_Data *from_wd = elm_widget_data_get(from_menu);
668 if (!from_wd) return;
669 EINA_LIST_FOREACH(from_wd->items, iter, item)
670 _item_clone(to_menu, (Elm_Menu_Item *) parent, item);
674 _elm_menu_item_add_helper(Evas_Object *obj, Elm_Menu_Item *parent, Elm_Menu_Item *subitem, Widget_Data *wd)
678 if (!parent->submenu.bx) _item_submenu_obj_create(parent);
679 elm_box_pack_end(parent->submenu.bx, VIEW(subitem));
680 parent->submenu.items = eina_list_append(parent->submenu.items, subitem);
681 subitem->idx = eina_list_count(parent->submenu.items) - 1;
685 elm_box_pack_end(wd->bx, VIEW(subitem));
686 wd->items = eina_list_append(wd->items, subitem);
687 subitem->idx = eina_list_count(wd->items) - 1;
694 _item_del_pre_hook(Elm_Object_Item *it)
696 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
697 Elm_Menu_Item *item = (Elm_Menu_Item *) it;
698 Elm_Object_Item *_item;
700 EINA_LIST_FREE(item->submenu.items, _item) elm_object_item_del(_item);
701 if (item->label) eina_stringshare_del(item->label);
702 if (item->content) evas_object_del(item->content);
703 if (item->submenu.hv) evas_object_del(item->submenu.hv);
704 if (item->submenu.location) evas_object_del(item->submenu.location);
707 item->parent->submenu.items = eina_list_remove(item->parent->submenu.items, item);
710 Widget_Data *wd = elm_widget_data_get(WIDGET(item));
711 wd->items = eina_list_remove(wd->items, item);
717 EAPI Elm_Object_Item *
718 elm_menu_item_add(Evas_Object *obj, Elm_Object_Item *parent, const char *icon, const char *label, Evas_Smart_Cb func, const void *data)
720 Elm_Menu_Item *subitem;
721 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
722 Widget_Data *wd = elm_widget_data_get(obj);
723 Evas_Object *icon_obj;
725 if (!wd) return NULL;
726 icon_obj = elm_icon_add(obj);
727 if (!icon_obj) return NULL;
728 subitem = elm_widget_item_new(obj, Elm_Menu_Item);
731 evas_object_del(icon_obj);
735 elm_widget_item_del_pre_hook_set(subitem, _item_del_pre_hook);
736 elm_widget_item_disable_hook_set(subitem, _item_disable_hook);
737 elm_widget_item_text_set_hook_set(subitem, _item_text_set_hook);
738 elm_widget_item_text_get_hook_set(subitem, _item_text_get_hook);
739 elm_widget_item_content_set_hook_set(subitem, _item_content_set_hook);
740 elm_widget_item_content_get_hook_set(subitem, _item_content_get_hook);
742 subitem->base.data = data;
743 subitem->func = func;
744 subitem->parent = (Elm_Menu_Item *) parent;
745 subitem->content = icon_obj;
747 _item_obj_create(subitem);
748 elm_object_item_text_set((Elm_Object_Item *) subitem, label);
750 elm_widget_sub_object_add(WIDGET(subitem), subitem->content);
751 edje_object_part_swallow(VIEW(subitem), "elm.swallow.content", subitem->content);
753 elm_menu_item_object_icon_name_set((Elm_Object_Item *) subitem, icon);
755 _elm_menu_item_add_helper(obj, (Elm_Menu_Item *) parent, subitem, wd);
757 return (Elm_Object_Item *) subitem;
760 EAPI Elm_Object_Item *
761 elm_menu_item_add_object(Evas_Object *obj, Elm_Object_Item *parent, Evas_Object *subobj, Evas_Smart_Cb func, const void *data)
763 Elm_Menu_Item *subitem;
764 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
765 Widget_Data *wd = elm_widget_data_get(obj);
767 if (!wd) return NULL;
768 subitem = elm_widget_item_new(obj, Elm_Menu_Item);
769 if (!subitem) return NULL;
771 elm_widget_item_del_pre_hook_set(subitem, _item_del_pre_hook);
772 elm_widget_item_disable_hook_set(subitem, _item_disable_hook);
773 elm_widget_item_text_set_hook_set(subitem, _item_text_set_hook);
774 elm_widget_item_text_get_hook_set(subitem, _item_text_get_hook);
775 elm_widget_item_content_set_hook_set(subitem, _item_content_set_hook);
776 elm_widget_item_content_get_hook_set(subitem, _item_content_get_hook);
778 subitem->base.data = data;
779 subitem->func = func;
780 subitem->parent = (Elm_Menu_Item *) parent;
781 subitem->object_item = EINA_TRUE;
782 subitem->content = subobj;
784 _item_obj_create(subitem);
786 elm_widget_sub_object_add(WIDGET(subitem), subitem->content);
787 edje_object_part_swallow(VIEW(subitem), "elm.swallow.content", subobj);
788 _sizing_eval(WIDGET(subitem));
790 _elm_menu_item_add_helper(obj, (Elm_Menu_Item *) parent, subitem, wd);
792 return (Elm_Object_Item *) subitem;
796 elm_menu_item_index_get(const Elm_Object_Item *it)
798 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, 0);
799 return ((Elm_Menu_Item *) it)->idx;
803 elm_menu_item_label_set(Elm_Object_Item *it, const char *label)
805 _item_text_set_hook(it, NULL, label);
809 elm_menu_item_label_get(const Elm_Object_Item *it)
811 return _item_text_get_hook(it, NULL);
815 elm_menu_item_object_icon_name_set(Elm_Object_Item *it, const char *icon)
817 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
818 EINA_SAFETY_ON_NULL_RETURN(icon);
820 Elm_Menu_Item *item = (Elm_Menu_Item *) it;
823 if ((item->icon_str) && (!strcmp(item->icon_str, icon))) return;
824 if ((snprintf(icon_tmp, sizeof(icon_tmp), "menu/%s", icon) > 0) &&
825 (elm_icon_standard_set(item->content, icon_tmp) ||
826 elm_icon_standard_set(item->content, icon)))
828 eina_stringshare_replace(&item->icon_str, icon);
829 edje_object_signal_emit(VIEW(item), "elm,state,icon,visible", "elm");
832 edje_object_signal_emit(VIEW(item), "elm,state,icon,hidden", "elm");
833 edje_object_message_signal_process(VIEW(item));
834 _sizing_eval(WIDGET(item));
838 elm_menu_item_disabled_set(Elm_Object_Item *it, Eina_Bool disabled)
840 elm_object_item_disabled_set(it, disabled);
844 elm_menu_item_disabled_get(const Elm_Object_Item *it)
846 return elm_object_item_disabled_get(it);
849 EAPI Elm_Object_Item *
850 elm_menu_item_separator_add(Evas_Object *obj, Elm_Object_Item *parent)
852 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
853 Elm_Menu_Item *subitem;
854 Widget_Data *wd = elm_widget_data_get(obj);
855 Elm_Menu_Item *p_item = (Elm_Menu_Item *) parent;
856 if (!wd) return NULL;
857 /* don't add a separator as the first item */
858 if (!wd->items) return NULL;
859 /* don't allow adding more than one separator in a row */
860 if (p_item) subitem = eina_list_last(p_item->submenu.items)->data;
861 else subitem = eina_list_last(wd->items)->data;
862 if (subitem->separator) return NULL;
864 subitem = elm_widget_item_new(obj, Elm_Menu_Item);
865 if (!subitem) return NULL;
867 elm_widget_item_del_pre_hook_set(subitem, _item_del_pre_hook);
868 elm_widget_item_disable_hook_set(subitem, _item_disable_hook);
869 elm_widget_item_text_set_hook_set(subitem, _item_text_set_hook);
870 elm_widget_item_text_get_hook_set(subitem, _item_text_get_hook);
871 elm_widget_item_content_set_hook_set(subitem, _item_content_set_hook);
872 elm_widget_item_content_get_hook_set(subitem, _item_content_get_hook);
874 subitem->separator = EINA_TRUE;
875 _item_separator_obj_create(subitem);
878 elm_box_pack_end(wd->bx, VIEW(subitem));
879 wd->items = eina_list_append(wd->items, subitem);
883 if (!p_item->submenu.bx) _item_submenu_obj_create(p_item);
884 elm_box_pack_end(p_item->submenu.bx, VIEW(subitem));
885 p_item->submenu.items = eina_list_append(p_item->submenu.items,
889 return (Elm_Object_Item *) subitem;
893 elm_menu_item_object_content_set(Elm_Object_Item *it, Evas_Object *obj)
895 _item_content_set_hook(it, NULL, obj);
900 elm_menu_item_object_content_get(const Elm_Object_Item *it)
902 return _item_content_get_hook(it, NULL);
906 elm_menu_item_object_icon_name_get(const Elm_Object_Item *it)
908 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
909 return ((Elm_Menu_Item *) it)->icon_str;
913 elm_menu_item_is_separator(Elm_Object_Item *it)
915 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
916 return ((Elm_Menu_Item *) it)->separator;
920 elm_menu_item_del(Elm_Object_Item *it)
922 elm_object_item_del(it);
926 elm_menu_item_del_cb_set(Elm_Object_Item *it, Evas_Smart_Cb func)
928 elm_object_item_del_cb_set(it, func);
932 elm_menu_item_data_get(const Elm_Object_Item *it)
934 return elm_object_item_data_get(it);
938 elm_menu_item_data_set(Elm_Object_Item *it, const void *data)
940 elm_object_item_data_set(it, (void *) data);
943 EAPI const Eina_List *
944 elm_menu_item_subitems_get(const Elm_Object_Item *it)
946 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
947 return ((Elm_Menu_Item *) it)->submenu.items;
950 EAPI const Eina_List *
951 elm_menu_items_get(const Evas_Object * obj)
953 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
954 Widget_Data *wd = elm_widget_data_get(obj);
959 elm_menu_item_selected_set(Elm_Object_Item *it, Eina_Bool selected)
961 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
962 Elm_Menu_Item *item = (Elm_Menu_Item *) it;
964 if (selected == item->selected) return;
965 item->selected = selected;
968 edje_object_signal_emit(VIEW(item), "elm,state,selected", "elm");
969 _menu_item_activate(item, NULL, NULL, NULL);
973 edje_object_signal_emit(VIEW(item), "elm,state,unselected", "elm");
974 _menu_item_inactivate(item, NULL, NULL, NULL);
976 edje_object_message_signal_process(VIEW(item));
980 elm_menu_item_selected_get(const Elm_Object_Item *it)
982 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
983 return ((Elm_Menu_Item *) it)->selected;
986 EAPI Elm_Object_Item *
987 elm_menu_item_prev_get(const Elm_Object_Item *it)
989 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
990 Elm_Menu_Item *item = (Elm_Menu_Item *) it;
994 Eina_List *l = eina_list_data_find_list(item->parent->submenu.items,
996 l = eina_list_prev(l);
1002 Widget_Data *wd = elm_widget_data_get(WIDGET(item));
1003 if (!wd || !wd->items) return NULL;
1004 Eina_List *l = eina_list_data_find_list(wd->items, item);
1005 l = eina_list_prev(l);
1006 if (!l) return NULL;
1012 EAPI Elm_Object_Item *
1013 elm_menu_item_next_get(const Elm_Object_Item *it)
1015 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
1016 Elm_Menu_Item *item = (Elm_Menu_Item *) it;
1020 Eina_List *l = eina_list_data_find_list(item->parent->submenu.items,
1022 l = eina_list_next(l);
1023 if (!l) return NULL;
1028 Widget_Data *wd = elm_widget_data_get(WIDGET(item));
1029 if (!wd || !wd->items) return NULL;
1030 Eina_List *l = eina_list_data_find_list(wd->items, item);
1031 l = eina_list_next(l);
1032 if (!l) return NULL;
1039 elm_menu_item_menu_get(const Elm_Object_Item *it)
1041 return elm_object_item_widget_get(it);
1044 EAPI Elm_Object_Item *
1045 elm_menu_first_item_get(const Evas_Object * obj)
1047 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1048 Widget_Data *wd = elm_widget_data_get(obj);
1049 if (!wd) return NULL;
1050 if (wd->items) return wd->items->data;
1054 EAPI Elm_Object_Item *
1055 elm_menu_last_item_get(const Evas_Object * obj)
1057 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1058 Widget_Data *wd = elm_widget_data_get(obj);
1059 if (!wd) return NULL;
1060 Eina_List *l = eina_list_last(wd->items);
1061 if (l) return l->data;
1065 EAPI Elm_Object_Item *
1066 elm_menu_selected_item_get(const Evas_Object * obj)
1068 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1069 Widget_Data *wd = elm_widget_data_get(obj);
1070 if (!wd) return NULL;
1072 Elm_Menu_Item *item;
1073 EINA_LIST_FOREACH(wd->items, l, item)
1075 if (item->selected) return ((Elm_Object_Item *) item);