genlist: Add item loop feature

Summary:
If item loop feature is enabled, item is moved infinitely.

    1. Refactor direction key event handling routine
      - added internal function _elm_genlist_elm_widget_event_direction.
    2. Add looping feature for genlist
      - added Eolian function _elm_genlist_elm_widget_item_loop_enabled_set/get.
    3. Add demo - test_genlist.c / genlist focus

Reviewers: seoz, woohyun, jaehwan, Hermet, raster

Reviewed By: Hermet

Differential Revision: https://phab.enlightenment.org/D778

Conflicts:

	src/lib/elm_widget_genlist.h
This commit is contained in:
Hosang Kim 2014-04-24 14:12:52 +09:00 committed by ChunEon Park
parent dab2097569
commit 0f636e890a
4 changed files with 126 additions and 7 deletions

View File

@ -3615,7 +3615,7 @@ test_genlist_del(void *data EINA_UNUSED,
}
/*************/
static unsigned _gl_focus_objects = 5;
static unsigned _gl_focus_objects = 3;
static const char *_gl_focus_object_names[] = {"None", "Square", "Button", "Check", "Box"};
static char *
@ -3674,6 +3674,14 @@ gl_focus_content_get(void *data, Evas_Object *obj, const char *part)
return cnt;
}
static void
test_genlist_focus_item_loop_enable_check_changed(void *data, Evas_Object *obj,
void *event_info EINA_UNUSED)
{
Evas_Object *gl = data;
elm_object_scroll_item_loop_enabled_set(gl, elm_check_state_get(obj));
}
static void
test_genlist_focus_focus_on_selection_set(Evas_Object *gl,
Evas_Object *chk, Eina_Bool focus)
@ -3947,6 +3955,14 @@ test_genlist_focus(void *data EINA_UNUSED,
elm_box_pack_end(bx_opt, chk);
evas_object_show(chk);
chk = elm_check_add(bx_opt);
elm_object_text_set(chk, "Item Looping Enalbe");
evas_object_size_hint_weight_set(chk, EVAS_HINT_EXPAND, 0.0);
evas_object_smart_callback_add(chk, "changed",
test_genlist_focus_item_loop_enable_check_changed, gl);
elm_box_pack_end(bx_opt, chk);
evas_object_show(chk);
// Focus Movement Policy
fr = elm_frame_add(bx);
elm_object_text_set(fr, "Focus Movement Policy");

View File

@ -2576,6 +2576,64 @@ _elm_genlist_item_content_focus_set(Elm_Gen_Item *it, Elm_Focus_Direction dir)
elm_object_focus_set(eina_list_data_get(l), EINA_TRUE);
}
static Eina_Bool
_elm_genlist_elm_widget_event_direction(Evas_Object *obj, Elm_Focus_Direction dir, Eina_Bool multi)
{
ELM_GENLIST_DATA_GET(obj, sd);
Elm_Object_Item *it = NULL;
Eina_Bool ret = EINA_FALSE;
Evas_Coord v = 0;
Evas_Coord min = 0;
// get content size and viewport size
eo_do(obj,
elm_interface_scrollable_content_viewport_geometry_get
(NULL, NULL, NULL, &v),
elm_interface_scrollable_content_size_get(NULL, &min));
if (multi)
{
if (dir == ELM_FOCUS_UP)
ret = _item_multi_select_up(sd);
else if (dir == ELM_FOCUS_DOWN)
ret = _item_multi_select_down(sd);
}
else
{
if (dir == ELM_FOCUS_UP)
ret = _item_single_select_up(sd);
else if (dir == ELM_FOCUS_DOWN)
ret = _item_single_select_down(sd);
}
if (ret)
return EINA_TRUE;
// handle item loop feature
if (sd->item_loop_enable)
{
if (min > v)
{
if (dir == ELM_FOCUS_UP)
elm_layout_signal_emit(obj, "elm,action,looping,up", "elm");
else if (dir == ELM_FOCUS_DOWN)
elm_layout_signal_emit(obj, "elm,action,looping,down", "elm");
}
else
{
if (dir == ELM_FOCUS_UP)
it = elm_genlist_last_item_get(obj);
else if(dir == ELM_FOCUS_DOWN)
it = elm_genlist_first_item_get(obj);
if (it)
elm_genlist_item_selected_set(it, EINA_TRUE);
}
return EINA_TRUE;
}
return EINA_FALSE;
}
static Eina_Bool
_key_action_move(Evas_Object *obj, const char *params)
{
@ -2620,24 +2678,24 @@ _key_action_move(Evas_Object *obj, const char *params)
}
else if (!strcmp(dir, "up"))
{
if (_item_single_select_up(sd)) return EINA_TRUE;
if (_elm_genlist_elm_widget_event_direction(obj, ELM_FOCUS_UP, EINA_FALSE)) return EINA_TRUE;
else return EINA_FALSE;
}
else if (!strcmp(dir, "up_multi"))
{
if (_item_multi_select_up(sd)) return EINA_TRUE;
else if (_item_single_select_up(sd)) return EINA_TRUE;
if (_elm_genlist_elm_widget_event_direction(obj, ELM_FOCUS_UP, EINA_TRUE)) return EINA_TRUE;
else if (_elm_genlist_elm_widget_event_direction(obj, ELM_FOCUS_UP, EINA_FALSE)) return EINA_TRUE;
else return EINA_FALSE;
}
else if (!strcmp(dir, "down"))
{
if (_item_single_select_down(sd)) return EINA_TRUE;
if (_elm_genlist_elm_widget_event_direction(obj, ELM_FOCUS_DOWN, EINA_FALSE)) return EINA_TRUE;
else return EINA_FALSE;
}
else if (!strcmp(dir, "down_multi"))
{
if (_item_multi_select_down(sd)) return EINA_TRUE;
else if (_item_single_select_down(sd)) return EINA_TRUE;
if (_elm_genlist_elm_widget_event_direction(obj, ELM_FOCUS_DOWN, EINA_TRUE)) return EINA_TRUE;
else if (_elm_genlist_elm_widget_event_direction(obj, ELM_FOCUS_DOWN, EINA_FALSE)) return EINA_TRUE;
else return EINA_FALSE;
}
else if (!strcmp(dir, "first"))
@ -5092,6 +5150,31 @@ _decorate_item_unset(Elm_Genlist_Data *sd)
sd->mode_item = NULL;
}
static void
_elm_genlist_looping_up_cb(void *data,
Evas_Object *obj EINA_UNUSED,
const char *emission EINA_UNUSED,
const char *source EINA_UNUSED)
{
Evas_Object *genlist = data;
Elm_Object_Item *it = elm_genlist_last_item_get(genlist);
elm_genlist_item_selected_set(it, EINA_TRUE);
elm_layout_signal_emit(genlist, "elm,action,looping,up,end", "elm");
}
static void
_elm_genlist_looping_down_cb(void *data,
Evas_Object *obj EINA_UNUSED,
const char *emission EINA_UNUSED,
const char *source EINA_UNUSED)
{
Evas_Object *genlist = data;
Elm_Object_Item *it = elm_genlist_first_item_get(genlist);
elm_genlist_item_selected_set(it, EINA_TRUE);
elm_layout_signal_emit(genlist, "elm,action,looping,down,end", "elm");
}
EOLIAN static void
_elm_genlist_evas_smart_add(Eo *obj, Elm_Genlist_Data *priv)
{
@ -5169,6 +5252,9 @@ _elm_genlist_evas_smart_add(Eo *obj, Elm_Genlist_Data *priv)
_mirrored_set(obj, elm_widget_mirrored_get(obj));
elm_layout_sizing_eval(obj);
edje_object_signal_callback_add(wd->resize_obj, "elm,looping,up,done", "elm", _elm_genlist_looping_up_cb, obj);
edje_object_signal_callback_add(wd->resize_obj, "elm,looping,down,done", "elm", _elm_genlist_looping_down_cb, obj);
}
EOLIAN static void
@ -7373,6 +7459,19 @@ _elm_genlist_elm_widget_focused_item_get(Eo *obj EINA_UNUSED, Elm_Genlist_Data *
return sd->focused_item;
}
EOLIAN static void
_elm_genlist_elm_widget_item_loop_enabled_set(Eo *obj EINA_UNUSED, Elm_Genlist_Data *sd, Eina_Bool enable)
{
if (sd->item_loop_enable == enable) return;
sd->item_loop_enable = !!enable;
}
EOLIAN static Eina_Bool
_elm_genlist_elm_widget_item_loop_enabled_get(Eo *obj EINA_UNUSED, Elm_Genlist_Data *sd)
{
return sd->item_loop_enable;
}
EOLIAN static void
_elm_genlist_class_constructor(Eo_Class *klass)
{

View File

@ -701,6 +701,8 @@ class Elm_Genlist (Elm_Layout, Elm_Interface_Scrollable, Evas_Clickable_Interfac
Elm_Widget::sub_object_del;
Elm_Widget::event;
Elm_Widget::focused_item::get;
Elm_Widget::item_loop_enabled::set;
Elm_Widget::item_loop_enabled::get;
Elm_Layout::sub_object_add_enable;
Elm_Layout::sizing_eval;
Elm_Interface_Scrollable::bounce_allow;

View File

@ -184,6 +184,8 @@ struct _Elm_Genlist_Data
* selection */
Eina_Bool swipe : 1;
/**< value whether item loop feature is enabled or not. */
Eina_Bool item_loop_enable : 1;
};
typedef struct _Item_Block Item_Block;