From: Hosang Kim Date: Mon, 24 Mar 2014 08:35:07 +0000 (+0900) Subject: list: Add item loop feature X-Git-Tag: v1.10.0+tech+preview~26 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=db00f2e93c12deb56f813087deadc14e1c89147a;p=platform%2Fupstream%2Felementary.git list: Add item loop feature Summary: If item loop feature is enabled, item is moved infinitely. 1. add new widget api - item_loop_enabled 2. add smart event using new config - elm_list.c 3. add demo - test_list.c/list_focus Reviewers: seoz, woohyun, raster, jaehwan, Hermet CC: singh.amitesh, c Differential Revision: https://phab.enlightenment.org/D619 --- diff --git a/data/themes/edc/elm/scroller.edc b/data/themes/edc/elm/scroller.edc index 9898161..0c72146 100644 --- a/data/themes/edc/elm/scroller.edc +++ b/data/themes/edc/elm/scroller.edc @@ -769,6 +769,14 @@ group { name: "elm/scroller/base/default"; visible: 1; } } + part { name: "dim_effect"; type: RECT; mouse_events: 0; + description { state: "default" 0.0; + color: 0 0 0 0; + } + description { state: "effect" 0.0; + color: 50 50 50 255; + } + } } programs { program { @@ -803,6 +811,70 @@ group { name: "elm/scroller/base/default"; target: "glow_hbar"; target: "center_glow_hbar"; } + program { + signal: "elm,action,looping,left"; source: "elm"; + action: STATE_SET "effect" 0.0; + transition: LINEAR 0.3; + target: "dim_effect"; + after: "looping,left,done"; + } + program { name: "looping,left,done"; + action: SIGNAL_EMIT "elm,looping,left,done" "elm"; + } + program { + signal: "elm,action,looping,left,end"; source: "elm"; + action: STATE_SET "default" 0.0; + transition: LINEAR 0.3; + target: "dim_effect"; + } + program { + signal: "elm,action,looping,right"; source: "elm"; + action: STATE_SET "effect" 0.0; + transition: LINEAR 0.3; + target: "dim_effect"; + after: "looping,right,done"; + } + program { name: "looping,right,done"; + action: SIGNAL_EMIT "elm,looping,right,done" "elm"; + } + program { + signal: "elm,action,looping,right,end"; source: "elm"; + action: STATE_SET "default" 0.0; + transition: LINEAR 0.3; + target: "dim_effect"; + } + program { + signal: "elm,action,looping,up"; source: "elm"; + action: STATE_SET "effect" 0.0; + transition: LINEAR 0.3; + target: "dim_effect"; + after: "looping,up,done"; + } + program { name: "looping,up,done"; + action: SIGNAL_EMIT "elm,looping,up,done" "elm"; + } + program { + signal: "elm,action,looping,up,end"; source: "elm"; + action: STATE_SET "default" 0.0; + transition: LINEAR 0.3; + target: "dim_effect"; + } + program { + signal: "elm,action,looping,down"; source: "elm"; + action: STATE_SET "effect" 0.0; + transition: LINEAR 0.3; + target: "dim_effect"; + after: "looping,down,done"; + } + program { name: "looping,down,done"; + action: SIGNAL_EMIT "elm,looping,down,done" "elm"; + } + program { + signal: "elm,action,looping,down,end"; source: "elm"; + action: STATE_SET "default" 0.0; + transition: LINEAR 0.3; + target: "dim_effect"; + } } } diff --git a/src/bin/test_list.c b/src/bin/test_list.c index d864860..faa7a05 100644 --- a/src/bin/test_list.c +++ b/src/bin/test_list.c @@ -1310,6 +1310,14 @@ test_list_focus_focus_move_policy_changed(void *data EINA_UNUSED, } static void +test_list_focus_item_loop_enable_check_changed(void *data, Evas_Object *obj, + void *event_info EINA_UNUSED) +{ + Evas_Object *li = data; + elm_object_scroll_item_loop_enabled_set(li, elm_check_state_get(obj)); +} + +static void _item_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info) { printf("%s: %p\n", (char *)data, event_info); @@ -1497,6 +1505,17 @@ _test_list_focus(const char *name, const char *title, Eina_Bool horiz) test_list_focus_focus_on_selection_set(li, chk, EINA_FALSE); + chk = elm_check_add(bx_opt); + elm_object_text_set(chk, "Item Looping Enable"); + elm_check_state_set(chk, elm_object_scroll_item_loop_enabled_get(li)); + evas_object_size_hint_weight_set(chk, EVAS_HINT_EXPAND, 0.0); + evas_object_smart_callback_add(chk, "changed", + test_list_focus_item_loop_enable_check_changed, + li); + elm_box_pack_end(bx_opt, chk); + evas_object_show(chk); + + elm_box_pack_end(bx, bx_opt); // Focus Movement Policy fr = elm_frame_add(bx); elm_object_text_set(fr, "Focus Movement Policy"); @@ -1572,8 +1591,8 @@ _test_list_focus(const char *name, const char *title, Eina_Bool horiz) if (lhand > 4) lhand = 4; if (rhand > 4) rhand = 4; snprintf(buf, sizeof(buf), " %s / %s ", - _list_focus_names[lhand], - _list_focus_names[rhand]); + _list_focus_names[lhand], + _list_focus_names[rhand]); it = elm_list_item_append(li, buf, test_list_focus_content_get(li, lhand, horiz), diff --git a/src/lib/elm_list.c b/src/lib/elm_list.c index aa0367a..9ae2eff 100644 --- a/src/lib/elm_list.c +++ b/src/lib/elm_list.c @@ -334,6 +334,8 @@ _elm_list_smart_event(Eo *obj, void *_pd, va_list *list) Evas_Coord step_y = 0; Evas_Coord page_x = 0; Evas_Coord page_y = 0; + Evas_Coord minw = 0; + Evas_Coord minh = 0; Elm_List_Item *it = NULL; Eina_Bool sel_ret = EINA_FALSE; @@ -346,7 +348,8 @@ _elm_list_smart_event(Eo *obj, void *_pd, va_list *list) elm_interface_scrollable_content_pos_get(&x, &y), elm_interface_scrollable_step_size_get(&step_x, &step_y), elm_interface_scrollable_page_size_get(&page_x, &page_y), - elm_interface_scrollable_content_viewport_size_get(&v_w, &v_h)); + elm_interface_scrollable_content_viewport_size_get(&v_w, &v_h), + elm_interface_scrollable_content_size_get(&minw, &minh)); /* TODO: fix logic for horizontal mode */ if ((!strcmp(ev->key, "Left")) || @@ -369,6 +372,24 @@ _elm_list_smart_event(Eo *obj, void *_pd, va_list *list) if (ret) *ret = EINA_TRUE; return; } + else + { + if (sd->item_loop_enable) + { + if (minw > v_w) + { + elm_layout_signal_emit(obj, "elm,action,looping,left", "elm"); + } + else + { + it = (Elm_List_Item *)elm_list_last_item_get(obj); + elm_list_item_selected_set((Elm_Object_Item *)it, EINA_TRUE); + } + ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD; + if (ret) *ret = EINA_TRUE; + return; + } + } } if (ret) *ret = EINA_FALSE; return; @@ -393,6 +414,24 @@ _elm_list_smart_event(Eo *obj, void *_pd, va_list *list) if (ret) *ret = EINA_TRUE; return; } + else + { + if (sd->item_loop_enable) + { + if (minw > v_w) + { + elm_layout_signal_emit(obj, "elm,action,looping,right", "elm"); + } + else + { + it = (Elm_List_Item *)elm_list_first_item_get(obj); + elm_list_item_selected_set((Elm_Object_Item *)it, EINA_TRUE); + } + ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD; + if (ret) *ret = EINA_TRUE; + return; + } + } } if (ret) *ret = EINA_FALSE; return; @@ -417,6 +456,24 @@ _elm_list_smart_event(Eo *obj, void *_pd, va_list *list) if (ret) *ret = EINA_TRUE; return; } + else + { + if (sd->item_loop_enable) + { + if (minh > v_h) + { + elm_layout_signal_emit(obj, "elm,action,looping,up", "elm"); + } + else + { + it = (Elm_List_Item *)elm_list_last_item_get(obj); + elm_list_item_selected_set((Elm_Object_Item *)it, EINA_TRUE); + } + ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD; + if (ret) *ret = EINA_TRUE; + return; + } + } } if (ret) *ret = EINA_FALSE; return; @@ -441,6 +498,24 @@ _elm_list_smart_event(Eo *obj, void *_pd, va_list *list) if (ret) *ret = EINA_TRUE; return; } + else + { + if (sd->item_loop_enable) + { + if (minh > v_h) + { + elm_layout_signal_emit(obj, "elm,action,looping,down", "elm"); + } + else + { + it = (Elm_List_Item *)elm_list_first_item_get(obj); + elm_list_item_selected_set((Elm_Object_Item *)it, EINA_TRUE); + } + ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD; + if (ret) *ret = EINA_TRUE; + return; + } + } } if (ret) *ret = EINA_FALSE; return; @@ -1622,6 +1697,58 @@ _mouse_up_cb(void *data, } static void +_elm_list_looping_left_cb(void *data, + Evas_Object *obj EINA_UNUSED, + const char *emission EINA_UNUSED, + const char *source EINA_UNUSED) +{ + Evas_Object *list = data; + Elm_List_Item *it = (Elm_List_Item *)elm_list_last_item_get(list); + elm_list_item_selected_set((Elm_Object_Item *)it, EINA_TRUE); + elm_object_item_focus_set((Elm_Object_Item *)it, EINA_TRUE); + elm_layout_signal_emit(list, "elm,action,looping,left,end", "elm"); +} + +static void +_elm_list_looping_right_cb(void *data, + Evas_Object *obj EINA_UNUSED, + const char *emission EINA_UNUSED, + const char *source EINA_UNUSED) +{ + Evas_Object *list = data; + Elm_List_Item *it = (Elm_List_Item *)elm_list_first_item_get(list); + elm_list_item_selected_set((Elm_Object_Item *)it, EINA_TRUE); + elm_object_item_focus_set((Elm_Object_Item *)it, EINA_TRUE); + elm_layout_signal_emit(list, "elm,action,looping,right,end", "elm"); +} + +static void +_elm_list_looping_up_cb(void *data, + Evas_Object *obj EINA_UNUSED, + const char *emission EINA_UNUSED, + const char *source EINA_UNUSED) +{ + Evas_Object *list = data; + Elm_List_Item *it = (Elm_List_Item *)elm_list_last_item_get(list); + elm_list_item_selected_set((Elm_Object_Item *)it, EINA_TRUE); + elm_object_item_focus_set((Elm_Object_Item *)it, EINA_TRUE); + elm_layout_signal_emit(list, "elm,action,looping,up,end", "elm"); +} + +static void +_elm_list_looping_down_cb(void *data, + Evas_Object *obj EINA_UNUSED, + const char *emission EINA_UNUSED, + const char *source EINA_UNUSED) +{ + Evas_Object *list = data; + Elm_List_Item *it = (Elm_List_Item *)elm_list_first_item_get(list); + elm_list_item_selected_set((Elm_Object_Item *)it, EINA_TRUE); + elm_object_item_focus_set((Elm_Object_Item *)it, EINA_TRUE); + elm_layout_signal_emit(list, "elm,action,looping,down,end", "elm"); +} + +static void _item_disable_hook(Elm_Object_Item *it) { Elm_List_Item *item = (Elm_List_Item *)it; @@ -2133,6 +2260,11 @@ _elm_list_smart_add(Eo *obj, void *_pd, va_list *list EINA_UNUSED) evas_object_event_callback_add (priv->box, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _size_hints_changed_cb, obj); + + edje_object_signal_callback_add(wd->resize_obj, "elm,looping,left,done", "elm", _elm_list_looping_left_cb, obj); + edje_object_signal_callback_add(wd->resize_obj, "elm,looping,right,done", "elm", _elm_list_looping_right_cb, obj); + edje_object_signal_callback_add(wd->resize_obj, "elm,looping,up,done", "elm", _elm_list_looping_up_cb, obj); + edje_object_signal_callback_add(wd->resize_obj, "elm,looping,down,done", "elm", _elm_list_looping_down_cb, obj); } static void @@ -3177,6 +3309,25 @@ _elm_list_focused_item_get(Eo *obj EINA_UNUSED, void *_pd, va_list *list) } static void +_elm_list_item_loop_enabled_set(Eo *obj EINA_UNUSED, void *_pd, va_list *list) +{ + Eina_Bool enable = va_arg(*list, int); + Elm_List_Smart_Data *sd = _pd; + + if (sd->item_loop_enable == enable) return; + sd->item_loop_enable = !!enable; +} + +static void +_elm_list_item_loop_enabled_get(Eo *obj EINA_UNUSED, void *_pd, va_list *list) +{ + Eina_Bool *ret = va_arg(*list, Eina_Bool *); + Elm_List_Smart_Data *sd = _pd; + + if (ret) *ret = sd->item_loop_enable; +} + +static void _class_constructor(Eo_Class *klass) { const Eo_Op_Func_Description func_desc[] = { @@ -3200,6 +3351,8 @@ _class_constructor(Eo_Class *klass) EO_OP_FUNC(ELM_OBJ_WIDGET_ID(ELM_OBJ_WIDGET_SUB_ID_ACCESS), _elm_list_smart_access), EO_OP_FUNC(ELM_OBJ_WIDGET_ID(ELM_OBJ_WIDGET_SUB_ID_FOCUS_HIGHLIGHT_GEOMETRY_GET), _elm_list_focus_highlight_geometry_get), EO_OP_FUNC(ELM_OBJ_WIDGET_ID(ELM_OBJ_WIDGET_SUB_ID_FOCUSED_ITEM_GET), _elm_list_focused_item_get), + EO_OP_FUNC(ELM_OBJ_WIDGET_ID(ELM_OBJ_WIDGET_SUB_ID_ITEM_LOOP_ENABLED_SET), _elm_list_item_loop_enabled_set), + EO_OP_FUNC(ELM_OBJ_WIDGET_ID(ELM_OBJ_WIDGET_SUB_ID_ITEM_LOOP_ENABLED_GET), _elm_list_item_loop_enabled_get), EO_OP_FUNC(ELM_OBJ_LAYOUT_ID(ELM_OBJ_LAYOUT_SUB_ID_SIZING_EVAL), _elm_list_smart_sizing_eval), diff --git a/src/lib/elm_main.c b/src/lib/elm_main.c index 4268811..aacc4f4 100644 --- a/src/lib/elm_main.c +++ b/src/lib/elm_main.c @@ -1530,6 +1530,21 @@ elm_object_scroll_lock_y_get(const Evas_Object *obj) return elm_widget_drag_lock_y_get(obj); } +EAPI void +elm_object_scroll_item_loop_enabled_set(Evas_Object *obj, + Eina_Bool enable) +{ + EINA_SAFETY_ON_NULL_RETURN(obj); + elm_widget_item_loop_enabled_set(obj, enable); +} + +EAPI Eina_Bool +elm_object_scroll_item_loop_enabled_get(const Evas_Object *obj) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EINA_FALSE); + return elm_widget_item_loop_enabled_get(obj); +} + EAPI Eina_Bool elm_object_widget_check(const Evas_Object *obj) { diff --git a/src/lib/elm_scroll.h b/src/lib/elm_scroll.h index 3d5546b..feb541c 100644 --- a/src/lib/elm_scroll.h +++ b/src/lib/elm_scroll.h @@ -134,5 +134,34 @@ EAPI Eina_Bool elm_object_scroll_lock_x_get(const Evas_Object *obj); EAPI Eina_Bool elm_object_scroll_lock_y_get(const Evas_Object *obj); /** + * Enable item loop feature of the given widget + * + * If @p enable is @c EINA_TRUE, item selection/focus will loop internally. + * This means if arrow keys are pressed at end of scroller's item, + * screen is moved to opposite side. + * + * @param obj The object + * @param enable item loop feature (@c EINA_TRUE == enable, @c EINA_FALSE == disable) + * + * @see elm_object_scroll_item_loop_enabled_get() + * @since 1.10 + * @ingroup Scrollitem + */ +EAPI void elm_object_scroll_item_loop_enabled_set(Evas_Object *obj, Eina_Bool enable); + +/** + * Get the item loop enable status of the given widget + * + * This gets the item loop enabled status. + * + * @param obj The object + * + * @see elm_objecdt_scroll_item_enabled_set() + * @since 1.10 + * @ingroup Scrollitem + */ +EAPI Eina_Bool elm_object_scroll_item_loop_enabled_get(const Evas_Object *obj); + +/** * @} */ diff --git a/src/lib/elm_widget.c b/src/lib/elm_widget.c index 4249d75..2ad01bd 100644 --- a/src/lib/elm_widget.c +++ b/src/lib/elm_widget.c @@ -3406,6 +3406,18 @@ _elm_widget_drag_child_locked_y_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data * return sd->child_drag_y_locked; } +EOLIAN static void +_elm_widget_item_loop_enabled_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd EINA_UNUSED, Eina_Bool enable EINA_UNUSED) +{ + return; +} + +EOLIAN static Eina_Bool +_elm_widget_item_loop_enabled_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd EINA_UNUSED) +{ + return EINA_FALSE; +} + EOLIAN static Eina_Bool _elm_widget_theme_object_set(Eo *obj, Elm_Widget_Smart_Data *sd, Evas_Object *edj, const char *wname, const char *welement, const char *wstyle) { diff --git a/src/lib/elm_widget.eo b/src/lib/elm_widget.eo index 0a770fe..8bc1421 100644 --- a/src/lib/elm_widget.eo +++ b/src/lib/elm_widget.eo @@ -317,6 +317,17 @@ abstract Elm_Widget (Evas_Smart) return int; } } + item_loop_enabled { + set { + /*@ Set enable or disable item loop feature. */ + } + get { + /*@ Get the value whether item loop feature is enabled or not. */ + } + values { + Eina_Bool enable; + } + } child_can_focus { get { /*@ No description supplied by the EAPI. */ diff --git a/src/lib/elm_widget.h b/src/lib/elm_widget.h index 9706cfd..da8c432 100644 --- a/src/lib/elm_widget.h +++ b/src/lib/elm_widget.h @@ -727,6 +727,8 @@ EAPI Eina_Bool elm_widget_drag_lock_x_get(const Evas_Object *obj); EAPI Eina_Bool elm_widget_drag_lock_y_get(const Evas_Object *obj); EAPI int elm_widget_drag_child_locked_x_get(const Evas_Object *obj); EAPI int elm_widget_drag_child_locked_y_get(const Evas_Object *obj); +EAPI void elm_widget_item_loop_enabled_set(Evas_Object *obj, Eina_Bool enable); +EAPI Eina_Bool elm_widget_item_loop_enabled_get(const Evas_Object *obj); EAPI Eina_Bool elm_widget_theme_object_set(Evas_Object *obj, Evas_Object *edj, const char *wname, const char *welement, const char *wstyle); EAPI Eina_Bool elm_widget_type_check(const Evas_Object *obj, const char *type, const char *func); EAPI Evas_Object *elm_widget_name_find(const Evas_Object *obj, const char *name, int recurse); @@ -1281,6 +1283,8 @@ enum ELM_WIDGET_SUB_ID_DRAG_LOCK_Y_GET, ELM_WIDGET_SUB_ID_DRAG_CHILD_LOCKED_X_GET, ELM_WIDGET_SUB_ID_DRAG_CHILD_LOCKED_Y_GET, + ELM_WIDGET_SUB_ID_ITEM_LOOP_ENABLED_SET, + ELM_WIDGET_SUB_ID_ITEM_LOOP_ENABLED_GET, ELM_WIDGET_SUB_ID_EVENT_CALLBACK_ADD, ELM_WIDGET_SUB_ID_EVENT_CALLBACK_DEL, @@ -2257,6 +2261,25 @@ enum */ #define elm_wdg_drag_child_locked_y_get(ret) ELM_WIDGET_ID(ELM_WIDGET_SUB_ID_DRAG_CHILD_LOCKED_Y_GET), EO_TYPECHECK(int *, ret) +/** + * @def elm_wdg_item_loop_enabled_set + * @since 1.10 + * + * Set enable or disable item loop feature. + * + * @param[in] enable + */ +#define elm_wdg_item_loop_enabled_set(enable) ELM_WIDGET_ID(ELM_WIDGET_SUB_ID_ITEM_LOOP_ENABLED_SET), EO_TYPECHECK(Eina_Bool, enable) + +/** + * @def elm_wdg_item_loop_enabled_get + * @since 1.10 + * + * Get the value whether item loop feature is enabled or not. + * + * @param[out] ret + */ +#define elm_wdg_item_loop_enabled_get(ret) ELM_WIDGET_ID(ELM_WIDGET_SUB_ID_ITEM_LOOP_ENABLED_GET), EO_TYPECHECK(Eina_Bool *, ret) /** * @def elm_wdg_event_callback_add diff --git a/src/lib/elm_widget_list.h b/src/lib/elm_widget_list.h index b6dfb9e..ddb0f42 100644 --- a/src/lib/elm_widget_list.h +++ b/src/lib/elm_widget_list.h @@ -54,6 +54,7 @@ struct _Elm_List_Smart_Data Eina_Bool swipe : 1; Eina_Bool delete_me : 1; Eina_Bool mouse_down : 1; /**< a flag that mouse is down on the list at the moment. this flag is set to true on mouse and reset to false on mouse up */ + Eina_Bool item_loop_enable : 1; /**< value whether item loop feature is enabled or not. */ }; typedef struct _Elm_List_Item Elm_List_Item;