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
This commit is contained in:
Hosang Kim 2014-03-24 17:35:07 +09:00 committed by Daniel Juyung Seo
parent ce30683587
commit 7b4a539e9e
9 changed files with 338 additions and 3 deletions

View File

@ -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";
}
}
}

View File

@ -1309,6 +1309,14 @@ test_list_focus_focus_move_policy_changed(void *data EINA_UNUSED,
elm_config_focus_move_policy_set(ELM_FOCUS_MOVE_POLICY_IN);
}
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)
{
@ -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),

View File

@ -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;
@ -1621,6 +1696,58 @@ _mouse_up_cb(void *data,
evas_object_unref(obj);
}
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)
{
@ -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
@ -3176,6 +3308,25 @@ _elm_list_focused_item_get(Eo *obj EINA_UNUSED, void *_pd, va_list *list)
if (ret) *ret = sd->focused_item;
}
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)
{
@ -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),

View File

@ -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)
{

View File

@ -133,6 +133,35 @@ 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);
/**
* @}
*/

View File

@ -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)
{

View File

@ -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. */

View File

@ -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

View File

@ -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;