seoz pushed a commit to branch master. http://git.enlightenment.org/core/elementary.git/commit/?id=0a9fe5fb4da5e83551df2dfdee2e90f3fda3facc
commit 0a9fe5fb4da5e83551df2dfdee2e90f3fda3facc Author: Amitesh Singh <[email protected]> Date: Mon Mar 24 00:22:32 2014 +0900 toolbar: implemented widget item focus feature. Summary: 1. Added "item,focused" and "item,unfocused" smart callbacks. 2. Added _elm_toolbar_focus_highlight_geometry_get(). 3. Implemented elm_object_item_focus_set() and elm_object_item_focus_get(). 4. Implemented elm_object_focused_item_get() 5. Ported _elm_toolbar_nearest_visible_item_get from cc827fef6. 6. Added Test Case "Toolbar Focus". @feature Test Plan: elementary_test->Toolbar Item Focus Reviewers: seoz, woohyun, raster CC: nirajkr, raster Differential Revision: https://phab.enlightenment.org/D555 --- data/themes/edc/elm/toolbar.edc | 3 +- src/bin/test.c | 2 + src/bin/test_toolbar.c | 169 ++++++++++++++++++ src/lib/elm_toolbar.c | 372 +++++++++++++++++++++++++++++++++++----- src/lib/elm_toolbar.h | 4 + src/lib/elm_widget_toolbar.h | 5 +- 6 files changed, 513 insertions(+), 42 deletions(-) diff --git a/data/themes/edc/elm/toolbar.edc b/data/themes/edc/elm/toolbar.edc index e3c4d9b..f0cb0a7 100644 --- a/data/themes/edc/elm/toolbar.edc +++ b/data/themes/edc/elm/toolbar.edc @@ -366,7 +366,8 @@ group { name: "elm/toolbar/base/default"; // === item: standard default item group { name: "elm/toolbar/item/default"; data.item: "transition_animation_on" "1"; - + data.item: "focusraise" "on"; + images.image: "shadow_inset_bevels.png" COMP; images.image: "shadow_angled_in_sides.png" COMP; images.image: "horizontal_separated_bar_small_glow.png" COMP; diff --git a/src/bin/test.c b/src/bin/test.c index bc5db8a..1dd840c 100644 --- a/src/bin/test.c +++ b/src/bin/test.c @@ -72,6 +72,7 @@ void test_toolbar6(void *data, Evas_Object *obj, void *event_info); void test_toolbar7(void *data, Evas_Object *obj, void *event_info); void test_toolbar8(void *data, Evas_Object *obj, void *event_info); void test_toolbar_vertical(void *data, Evas_Object *obj, void *event_info); +void test_toolbar_focus(void *data, Evas_Object *obj, void *event_info); void test_hoversel(void *data, Evas_Object *obj, void *event_info); void test_hoversel_focus(void *data, Evas_Object *obj, void *event_info); void test_list(void *data, Evas_Object *obj, void *event_info); @@ -610,6 +611,7 @@ add_tests: ADD_TEST(NULL, "Toolbars", "Toolbar 7", test_toolbar7); ADD_TEST(NULL, "Toolbars", "Toolbar 8", test_toolbar8); ADD_TEST(NULL, "Toolbars", "Toolbar Vertical", test_toolbar_vertical); + ADD_TEST(NULL, "Toolbars", "Toolbar Focus", test_toolbar_focus); //------------------------------// ADD_TEST(NULL, "Lists - List", "List", test_list); diff --git a/src/bin/test_toolbar.c b/src/bin/test_toolbar.c index 433d188..44723b9 100644 --- a/src/bin/test_toolbar.c +++ b/src/bin/test_toolbar.c @@ -1047,3 +1047,172 @@ test_toolbar8(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_ evas_object_resize(win, 420, 250); evas_object_show(win); } + +static void +_item_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info) +{ + printf("%s: %p\n", (char *)data, event_info); +} + +static void +_test_toolbar_focus_focus_highlight_check_changed(void *data, Evas_Object *obj, + void *event_info EINA_UNUSED) +{ + elm_win_focus_highlight_enabled_set(data, + elm_check_state_get(obj)); +} + +static void +_test_toolbar_focus_focus_animate_check_changed(void *data, Evas_Object *obj, + void *event_info EINA_UNUSED) +{ + elm_win_focus_highlight_animate_set(data, + elm_check_state_get(obj)); +} + +static void +_toolbar_focus_key_down_cb(void *data EINA_UNUSED, Evas *e EINA_UNUSED, + Evas_Object *obj EINA_UNUSED, void *event_info) +{ + Evas_Event_Key_Down *ev = event_info; + printf("\n=== Key Down : %s ===\n", ev->keyname); +} + +static Ecore_Timer *timer = NULL; +static void +_test_toolbar_focus_win_del_cb(void *data EINA_UNUSED, Evas *e EINA_UNUSED, + Evas_Object *obj EINA_UNUSED, + void *event_info EINA_UNUSED) +{ + ecore_timer_del(timer); + timer = NULL; +} + +static Eina_Bool +_focus_timer_cb(void *data) +{ + Elm_Object_Item *it = data; + elm_object_item_focus_set(it, EINA_TRUE); + timer = NULL; + + return ECORE_CALLBACK_CANCEL; +} + +static void +_test_toolbar_focus_item_set_btn_cb(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, + void *event_info EINA_UNUSED) +{ + ecore_timer_del(timer); + timer = ecore_timer_add(1.5, _focus_timer_cb, data); +} + +void +test_toolbar_focus(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) +{ + Evas_Object *win, *bx, *toolbar, *fr, *btn, *bx_opt, *chk; + Elm_Object_Item *tb_it, *it_3; + + win = elm_win_util_standard_add("toolbar-focus", "Toolbar Focus"); + elm_win_autodel_set(win, EINA_TRUE); + evas_object_event_callback_add(win, EVAS_CALLBACK_DEL, + _test_toolbar_focus_win_del_cb, NULL); + elm_win_focus_highlight_enabled_set(win, EINA_TRUE); + elm_win_focus_highlight_animate_set(win, EINA_TRUE); + + bx = elm_box_add(win); + evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + elm_win_resize_object_add(win, bx); + evas_object_show(bx); + + btn = elm_button_add(win); + elm_object_text_set(btn, "Up"); + elm_box_pack_end(bx, btn); + evas_object_show(btn); + + toolbar = elm_toolbar_add(win); + elm_toolbar_shrink_mode_set(toolbar, ELM_TOOLBAR_SHRINK_SCROLL); + evas_object_size_hint_align_set(toolbar, EVAS_HINT_FILL, 0.0); + elm_toolbar_item_append(toolbar, "document-print", "Print", NULL, NULL); + elm_toolbar_item_append(toolbar, "folder-new", "Folder", NULL, NULL); + it_3 = elm_toolbar_item_append(toolbar, "clock", "Clock", NULL, NULL); + elm_toolbar_item_append(toolbar, "refresh", "Update", NULL, NULL); + elm_toolbar_item_append(toolbar, "folder-new", "Folder", NULL, NULL); + elm_toolbar_item_append(toolbar, "clock", "Clock", NULL, NULL); + tb_it = elm_toolbar_item_append(toolbar, "document-print", "Print", NULL, NULL); + elm_object_item_disabled_set(tb_it, EINA_TRUE); + elm_toolbar_item_append(toolbar, "folder-new", "Folder", NULL, NULL); + elm_toolbar_item_append(toolbar, "refresh", "Update", NULL, NULL); + elm_toolbar_item_append(toolbar, "folder-new", "Folder", NULL, NULL); + elm_toolbar_item_append(toolbar, "clock", "Clock", NULL, NULL); + elm_toolbar_item_append(toolbar, "document-print", "Print", NULL, NULL); + elm_toolbar_item_append(toolbar, "folder-new", "Folder", NULL, NULL); + elm_toolbar_item_append(toolbar, "refresh", "Update", NULL, NULL); + elm_toolbar_item_append(toolbar, "folder-new", "Folder", NULL, NULL); + elm_box_pack_end(bx, toolbar); + evas_object_show(toolbar); + evas_object_smart_callback_add(toolbar, "clicked", _item_cb, "clicked"); + evas_object_smart_callback_add(toolbar, "item,focused", _item_cb, "item,focused"); + evas_object_smart_callback_add(toolbar, "item,unfocused", _item_cb, "item,unfcoused"); + evas_object_event_callback_add(toolbar, EVAS_CALLBACK_KEY_DOWN, _toolbar_focus_key_down_cb, NULL); + + btn = elm_button_add(win); + elm_object_text_set(btn, "Down"); + elm_box_pack_end(bx, btn); + evas_object_show(btn); + + //Options + fr = elm_frame_add(bx); + elm_object_text_set(fr, "Options"); + evas_object_size_hint_weight_set(fr, EVAS_HINT_EXPAND, 0.0); + evas_object_size_hint_align_set(fr, EVAS_HINT_FILL, EVAS_HINT_FILL); + elm_box_pack_end(bx, fr); + evas_object_show(fr); + + bx_opt = elm_box_add(fr); + elm_box_horizontal_set(bx_opt, EINA_TRUE); + elm_object_content_set(fr, bx_opt); + evas_object_show(bx_opt); + + chk = elm_check_add(bx_opt); + elm_object_text_set(chk, "Focus Highlight"); + elm_check_state_set(chk, EINA_TRUE); + evas_object_size_hint_weight_set(chk, EVAS_HINT_EXPAND, 0.0); + elm_box_pack_end(bx_opt, chk); + evas_object_show(chk); + evas_object_smart_callback_add(chk, "changed", + _test_toolbar_focus_focus_highlight_check_changed, + win); + + chk = elm_check_add(bx_opt); + elm_object_text_set(chk, "Focus Animation"); + elm_check_state_set(chk, EINA_TRUE); + evas_object_size_hint_weight_set(chk, EVAS_HINT_EXPAND, 0.0); + elm_box_pack_end(bx_opt, chk); + evas_object_show(chk); + evas_object_smart_callback_add(chk, "changed", + _test_toolbar_focus_focus_animate_check_changed, + win); + fr = elm_frame_add(bx); + elm_object_text_set(fr, "Focus"); + evas_object_size_hint_weight_set(fr, EVAS_HINT_EXPAND, 0.0); + evas_object_size_hint_align_set(fr, EVAS_HINT_FILL, EVAS_HINT_FILL); + elm_box_pack_end(bx, fr); + evas_object_show(fr); + + bx_opt = elm_box_add(fr); + elm_object_content_set(fr, bx_opt); + evas_object_show(bx_opt); + + btn = elm_button_add(bx_opt); + elm_object_text_set(btn, "Set focus to 3rd toolbar item after 1.5 seconds."); + evas_object_size_hint_weight_set(btn, 0.0, EVAS_HINT_EXPAND); + evas_object_size_hint_align_set(btn, EVAS_HINT_FILL, EVAS_HINT_FILL); + elm_box_pack_end(bx_opt, btn); + evas_object_show(btn); + evas_object_smart_callback_add(btn, "clicked", + _test_toolbar_focus_item_set_btn_cb, + it_3); + + evas_object_resize(win, 420, 200); + evas_object_show(win); +} diff --git a/src/lib/elm_toolbar.c b/src/lib/elm_toolbar.c index 5463339..e5ea35a 100644 --- a/src/lib/elm_toolbar.c +++ b/src/lib/elm_toolbar.c @@ -26,6 +26,8 @@ static const char SIG_SCROLL_DRAG_STOP[] = "scroll,drag,stop"; static const char SIG_CLICKED[] = "clicked"; static const char SIG_LONGPRESSED[] = "longpressed"; static const char SIG_CLICKED_DOUBLE[] = "clicked,double"; +static const char SIG_ITEM_FOCUSED[] = "item,focused"; +static const char SIG_ITEM_UNFOCUSED[] = "item,unfocused"; static const Evas_Smart_Cb_Description _smart_callbacks[] = { {SIG_SCROLL, ""}, {SIG_SCROLL_ANIM_START, ""}, @@ -35,6 +37,8 @@ static const Evas_Smart_Cb_Description _smart_callbacks[] = { {SIG_CLICKED, ""}, {SIG_LONGPRESSED, ""}, {SIG_CLICKED_DOUBLE, ""}, + {SIG_ITEM_FOCUSED, ""}, + {SIG_ITEM_UNFOCUSED, ""}, {SIG_WIDGET_LANG_CHANGED, ""}, /**< handled by elm_widget */ {SIG_WIDGET_ACCESS_CHANGED, ""}, /**< handled by elm_widget */ {SIG_WIDGET_FOCUSED, ""}, /**< handled by elm_widget */ @@ -577,46 +581,158 @@ _resize_job(void *data) } static void +_elm_toolbar_item_focused(Elm_Toolbar_Item *it) +{ + Evas_Object *obj = WIDGET(it); + ELM_TOOLBAR_DATA_GET(obj, sd); + const char *focus_raise; + + if ((!sd) || (sd->select_mode == ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY) || + (it == sd->focused_item)) + return; + + sd->focused_item = it; + elm_toolbar_item_show((Elm_Object_Item *)it, ELM_TOOLBAR_ITEM_SCROLLTO_IN); + if (elm_widget_focus_highlight_enabled_get(obj)) + { + edje_object_signal_emit + (VIEW(it), "elm,state,focused", "elm"); + } + edje_object_signal_emit + (VIEW(it), "elm,highlight,on", "elm"); + focus_raise = edje_object_data_get(VIEW(it), "focusraise"); + if ((focus_raise) && (!strcmp(focus_raise, "on"))) + evas_object_raise(VIEW(it)); + evas_object_smart_callback_call + (obj, SIG_ITEM_FOCUSED, it); +} + +static void +_elm_toolbar_item_unfocused(Elm_Toolbar_Item *it) +{ + Evas_Object *obj = WIDGET(it); + ELM_TOOLBAR_DATA_GET(obj, sd); + + if ((!sd) || !sd->focused_item || + (it != sd->focused_item)) + return; + if (sd->select_mode == ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY) + return; + sd->prev_focused_item = it; + if (elm_widget_focus_highlight_enabled_get(obj)) + { + edje_object_signal_emit + (VIEW(sd->focused_item), "elm,state,unfocused", "elm"); + } + edje_object_signal_emit + (VIEW(it), "elm,highlight,off", "elm"); + sd->focused_item = NULL; + evas_object_smart_callback_call + (obj, SIG_ITEM_UNFOCUSED, it); +} + +/* + * This function searches the nearest visible item based on the given item. + * If the given item is in the toolbar viewport, this returns the given item. + * Or this searches other items and checks the nearest fully visible item + * according to the given item's position. + */ +static Elm_Object_Item * +_elm_toolbar_nearest_visible_item_get(Evas_Object *obj, Elm_Object_Item *it) +{ + Evas_Coord vx = 0, vy = 0, vw = 0, vh = 0; // toolbar viewport geometry + Evas_Coord ix = 0, iy = 0, iw = 0, ih = 0; // given item geometry + Evas_Coord cx = 0, cy = 0, cw = 0, ch = 0; // candidate item geometry + Eina_List *item_list = NULL; + Elm_Object_Item *item = NULL; + ELM_TOOLBAR_DATA_GET(obj, sd); + + if (!it) return NULL; + + evas_object_geometry_get(obj, &vx, &vy, &vw, &vh); + evas_object_geometry_get(VIEW(it), &ix, &iy, &iw, &ih); + + if (ELM_RECTS_INCLUDE(vx, vy, vw, vh, ix, iy, iw, ih)) + return it; + + item_list = evas_object_box_children_get(sd->bx); + + if ((sd->vertical && (iy < vy)) || + (!sd->vertical && (iw < vw))) + { + while ((item_list = eina_list_next(item_list))) + { + item = eina_list_data_get(item_list); + evas_object_geometry_get(VIEW(item), &cx, &cy, &cw, &ch); + if (ELM_RECTS_INCLUDE(vx, vy, vw, vh, cx, cy, cw, ch)) + return item; + } + } + else + { + while ((item_list = eina_list_prev(item_list))) + { + item = eina_list_data_get(item_list); + evas_object_geometry_get(VIEW(item), &cx, &cy, &cw, &ch); + if (ELM_RECTS_INCLUDE(vx, vy, vw, vh, cx, cy, cw, ch)) + return item; + } + } + return NULL; +} + +static void _elm_toolbar_smart_on_focus(Eo *obj, void *_pd EINA_UNUSED, va_list *list) { Eina_Bool *ret = va_arg(*list, Eina_Bool *); ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd); ELM_TOOLBAR_DATA_GET(obj, sd); Eina_Bool int_ret = EINA_FALSE; + Elm_Object_Item *it = NULL; eo_do_super(obj, MY_CLASS, elm_obj_widget_on_focus(&int_ret)); if (!int_ret) return; + if (!sd->items) return; - if (elm_widget_focus_get(obj)) - evas_object_focus_set(wd->resize_obj, EINA_TRUE); - else + if (elm_widget_focus_get(obj) && !sd->mouse_down) { - if (sd->highlighted_item) + if (sd->last_focused_item) + it = (Elm_Object_Item *)sd->last_focused_item; + else + it = (Elm_Object_Item *)ELM_TOOLBAR_ITEM_FROM_INLIST(sd->items); + if (it) { - edje_object_signal_emit(VIEW(sd->highlighted_item), "elm,highlight,off", "elm"); - sd->highlighted_item = NULL; + it = _elm_toolbar_nearest_visible_item_get(obj, it); + _elm_toolbar_item_focused((Elm_Toolbar_Item *)it); } + evas_object_focus_set(wd->resize_obj, EINA_TRUE); + } + else + { + sd->prev_focused_item = sd->focused_item; + sd->last_focused_item = sd->focused_item; + if (sd->focused_item) + _elm_toolbar_item_unfocused(sd->focused_item); evas_object_focus_set(wd->resize_obj, EINA_FALSE); } - if (ret) *ret = EINA_TRUE; } static Elm_Toolbar_Item * -_highlight_next_item_get(Evas_Object *obj, Evas_Object *box, Eina_Bool reverse) +_focus_next_item_get(Evas_Object *obj, Eina_Bool reverse) { ELM_TOOLBAR_DATA_GET(obj, sd); Eina_List *list = NULL; Elm_Toolbar_Item *it = NULL; Evas_Object *it_obj = NULL; - list = evas_object_box_children_get(box); + list = evas_object_box_children_get(sd->bx); if (reverse) list = eina_list_reverse(list); - if (sd->highlighted_item) + if (sd->focused_item) { - list = eina_list_data_find_list(list, VIEW(sd->highlighted_item)); + list = eina_list_data_find_list(list, VIEW(sd->focused_item)); if (list) list = eina_list_next(list); } it_obj = eina_list_data_get(list); @@ -642,6 +758,67 @@ _highlight_next_item_get(Evas_Object *obj, Evas_Object *box, Eina_Bool reverse) } static void +_item_focus_set_hook(Elm_Object_Item *it, Eina_Bool focused) +{ + ELM_TOOLBAR_ITEM_CHECK(it); + Evas_Object *obj = WIDGET(it); + ELM_TOOLBAR_DATA_GET(obj, sd); + + if (focused) + { + if (!elm_object_focus_get(obj)) + elm_object_focus_set(obj, EINA_TRUE); + if (it != (Elm_Object_Item *)sd->focused_item) + { + if (sd->focused_item) + _elm_toolbar_item_unfocused(sd->focused_item); + _elm_toolbar_item_focused((Elm_Toolbar_Item *)it); + } + } + else + { + if (it) + _elm_toolbar_item_unfocused((Elm_Toolbar_Item *)it); + } + _elm_widget_focus_highlight_start(obj); +} + +static Eina_Bool +_item_focus_get_hook(Elm_Object_Item *it) +{ + ELM_TOOLBAR_ITEM_CHECK_OR_RETURN(it, EINA_FALSE); + Evas_Object *obj = WIDGET(it); + ELM_TOOLBAR_CHECK(obj) EINA_FALSE; + ELM_TOOLBAR_DATA_GET(obj, sd); + + if (it == (Elm_Object_Item *)sd->focused_item) + return EINA_TRUE; + return EINA_FALSE; +} + +static Eina_Bool +_item_focused_next( Evas_Object *obj, + Eina_Bool reverse, + Elm_Focus_Direction dir) +{ + ELM_TOOLBAR_DATA_GET(obj, sd); + Elm_Toolbar_Item *next_focused_item; + + next_focused_item = _focus_next_item_get(obj, reverse); + if (!next_focused_item) + return EINA_FALSE; + + if ((!sd->vertical && (dir == ELM_FOCUS_LEFT || dir == ELM_FOCUS_RIGHT)) + || (sd->vertical && (dir == ELM_FOCUS_UP || dir == ELM_FOCUS_DOWN))) + { + elm_object_item_focus_set((Elm_Object_Item *)next_focused_item, EINA_TRUE); + return EINA_TRUE; + } + _elm_widget_focus_highlight_start(obj); + return EINA_FALSE; +} + +static void _elm_toolbar_smart_event(Eo *obj, void *_pd, va_list *list) { Evas_Object *src = va_arg(*list, Evas_Object *); @@ -654,9 +831,6 @@ _elm_toolbar_smart_event(Eo *obj, void *_pd, va_list *list) (void) src; (void) type; - Elm_Toolbar_Item *it = NULL; - Evas_Coord x, y, w, h; - if (elm_widget_disabled_get(obj)) return; if (type != EVAS_CALLBACK_KEY_DOWN) return; if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return; @@ -666,56 +840,64 @@ _elm_toolbar_smart_event(Eo *obj, void *_pd, va_list *list) (!strcmp(ev->key, "KP_Enter")) || (!strcmp(ev->key, "space"))) { - if (sd->highlighted_item) - _item_select(sd->highlighted_item); + if (sd->focused_item) + _item_select(sd->focused_item); goto success; } else if ((!strcmp(ev->key, "Left")) || ((!strcmp(ev->key, "KP_Left")) && !ev->string)) { - if (!sd->vertical) - it = _highlight_next_item_get(obj, sd->bx, EINA_TRUE); + if (_item_focused_next(obj, EINA_TRUE, ELM_FOCUS_LEFT)) + { + goto success; + } else - return; + { + if (ret) *ret = EINA_FALSE; + return; + } } else if ((!strcmp(ev->key, "Right")) || ((!strcmp(ev->key, "KP_Right")) && !ev->string)) { - if (!sd->vertical) - it = _highlight_next_item_get(obj, sd->bx, EINA_FALSE); + if (_item_focused_next(obj, EINA_FALSE, ELM_FOCUS_RIGHT)) + { + goto success; + } else - return; + { + if (ret) *ret = EINA_FALSE; + return; + } } else if ((!strcmp(ev->key, "Up")) || ((!strcmp(ev->key, "KP_Up")) && !ev->string)) { - if (sd->vertical) - it = _highlight_next_item_get(obj, sd->bx, EINA_TRUE); + if (_item_focused_next(obj, EINA_TRUE, ELM_FOCUS_UP)) + { + goto success; + } else - return; + { + if (ret) *ret = EINA_FALSE; + return; + } } else if ((!strcmp(ev->key, "Down")) || ((!strcmp(ev->key, "KP_Down")) && !ev->string)) { - if (sd->vertical) - it = _highlight_next_item_get(obj, sd->bx, EINA_FALSE); + if (_item_focused_next(obj, EINA_FALSE, ELM_FOCUS_DOWN)) + { + goto success; + } else - return; + { + if (ret) *ret = EINA_FALSE; + return; + } } - if (!it) - return; - - if (sd->highlighted_item) - edje_object_signal_emit(VIEW(sd->highlighted_item), "elm,highlight,off", "elm"); - sd->highlighted_item = it; - edje_object_signal_emit(VIEW(sd->highlighted_item), "elm,highlight,on", "elm"); - - if (_elm_toolbar_item_coordinates_calc( - sd->highlighted_item, ELM_TOOLBAR_ITEM_SCROLLTO_IN, &x, &y, &w, &h)) - eo_do(obj, elm_interface_scrollable_region_bring_in(x, y, w, h)); - success: ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD; if (ret) *ret = EINA_TRUE; @@ -907,6 +1089,7 @@ static void _item_del(Elm_Toolbar_Item *it) { Elm_Toolbar_Item_State *it_state; + ELM_TOOLBAR_DATA_GET(WIDGET(it), sd); _item_unselect(it); @@ -931,6 +1114,13 @@ _item_del(Elm_Toolbar_Item *it) evas_object_del(it->icon); } + if (sd->focused_item == it) + sd->focused_item = NULL; + if (sd->last_focused_item == it) + sd->last_focused_item = NULL; + if (sd->prev_focused_item == it) + sd->prev_focused_item = NULL; + evas_object_del(it->object); //TODO: See if checking for sd->menu_parent is necessary before //deleting menu @@ -1139,6 +1329,20 @@ _sizing_eval(Evas_Object *obj) } static void +_elm_toolbar_highlight_in_theme(Evas_Object *obj) +{ + const char *fh; + ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd); + + fh = edje_object_data_get + (wd->resize_obj, "focus_highlight"); + if ((fh) && (!strcmp(fh, "on"))) + elm_widget_highlight_in_theme_set(obj, EINA_TRUE); + else + elm_widget_highlight_in_theme_set(obj, EINA_FALSE); +} + +static void _elm_toolbar_smart_theme(Eo *obj, void *_pd, va_list *list) { Elm_Toolbar_Item *it; @@ -1188,6 +1392,7 @@ _elm_toolbar_smart_theme(Eo *obj, void *_pd, va_list *list) if (sd->more_item) _item_theme_hook(obj, sd->more_item, scale, sd->icon_size); + _elm_toolbar_highlight_in_theme(obj); _sizing_eval(obj); if (ret) *ret = EINA_TRUE; @@ -1856,6 +2061,7 @@ _mouse_down_cb(Elm_Toolbar_Item *it, if (ev->button != 1) return; if (ev->flags & EVAS_BUTTON_DOUBLE_CLICK) evas_object_smart_callback_call(WIDGET(it), SIG_CLICKED_DOUBLE, it); + sd->mouse_down = EINA_TRUE; sd->long_press = EINA_FALSE; if (sd->long_timer) ecore_timer_interval_set @@ -1877,7 +2083,11 @@ _mouse_up_cb(Elm_Toolbar_Item *it, ELM_TOOLBAR_DATA_GET(WIDGET(it), sd); if (ev->button != 1) return; + sd->mouse_down = EINA_FALSE; ELM_SAFE_FREE(sd->long_timer, ecore_timer_del); + if ((!elm_object_item_disabled_get((Elm_Object_Item *)it)) && + (sd->focused_item != it)) + elm_object_item_focus_set((Elm_Object_Item *)it, EINA_TRUE); evas_object_event_callback_del_full (VIEW(it), EVAS_CALLBACK_MOUSE_MOVE, (Evas_Object_Event_Cb)_mouse_move_cb, it); @@ -2089,6 +2299,8 @@ _item_new(Evas_Object *obj, elm_widget_item_content_set_hook_set(it, _item_content_set_hook); elm_widget_item_content_get_hook_set(it, _item_content_get_hook); elm_widget_item_content_unset_hook_set(it, _item_content_unset_hook); + elm_widget_item_focus_set_hook_set(it, _item_focus_set_hook); + elm_widget_item_focus_get_hook_set(it, _item_focus_get_hook); it->label = eina_stringshare_add(label); it->prio.visible = 1; @@ -2570,6 +2782,7 @@ _elm_toolbar_smart_add(Eo *obj, void *_pd, va_list *list EINA_UNUSED) (priv->bx, EVAS_CALLBACK_RESIZE, _resize_cb, obj); elm_toolbar_icon_order_lookup_set(obj, ELM_ICON_LOOKUP_THEME_FDO); + _elm_toolbar_highlight_in_theme(obj); _sizing_eval(obj); } @@ -2717,6 +2930,74 @@ _elm_toolbar_smart_access(Eo *obj EINA_UNUSED, void *_pd, va_list *list) _access_obj_process(sd, _elm_toolbar_smart_focus_next_enable); } +static void +_elm_toolbar_coordinates_adjust(Elm_Toolbar_Item *it, + Evas_Coord *x, + Evas_Coord *y, + Evas_Coord *w, + Evas_Coord *h) +{ + ELM_TOOLBAR_DATA_GET(WIDGET(it), sd); + + Evas_Coord ix, iy, iw, ih, vx, vy, vw, vh; + + evas_object_geometry_get(sd->hit_rect, &vx, &vy, &vw, &vh); + evas_object_geometry_get(VIEW(it), &ix, &iy, &iw, &ih); + *x = ix; + *y = iy; + *w = iw; + *h = ih; + if (sd->vertical) + { + //TODO: Enhance it later. + if ((ix < vx) || (ix + iw) > (vx + vw) || (iy + ih) > (vy + vh)) + *y = iy - ih; + else if (iy < vy) + *y = iy + ih; + } + else + { + //TODO: Enhance it later. + if ((iy < vy) || (ix + iw) > (vx + vw) || (iy + ih) > (vy + vh)) + *x = ix - iw; + else if (ix < vx) + *x = ix + iw; + } +} + +static void +_elm_toolbar_focus_highlight_geometry_get(Eo *obj EINA_UNUSED, void *_pd, va_list *list) +{ + Evas_Coord *x = va_arg(*list, Evas_Coord *); + Evas_Coord *y = va_arg(*list, Evas_Coord *); + Evas_Coord *w = va_arg(*list, Evas_Coord *); + Evas_Coord *h = va_arg(*list, Evas_Coord *); + Eina_Bool is_next = va_arg(*list, int); + + Elm_Toolbar_Smart_Data *sd = _pd; + + if (is_next) + { + if (sd->focused_item) + { + _elm_toolbar_coordinates_adjust + (sd->focused_item, x, y, w, h); + elm_widget_focus_highlight_focus_part_geometry_get + (VIEW(sd->focused_item), x, y, w, h); + } + } + else + { + if (sd->prev_focused_item) + { + _elm_toolbar_coordinates_adjust + (sd->prev_focused_item, x, y, w, h); + elm_widget_focus_highlight_focus_part_geometry_get + (VIEW(sd->prev_focused_item), x, y, w, h); + } + } +} + EAPI Evas_Object * elm_toolbar_add(Evas_Object *parent) { @@ -3951,6 +4232,15 @@ elm_toolbar_item_bring_in(Elm_Object_Item *it, Elm_Toolbar_Item_Scrollto_Type ty } static void +_elm_toolbar_focused_item_get(Eo *obj EINA_UNUSED, void *_pd, va_list *list) +{ + Elm_Object_Item **ret = va_arg(*list, Elm_Object_Item **); + Elm_Toolbar_Smart_Data *sd = _pd; + + if (ret) *ret = (Elm_Object_Item *)sd->focused_item; +} + +static void _class_constructor(Eo_Class *klass) { const Eo_Op_Func_Description func_desc[] = { @@ -3969,6 +4259,8 @@ _class_constructor(Eo_Class *klass) EO_OP_FUNC(ELM_OBJ_WIDGET_ID(ELM_OBJ_WIDGET_SUB_ID_FOCUS_NEXT_MANAGER_IS), _elm_toolbar_smart_focus_next_manager_is), EO_OP_FUNC(ELM_OBJ_WIDGET_ID(ELM_OBJ_WIDGET_SUB_ID_FOCUS_NEXT), _elm_toolbar_smart_focus_next), EO_OP_FUNC(ELM_OBJ_WIDGET_ID(ELM_OBJ_WIDGET_SUB_ID_ACCESS), _elm_toolbar_smart_access), + EO_OP_FUNC(ELM_OBJ_WIDGET_ID(ELM_OBJ_WIDGET_SUB_ID_FOCUS_HIGHLIGHT_GEOMETRY_GET), _elm_toolbar_focus_highlight_geometry_get), + EO_OP_FUNC(ELM_OBJ_WIDGET_ID(ELM_OBJ_WIDGET_SUB_ID_FOCUSED_ITEM_GET), _elm_toolbar_focused_item_get), EO_OP_FUNC(ELM_OBJ_TOOLBAR_ID(ELM_OBJ_TOOLBAR_SUB_ID_ICON_SIZE_SET), _icon_size_set), EO_OP_FUNC(ELM_OBJ_TOOLBAR_ID(ELM_OBJ_TOOLBAR_SUB_ID_ICON_SIZE_GET), _icon_size_get), diff --git a/src/lib/elm_toolbar.h b/src/lib/elm_toolbar.h index 818ba88..d80deda 100644 --- a/src/lib/elm_toolbar.h +++ b/src/lib/elm_toolbar.h @@ -31,6 +31,8 @@ * - @c "language,changed" - when the program language changes. * - @c "focused" - When the toolbar has received focus. (since 1.8) * - @c "unfocused" - When the toolbar has lost focus. (since 1.8) + * - @c "item,focused" - When the toolbar item has received focus. (since 1.10) + * - @c "item,unfocused" - When the toolbar item has lost focus. (since 1.10) * * Available styles for it: * - @c "default" @@ -48,6 +50,8 @@ * @li @ref elm_object_item_part_content_set * @li @ref elm_object_item_part_content_get * @li @ref elm_object_item_part_content_unset + * @li @ref elm_object_item_focus_set + * @li @ref elm_object_item_focus_get * * List of examples: * @li @ref toolbar_example_01 diff --git a/src/lib/elm_widget_toolbar.h b/src/lib/elm_widget_toolbar.h index 9c731ea..381dba3 100644 --- a/src/lib/elm_widget_toolbar.h +++ b/src/lib/elm_widget_toolbar.h @@ -29,7 +29,9 @@ struct _Elm_Toolbar_Smart_Data Eina_Inlist *items; Elm_Toolbar_Item *more_item; Elm_Toolbar_Item *selected_item; /**< a selected item by mouse click, return key, api, and etc. */ - Elm_Toolbar_Item *highlighted_item; /**< a highlighted item by keypard arrow */ + Elm_Toolbar_Item *focused_item; /**< a focused item by keypad arrow or mouse. This is set to NULL if widget looses focus. */ + Elm_Toolbar_Item *prev_focused_item; /**< previous focused item by keypad arrow or mouse. */ + Elm_Toolbar_Item *last_focused_item; /**< This records the last focused item when widget looses focus. This is required to set the focus on last focused item when widgets gets focus. */ Elm_Toolbar_Item *reorder_empty, *reorder_item; Elm_Toolbar_Shrink_Mode shrink_mode; Elm_Icon_Lookup_Order lookup_order; @@ -49,6 +51,7 @@ struct _Elm_Toolbar_Smart_Data Eina_Bool delete_me : 1; Eina_Bool reorder_mode : 1; Eina_Bool transverse_expanded : 1; + Eina_Bool mouse_down : 1; /**< a flag that mouse is down on the toolbar at the moment. This flag is set to true on mouse and reset to false on mouse up. */ }; struct _Elm_Toolbar_Item --
