X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Flib%2Felm_list.c;h=d370baac54d95726acdc5e79543f8ec58e857943;hb=7fe2818cc3815724be0e6957d4c862688505fd6d;hp=2272fddce13a33d3d827d4924785ebc378892ced;hpb=112bd08738fd3112a59bdd084d3fd40d68507ef4;p=framework%2Fuifw%2Felementary.git diff --git a/src/lib/elm_list.c b/src/lib/elm_list.c index 2272fdd..d370baa 100644 --- a/src/lib/elm_list.c +++ b/src/lib/elm_list.c @@ -1,55 +1,40 @@ #include #include "elm_priv.h" +#include "els_scroller.h" #define SWIPE_MOVES 12 -/** - * @defgroup List List - * - * A list is a very simple type of list widget. For more robust - * lists, @ref Genlist should probably be used. - * - * Signals that you can add callbacks for are: - * - * "clicked,double" - when the user double-clicked an item - * "selected" - when the user selected an item - * "unselected" - when the user selected an item - * "longpressed" - an item in the hoversel list is long-pressed - * "scroll,edge,top" - the list is scrolled until the top edge - * "scroll,edge,bottom" - the list is scrolled until the bottom edge - * "scroll,edge,left" - the list is scrolled until the left edge - * "scroll,edge,right" - the list is scrolled until the right edge - */ - typedef struct _Widget_Data Widget_Data; +typedef struct _Elm_List_Item Elm_List_Item; struct _Widget_Data { Evas_Object *scr, *box, *self; Eina_List *items, *selected, *to_delete; - Elm_List_Item *last_selected_item; + Elm_Object_Item *last_selected_item; Elm_List_Mode mode; Elm_List_Mode h_mode; Evas_Coord minw[2], minh[2]; - Eina_Bool scr_minw : 1; - Eina_Bool scr_minh : 1; + Elm_Object_Select_Mode select_mode; int walking; int movements; - struct { + struct + { Evas_Coord x, y; - } history[SWIPE_MOVES]; + } history[SWIPE_MOVES]; + Eina_Bool scr_minw : 1; + Eina_Bool scr_minh : 1; Eina_Bool swipe : 1; Eina_Bool fix_pending : 1; Eina_Bool on_hold : 1; Eina_Bool multi : 1; - Eina_Bool always_select : 1; Eina_Bool longpressed : 1; Eina_Bool wasselected : 1; }; struct _Elm_List_Item { - Elm_Widget_Item base; + ELM_WIDGET_ITEM; Widget_Data *wd; Eina_List *node; const char *label; @@ -58,13 +43,12 @@ struct _Elm_List_Item Ecore_Timer *long_timer; Ecore_Timer *swipe_timer; Eina_Bool deleted : 1; - Eina_Bool disabled : 1; Eina_Bool even : 1; Eina_Bool is_even : 1; Eina_Bool is_separator : 1; Eina_Bool fixed : 1; Eina_Bool selected : 1; - Eina_Bool hilighted : 1; + Eina_Bool highlighted : 1; Eina_Bool dummy_icon : 1; Eina_Bool dummy_end : 1; }; @@ -83,10 +67,10 @@ static void _fix_items(Evas_Object *obj); static void _mouse_down(void *data, Evas *evas, Evas_Object *obj, void *event_info); static void _mouse_up(void *data, Evas *evas, Evas_Object *obj, void *event_info); static void _mouse_move(void *data, Evas *evas, Evas_Object *obj, void *event_info); -static void _scroll_edge_left(void *data, Evas_Object *scr, void *event_info); -static void _scroll_edge_right(void *data, Evas_Object *scr, void *event_info); -static void _scroll_edge_top(void *data, Evas_Object *scr, void *event_info); -static void _scroll_edge_bottom(void *data, Evas_Object *scr, void *event_info); +static void _edge_left(void *data, Evas_Object *scr, void *event_info); +static void _edge_right(void *data, Evas_Object *scr, void *event_info); +static void _edge_top(void *data, Evas_Object *scr, void *event_info); +static void _edge_bottom(void *data, Evas_Object *scr, void *event_info); static Eina_Bool _item_multi_select_up(Widget_Data *wd); static Eina_Bool _item_multi_select_down(Widget_Data *wd); static Eina_Bool _item_single_select_up(Widget_Data *wd); @@ -95,30 +79,32 @@ static Eina_Bool _event_hook(Evas_Object *obj, Evas_Object *src, Evas_Callback_Type type, void *event_info); static Eina_Bool _deselect_all_items(Widget_Data *wd); +static const char SIG_ACTIVATED[] = "activated"; static const char SIG_CLICKED_DOUBLE[] = "clicked,double"; static const char SIG_SELECTED[] = "selected"; static const char SIG_UNSELECTED[] = "unselected"; static const char SIG_LONGPRESSED[] = "longpressed"; -static const char SIG_SCROLL_EDGE_TOP[] = "scroll,edge,top"; -static const char SIG_SCROLL_EDGE_BOTTOM[] = "scroll,edge,bottom"; -static const char SIG_SCROLL_EDGE_LEFT[] = "scroll,edge,left"; -static const char SIG_SCROLL_EDGE_RIGHT[] = "scroll,edge,right"; +static const char SIG_EDGE_TOP[] = "edge,top"; +static const char SIG_EDGE_BOTTOM[] = "edge,bottom"; +static const char SIG_EDGE_LEFT[] = "edge,left"; +static const char SIG_EDGE_RIGHT[] = "edge,right"; static const Evas_Smart_Cb_Description _signals[] = { + {SIG_ACTIVATED, ""}, {SIG_CLICKED_DOUBLE, ""}, {SIG_SELECTED, ""}, {SIG_UNSELECTED, ""}, {SIG_LONGPRESSED, ""}, - {SIG_SCROLL_EDGE_TOP, ""}, - {SIG_SCROLL_EDGE_BOTTOM, ""}, - {SIG_SCROLL_EDGE_LEFT, ""}, - {SIG_SCROLL_EDGE_RIGHT, ""}, + {SIG_EDGE_TOP, ""}, + {SIG_EDGE_BOTTOM, ""}, + {SIG_EDGE_LEFT, ""}, + {SIG_EDGE_RIGHT, ""}, {NULL, NULL} }; #define ELM_LIST_ITEM_CHECK_DELETED_RETURN(it, ...) \ - ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, __VA_ARGS__); \ -if (it->deleted) \ + ELM_OBJ_ITEM_CHECK_OR_RETURN(it, __VA_ARGS__); \ +if (((Elm_List_Item *)it)->deleted) \ { \ ERR("ERROR: "#it" has been DELETED.\n"); \ return __VA_ARGS__; \ @@ -128,30 +114,30 @@ static inline void _elm_list_item_free(Elm_List_Item *it) { evas_object_event_callback_del_full - (it->base.view, EVAS_CALLBACK_MOUSE_DOWN, _mouse_down, it); + (VIEW(it), EVAS_CALLBACK_MOUSE_DOWN, _mouse_down, it); evas_object_event_callback_del_full - (it->base.view, EVAS_CALLBACK_MOUSE_UP, _mouse_up, it); + (VIEW(it), EVAS_CALLBACK_MOUSE_UP, _mouse_up, it); evas_object_event_callback_del_full - (it->base.view, EVAS_CALLBACK_MOUSE_MOVE, _mouse_move, it); + (VIEW(it), EVAS_CALLBACK_MOUSE_MOVE, _mouse_move, it); if (it->icon) evas_object_event_callback_del_full (it->icon, EVAS_CALLBACK_CHANGED_SIZE_HINTS, - _changed_size_hints, it->base.widget); + _changed_size_hints, WIDGET(it)); if (it->end) evas_object_event_callback_del_full (it->end, EVAS_CALLBACK_CHANGED_SIZE_HINTS, - _changed_size_hints, it->base.widget); + _changed_size_hints, WIDGET(it)); eina_stringshare_del(it->label); if (it->swipe_timer) ecore_timer_del(it->swipe_timer); + it->swipe_timer = NULL; if (it->long_timer) ecore_timer_del(it->long_timer); + it->long_timer = NULL; if (it->icon) evas_object_del(it->icon); if (it->end) evas_object_del(it->end); - - elm_widget_item_del(it); } static Eina_Bool @@ -182,7 +168,7 @@ _event_hook(Evas_Object *obj, Evas_Object *src __UNUSED__, Evas_Callback_Type ty /* TODO: fix logic for horizontal mode */ if ((!strcmp(ev->keyname, "Left")) || - (!strcmp(ev->keyname, "KP_Left"))) + ((!strcmp(ev->keyname, "KP_Left")) && !ev->string)) { if ((wd->h_mode) && (((evas_key_modifier_is_set(ev->modifiers, "Shift")) && @@ -196,7 +182,7 @@ _event_hook(Evas_Object *obj, Evas_Object *src __UNUSED__, Evas_Callback_Type ty x -= step_x; } else if ((!strcmp(ev->keyname, "Right")) || - (!strcmp(ev->keyname, "KP_Right"))) + ((!strcmp(ev->keyname, "KP_Right")) && !ev->string)) { if ((wd->h_mode) && (((evas_key_modifier_is_set(ev->modifiers, "Shift")) && @@ -210,7 +196,7 @@ _event_hook(Evas_Object *obj, Evas_Object *src __UNUSED__, Evas_Callback_Type ty x += step_x; } else if ((!strcmp(ev->keyname, "Up")) || - (!strcmp(ev->keyname, "KP_Up"))) + ((!strcmp(ev->keyname, "KP_Up")) && !ev->string)) { if ((!wd->h_mode) && (((evas_key_modifier_is_set(ev->modifiers, "Shift")) && @@ -224,7 +210,7 @@ _event_hook(Evas_Object *obj, Evas_Object *src __UNUSED__, Evas_Callback_Type ty y -= step_y; } else if ((!strcmp(ev->keyname, "Down")) || - (!strcmp(ev->keyname, "KP_Down"))) + ((!strcmp(ev->keyname, "KP_Down")) && !ev->string)) { if ((!wd->h_mode) && (((evas_key_modifier_is_set(ev->modifiers, "Shift")) && @@ -238,23 +224,23 @@ _event_hook(Evas_Object *obj, Evas_Object *src __UNUSED__, Evas_Callback_Type ty y += step_y; } else if ((!strcmp(ev->keyname, "Home")) || - (!strcmp(ev->keyname, "KP_Home"))) + ((!strcmp(ev->keyname, "KP_Home")) && !ev->string)) { it = eina_list_data_get(wd->items); - elm_list_item_bring_in(it); + elm_list_item_bring_in((Elm_Object_Item *)it); ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD; return EINA_TRUE; } else if ((!strcmp(ev->keyname, "End")) || - (!strcmp(ev->keyname, "KP_End"))) + ((!strcmp(ev->keyname, "KP_End")) && !ev->string)) { it = eina_list_data_get(eina_list_last(wd->items)); - elm_list_item_bring_in(it); + elm_list_item_bring_in((Elm_Object_Item *)it); ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD; return EINA_TRUE; } else if ((!strcmp(ev->keyname, "Prior")) || - (!strcmp(ev->keyname, "KP_Prior"))) + ((!strcmp(ev->keyname, "KP_Prior")) && !ev->string)) { if (wd->h_mode) { @@ -272,7 +258,7 @@ _event_hook(Evas_Object *obj, Evas_Object *src __UNUSED__, Evas_Callback_Type ty } } else if ((!strcmp(ev->keyname, "Next")) || - (!strcmp(ev->keyname, "KP_Next"))) + ((!strcmp(ev->keyname, "KP_Next")) && !ev->string)) { if (wd->h_mode) { @@ -289,6 +275,14 @@ _event_hook(Evas_Object *obj, Evas_Object *src __UNUSED__, Evas_Callback_Type ty y += page_y; } } + else if (((!strcmp(ev->keyname, "Return")) || + (!strcmp(ev->keyname, "KP_Enter")) || + (!strcmp(ev->keyname, "space"))) + && (!wd->multi) && (wd->selected)) + { + it = (Elm_List_Item *) elm_list_selected_item_get(obj); + evas_object_smart_callback_call(WIDGET(it), SIG_ACTIVATED, it); + } else if (!strcmp(ev->keyname, "Escape")) { if (!_deselect_all_items(wd)) return EINA_FALSE; @@ -302,12 +296,19 @@ _event_hook(Evas_Object *obj, Evas_Object *src __UNUSED__, Evas_Callback_Type ty return EINA_TRUE; } +static void +_translate_hook(Evas_Object *obj) +{ + evas_object_smart_callback_call(obj, "language,changed", NULL); +} + static Eina_Bool _deselect_all_items(Widget_Data *wd) { if (!wd->selected) return EINA_FALSE; while (wd->selected) - elm_list_item_selected_set(wd->selected->data, EINA_FALSE); + elm_list_item_selected_set((Elm_Object_Item *) wd->selected->data, + EINA_FALSE); return EINA_TRUE; } @@ -318,7 +319,7 @@ _item_multi_select_up(Widget_Data *wd) if (!wd->selected) return EINA_FALSE; if (!wd->multi) return EINA_FALSE; - Elm_List_Item *prev = elm_list_item_prev(wd->last_selected_item); + Elm_Object_Item *prev = elm_list_item_prev(wd->last_selected_item); if (!prev) return EINA_TRUE; if (elm_list_item_selected_get(prev)) @@ -341,7 +342,7 @@ _item_multi_select_down(Widget_Data *wd) if (!wd->selected) return EINA_FALSE; if (!wd->multi) return EINA_FALSE; - Elm_List_Item *next = elm_list_item_next(wd->last_selected_item); + Elm_Object_Item *next = elm_list_item_next(wd->last_selected_item); if (!next) return EINA_TRUE; if (elm_list_item_selected_get(next)) @@ -361,11 +362,10 @@ _item_multi_select_down(Widget_Data *wd) static Eina_Bool _item_single_select_up(Widget_Data *wd) { - Elm_List_Item *prev; + Elm_Object_Item *prev; if (!wd->selected) prev = eina_list_data_get(eina_list_last(wd->items)); else prev = elm_list_item_prev(wd->last_selected_item); - if (!prev) return EINA_FALSE; _deselect_all_items(wd); @@ -378,11 +378,10 @@ _item_single_select_up(Widget_Data *wd) static Eina_Bool _item_single_select_down(Widget_Data *wd) { - Elm_List_Item *next; + Elm_Object_Item *next; if (!wd->selected) next = eina_list_data_get(wd->items); else next = elm_list_item_next(wd->last_selected_item); - if (!next) return EINA_FALSE; _deselect_all_items(wd); @@ -401,10 +400,9 @@ _elm_list_process_deletions(Widget_Data *wd) EINA_LIST_FREE(wd->to_delete, it) { - elm_widget_item_pre_notify_del(it); - wd->items = eina_list_remove_list(wd->items, it->node); _elm_list_item_free(it); + elm_widget_item_free(it); } wd->walking--; @@ -449,8 +447,25 @@ static void _del_pre_hook(Evas_Object *obj) { Widget_Data *wd = elm_widget_data_get(obj); + const Eina_List *l; + Elm_List_Item *it; + + evas_object_smart_callback_del(obj, "sub-object-del", _sub_del); + if (!wd) return; + EINA_LIST_FOREACH(wd->items, l, it) + { + if (it->icon) + evas_object_event_callback_del(it->icon, + EVAS_CALLBACK_CHANGED_SIZE_HINTS, + _changed_size_hints); + if (it->end) + evas_object_event_callback_del(it->end, + EVAS_CALLBACK_CHANGED_SIZE_HINTS, + _changed_size_hints); + } + evas_object_event_callback_del(wd->scr, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _changed_size_hints); @@ -476,7 +491,11 @@ _del_hook(Evas_Object *obj) if (wd->to_delete) ERR("ERROR: leaking nodes!\n"); - EINA_LIST_FREE(wd->items, it) _elm_list_item_free(it); + EINA_LIST_FREE(wd->items, it) + { + _elm_list_item_free(it); + elm_widget_item_free(it); + } eina_list_free(wd->selected); free(wd); } @@ -501,7 +520,7 @@ _disable_hook(Evas_Object *obj) _signal_emit_hook(obj, "elm,state,disabled", "elm"); elm_widget_scroll_freeze_push(obj); elm_widget_scroll_hold_push(obj); - /* FIXME: if we get to have a way to only un-hilight items + /* FIXME: if we get to have a way to only un-highlight items * in the future, keeping them selected... */ _deselect_all_items(wd); } @@ -593,7 +612,7 @@ _mirrored_set(Evas_Object *obj, Eina_Bool rtl) elm_smart_scroller_mirrored_set(wd->scr, rtl); EINA_LIST_FOREACH(wd->items, n, it) - edje_object_mirrored_set(it->base.view, rtl); + edje_object_mirrored_set(VIEW(it), rtl); } static void @@ -625,7 +644,7 @@ _theme_hook(Evas_Object *obj) } EINA_LIST_FOREACH(wd->items, n, it) { - edje_object_scale_set(it->base.view, elm_widget_scale_get(obj) * _elm_config->scale); + edje_object_scale_set(VIEW(it), elm_widget_scale_get(obj) * _elm_config->scale); it->fixed = 0; } _fix_items(obj); @@ -695,24 +714,25 @@ _sub_del(void *data __UNUSED__, Evas_Object *obj, void *event_info) } static void -_item_hilight(Elm_List_Item *it) +_item_highlight(Elm_List_Item *it) { - Evas_Object *obj = it->base.widget; + Evas_Object *obj = WIDGET(it); Widget_Data *wd = elm_widget_data_get(obj); const char *selectraise; if (!wd) return; ELM_LIST_ITEM_CHECK_DELETED_RETURN(it); - if (it->hilighted) return; + if ((it->highlighted) || (it->base.disabled) || + (wd->select_mode == ELM_OBJECT_SELECT_MODE_NONE)) return; evas_object_ref(obj); _elm_list_walk(wd); - edje_object_signal_emit(it->base.view, "elm,state,selected", "elm"); - selectraise = edje_object_data_get(it->base.view, "selectraise"); + edje_object_signal_emit(VIEW(it), "elm,state,selected", "elm"); + selectraise = edje_object_data_get(VIEW(it), "selectraise"); if ((selectraise) && (!strcmp(selectraise, "on"))) - evas_object_raise(it->base.view); - it->hilighted = EINA_TRUE; + evas_object_raise(VIEW(it)); + it->highlighted = EINA_TRUE; _elm_list_unwalk(wd); evas_object_unref(obj); @@ -721,14 +741,15 @@ _item_hilight(Elm_List_Item *it) static void _item_select(Elm_List_Item *it) { - Evas_Object *obj = it->base.widget; + Evas_Object *obj = WIDGET(it); Widget_Data *wd = elm_widget_data_get(obj); if (!wd) return; ELM_LIST_ITEM_CHECK_DELETED_RETURN(it); + if (it->base.disabled || (wd->select_mode == ELM_OBJECT_SELECT_MODE_NONE)) return; if (it->selected) { - if (wd->always_select) goto call; + if (wd->select_mode == ELM_OBJECT_SELECT_MODE_ALWAYS) goto call; return; } it->selected = EINA_TRUE; @@ -738,9 +759,9 @@ call: evas_object_ref(obj); _elm_list_walk(wd); - if (it->func) it->func((void *)it->base.data, it->base.widget, it); + if (it->func) it->func((void *)it->base.data, WIDGET(it), it); evas_object_smart_callback_call(obj, SIG_SELECTED, it); - it->wd->last_selected_item = it; + it->wd->last_selected_item = (Elm_Object_Item *)it; _elm_list_unwalk(wd); evas_object_unref(obj); @@ -749,31 +770,31 @@ call: static void _item_unselect(Elm_List_Item *it) { - Evas_Object *obj = it->base.widget; + Evas_Object *obj = WIDGET(it); Widget_Data *wd = elm_widget_data_get(obj); const char *stacking, *selectraise; if (!wd) return; ELM_LIST_ITEM_CHECK_DELETED_RETURN(it); - if (!it->hilighted) return; + if (!it->highlighted) return; evas_object_ref(obj); _elm_list_walk(wd); - edje_object_signal_emit(it->base.view, "elm,state,unselected", "elm"); - stacking = edje_object_data_get(it->base.view, "stacking"); - selectraise = edje_object_data_get(it->base.view, "selectraise"); + edje_object_signal_emit(VIEW(it), "elm,state,unselected", "elm"); + stacking = edje_object_data_get(VIEW(it), "stacking"); + selectraise = edje_object_data_get(VIEW(it), "selectraise"); if ((selectraise) && (!strcmp(selectraise, "on"))) { if ((stacking) && (!strcmp(stacking, "below"))) - evas_object_lower(it->base.view); + evas_object_lower(VIEW(it)); } - it->hilighted = EINA_FALSE; + it->highlighted = EINA_FALSE; if (it->selected) { it->selected = EINA_FALSE; wd->selected = eina_list_remove(wd->selected, it); - evas_object_smart_callback_call(it->base.widget, SIG_UNSELECTED, it); + evas_object_smart_callback_call(WIDGET(it), SIG_UNSELECTED, it); } _elm_list_unwalk(wd); @@ -784,7 +805,7 @@ static Eina_Bool _swipe_cancel(void *data) { Elm_List_Item *it = data; - Widget_Data *wd = elm_widget_data_get(it->base.widget); + Widget_Data *wd = elm_widget_data_get(WIDGET(it)); if (!wd) return ECORE_CALLBACK_CANCEL; ELM_LIST_ITEM_CHECK_DELETED_RETURN(it, ECORE_CALLBACK_CANCEL); @@ -797,7 +818,7 @@ static void _mouse_move(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info) { Elm_List_Item *it = data; - Evas_Object *obj2 = it->base.widget; + Evas_Object *obj2 = WIDGET(it); Widget_Data *wd = elm_widget_data_get(obj2); Evas_Event_Mouse_Move *ev = event_info; @@ -837,48 +858,48 @@ _mouse_move(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void } static void -_scroll_edge_left(void *data, Evas_Object *scr __UNUSED__, void *event_info __UNUSED__) +_edge_left(void *data, Evas_Object *scr __UNUSED__, void *event_info __UNUSED__) { Evas_Object *obj = data; - evas_object_smart_callback_call(obj, SIG_SCROLL_EDGE_LEFT, NULL); + evas_object_smart_callback_call(obj, SIG_EDGE_LEFT, NULL); } static void -_scroll_edge_right(void *data, Evas_Object *scr __UNUSED__, void *event_info __UNUSED__) +_edge_right(void *data, Evas_Object *scr __UNUSED__, void *event_info __UNUSED__) { Evas_Object *obj = data; - evas_object_smart_callback_call(obj, SIG_SCROLL_EDGE_RIGHT, NULL); + evas_object_smart_callback_call(obj, SIG_EDGE_RIGHT, NULL); } static void -_scroll_edge_top(void *data, Evas_Object *scr __UNUSED__, void *event_info __UNUSED__) +_edge_top(void *data, Evas_Object *scr __UNUSED__, void *event_info __UNUSED__) { Evas_Object *obj = data; - evas_object_smart_callback_call(obj, SIG_SCROLL_EDGE_TOP, NULL); + evas_object_smart_callback_call(obj, SIG_EDGE_TOP, NULL); } static void -_scroll_edge_bottom(void *data, Evas_Object *scr __UNUSED__, void *event_info __UNUSED__) +_edge_bottom(void *data, Evas_Object *scr __UNUSED__, void *event_info __UNUSED__) { Evas_Object *obj = data; - evas_object_smart_callback_call(obj, SIG_SCROLL_EDGE_BOTTOM, NULL); + evas_object_smart_callback_call(obj, SIG_EDGE_BOTTOM, NULL); } static Eina_Bool _long_press(void *data) { Elm_List_Item *it = data; - Evas_Object *obj = it->base.widget; + Evas_Object *obj = WIDGET(it); Widget_Data *wd = elm_widget_data_get(obj); if (!wd) goto end; ELM_LIST_ITEM_CHECK_DELETED_RETURN(it, ECORE_CALLBACK_CANCEL); it->long_timer = NULL; - if (it->disabled) goto end; + if (it->base.disabled) goto end; wd->longpressed = EINA_TRUE; - evas_object_smart_callback_call(it->base.widget, SIG_LONGPRESSED, it); + evas_object_smart_callback_call(WIDGET(it), SIG_LONGPRESSED, it); end: return ECORE_CALLBACK_CANCEL; @@ -888,7 +909,7 @@ static void _swipe(Elm_List_Item *it) { int i, sum = 0; - Widget_Data *wd = elm_widget_data_get(it->base.widget); + Widget_Data *wd = elm_widget_data_get(WIDGET(it)); ELM_LIST_ITEM_CHECK_DELETED_RETURN(it); if (!wd) return; @@ -901,14 +922,14 @@ _swipe(Elm_List_Item *it) sum /= wd->movements; if (abs(sum - wd->history[0].x) <= 10) return; - evas_object_smart_callback_call(it->base.widget, "swipe", it); + evas_object_smart_callback_call(WIDGET(it), "swipe", it); } static void _mouse_down(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info) { Elm_List_Item *it = data; - Evas_Object *obj2 = it->base.widget; + Evas_Object *obj2 = WIDGET(it); Widget_Data *wd = elm_widget_data_get(obj2); Evas_Event_Mouse_Down *ev = event_info; @@ -923,7 +944,7 @@ _mouse_down(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void evas_object_ref(obj2); _elm_list_walk(wd); - _item_hilight(it); + _item_highlight(it); wd->longpressed = EINA_FALSE; if (it->long_timer) ecore_timer_del(it->long_timer); it->long_timer = ecore_timer_add(_elm_config->longpress_timeout, _long_press, it); @@ -931,7 +952,10 @@ _mouse_down(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void it->swipe_timer = ecore_timer_add(0.4, _swipe_cancel, it); /* Always call the callbacks last - the user may delete our context! */ if (ev->flags & EVAS_BUTTON_DOUBLE_CLICK) - evas_object_smart_callback_call(it->base.widget, SIG_CLICKED_DOUBLE, it); + { + evas_object_smart_callback_call(WIDGET(it), SIG_CLICKED_DOUBLE, it); + evas_object_smart_callback_call(WIDGET(it), SIG_ACTIVATED, it); + } wd->swipe = EINA_FALSE; wd->movements = 0; @@ -943,7 +967,7 @@ static void _mouse_up(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info) { Elm_List_Item *it = data; - Evas_Object *obj2 = it->base.widget; + Evas_Object *obj2 = WIDGET(it); Widget_Data *wd = elm_widget_data_get(obj2); Evas_Event_Mouse_Up *ev = event_info; @@ -976,7 +1000,7 @@ _mouse_up(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void * return; } - if (it->disabled) + if (it->base.disabled) return; if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return; @@ -987,7 +1011,7 @@ _mouse_up(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void * { if (!it->selected) { - _item_hilight(it); + _item_highlight(it); _item_select(it); } else _item_unselect(it); @@ -998,7 +1022,7 @@ _mouse_up(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void * { while (wd->selected) _item_unselect(wd->selected->data); - _item_hilight(it); + _item_highlight(it); _item_select(it); } else @@ -1008,7 +1032,7 @@ _mouse_up(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void * EINA_LIST_FOREACH_SAFE(wd->selected, l, l_next, it2) if (it2 != it) _item_unselect(it2); - _item_hilight(it); + _item_highlight(it); _item_select(it); } } @@ -1017,6 +1041,144 @@ _mouse_up(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void * evas_object_unref(obj2); } +static void +_item_disable(Elm_Object_Item *it) +{ + Elm_List_Item *item = (Elm_List_Item *)it; + if (item->base.disabled) + edje_object_signal_emit(VIEW(item), "elm,state,disabled", "elm"); + else + edje_object_signal_emit(VIEW(item), "elm,state,enabled", "elm"); +} + +static void +_item_content_set_hook(Elm_Object_Item *it, const char *part, Evas_Object *content) +{ + Elm_List_Item *item = (Elm_List_Item *)it; + Evas_Object **icon_p = NULL; + Eina_Bool dummy = EINA_FALSE; + + if ((!part) || (!strcmp(part, "start"))) + { + icon_p = &(item->icon); + dummy = item->dummy_icon; + if (!content) item->dummy_icon = EINA_TRUE; + else item->dummy_icon = EINA_FALSE; + } + else if (!strcmp(part, "end")) + { + icon_p = &(item->end); + dummy = item->dummy_end; + if (!content) item->dummy_end = EINA_TRUE; + else item->dummy_end = EINA_FALSE; + } + else + return; + + if (content == *icon_p) return; + if ((dummy) && (!content)) return; + if (dummy) evas_object_del(*icon_p); + if (!content) + { + content = evas_object_rectangle_add(evas_object_evas_get(WIDGET(item))); + evas_object_color_set(content, 0, 0, 0, 0); + } + if (*icon_p) + { + evas_object_del(*icon_p); + *icon_p = NULL; + } + *icon_p = content; + if (VIEW(item)) + edje_object_part_swallow(VIEW(item), "elm.swallow.icon", content); +} + +static Evas_Object * +_item_content_get_hook(const Elm_Object_Item *it, const char *part) +{ + Elm_List_Item *item = (Elm_List_Item *)it; + + if ((!part) || (!strcmp(part, "start"))) + { + if (item->dummy_icon) return NULL; + return item->icon; + } + else if (!strcmp(part, "end")) + { + if (item->dummy_end) return NULL; + return item->end; + } + return NULL; +} + +static Evas_Object * +_item_content_unset_hook(const Elm_Object_Item *it, const char *part) +{ + Elm_List_Item *item = (Elm_List_Item *)it; + + if ((!part) || (!strcmp(part, "start"))) + { + Evas_Object *obj = item->icon; + _item_content_set_hook((Elm_Object_Item *)it, part, NULL); + return obj; + } + else if (!strcmp(part, "end")) + { + Evas_Object *obj = item->end; + _item_content_set_hook((Elm_Object_Item *)it, part, NULL); + return obj; + } + return NULL; +} + +static void +_item_text_set_hook(Elm_Object_Item *it, const char *part, const char *text) +{ + Elm_List_Item *list_it = (Elm_List_Item *)it; + if (part && strcmp(part, "default")) return; + if (!eina_stringshare_replace(&list_it->label, text)) return; + if (VIEW(list_it)) + edje_object_part_text_escaped_set(VIEW(list_it), "elm.text", text); +} + +static const char * +_item_text_get_hook(const Elm_Object_Item *it, const char *part) +{ + if (part && strcmp(part, "default")) return NULL; + return ((Elm_List_Item *)it)->label; +} + +static Eina_Bool +_item_del_pre_hook(Elm_Object_Item *it) +{ + Evas_Object *obj = WIDGET(it); + Elm_List_Item *item = (Elm_List_Item *)it; + Widget_Data *wd = elm_widget_data_get(obj); + if (!wd) return EINA_FALSE; + + if (item->selected) _item_unselect(item); + + if (wd->walking > 0) + { + if (item->deleted) return EINA_FALSE; + item->deleted = EINA_TRUE; + wd->to_delete = eina_list_append(wd->to_delete, item); + return EINA_FALSE; + } + + wd->items = eina_list_remove_list(wd->items, item->node); + + evas_object_ref(obj); + _elm_list_walk(wd); + + _elm_list_item_free(item); + + _elm_list_unwalk(wd); + evas_object_unref(obj); + + return EINA_TRUE; +} + static Elm_List_Item * _item_new(Evas_Object *obj, const char *label, Evas_Object *icon, Evas_Object *end, Evas_Smart_Cb func, const void *data) { @@ -1031,16 +1193,16 @@ _item_new(Evas_Object *obj, const char *label, Evas_Object *icon, Evas_Object *e it->end = end; it->func = func; it->base.data = data; - it->base.view = edje_object_add(evas_object_evas_get(obj)); - edje_object_mirrored_set(it->base.view, elm_widget_mirrored_get(obj)); - evas_object_event_callback_add(it->base.view, EVAS_CALLBACK_MOUSE_DOWN, + VIEW(it) = edje_object_add(evas_object_evas_get(obj)); + edje_object_mirrored_set(VIEW(it), elm_widget_mirrored_get(obj)); + evas_object_event_callback_add(VIEW(it), EVAS_CALLBACK_MOUSE_DOWN, _mouse_down, it); - evas_object_event_callback_add(it->base.view, EVAS_CALLBACK_MOUSE_UP, + evas_object_event_callback_add(VIEW(it), EVAS_CALLBACK_MOUSE_UP, _mouse_up, it); - evas_object_event_callback_add(it->base.view, EVAS_CALLBACK_MOUSE_MOVE, + evas_object_event_callback_add(VIEW(it), EVAS_CALLBACK_MOUSE_MOVE, _mouse_move, it); - evas_object_size_hint_weight_set(it->base.view, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); - evas_object_size_hint_align_set(it->base.view, EVAS_HINT_FILL, EVAS_HINT_FILL); + evas_object_size_hint_weight_set(VIEW(it), EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + evas_object_size_hint_align_set(VIEW(it), EVAS_HINT_FILL, EVAS_HINT_FILL); if (it->icon) { elm_widget_sub_object_add(obj, it->icon); @@ -1053,6 +1215,13 @@ _item_new(Evas_Object *obj, const char *label, Evas_Object *icon, Evas_Object *e evas_object_event_callback_add(it->end, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _changed_size_hints, obj); } + elm_widget_item_disable_hook_set(it, _item_disable); + 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_text_set_hook_set(it, _item_text_set_hook); + elm_widget_item_text_get_hook_set(it, _item_text_get_hook); + elm_widget_item_del_pre_hook_set(it, _item_del_pre_hook); return it; } @@ -1153,46 +1322,46 @@ _fix_items(Evas_Object *obj) /* FIXME: separators' themes seem to be b0rked */ if (it->is_separator) - _elm_theme_object_set(obj, it->base.view, "separator", + _elm_theme_object_set(obj, VIEW(it), "separator", wd->h_mode ? "horizontal" : "vertical", style); else if (wd->mode == ELM_LIST_COMPRESS) { if (it->even) - _elm_theme_object_set(obj, it->base.view, "list", + _elm_theme_object_set(obj, VIEW(it), "list", it_compress, style); else - _elm_theme_object_set(obj, it->base.view, "list", + _elm_theme_object_set(obj, VIEW(it), "list", it_compress_odd, style); } else { if (it->even) - _elm_theme_object_set(obj, it->base.view, "list", it_plain, + _elm_theme_object_set(obj, VIEW(it), "list", it_plain, style); else - _elm_theme_object_set(obj, it->base.view, "list", it_odd, + _elm_theme_object_set(obj, VIEW(it), "list", it_odd, style); } - stacking = edje_object_data_get(it->base.view, "stacking"); + stacking = edje_object_data_get(VIEW(it), "stacking"); if (stacking) { if (!strcmp(stacking, "below")) - evas_object_lower(it->base.view); + evas_object_lower(VIEW(it)); else if (!strcmp(stacking, "above")) - evas_object_raise(it->base.view); + evas_object_raise(VIEW(it)); } - edje_object_part_text_set(it->base.view, "elm.text", it->label); + edje_object_part_text_escaped_set(VIEW(it), "elm.text", it->label); if ((!it->icon) && (minh[0] > 0)) { - it->icon = evas_object_rectangle_add(evas_object_evas_get(it->base.view)); + it->icon = evas_object_rectangle_add(evas_object_evas_get(VIEW(it))); evas_object_color_set(it->icon, 0, 0, 0, 0); it->dummy_icon = EINA_TRUE; } if ((!it->end) && (minh[1] > 0)) { - it->end = evas_object_rectangle_add(evas_object_evas_get(it->base.view)); + it->end = evas_object_rectangle_add(evas_object_evas_get(VIEW(it))); evas_object_color_set(it->end, 0, 0, 0, 0); it->dummy_end = EINA_TRUE; } @@ -1200,46 +1369,46 @@ _fix_items(Evas_Object *obj) { evas_object_size_hint_min_set(it->icon, minw[0], minh[0]); evas_object_size_hint_max_set(it->icon, 99999, 99999); - edje_object_part_swallow(it->base.view, "elm.swallow.icon", it->icon); + edje_object_part_swallow(VIEW(it), "elm.swallow.icon", it->icon); } if (it->end) { evas_object_size_hint_min_set(it->end, minw[1], minh[1]); evas_object_size_hint_max_set(it->end, 99999, 99999); - edje_object_part_swallow(it->base.view, "elm.swallow.end", it->end); + edje_object_part_swallow(VIEW(it), "elm.swallow.end", it->end); } if (!it->fixed) { // this may call up user and it may modify the list item // but we're safe as we're flagged as walking. // just don't process further - edje_object_message_signal_process(it->base.view); + edje_object_message_signal_process(VIEW(it)); if (it->deleted) continue; mw = mh = -1; elm_coords_finger_size_adjust(1, &mw, 1, &mh); - edje_object_size_min_restricted_calc(it->base.view, &mw, &mh, mw, mh); + edje_object_size_min_restricted_calc(VIEW(it), &mw, &mh, mw, mh); elm_coords_finger_size_adjust(1, &mw, 1, &mh); - evas_object_size_hint_min_set(it->base.view, mw, mh); - evas_object_show(it->base.view); + evas_object_size_hint_min_set(VIEW(it), mw, mh); + evas_object_show(VIEW(it)); } - if ((it->selected) || (it->hilighted)) + if ((it->selected) || (it->highlighted)) { const char *selectraise; // this may call up user and it may modify the list item // but we're safe as we're flagged as walking. // just don't process further - edje_object_signal_emit(it->base.view, "elm,state,selected", "elm"); + edje_object_signal_emit(VIEW(it), "elm,state,selected", "elm"); if (it->deleted) continue; - selectraise = edje_object_data_get(it->base.view, "selectraise"); + selectraise = edje_object_data_get(VIEW(it), "selectraise"); if ((selectraise) && (!strcmp(selectraise, "on"))) - evas_object_raise(it->base.view); + evas_object_raise(VIEW(it)); } - if (it->disabled) - edje_object_signal_emit(it->base.view, "elm,state,disabled", + if (it->base.disabled) + edje_object_signal_emit(VIEW(it), "elm,state,disabled", "elm"); it->fixed = EINA_TRUE; @@ -1299,14 +1468,6 @@ _resize(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event _sizing_eval(data); } -/** - * Adds a list object. - * - * @param parent The parent object - * @return The created object or NULL upon failure - * - * @ingroup List - */ EAPI Evas_Object * elm_list_add(Evas_Object *parent) { @@ -1331,7 +1492,9 @@ elm_list_add(Evas_Object *parent) elm_widget_signal_callback_add_hook_set(obj, _signal_callback_add_hook); elm_widget_signal_callback_del_hook_set(obj, _signal_callback_del_hook); elm_widget_event_hook_set(obj, _event_hook); + elm_widget_translate_hook_set(obj, _translate_hook); + wd->self = obj; wd->scr = elm_smart_scroller_add(e); elm_smart_scroller_widget_set(wd->scr, obj); elm_widget_resize_object_set(obj, wd->scr); @@ -1360,10 +1523,10 @@ elm_list_add(Evas_Object *parent) wd->mode = ELM_LIST_SCROLL; - evas_object_smart_callback_add(wd->scr, "edge,left", _scroll_edge_left, obj); - evas_object_smart_callback_add(wd->scr, "edge,right", _scroll_edge_right, obj); - evas_object_smart_callback_add(wd->scr, "edge,top", _scroll_edge_top, obj); - evas_object_smart_callback_add(wd->scr, "edge,bottom", _scroll_edge_bottom, obj); + evas_object_smart_callback_add(wd->scr, "edge,left", _edge_left, obj); + evas_object_smart_callback_add(wd->scr, "edge,right", _edge_right, obj); + evas_object_smart_callback_add(wd->scr, "edge,top", _edge_top, obj); + evas_object_smart_callback_add(wd->scr, "edge,bottom", _edge_bottom, obj); evas_object_smart_callback_add(obj, "sub-object-del", _sub_del, obj); evas_object_smart_callback_add(obj, "scroll-hold-on", _hold_on, obj); @@ -1378,226 +1541,6 @@ elm_list_add(Evas_Object *parent) return obj; } -/** - * Appends an item to the list object. - * - * @param obj The list object - * @param label The label of the list item - * @param icon The icon object to use for the left side of the item - * @param end The icon object to use for the right side of the item - * @param func The function to call when the item is clicked - * @param data The data to associate with the item for related callbacks - * - * @return The created item or NULL upon failure - * - * @ingroup List - */ -EAPI Elm_List_Item * -elm_list_item_append(Evas_Object *obj, const char *label, Evas_Object *icon, Evas_Object *end, Evas_Smart_Cb func, const void *data) -{ - ELM_CHECK_WIDTYPE(obj, widtype) NULL; - Widget_Data *wd = elm_widget_data_get(obj); - Elm_List_Item *it = _item_new(obj, label, icon, end, func, data); - - wd->items = eina_list_append(wd->items, it); - it->node = eina_list_last(wd->items); - elm_box_pack_end(wd->box, it->base.view); - return it; -} - -/** - * Prepends an item to the list object. - * - * @param obj The list object - * @param label The label of the list item - * @param icon The icon object to use for the left side of the item - * @param end The icon object to use for the right side of the item - * @param func The function to call when the item is clicked - * @param data The data to associate with the item for related callbacks - * - * @return The created item or NULL upon failure - * - * @ingroup List - */ -EAPI Elm_List_Item * -elm_list_item_prepend(Evas_Object *obj, const char *label, Evas_Object *icon, Evas_Object *end, Evas_Smart_Cb func, const void *data) -{ - ELM_CHECK_WIDTYPE(obj, widtype) NULL; - Widget_Data *wd = elm_widget_data_get(obj); - Elm_List_Item *it = _item_new(obj, label, icon, end, func, data); - - wd->items = eina_list_prepend(wd->items, it); - it->node = wd->items; - elm_box_pack_start(wd->box, it->base.view); - return it; -} - -/** - * Inserts an item into the list object before @p before. - * - * @param obj The list object - * @param before The list item to insert before - * @param label The label of the list item - * @param icon The icon object to use for the left side of the item - * @param end The icon object to use for the right side of the item - * @param func The function to call when the item is clicked - * @param data The data to associate with the item for related callbacks - * - * @return The created item or NULL upon failure - * - * @ingroup List - */ -EAPI Elm_List_Item * -elm_list_item_insert_before(Evas_Object *obj, Elm_List_Item *before, const char *label, Evas_Object *icon, Evas_Object *end, Evas_Smart_Cb func, const void *data) -{ - Widget_Data *wd; - Elm_List_Item *it; - - EINA_SAFETY_ON_NULL_RETURN_VAL(before, NULL); - if (!before->node) return NULL; - ELM_LIST_ITEM_CHECK_DELETED_RETURN(before, NULL); - - ELM_CHECK_WIDTYPE(obj, widtype) NULL; - wd = elm_widget_data_get(obj); - if (!wd) return NULL; - it = _item_new(obj, label, icon, end, func, data); - wd->items = eina_list_prepend_relative_list(wd->items, it, before->node); - it->node = before->node->prev; - elm_box_pack_before(wd->box, it->base.view, before->base.view); - return it; -} - -/** - * Inserts an item into the list object after @p after. - * - * @param obj The list object - * @param after The list item to insert after - * @param label The label of the list item - * @param icon The icon object to use for the left side of the item - * @param end The icon object to use for the right side of the item - * @param func The function to call when the item is clicked - * @param data The data to associate with the item for related callbacks - * - * @return The created item or NULL upon failure - * - * @ingroup List - */ -EAPI Elm_List_Item * -elm_list_item_insert_after(Evas_Object *obj, Elm_List_Item *after, const char *label, Evas_Object *icon, Evas_Object *end, Evas_Smart_Cb func, const void *data) -{ - Widget_Data *wd; - Elm_List_Item *it; - - EINA_SAFETY_ON_NULL_RETURN_VAL(after, NULL); - if (!after->node) return NULL; - ELM_LIST_ITEM_CHECK_DELETED_RETURN(after, NULL); - - ELM_CHECK_WIDTYPE(obj, widtype) NULL; - wd = elm_widget_data_get(obj); - if (!wd) return NULL; - it = _item_new(obj, label, icon, end, func, data); - wd->items = eina_list_append_relative_list(wd->items, it, after->node); - it->node = after->node->next; - elm_box_pack_after(wd->box, it->base.view, after->base.view); - return it; -} - -/** - * Insert a new item into the sorted list object. - * - * @param obj The list object - * @param label The label of the list item - * @param icon The icon object to use for the left side of the item - * @param end The icon object to use for the right side of the item - * @param func The function to call when the item is clicked - * @param data The data to associate with the item for related callbacks - * @param cmp_func The function called for the sort. - * - * @return The created item or NULL upon failure - * - * @ingroup List - */ -EAPI Elm_List_Item * -elm_list_item_sorted_insert(Evas_Object *obj, const char *label, Evas_Object *icon, Evas_Object *end, Evas_Smart_Cb func, const void *data, Eina_Compare_Cb cmp_func) -{ - ELM_CHECK_WIDTYPE(obj, widtype) NULL; - Widget_Data *wd = elm_widget_data_get(obj); - Elm_List_Item *it = _item_new(obj, label, icon, end, func, data); - Eina_List *l; - - wd->items = eina_list_sorted_insert(wd->items, cmp_func, it); - l = eina_list_data_find_list(wd->items, it); - l = eina_list_next(l); - if (!l) - { - it->node = eina_list_last(wd->items); - elm_box_pack_end(wd->box, it->base.view); - } - else - { - Elm_List_Item *before = eina_list_data_get(l); - it->node = before->node->prev; - elm_box_pack_before(wd->box, it->base.view, before->base.view); - } - return it; -} - -/** - * Clears a list of all items. - * - * @param obj The list object - * - * @ingroup List - */ -EAPI void -elm_list_clear(Evas_Object *obj) -{ - ELM_CHECK_WIDTYPE(obj, widtype); - Widget_Data *wd = elm_widget_data_get(obj); - Elm_List_Item *it; - - if (!wd) return; - if (!wd->items) return; - - eina_list_free(wd->selected); - wd->selected = NULL; - - if (wd->walking > 0) - { - Eina_List *n; - - EINA_LIST_FOREACH(wd->items, n, it) - { - if (it->deleted) continue; - it->deleted = EINA_TRUE; - wd->to_delete = eina_list_append(wd->to_delete, it); - } - return; - } - - evas_object_ref(obj); - _elm_list_walk(wd); - - EINA_LIST_FREE(wd->items, it) - { - elm_widget_item_pre_notify_del(it); - _elm_list_item_free(it); - } - - _elm_list_unwalk(wd); - - _fix_items(obj); - _sizing_eval(obj); - evas_object_unref(obj); -} - -/** - * Starts the list. Call before running show() on the list object. - * - * @param obj The list object - * - * @ingroup List - */ EAPI void elm_list_go(Evas_Object *obj) { @@ -1607,14 +1550,6 @@ elm_list_go(Evas_Object *obj) _fix_items(obj); } -/** - * Enables/disables the state of multi-select on the list object. - * - * @param obj The list object - * @param multi If true, multi-select is enabled - * - * @ingroup List - */ EAPI void elm_list_multi_select_set(Evas_Object *obj, Eina_Bool multi) { @@ -1624,14 +1559,6 @@ elm_list_multi_select_set(Evas_Object *obj, Eina_Bool multi) wd->multi = multi; } -/** - * Gets the state of multi-select on the list object. - * - * @param obj The list object - * @return If true, multi-select is enabled - * - * @ingroup List - */ EAPI Eina_Bool elm_list_multi_select_get(const Evas_Object *obj) { @@ -1641,35 +1568,6 @@ elm_list_multi_select_get(const Evas_Object *obj) return wd->multi; } -/** - * Set which mode to use for the list with. - * - * @param obj The list object - * @param mode One of @c ELM_LIST_COMPRESS, @c ELM_LIST_SCROLL, @c - * ELM_LIST_LIMIT or @c ELM_LIST_EXPAND. - * - * @note Default value is @c ELM_LIST_SCROLL. At this mode, the list - * object won't set any of its size hints to inform how a possible - * container should resize it. Then, if it's not created as a "resize - * object", it might end with zero dimensions. The list will respect - * the container's geometry and, if any of its items won't fit into - * its transverse axis, one will be able to scroll it in that - * direction. @c ELM_LIST_COMPRESS is the same as the previous, except - * that it won't let one scroll in the transverse axis, on - * those cases (large items will get cropped). @c ELM_LIST_LIMIT will - * actually set a minimun size hint on the list object, so that - * containers may respect it (and resize itself to fit the child - * properly). More specifically, a minimum size hint will be set for - * its transverse axis, so that the largest item in that - * direction fits well. @c ELM_LIST_EXPAND, besides setting a minimum - * size on the transverse axis, just like the previous mode, will set - * a minimum size on the longitudinal axis too, trying to reserve - * space to all its children to be visible at a time. The last two - * modes can always have effects bounded by setting the list object's - * maximum size hints, though. - * - * @ingroup List - */ EAPI void elm_list_mode_set(Evas_Object *obj, Elm_List_Mode mode) { @@ -1687,17 +1585,6 @@ elm_list_mode_set(Evas_Object *obj, Elm_List_Mode mode) _elm_list_mode_set_internal(wd); } -/** - * Get the mode the list is at. - * - * @param obj The list object - * @return mode One of @c ELM_LIST_COMPRESS, @c ELM_LIST_SCROLL or @c - * ELM_LIST_LIMIT (@c ELM_LIST_LAST on errors). - * - * @note see elm_list_mode_set() for more information. - * - * @ingroup List - */ EAPI Elm_List_Mode elm_list_mode_get(const Evas_Object *obj) { @@ -1707,18 +1594,6 @@ elm_list_mode_get(const Evas_Object *obj) return wd->mode; } -/** - * Enables/disables horizontal mode of the list. - * - * @param obj The list object - * @param mode If true, horizontale mode is enabled - * - * @note Bounce options for the list will be reset to default values - * with this funcion. Re-call elm_list_bounce_set() once more after - * this one, if you had custom values. - * - * @ingroup List - */ EAPI void elm_list_horizontal_set(Evas_Object *obj, Eina_Bool horizontal) { @@ -1753,17 +1628,6 @@ elm_list_horizontal_set(Evas_Object *obj, Eina_Bool horizontal) _elm_list_mode_set_internal(wd); } -/** - * Retrieve whether horizontal mode is enabled for a list. - * - * @param obj The list object - * @return @c EINA_TRUE, if horizontal mode is enabled and @c - * EINA_FALSE, otherwise. - * - * @note see elm_list_horizontal_set() for more information. - * - * @ingroup List - */ EAPI Eina_Bool elm_list_horizontal_get(const Evas_Object *obj) { @@ -1778,50 +1642,112 @@ elm_list_horizontal_get(const Evas_Object *obj) return wd->h_mode; } -/** - * Enables/disables the state of always_select, meaning that - * an item will always be selected. - * - * @param obj The list object - * @param always_select If true, always_select is enabled - * - * @ingroup List - */ EAPI void -elm_list_always_select_mode_set(Evas_Object *obj, Eina_Bool always_select) +elm_list_select_mode_set(Evas_Object *obj, Elm_Object_Select_Mode mode) { ELM_CHECK_WIDTYPE(obj, widtype); Widget_Data *wd = elm_widget_data_get(obj); if (!wd) return; - wd->always_select = always_select; -} - -/** - * Gets the state of always_select. - * See also elm_list_always_select_mode_set() - * - * @param obj The list object - * @return If true, always_select is enabled - * - * @ingroup List - */ -EAPI Eina_Bool -elm_list_always_select_mode_get(const Evas_Object *obj) + if (mode >= ELM_OBJECT_SELECT_MODE_MAX) + return; + if (wd->select_mode != mode) + wd->select_mode = mode; +} + +EAPI Elm_Object_Select_Mode +elm_list_select_mode_get(const Evas_Object *obj) { - ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE; + ELM_CHECK_WIDTYPE(obj, widtype) ELM_OBJECT_SELECT_MODE_MAX; Widget_Data *wd = elm_widget_data_get(obj); - if (!wd) return EINA_FALSE; - return wd->always_select; + if (!wd) return ELM_OBJECT_SELECT_MODE_MAX; + return wd->select_mode; +} + +EAPI void +elm_list_bounce_set(Evas_Object *obj, Eina_Bool h_bounce, Eina_Bool v_bounce) +{ + ELM_CHECK_WIDTYPE(obj, widtype); + Widget_Data *wd = elm_widget_data_get(obj); + if (!wd) return; + if (wd->scr) + elm_smart_scroller_bounce_allow_set(wd->scr, h_bounce, v_bounce); +} + +EAPI void +elm_list_bounce_get(const Evas_Object *obj, Eina_Bool *h_bounce, Eina_Bool *v_bounce) +{ + ELM_CHECK_WIDTYPE(obj, widtype); + Widget_Data *wd = elm_widget_data_get(obj); + if (!wd) return; + elm_smart_scroller_bounce_allow_get(wd->scr, h_bounce, v_bounce); +} + +EAPI void +elm_list_scroller_policy_set(Evas_Object *obj, Elm_Scroller_Policy policy_h, Elm_Scroller_Policy policy_v) +{ + ELM_CHECK_WIDTYPE(obj, widtype); + Widget_Data *wd = elm_widget_data_get(obj); + if ((!wd) || (!wd->scr)) return; + if ((policy_h >= ELM_SCROLLER_POLICY_LAST) || + (policy_v >= ELM_SCROLLER_POLICY_LAST)) + return; + elm_smart_scroller_policy_set(wd->scr, policy_h, policy_v); +} + +EAPI void +elm_list_scroller_policy_get(const Evas_Object *obj, Elm_Scroller_Policy *policy_h, Elm_Scroller_Policy *policy_v) +{ + ELM_CHECK_WIDTYPE(obj, widtype); + Widget_Data *wd = elm_widget_data_get(obj); + Elm_Smart_Scroller_Policy s_policy_h, s_policy_v; + if ((!wd) || (!wd->scr)) return; + elm_smart_scroller_policy_get(wd->scr, &s_policy_h, &s_policy_v); + if (policy_h) *policy_h = (Elm_Scroller_Policy) s_policy_h; + if (policy_v) *policy_v = (Elm_Scroller_Policy) s_policy_v; +} + +EAPI void +elm_list_clear(Evas_Object *obj) +{ + ELM_CHECK_WIDTYPE(obj, widtype); + Widget_Data *wd = elm_widget_data_get(obj); + Elm_List_Item *it; + + if (!wd) return; + if (!wd->items) return; + + eina_list_free(wd->selected); + wd->selected = NULL; + + if (wd->walking > 0) + { + Eina_List *n; + + EINA_LIST_FOREACH(wd->items, n, it) + { + if (it->deleted) continue; + it->deleted = EINA_TRUE; + wd->to_delete = eina_list_append(wd->to_delete, it); + } + return; + } + + evas_object_ref(obj); + _elm_list_walk(wd); + + EINA_LIST_FREE(wd->items, it) + { + _elm_list_item_free(it); + elm_widget_item_free(it); + } + + _elm_list_unwalk(wd); + + _fix_items(obj); + _sizing_eval(obj); + evas_object_unref(obj); } -/** - * Returns a list of all the list items. - * - * @param obj The list object - * @return An Eina_List* of the list items, or NULL on failure - * - * @ingroup List - */ EAPI const Eina_List * elm_list_items_get(const Evas_Object *obj) { @@ -1831,32 +1757,16 @@ elm_list_items_get(const Evas_Object *obj) return wd->items; } -/** - * Returns the currently selected list item. - * - * @param obj The list object - * @return The selected list item, or NULL on failure - * - * @ingroup List - */ -EAPI Elm_List_Item * +EAPI Elm_Object_Item * elm_list_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; - if (wd->selected) return wd->selected->data; + if (wd->selected) return (Elm_Object_Item *) wd->selected->data; return NULL; } -/** - * Returns a list of the currently selected list items. - * - * @param obj The list object - * @return An Eina_List* of the selected list items, or NULL on failure - * - * @ingroup List - */ EAPI const Eina_List * elm_list_selected_items_get(const Evas_Object *obj) { @@ -1866,50 +1776,126 @@ elm_list_selected_items_get(const Evas_Object *obj) return wd->selected; } -/** - * Sets if item is a separator. - * - * @param it The list item object - * @param setting - */ +EAPI Elm_Object_Item * +elm_list_item_append(Evas_Object *obj, const char *label, Evas_Object *icon, Evas_Object *end, Evas_Smart_Cb func, const void *data) +{ + ELM_CHECK_WIDTYPE(obj, widtype) NULL; + Widget_Data *wd = elm_widget_data_get(obj); + Elm_List_Item *it = _item_new(obj, label, icon, end, func, data); + + wd->items = eina_list_append(wd->items, it); + it->node = eina_list_last(wd->items); + elm_box_pack_end(wd->box, VIEW(it)); + return (Elm_Object_Item *)it; +} + +EAPI Elm_Object_Item * +elm_list_item_prepend(Evas_Object *obj, const char *label, Evas_Object *icon, Evas_Object *end, Evas_Smart_Cb func, const void *data) +{ + ELM_CHECK_WIDTYPE(obj, widtype) NULL; + Widget_Data *wd = elm_widget_data_get(obj); + Elm_List_Item *it = _item_new(obj, label, icon, end, func, data); + + wd->items = eina_list_prepend(wd->items, it); + it->node = wd->items; + elm_box_pack_start(wd->box, VIEW(it)); + return (Elm_Object_Item *)it; +} + +EAPI Elm_Object_Item * +elm_list_item_insert_before(Evas_Object *obj, Elm_Object_Item *before, const char *label, Evas_Object *icon, Evas_Object *end, Evas_Smart_Cb func, const void *data) +{ + ELM_CHECK_WIDTYPE(obj, widtype) NULL; + ELM_LIST_ITEM_CHECK_DELETED_RETURN(before, NULL); + + Widget_Data *wd; + Elm_List_Item *it, *before_it; + + wd = elm_widget_data_get(obj); + if (!wd) return NULL; + + before_it = (Elm_List_Item *) before; + if (!before_it->node) return NULL; + + it = _item_new(obj, label, icon, end, func, data); + wd->items = eina_list_prepend_relative_list(wd->items, it, before_it->node); + it->node = before_it->node->prev; + elm_box_pack_before(wd->box, VIEW(it), VIEW(before_it)); + return (Elm_Object_Item *)it; +} + +EAPI Elm_Object_Item * +elm_list_item_insert_after(Evas_Object *obj, Elm_Object_Item *after, const char *label, Evas_Object *icon, Evas_Object *end, Evas_Smart_Cb func, const void *data) +{ + ELM_CHECK_WIDTYPE(obj, widtype) NULL; + ELM_LIST_ITEM_CHECK_DELETED_RETURN(after, NULL); + + Widget_Data *wd; + Elm_List_Item *it, *after_it; + + wd = elm_widget_data_get(obj); + if (!wd) return NULL; + + after_it = (Elm_List_Item *) after; + if (!after_it->node) return NULL; + + it = _item_new(obj, label, icon, end, func, data); + wd->items = eina_list_append_relative_list(wd->items, it, after_it->node); + it->node = after_it->node->next; + elm_box_pack_after(wd->box, VIEW(it), VIEW(after_it)); + return (Elm_Object_Item *)it; +} + +EAPI Elm_Object_Item * +elm_list_item_sorted_insert(Evas_Object *obj, const char *label, Evas_Object *icon, Evas_Object *end, Evas_Smart_Cb func, const void *data, Eina_Compare_Cb cmp_func) +{ + ELM_CHECK_WIDTYPE(obj, widtype) NULL; + Widget_Data *wd = elm_widget_data_get(obj); + Elm_List_Item *it = _item_new(obj, label, icon, end, func, data); + Eina_List *l; + + wd->items = eina_list_sorted_insert(wd->items, cmp_func, it); + l = eina_list_data_find_list(wd->items, it); + l = eina_list_next(l); + if (!l) + { + it->node = eina_list_last(wd->items); + elm_box_pack_end(wd->box, VIEW(it)); + } + else + { + Elm_List_Item *before = eina_list_data_get(l); + it->node = before->node->prev; + elm_box_pack_before(wd->box, VIEW(it), VIEW(before)); + } + return (Elm_Object_Item *)it; +} + EAPI void -elm_list_item_separator_set(Elm_List_Item *it, Eina_Bool setting) +elm_list_item_separator_set(Elm_Object_Item *it, Eina_Bool setting) { ELM_LIST_ITEM_CHECK_DELETED_RETURN(it); - it->is_separator = !!setting; + ((Elm_List_Item *)it)->is_separator = !!setting; } -/** - * Returns EINA_TRUE if Elm_List_Item is a separator. - * - * @param it The list item object - */ EAPI Eina_Bool -elm_list_item_separator_get(const Elm_List_Item *it) +elm_list_item_separator_get(const Elm_Object_Item *it) { ELM_LIST_ITEM_CHECK_DELETED_RETURN(it, EINA_FALSE); - return it->is_separator; + return ((Elm_List_Item *)it)->is_separator; } - -/** - * Sets the selected state of @p it. - * - * @param it The list item - * @param selected Enables/disables the selected state - * - * @ingroup List - */ EAPI void -elm_list_item_selected_set(Elm_List_Item *it, Eina_Bool selected) +elm_list_item_selected_set(Elm_Object_Item *it, Eina_Bool selected) { ELM_LIST_ITEM_CHECK_DELETED_RETURN(it); - Evas_Object *obj = it->base.widget; + Evas_Object *obj = WIDGET(it); Widget_Data *wd = elm_widget_data_get(obj); + Elm_List_Item *item = (Elm_List_Item *)it; if (!wd) return; selected = !!selected; - if (it->selected == selected) return; + if (item->selected == selected) return; evas_object_ref(obj); _elm_list_walk(wd); @@ -1921,677 +1907,98 @@ elm_list_item_selected_set(Elm_List_Item *it, Eina_Bool selected) while (wd->selected) _item_unselect(wd->selected->data); } - _item_hilight(it); - _item_select(it); + _item_highlight(item); + _item_select(item); } else - _item_unselect(it); + _item_unselect(item); _elm_list_unwalk(wd); evas_object_unref(obj); } -/** - * Gets the selected state of @p it. - * - * @param it The list item - * @return If true, the item is selected - * - * @ingroup List - */ EAPI Eina_Bool -elm_list_item_selected_get(const Elm_List_Item *it) +elm_list_item_selected_get(const Elm_Object_Item *it) { ELM_LIST_ITEM_CHECK_DELETED_RETURN(it, EINA_FALSE); - return it->selected; + return ((Elm_List_Item *)it)->selected; } -/** - * Brings @p it to the center of the list view. - * - * @param it The list item - * - * @ingroup List - */ EAPI void -elm_list_item_show(Elm_List_Item *it) +elm_list_item_show(Elm_Object_Item *it) { ELM_LIST_ITEM_CHECK_DELETED_RETURN(it); - Widget_Data *wd = elm_widget_data_get(it->base.widget); + Widget_Data *wd = elm_widget_data_get(WIDGET(it)); + if (!wd) return; Evas_Coord bx, by, bw, bh; Evas_Coord x, y, w, h; + evas_smart_objects_calculate(evas_object_evas_get(wd->box)); evas_object_geometry_get(wd->box, &bx, &by, &bw, &bh); - evas_object_geometry_get(it->base.view, &x, &y, &w, &h); + evas_object_geometry_get(VIEW(it), &x, &y, &w, &h); x -= bx; y -= by; - if (wd->scr) - elm_smart_scroller_child_region_show(wd->scr, x, y, w, h); -} - -/** - * Bring in the given item - * - * This causes list to jump to the given item @p it and show it (by scrolling), - * if it is not fully visible. This may use animation to do so and take a - * period of time - * - * @param it The item - * - * @ingroup List - */ + if (wd->scr) elm_smart_scroller_child_region_show(wd->scr, x, y, w, h); +} + EAPI void -elm_list_item_bring_in(Elm_List_Item *it) +elm_list_item_bring_in(Elm_Object_Item *it) { ELM_LIST_ITEM_CHECK_DELETED_RETURN(it); - Widget_Data *wd = elm_widget_data_get(it->base.widget); + Widget_Data *wd = elm_widget_data_get(WIDGET(it)); + if (!wd) return; Evas_Coord bx, by, bw, bh; Evas_Coord x, y, w, h; + evas_smart_objects_calculate(evas_object_evas_get(wd->box)); evas_object_geometry_get(wd->box, &bx, &by, &bw, &bh); - evas_object_geometry_get(it->base.view, &x, &y, &w, &h); + evas_object_geometry_get(VIEW(it), &x, &y, &w, &h); x -= bx; y -= by; - if (wd->scr) - elm_smart_scroller_region_bring_in(wd->scr, x, y, w, h); + if (wd->scr) elm_smart_scroller_region_bring_in(wd->scr, x, y, w, h); } -/** - * Deletes item @p it from the list. - * - * @param it The list item to delete - * - * @ingroup List - */ -EAPI void -elm_list_item_del(Elm_List_Item *it) -{ - ELM_LIST_ITEM_CHECK_DELETED_RETURN(it); - Evas_Object *obj = it->base.widget; - Widget_Data *wd = elm_widget_data_get(obj); - if (!wd) return; - - if (it->selected) _item_unselect(it); - - if (wd->walking > 0) - { - if (it->deleted) return; - it->deleted = EINA_TRUE; - wd->to_delete = eina_list_append(wd->to_delete, it); - return; - } - - wd->items = eina_list_remove_list(wd->items, it->node); - - evas_object_ref(obj); - _elm_list_walk(wd); - - elm_widget_item_pre_notify_del(it); - _elm_list_item_free(it); - - _elm_list_unwalk(wd); - evas_object_unref(obj); -} - -/** - * Set the function called when a list item is freed. - * - * @param it The item to set the callback on - * @param func The function called - * - * @ingroup List - */ -EAPI void -elm_list_item_del_cb_set(Elm_List_Item *it, Evas_Smart_Cb func) -{ - ELM_LIST_ITEM_CHECK_DELETED_RETURN(it); - elm_widget_item_del_cb_set(it, func); -} - -/** - * Returns the data associated with the item. - * - * @param it The list item - * @return The data associated with @p it - * - * @ingroup List - */ -EAPI void * -elm_list_item_data_get(const Elm_List_Item *it) -{ - ELM_LIST_ITEM_CHECK_DELETED_RETURN(it, NULL); - return elm_widget_item_data_get(it); -} - -/** - * Returns the left side icon associated with the item. - * - * @param it The list item - * @return The left side icon associated with @p it - * - * @ingroup List - */ -EAPI Evas_Object * -elm_list_item_icon_get(const Elm_List_Item *it) -{ - ELM_LIST_ITEM_CHECK_DELETED_RETURN(it, NULL); - if (it->dummy_icon) return NULL; - return it->icon; -} - -/** - * Sets the left side icon associated with the item. - * - * Once the icon object is set, a previously set one will be deleted. - * You probably don't want, then, to have the same icon object set - * for more than one item of the list. - * - * @param it The list item - * @param icon The left side icon object to associate with @p it - * - * @ingroup List - */ -EAPI void -elm_list_item_icon_set(Elm_List_Item *it, Evas_Object *icon) -{ - ELM_LIST_ITEM_CHECK_DELETED_RETURN(it); - if (it->icon == icon) return; - if ((it->dummy_icon) && (!icon)) return; - if (it->dummy_icon) - { - evas_object_del(it->icon); - it->dummy_icon = EINA_FALSE; - } - if (!icon) - { - icon = evas_object_rectangle_add(evas_object_evas_get(it->base.widget)); - evas_object_color_set(icon, 0, 0, 0, 0); - it->dummy_icon = EINA_TRUE; - } - if (it->icon) - { - evas_object_del(it->icon); - it->icon = NULL; - } - it->icon = icon; - if (it->base.view) - edje_object_part_swallow(it->base.view, "elm.swallow.icon", icon); -} - -/** - * Gets the right side icon associated with the item. - * - * @param it The list item - * @return The right side icon object associated with @p it - * - * @ingroup List - */ EAPI Evas_Object * -elm_list_item_end_get(const Elm_List_Item *it) +elm_list_item_object_get(const Elm_Object_Item *it) { ELM_LIST_ITEM_CHECK_DELETED_RETURN(it, NULL); - if (it->dummy_end) return NULL; - return it->end; -} - -/** - * Sets the right side icon associated with the item. - * - * Once the icon object is set, a previously set one will be deleted. - * You probably don't want, then, to have the same icon object set - * for more than one item of the list. - * - * @param it The list item - * @param icon The right side icon object to associate with @p it - * - * @ingroup List - */ -EAPI void -elm_list_item_end_set(Elm_List_Item *it, Evas_Object *end) -{ - ELM_LIST_ITEM_CHECK_DELETED_RETURN(it); - if (it->end == end) return; - if ((it->dummy_end) && (!end)) return; - if (it->dummy_end) - { - evas_object_del(it->end); - it->dummy_icon = EINA_FALSE; - } - if (!end) - { - end = evas_object_rectangle_add(evas_object_evas_get(it->base.widget)); - evas_object_color_set(end, 0, 0, 0, 0); - it->dummy_end = EINA_TRUE; - } - if (it->end) - { - evas_object_del(it->end); - it->end = NULL; - } - it->end = end; - if (it->base.view) - edje_object_part_swallow(it->base.view, "elm.swallow.end", end); -} - -/** - * Gets the base object of the item. - * - * @param it The list item - * @return The base object associated with @p it - * - * @ingroup List - */ -EAPI Evas_Object * -elm_list_item_base_get(const Elm_List_Item *it) -{ - ELM_LIST_ITEM_CHECK_DELETED_RETURN(it, NULL); - return it->base.view; + return VIEW(it); } -/** - * Gets the label of the item. - * - * @param it The list item - * @return The label of @p it - * - * @ingroup List - */ -EAPI const char * -elm_list_item_label_get(const Elm_List_Item *it) -{ - ELM_LIST_ITEM_CHECK_DELETED_RETURN(it, NULL); - return it->label; -} - -/** - * Sets the label of the item. - * - * @param it The list item - * @param text The label of @p it - * - * @ingroup List - */ -EAPI void -elm_list_item_label_set(Elm_List_Item *it, const char *text) -{ - ELM_LIST_ITEM_CHECK_DELETED_RETURN(it); - if (!eina_stringshare_replace(&it->label, text)) return; - if (it->base.view) - edje_object_part_text_set(it->base.view, "elm.text", it->label); -} - -/** - * Gets the item before @p it in the list. - * - * @param it The list item - * @return The item before @p it, or NULL on failure - * - * @ingroup List - */ -EAPI Elm_List_Item * -elm_list_item_prev(const Elm_List_Item *it) +EAPI Elm_Object_Item * +elm_list_item_prev(const Elm_Object_Item *it) { ELM_LIST_ITEM_CHECK_DELETED_RETURN(it, NULL); - if (it->node->prev) return it->node->prev->data; + Elm_List_Item *item = (Elm_List_Item *)it; + if (item->node->prev) return item->node->prev->data; else return NULL; } -/** - * Gets the item after @p it in the list. - * - * @param it The list item - * @return The item after @p it, or NULL on failure - * - * @ingroup List - */ -EAPI Elm_List_Item * -elm_list_item_next(const Elm_List_Item *it) +EAPI Elm_Object_Item * +elm_list_item_next(const Elm_Object_Item *it) { ELM_LIST_ITEM_CHECK_DELETED_RETURN(it, NULL); - if (it->node->next) return it->node->next->data; + Elm_List_Item *item = (Elm_List_Item *)it; + if (item->node->next) return item->node->next->data; else return NULL; } -/** - * Set the text to be shown in the list item. - * - * @param item Target item - * @param text The text to set in the content - * - * Setup the text as tooltip to object. The item can have only one tooltip, - * so any previous tooltip data is removed. - * - * @ingroup List - */ -EAPI void -elm_list_item_tooltip_text_set(Elm_List_Item *item, const char *text) -{ - ELM_LIST_ITEM_CHECK_DELETED_RETURN(item); - elm_widget_item_tooltip_text_set(item, text); -} - -/** - * Set the content to be shown in the tooltip item - * - * Setup the tooltip to item. The item can have only one tooltip, - * so any previous tooltip data is removed. @p func(with @p data) will - * be called every time that need show the tooltip and it should - * return a valid Evas_Object. This object is then managed fully by - * tooltip system and is deleted when the tooltip is gone. - * - * @param item the list item being attached a tooltip. - * @param func the function used to create the tooltip contents. - * @param data what to provide to @a func as callback data/context. - * @param del_cb called when data is not needed anymore, either when - * another callback replaces @func, the tooltip is unset with - * elm_list_item_tooltip_unset() or the owner @a item - * dies. This callback receives as the first parameter the - * given @a data, and @c event_info is the item. - * - * @ingroup List - */ -EAPI void -elm_list_item_tooltip_content_cb_set(Elm_List_Item *item, Elm_Tooltip_Item_Content_Cb func, const void *data, Evas_Smart_Cb del_cb) -{ - ELM_LIST_ITEM_CHECK_DELETED_RETURN(item); - elm_widget_item_tooltip_content_cb_set(item, func, data, del_cb); -} - -/** - * Unset tooltip from item - * - * @param item list item to remove previously set tooltip. - * - * Remove tooltip from item. The callback provided as del_cb to - * elm_list_item_tooltip_content_cb_set() will be called to notify - * it is not used anymore. - * - * @see elm_list_item_tooltip_content_cb_set() - * - * @ingroup List - */ -EAPI void -elm_list_item_tooltip_unset(Elm_List_Item *item) -{ - ELM_LIST_ITEM_CHECK_DELETED_RETURN(item); - elm_widget_item_tooltip_unset(item); -} - -/** - * Sets a different style for this item tooltip. - * - * @note before you set a style you should define a tooltip with - * elm_list_item_tooltip_content_cb_set() or - * elm_list_item_tooltip_text_set() - * - * @param item list item with tooltip already set. - * @param style the theme style to use (default, transparent, ...) - * - * @ingroup List - */ -EAPI void -elm_list_item_tooltip_style_set(Elm_List_Item *item, const char *style) -{ - ELM_LIST_ITEM_CHECK_DELETED_RETURN(item); - elm_widget_item_tooltip_style_set(item, style); -} - -/** - * Get the style for this item tooltip. - * - * @param item list item with tooltip already set. - * @return style the theme style in use, defaults to "default". If the - * object does not have a tooltip set, then NULL is returned. - * - * @ingroup List - */ -EAPI const char * -elm_list_item_tooltip_style_get(const Elm_List_Item *item) -{ - ELM_LIST_ITEM_CHECK_DELETED_RETURN(item, NULL); - return elm_widget_item_tooltip_style_get(item); -} - -/** - * Set the cursor to be shown when mouse is over the list item - * - * @param item Target item - * @param cursor the cursor name to be used. - * - * @see elm_object_cursor_set() - * @ingroup List - */ -EAPI void -elm_list_item_cursor_set(Elm_List_Item *item, const char *cursor) -{ - ELM_LIST_ITEM_CHECK_DELETED_RETURN(item); - elm_widget_item_cursor_set(item, cursor); -} - -/** - * Get the cursor to be shown when mouse is over the list item - * - * @param item list item with cursor already set. - * @return the cursor name. - * - * @ingroup List - */ -EAPI const char * -elm_list_item_cursor_get(const Elm_List_Item *item) -{ - ELM_LIST_ITEM_CHECK_DELETED_RETURN(item, NULL); - return elm_widget_item_cursor_get(item); -} - -/** - * Unset the cursor to be shown when mouse is over the list item - * - * @param item Target item - * - * @see elm_object_cursor_unset() - * @ingroup List - */ -EAPI void -elm_list_item_cursor_unset(Elm_List_Item *item) -{ - ELM_LIST_ITEM_CHECK_DELETED_RETURN(item); - elm_widget_item_cursor_unset(item); -} - -/** - * Sets a different style for this item cursor. - * - * @note before you set a style you should define a cursor with - * elm_list_item_cursor_set() - * - * @param item list item with cursor already set. - * @param style the theme style to use (default, transparent, ...) - * - * @ingroup List - */ -EAPI void -elm_list_item_cursor_style_set(Elm_List_Item *item, const char *style) -{ - ELM_LIST_ITEM_CHECK_DELETED_RETURN(item); - elm_widget_item_cursor_style_set(item, style); -} - -/** - * Get the style for this item cursor. - * - * @param item list item with cursor already set. - * @return style the theme style in use, defaults to "default". If the - * object does not have a cursor set, then NULL is returned. - * - * @ingroup List - */ -EAPI const char * -elm_list_item_cursor_style_get(const Elm_List_Item *item) -{ - ELM_LIST_ITEM_CHECK_DELETED_RETURN(item, NULL); - return elm_widget_item_cursor_style_get(item); -} - -/** - * Set if the cursor set should be searched on the theme or should use - * the provided by the engine, only. - * - * @note before you set if should look on theme you should define a cursor - * with elm_object_cursor_set(). By default it will only look for cursors - * provided by the engine. - * - * @param item widget item with cursor already set. - * @param engine_only boolean to define it cursors should be looked only - * between the provided by the engine or searched on widget's theme as well. - * - * @ingroup List - */ -EAPI void -elm_list_item_cursor_engine_only_set(Elm_List_Item *item, Eina_Bool engine_only) -{ - ELM_LIST_ITEM_CHECK_DELETED_RETURN(item); - elm_widget_item_cursor_engine_only_set(item, engine_only); -} - -/** - * Get the cursor engine only usage for this item cursor. - * - * @param item widget item with cursor already set. - * @return engine_only boolean to define it cursors should be looked only - * between the provided by the engine or searched on widget's theme as well. If - * the object does not have a cursor set, then EINA_FALSE is returned. - * - * @ingroup List - */ -EAPI Eina_Bool -elm_list_item_cursor_engine_only_get(const Elm_List_Item *item) -{ - ELM_LIST_ITEM_CHECK_DELETED_RETURN(item, EINA_FALSE); - return elm_widget_item_cursor_engine_only_get(item); -} - -/** - * Set bounce mode - * - * This will enable or disable the scroller bounce mode for the list. See - * elm_scroller_bounce_set() for details - * - * @param obj The list object - * @param h_bounce Allow bounce horizontally - * @param v_bounce Allow bounce vertically - * - * @ingroup List - */ -EAPI void -elm_list_bounce_set(Evas_Object *obj, Eina_Bool h_bounce, Eina_Bool v_bounce) -{ - ELM_CHECK_WIDTYPE(obj, widtype); - Widget_Data *wd = elm_widget_data_get(obj); - if (!wd) return; - if (wd->scr) - elm_smart_scroller_bounce_allow_set(wd->scr, h_bounce, v_bounce); -} - -/** - * Get the bounce mode - * - * @param obj The List object - * @param h_bounce Allow bounce horizontally - * @param v_bounce Allow bounce vertically - * - * @ingroup List - */ -EAPI void -elm_list_bounce_get(const Evas_Object *obj, Eina_Bool *h_bounce, Eina_Bool *v_bounce) -{ - ELM_CHECK_WIDTYPE(obj, widtype); - Widget_Data *wd = elm_widget_data_get(obj); - if (!wd) return; - elm_smart_scroller_bounce_allow_get(wd->scr, h_bounce, v_bounce); -} - -/** - * Set the scrollbar policy - * - * This sets the scrollbar visibility policy for the given list scroller. - * ELM_SMART_SCROLLER_POLICY_AUTO means the scrollber is made visible if it - * is needed, and otherwise kept hidden. ELM_SMART_SCROLLER_POLICY_ON turns - * it on all the time, and ELM_SMART_SCROLLER_POLICY_OFF always keeps it off. - * This applies respectively for the horizontal and vertical scrollbars. - * - * @param obj The list object - * @param policy_h Horizontal scrollbar policy - * @param policy_v Vertical scrollbar policy - * - * @ingroup List - */ -EAPI void -elm_list_scroller_policy_set(Evas_Object *obj, Elm_Scroller_Policy policy_h, Elm_Scroller_Policy policy_v) +EAPI Elm_Object_Item * +elm_list_first_item_get(const Evas_Object *obj) { - ELM_CHECK_WIDTYPE(obj, widtype); + ELM_CHECK_WIDTYPE(obj, widtype) NULL; Widget_Data *wd = elm_widget_data_get(obj); - if (!wd) return; - if ((policy_h >= ELM_SCROLLER_POLICY_LAST) || - (policy_v >= ELM_SCROLLER_POLICY_LAST)) - if (wd->scr) - elm_smart_scroller_policy_set(wd->scr, policy_h, policy_v); + if (!wd) return NULL; + if (!wd->items) return NULL; + return eina_list_data_get(wd->items); } -EAPI void -elm_list_scroller_policy_get(const Evas_Object *obj, Elm_Scroller_Policy *policy_h, Elm_Scroller_Policy *policy_v) +EAPI Elm_Object_Item * +elm_list_last_item_get(const Evas_Object *obj) { - ELM_CHECK_WIDTYPE(obj, widtype); + ELM_CHECK_WIDTYPE(obj, widtype) NULL; Widget_Data *wd = elm_widget_data_get(obj); - Elm_Smart_Scroller_Policy s_policy_h, s_policy_v; - if ((!wd) || (!wd->scr)) return; - elm_smart_scroller_policy_get(wd->scr, &s_policy_h, &s_policy_v); - if (policy_h) *policy_h = (Elm_Scroller_Policy) s_policy_h; - if (policy_v) *policy_v = (Elm_Scroller_Policy) s_policy_v; -} - -/** - * Sets the disabled/enabled state of a list item. - * - * A disabled item cannot be selected or unselected. It will also - * change its appearance (generally greyed out). This sets the - * disabled state (@c EINA_TRUE for disabled, @c EINA_FALSE for - * enabled). - * - * @param it The item - * @param disabled The disabled state - * - * @ingroup List - */ -EAPI void -elm_list_item_disabled_set(Elm_List_Item *it, Eina_Bool disabled) -{ - ELM_LIST_ITEM_CHECK_DELETED_RETURN(it); - - if (it->disabled == disabled) - return; - - it->disabled = !!disabled; - - if (it->disabled) - edje_object_signal_emit(it->base.view, "elm,state,disabled", "elm"); - else - edje_object_signal_emit(it->base.view, "elm,state,enabled", "elm"); -} - -/** - * Get the disabled/enabled state of a list item - * - * @param it The item - * @return The disabled state - * - * See elm_list_item_disabled_set(). - * - * @ingroup List - */ -EAPI Eina_Bool -elm_list_item_disabled_get(const Elm_List_Item *it) -{ - ELM_LIST_ITEM_CHECK_DELETED_RETURN(it, EINA_FALSE); - - return it->disabled; + if (!wd) return NULL; + if (!wd->items) return NULL; + return eina_list_data_get(eina_list_last(wd->items)); }