From 7118cd369a1e1910c9ee2059f936c1c959886c35 Mon Sep 17 00:00:00 2001 From: raster Date: Tue, 22 Mar 2011 02:29:26 +0000 Subject: [PATCH] From: Tristan Lelong >>> Hello, >>> >>> I was using elementary on a target that only has a keyboard, and I add >>> to do several modification on the elm_menu to handle keyboard >>> navigation. >>> - patch 2: add accessors for menu items and add the ability to handle >>> selected item from C source code git-svn-id: svn+ssh://svn.enlightenment.org/var/svn/e/trunk/elementary@57957 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33 --- src/lib/Elementary.h.in | 9 +++ src/lib/elm_menu.c | 200 +++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 205 insertions(+), 4 deletions(-) diff --git a/src/lib/Elementary.h.in b/src/lib/Elementary.h.in index 1c5fc6b..0a3acdb 100644 --- a/src/lib/Elementary.h.in +++ b/src/lib/Elementary.h.in @@ -1553,6 +1553,7 @@ extern "C" { EAPI void elm_menu_parent_set(Evas_Object *obj, Evas_Object *parent) EINA_ARG_NONNULL(1); EAPI Evas_Object *elm_menu_parent_get(const Evas_Object *obj) EINA_ARG_NONNULL(1); EAPI void elm_menu_move(Evas_Object *obj, Evas_Coord x, Evas_Coord y) EINA_ARG_NONNULL(1); + EAPI const Eina_List *elm_menu_items_get(const Evas_Object *obj) EINA_ARG_NONNULL(1); EAPI Evas_Object *elm_menu_item_object_get(const Elm_Menu_Item *it) EINA_ARG_NONNULL(1); EAPI Elm_Menu_Item *elm_menu_item_add(Evas_Object *obj, Elm_Menu_Item *parent, const char *icon, const char *label, Evas_Smart_Cb func, const void *data) EINA_ARG_NONNULL(1); EAPI void elm_menu_item_label_set(Elm_Menu_Item *item, const char *label) EINA_ARG_NONNULL(1); @@ -1560,6 +1561,8 @@ extern "C" { EAPI void elm_menu_item_icon_set(Elm_Menu_Item *item, const char *icon) EINA_ARG_NONNULL(1, 2); EAPI const char *elm_menu_item_icon_get(const Elm_Menu_Item *item) EINA_ARG_NONNULL(1); EAPI const Evas_Object *elm_menu_item_object_icon_get(const Elm_Menu_Item *item) EINA_ARG_NONNULL(1); + EAPI void elm_menu_item_selected_set(Elm_Menu_Item *item, Eina_Bool selected) EINA_ARG_NONNULL(1); + EAPI Eina_Bool elm_menu_item_selected_get(const Elm_Menu_Item *item) EINA_ARG_NONNULL(1); EAPI void elm_menu_item_disabled_set(Elm_Menu_Item *item, Eina_Bool disabled) EINA_ARG_NONNULL(1); EAPI Eina_Bool elm_menu_item_disabled_get(const Elm_Menu_Item *item) EINA_ARG_NONNULL(1); EAPI Elm_Menu_Item *elm_menu_item_separator_add(Evas_Object *obj, Elm_Menu_Item *parent) EINA_ARG_NONNULL(1); @@ -1569,6 +1572,12 @@ extern "C" { EAPI void *elm_menu_item_data_get(const Elm_Menu_Item *it) EINA_ARG_NONNULL(1); EAPI void elm_menu_item_data_set(Elm_Menu_Item *item, const void *data) EINA_ARG_NONNULL(1); EAPI const Eina_List *elm_menu_item_subitems_get(const Elm_Menu_Item *item) EINA_ARG_NONNULL(1); + EAPI const Elm_Menu_Item *elm_menu_selected_item_get(const Evas_Object * obj) EINA_ARG_NONNULL(1); + EAPI const Elm_Menu_Item *elm_menu_last_item_get(const Evas_Object * obj) EINA_ARG_NONNULL(1); + EAPI const Elm_Menu_Item *elm_menu_first_item_get(const Evas_Object * obj) EINA_ARG_NONNULL(1); + EAPI const Elm_Menu_Item *elm_menu_item_next_get(const Elm_Menu_Item *it) EINA_ARG_NONNULL(1); + EAPI const Elm_Menu_Item *elm_menu_item_prev_get(const Elm_Menu_Item *it) EINA_ARG_NONNULL(1); + /* smart callbacks called: * "clicked" - the user clicked the empty space in the menu to dismiss. event_info is NULL. */ diff --git a/src/lib/elm_menu.c b/src/lib/elm_menu.c index d304370..b6936cb 100644 --- a/src/lib/elm_menu.c +++ b/src/lib/elm_menu.c @@ -29,6 +29,7 @@ struct _Elm_Menu_Item Eina_Bool separator : 1; Eina_Bool disabled : 1; + Eina_Bool selected: 1; }; struct _Widget_Data @@ -321,11 +322,12 @@ _menu_item_activate(void *data, Evas_Object *obj __UNUSED__, const char *emissio Eina_List *l; Elm_Menu_Item *item2; Elm_Menu_Item *item = data; + item->selected = 1; if (item->parent) { EINA_LIST_FOREACH(item->parent->submenu.items, l, item2) { - if ((item2->submenu.open) && (item2 != item)) _submenu_hide(item2); + if (item2 != item) elm_menu_item_selected_set(item2, 0); } } else @@ -333,12 +335,20 @@ _menu_item_activate(void *data, Evas_Object *obj __UNUSED__, const char *emissio Widget_Data *wd = elm_widget_data_get(item->base.widget); EINA_LIST_FOREACH(wd->items, l, item2) { - if ((item2->submenu.open) && (item2 != item)) _submenu_hide(item2); + if (item2 != item) elm_menu_item_selected_set(item2, 0); } } } static void +_menu_item_inactivate(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__) +{ + Elm_Menu_Item *item = data; + item->selected = 0; + if (item->submenu.open) _submenu_hide(item); +} + +static void _submenu_open(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__) { Elm_Menu_Item *item = data; @@ -369,6 +379,8 @@ _item_obj_create(Elm_Menu_Item *item) _menu_item_select, item); edje_object_signal_callback_add(item->base.view, "elm,action,activate", "", _menu_item_activate, item); + edje_object_signal_callback_add(item->base.view, "elm,action,inactivate", "", + _menu_item_inactivate, item); evas_object_show(item->base.view); } @@ -764,7 +776,6 @@ EAPI Eina_Bool elm_menu_item_disabled_get(const Elm_Menu_Item *item) { ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, EINA_FALSE); - if (!item) return EINA_FALSE; return item->disabled; } @@ -879,7 +890,7 @@ elm_menu_item_del(Elm_Menu_Item *item) if (item->submenu.location) evas_object_del(item->submenu.location); if (item->parent) - item->parent->submenu.items = eina_list_remove(item->parent->submenu.items, item); + item->parent->submenu.items = eina_list_remove(item->parent->submenu.items, item); else { Widget_Data *wd = elm_widget_data_get(item->base.widget); @@ -948,3 +959,184 @@ elm_menu_item_subitems_get(const Elm_Menu_Item *item) ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL); return item->submenu.items; } + +/** + * Returns a list of @p item's items. + * + * @param obj The menu object + * @return An Eina_List* of @p item's items + * + * @ingroup Menu + */ +EAPI const Eina_List * +elm_menu_items_get(const Evas_Object * obj) +{ + ELM_CHECK_WIDTYPE(obj, widtype) NULL; + Widget_Data *wd = elm_widget_data_get(obj); + return wd->items; +} + +/** + * Set the selected state of @p item. + * + * @param item The menu item object. + * @param selected The selected/unselected state of the item + * + * @ingroup Menu + */ +EAPI void +elm_menu_item_selected_set(Elm_Menu_Item *item, Eina_Bool selected) +{ + ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item); + if (selected == item->selected) return; + item->selected = selected; + if (selected) + { + edje_object_signal_emit(item->base.view, "elm,state,selected", "elm"); + _menu_item_activate(item, NULL, NULL, NULL); + } + else + { + edje_object_signal_emit(item->base.view, "elm,state,unselected", "elm"); + _menu_item_inactivate(item, NULL, NULL, NULL); + } + edje_object_message_signal_process(item->base.view); +} + +/** + * Get the selected state of @p item. + * + * @param item The menu item object. + * @return The selected/unselected state of the item + * + * @ingroup Menu + */ +EAPI Eina_Bool +elm_menu_item_selected_get(const Elm_Menu_Item *item) +{ + ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, EINA_FALSE); + return item->selected; +} + +/** + * Get the previous item in the menu. + * + * @param item The menu item object. + * @return The item before it, or NULL if none + * + * @ingroup Menu + */ +EAPI const Elm_Menu_Item * +elm_menu_item_prev_get(const Elm_Menu_Item *it) +{ + ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, NULL); + if (it->parent) + { + Eina_List *l = eina_list_data_find_list(it->parent->submenu.items, it); + l = eina_list_prev(l); + if (!l) return NULL; + return l->data; + } + else + { + Widget_Data *wd = elm_widget_data_get(it->base.widget); + if (!wd | !wd->items) return NULL; + Eina_List *l = eina_list_data_find_list(wd->items, it); + l = eina_list_prev(l); + if (!l) return NULL; + return l->data; + } + return NULL; +} + +/** + * Get the next item in the menu. + * + * @param item The menu item object. + * @return The item after it, or NULL if none + * + * @ingroup Menu + */ +EAPI const Elm_Menu_Item * +elm_menu_item_next_get(const Elm_Menu_Item *it) +{ + ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, NULL); + if (it->parent) + { + Eina_List *l = eina_list_data_find_list(it->parent->submenu.items, it); + l = eina_list_next(l); + if (!l) return NULL; + return l->data; + } + else + { + Widget_Data *wd = elm_widget_data_get(it->base.widget); + if (!wd | !wd->items) return NULL; + Eina_List *l = eina_list_data_find_list(wd->items, it); + l = eina_list_next(l); + if (!l) return NULL; + return l->data; + } + return NULL; +} + +/** + * Get the first item in the menu + * + * @param obj The menu object + * @return The first item, or NULL if none + * + * @ingroup Menu + */ +EAPI const Elm_Menu_Item * +elm_menu_first_item_get(const Evas_Object * obj) +{ + ELM_CHECK_WIDTYPE(obj, widtype) NULL; + Widget_Data *wd = elm_widget_data_get(obj); + if (!wd) return NULL; + if (wd->items) return wd->items->data; + return NULL; +} + +/** + * Get the last item in the menu + * + * @param obj The menu object + * @return The last item, or NULL if none + * + * @ingroup Menu + */ +EAPI const Elm_Menu_Item * +elm_menu_last_item_get(const Evas_Object * obj) +{ + ELM_CHECK_WIDTYPE(obj, widtype) NULL; + Widget_Data *wd = elm_widget_data_get(obj); + if (!wd) return NULL; + Eina_List *l = eina_list_last(wd->items); + if (l) return l->data; + return NULL; +} + +/** + * Get the selected item in the menu + * + * @param obj The menu object + * @return The selected item, or NULL if none + * + * @ingroup Menu + */ +EAPI const Elm_Menu_Item * +elm_menu_selected_item_get(const Evas_Object * obj) +{ + ELM_CHECK_WIDTYPE(obj, widtype) NULL; + Widget_Data *wd = elm_widget_data_get(obj); + if (!wd) return NULL; + Eina_List *l; + Elm_Menu_Item *item; + EINA_LIST_FOREACH(wd->items, l, item) + { + if (item->selected) return item; + } + return NULL; +} + -- 2.7.4