#ifdef HAVE_CONFIG_H # include "elementary_config.h" #endif #define EFL_ACCESS_OBJECT_PROTECTED #define EFL_ACCESS_WIDGET_ACTION_PROTECTED #define EFL_ACCESS_SELECTION_PROTECTED #define ELM_WIDGET_ITEM_PROTECTED #define EFL_UI_L10N_PROTECTED #include #include "elm_priv.h" #include "elm_widget_list.h" #include "elm_interface_scrollable.h" #define MY_CLASS ELM_LIST_CLASS #define MY_CLASS_NAME "Elm_List" #define MY_CLASS_NAME_LEGACY "elm_list" #define ELM_LIST_SWIPE_TIME 0.4 static const char SIG_ACTIVATED[] = "activated"; static const char SIG_CLICKED_DOUBLE[] = "clicked,double"; static const char SIG_CLICKED_RIGHT[] = "clicked,right"; static const char SIG_SELECTED[] = "selected"; static const char SIG_UNSELECTED[] = "unselected"; static const char SIG_LONGPRESSED[] = "longpressed"; 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 char SIG_SWIPE[] = "swipe"; static const char SIG_HIGHLIGHTED[] = "highlighted"; static const char SIG_UNHIGHLIGHTED[] = "unhighlighted"; static const char SIG_ITEM_FOCUSED[] = "item,focused"; static const char SIG_ITEM_UNFOCUSED[] = "item,unfocused"; static const Evas_Smart_Cb_Description _smart_callbacks[] = { {SIG_ACTIVATED, ""}, {SIG_CLICKED_DOUBLE, ""}, {SIG_CLICKED_RIGHT, ""}, {SIG_SELECTED, ""}, {SIG_UNSELECTED, ""}, {SIG_LONGPRESSED, ""}, {SIG_EDGE_TOP, ""}, {SIG_EDGE_BOTTOM, ""}, {SIG_EDGE_LEFT, ""}, {SIG_EDGE_RIGHT, ""}, {SIG_SWIPE, ""}, {SIG_HIGHLIGHTED, ""}, {SIG_UNHIGHLIGHTED, ""}, {SIG_ITEM_FOCUSED, ""}, {SIG_ITEM_UNFOCUSED, ""}, {SIG_WIDGET_LANG_CHANGED, ""}, /**< handled by elm_widget */ {SIG_WIDGET_ACCESS_CHANGED, ""}, /**< handled by elm_widget */ {SIG_LAYOUT_FOCUSED, ""}, /**< handled by elm_layout */ {SIG_LAYOUT_UNFOCUSED, ""}, /**< handled by elm_layout */ {NULL, NULL} }; static void _size_hints_changed_cb(void *, Evas *, Evas_Object *, void *); static void _mouse_up_cb(void *, Evas *, Evas_Object *, void *); static void _mouse_down_cb(void *, Evas *, Evas_Object *, void *); static void _mouse_move_cb(void *, Evas *, Evas_Object *, void *); static void _mouse_in_cb(void *, Evas *, Evas_Object *, void *); static void _items_fix(Evas_Object *); static Eina_Bool _key_action_move(Evas_Object *obj, const char *params); static Eina_Bool _key_action_select(Evas_Object *obj, const char *params); static Eina_Bool _key_action_escape(Evas_Object *obj, const char *params); EOLIAN static void _elm_list_item_elm_widget_item_del_pre(Eo *eo_item EINA_UNUSED, Elm_List_Item_Data *item); static const Elm_Action key_actions[] = { {"move", _key_action_move}, {"select", _key_action_select}, {"escape", _key_action_escape}, {NULL, NULL} }; static void _items_safe_process(Eina_List *items, void (*process)(void* data, Elm_Object_Item *sel, Elm_List_Item_Data *it), void *data) { Elm_Object_Item *sel; Eina_List *l; Eina_Array walk; eina_array_step_set(&walk, sizeof (walk), 4); EINA_LIST_FOREACH(items, l, sel) eina_array_push(&walk, efl_ref(sel)); while ((sel = eina_array_pop(&walk))) { if (efl_invalidated_get(sel)) goto noneed; ELM_LIST_ITEM_DATA_GET(sel, it); process(data, sel, it); noneed: efl_unref(sel); } eina_array_flush(&walk); } static Eina_Bool _is_no_select(Elm_List_Item_Data *it) { ELM_LIST_DATA_GET_FROM_ITEM(it, sd); if ((sd->select_mode == ELM_OBJECT_SELECT_MODE_NONE) || (sd->select_mode == ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY)) return EINA_TRUE; return EINA_FALSE; } static void _elm_list_item_efl_object_invalidate(Elm_Object_Item *eo_it, Elm_List_Item_Data *it) { ELM_LIST_DATA_GET_FROM_ITEM(it, sd); if (sd->focused_item == eo_it) sd->focused_item = NULL; if (sd->last_focused_item == eo_it) sd->last_focused_item = NULL; if (sd->last_selected_item == eo_it) sd->last_selected_item = NULL; evas_object_event_callback_del_full (VIEW(it), EVAS_CALLBACK_MOUSE_DOWN, _mouse_down_cb, it); evas_object_event_callback_del_full (VIEW(it), EVAS_CALLBACK_MOUSE_UP, _mouse_up_cb, it); evas_object_event_callback_del_full (VIEW(it), EVAS_CALLBACK_MOUSE_MOVE, _mouse_move_cb, it); evas_object_event_callback_del_full (VIEW(it), EVAS_CALLBACK_MOUSE_IN, _mouse_in_cb, it); if (it->icon) evas_object_event_callback_del_full (it->icon, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _size_hints_changed_cb, WIDGET(it)); if (it->end) evas_object_event_callback_del_full (it->end, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _size_hints_changed_cb, WIDGET(it)); efl_invalidate(efl_super(eo_it, ELM_LIST_ITEM_CLASS)); } static void _elm_list_item_efl_object_destructor(Elm_Object_Item *eo_it, Elm_List_Item_Data *it) { ELM_SAFE_FREE(it->label, eina_stringshare_del); ELM_SAFE_FREE(it->swipe_timer, ecore_timer_del); ELM_SAFE_FREE(it->long_timer, ecore_timer_del); ELM_SAFE_FREE(it->icon, evas_object_del); ELM_SAFE_FREE(it->end, evas_object_del); efl_destructor(efl_super(eo_it, ELM_LIST_ITEM_CLASS)); } static Eina_Bool _item_multi_select_up(Elm_List_Data *sd) { Elm_Object_Item *prev; if (!sd->selected) return EINA_FALSE; if (!sd->multi) return EINA_FALSE; prev = elm_list_item_prev(sd->last_selected_item); while (prev) { if (!elm_object_item_disabled_get(prev)) break; prev = elm_list_item_prev(prev); } if (!prev) return EINA_TRUE; if (elm_list_item_selected_get(prev)) { elm_list_item_selected_set(sd->last_selected_item, EINA_FALSE); sd->last_selected_item = prev; } else { elm_list_item_selected_set(prev, EINA_TRUE); } return EINA_TRUE; } static Eina_Bool _item_multi_select_down(Elm_List_Data *sd) { Elm_Object_Item *next; if (!sd->selected) return EINA_FALSE; if (!sd->multi) return EINA_FALSE; next = elm_list_item_next(sd->last_selected_item); while (next) { if (!elm_object_item_disabled_get(next)) break; next = elm_list_item_next(next); } if (!next) return EINA_TRUE; if (elm_list_item_selected_get(next)) { elm_list_item_selected_set(sd->last_selected_item, EINA_FALSE); sd->last_selected_item = next; } else { elm_list_item_selected_set(next, EINA_TRUE); } return EINA_TRUE; } static Eina_Bool _all_items_unselect(Elm_List_Data *sd) { if (!sd->selected) return EINA_FALSE; while (sd->selected) elm_list_item_selected_set (sd->selected->data, EINA_FALSE); return EINA_TRUE; } static Eina_Bool _item_single_select_up(Elm_List_Data *sd) { Elm_Object_Item *prev; if (!sd->selected) prev = eina_list_data_get(eina_list_last(sd->items)); else prev = elm_list_item_prev(sd->last_selected_item); while (prev) { if (!elm_object_item_disabled_get(prev)) break; prev = elm_list_item_prev(prev); } if (!prev) return EINA_FALSE; _all_items_unselect(sd); elm_list_item_selected_set(prev, EINA_TRUE); return EINA_TRUE; } static Eina_Bool _item_single_select_down(Elm_List_Data *sd) { Elm_Object_Item *next; if (!sd->selected) next = eina_list_data_get(sd->items); else next = elm_list_item_next(sd->last_selected_item); while (next) { if (!elm_object_item_disabled_get(next)) break; next = elm_list_item_next(next); } if (!next) return EINA_FALSE; _all_items_unselect(sd); elm_list_item_selected_set(next, EINA_TRUE); return EINA_TRUE; } static Eina_Bool _elm_list_item_content_focus_set(Elm_List_Item_Data *it, Elm_Focus_Direction dir, Eina_Bool h_mode) { if (!it) return EINA_FALSE; ELM_LIST_DATA_GET_FROM_ITEM(it, sd); if (!sd->focus_on_selection_enabled) return EINA_FALSE; if ((h_mode && (dir != ELM_FOCUS_UP) && (dir != ELM_FOCUS_DOWN)) || (!h_mode && (dir != ELM_FOCUS_LEFT) && (dir != ELM_FOCUS_RIGHT))) return EINA_FALSE; int focus_objs = 0; Evas_Object *focus_chain[2]; Evas_Object *focused = NULL; int idx; if (it->icon && elm_object_widget_check(it->icon) && elm_object_focus_allow_get(it->icon)) focus_chain[focus_objs++] = it->icon; if (it->end && elm_object_widget_check(it->end) && elm_object_focus_allow_get(it->end)) focus_chain[focus_objs++] = it->end; if (!focus_objs) return EINA_FALSE; for (idx = 0; idx < focus_objs; idx++) { if (elm_object_focus_get(focus_chain[idx])) { focused = focus_chain[idx]; break; } } if (!focused) { elm_object_focus_set(focus_chain[0], EINA_TRUE); return EINA_TRUE; } /* FOCUS-FIXME if (dir != ELM_FOCUS_PREVIOUS) { Evas_Object *nextfocus; Elm_Object_Item *nextfocus_item; if (efl_ui_widget_focus_next_get(focused, dir, &nextfocus, &nextfocus_item)) { if (nextfocus_item) elm_object_item_focus_set(nextfocus_item, EINA_TRUE); else elm_object_focus_set(nextfocus, EINA_TRUE); return EINA_TRUE; } idx += ((dir == ELM_FOCUS_UP) || (dir == ELM_FOCUS_LEFT)) ? -1 : 1; if (idx < 0) idx = focus_objs - 1; if (idx >= focus_objs) idx = 0; focused = focus_chain[idx]; } */ elm_object_focus_set(focused, EINA_TRUE); return EINA_TRUE; } static Elm_Object_Item * _next_item_get(Elm_List_Data *sd, Elm_Object_Item *eo_cur, Elm_Focus_Direction dir) { Eina_List *list = NULL; Elm_Object_Item *eo_it = NULL; list = eina_list_data_find_list(sd->items, eo_cur); if (!list) return NULL; if ((!sd->h_mode && (dir == ELM_FOCUS_UP)) || ((sd->h_mode) && (dir == ELM_FOCUS_LEFT))) eo_it = eina_list_data_get(eina_list_prev(list)); else if (((!sd->h_mode) && (dir == ELM_FOCUS_DOWN)) || ((sd->h_mode) && (dir == ELM_FOCUS_RIGHT))) eo_it = eina_list_data_get(eina_list_next(list)); return eo_it; } static Eina_Bool _item_focused_next(Evas_Object *obj, Elm_Focus_Direction dir) { ELM_LIST_DATA_GET_OR_RETURN_VAL(obj, sd, EINA_FALSE); Elm_Object_Item *eo_it = NULL; if (sd->focused_item) eo_it = _next_item_get(sd, sd->focused_item, dir); while (eo_it && elm_object_item_disabled_get(eo_it)) { eo_it = _next_item_get(sd, eo_it, dir); } if (eo_it) { elm_object_item_focus_set(eo_it, EINA_TRUE); return EINA_TRUE; } return EINA_FALSE; } static Eina_Bool _elm_list_efl_ui_widget_event_direction(Evas_Object *obj, Elm_Focus_Direction dir, Eina_Bool multi) { Elm_Object_Item *eo_it = NULL; ELM_LIST_DATA_GET(obj, sd); Eina_Bool ret = EINA_FALSE; Evas_Coord v = 0; Evas_Coord min = 0; Eina_Bool focus_only = EINA_FALSE; // check if the content can get the focus by direction key ELM_LIST_ITEM_DATA_GET(elm_object_focused_item_get(obj) , it); if (_elm_list_item_content_focus_set(it, dir, sd->h_mode)) return EINA_TRUE; if ((sd->h_mode && (dir != ELM_FOCUS_LEFT) && (dir != ELM_FOCUS_RIGHT)) || (!sd->h_mode && (dir != ELM_FOCUS_UP) && (dir != ELM_FOCUS_DOWN))) return EINA_FALSE; // check if list get focus at first focus_only = _elm_config->item_select_on_focus_disable; if (!sd->focused_item) { if ((dir == ELM_FOCUS_LEFT) || (dir == ELM_FOCUS_UP)) eo_it = elm_list_last_item_get(obj); else eo_it = elm_list_first_item_get(obj); if (focus_only) elm_object_item_focus_set(eo_it, EINA_TRUE); else elm_list_item_selected_set(eo_it, EINA_TRUE); return EINA_TRUE; } // get content size and viewport size if ((dir == ELM_FOCUS_LEFT) || (dir == ELM_FOCUS_RIGHT)) { elm_interface_scrollable_content_viewport_geometry_get (obj, NULL, NULL, &v, NULL); elm_interface_scrollable_content_size_get(obj, &min, NULL); } else { elm_interface_scrollable_content_viewport_geometry_get (obj, NULL, NULL, NULL, &v); elm_interface_scrollable_content_size_get(obj, NULL, &min); } // move focus or selection according to the configuration if (focus_only) ret = _item_focused_next(obj, dir); else { if (multi) { if ((dir == ELM_FOCUS_LEFT) || (dir == ELM_FOCUS_UP)) ret = _item_multi_select_up(sd); else ret = _item_multi_select_down(sd); } else { if ((dir == ELM_FOCUS_LEFT) || (dir == ELM_FOCUS_UP)) ret = _item_single_select_up(sd); else ret = _item_single_select_down(sd); } } if (ret) return EINA_TRUE; // handle item loop feature if (sd->item_loop_enable && !sd->item_looping_on) { if (min > v) { if (dir == ELM_FOCUS_LEFT) { elm_layout_signal_emit(obj, "elm,action,looping,left", "elm"); sd->item_looping_on = EINA_TRUE; } else if (dir == ELM_FOCUS_RIGHT) { elm_layout_signal_emit(obj, "elm,action,looping,right", "elm"); sd->item_looping_on = EINA_TRUE; } else if (dir == ELM_FOCUS_UP) { elm_layout_signal_emit(obj, "elm,action,looping,up", "elm"); sd->item_looping_on = EINA_TRUE; } else if (dir == ELM_FOCUS_DOWN) { elm_layout_signal_emit(obj, "elm,action,looping,down", "elm"); sd->item_looping_on = EINA_TRUE; } } else { if ((dir == ELM_FOCUS_LEFT) || (dir == ELM_FOCUS_UP)) eo_it = elm_list_last_item_get(obj); else eo_it = elm_list_first_item_get(obj); if (focus_only) elm_object_item_focus_set(eo_it, EINA_TRUE); else elm_list_item_selected_set(eo_it, EINA_TRUE); } return EINA_TRUE; } else if (sd->item_looping_on) return EINA_TRUE; return EINA_FALSE; } static Eina_Bool _key_action_move(Evas_Object *obj, const char *params) { ELM_LIST_DATA_GET(obj, sd); const char *dir = params; Evas_Coord x = 0; Evas_Coord y = 0; Evas_Coord v_w = 0; Evas_Coord v_h = 0; Evas_Coord step_x = 0; Evas_Coord step_y = 0; Evas_Coord page_x = 0; Evas_Coord page_y = 0; Elm_Object_Item *it = NULL; if (!sd->items) return EINA_FALSE; elm_interface_scrollable_content_pos_get(obj, &x, &y); elm_interface_scrollable_step_size_get(obj, &step_x, &step_y); elm_interface_scrollable_page_size_get(obj, &page_x, &page_y); elm_interface_scrollable_content_viewport_geometry_get (obj, NULL, NULL, &v_w, &v_h); _elm_widget_focus_auto_show(obj); /* TODO: fix logic for horizontal mode */ if (!strcmp(dir, "left")) { if (_elm_list_efl_ui_widget_event_direction(obj, ELM_FOCUS_LEFT, EINA_FALSE)) return EINA_TRUE; else return EINA_FALSE; } else if (!strcmp(dir, "left_multi")) { if (_elm_list_efl_ui_widget_event_direction(obj, ELM_FOCUS_LEFT, EINA_TRUE)) return EINA_TRUE; else return EINA_FALSE; } else if (!strcmp(dir, "right")) { if (_elm_list_efl_ui_widget_event_direction(obj, ELM_FOCUS_RIGHT, EINA_FALSE)) return EINA_TRUE; else return EINA_FALSE; } else if (!strcmp(dir, "right_multi")) { if (_elm_list_efl_ui_widget_event_direction(obj, ELM_FOCUS_RIGHT, EINA_TRUE)) return EINA_TRUE; else return EINA_FALSE; } else if (!strcmp(dir, "up")) { if (_elm_list_efl_ui_widget_event_direction(obj, ELM_FOCUS_UP, EINA_FALSE)) return EINA_TRUE; else return EINA_FALSE; } else if (!strcmp(dir, "up_multi")) { if (_elm_list_efl_ui_widget_event_direction(obj, ELM_FOCUS_UP, EINA_TRUE)) return EINA_TRUE; else return EINA_FALSE; } else if (!strcmp(dir, "down")) { if (_elm_list_efl_ui_widget_event_direction(obj, ELM_FOCUS_DOWN, EINA_FALSE)) return EINA_TRUE; else return EINA_FALSE; } else if (!strcmp(dir, "down_multi")) { if (_elm_list_efl_ui_widget_event_direction(obj, ELM_FOCUS_DOWN, EINA_TRUE)) return EINA_TRUE; else return EINA_FALSE; } else if (!strcmp(dir, "first")) { it = eina_list_data_get(sd->items); if (it) { elm_list_item_selected_set(it, EINA_TRUE); return EINA_TRUE; } else return EINA_FALSE; } else if (!strcmp(dir, "last")) { it = eina_list_data_get(eina_list_last(sd->items)); if (it) { elm_list_item_selected_set(it, EINA_TRUE); return EINA_TRUE; } else return EINA_FALSE; } else if (!strcmp(dir, "prior")) { if (sd->h_mode) { if (page_x < 0) x -= -(page_x * v_w) / 100; else x -= page_x; } else { if (page_y < 0) y -= -(page_y * v_h) / 100; else y -= page_y; } } else if (!strcmp(dir, "next")) { if (sd->h_mode) { if (page_x < 0) x += -(page_x * v_w) / 100; else x += page_x; } else { if (page_y < 0) y += -(page_y * v_h) / 100; else y += page_y; } } else return EINA_FALSE; elm_interface_scrollable_content_pos_set(obj, x, y, EINA_TRUE); return EINA_TRUE; } static Eina_Bool _key_action_select(Evas_Object *obj, const char *params EINA_UNUSED) { ELM_LIST_DATA_GET(obj, sd); Elm_Object_Item *eo_it = NULL; if (!sd->items) return EINA_FALSE; if (!_elm_config->item_select_on_focus_disable && (!sd->multi) && (sd->selected)) eo_it = elm_list_selected_item_get(obj); else eo_it = elm_object_focused_item_get(obj); elm_list_item_selected_set(eo_it, EINA_TRUE); if (eo_it) { ELM_LIST_ITEM_DATA_GET(eo_it, it); efl_event_callback_legacy_call (WIDGET(it), ELM_LIST_EVENT_ACTIVATED, eo_it); } return EINA_TRUE; } static Eina_Bool _key_action_escape(Evas_Object *obj, const char *params EINA_UNUSED) { ELM_LIST_DATA_GET(obj, sd); if (!sd->items) return EINA_FALSE; if (!_all_items_unselect(sd)) return EINA_FALSE; return EINA_TRUE; } EOLIAN static void _elm_list_efl_ui_l10n_translation_update(Eo *obj EINA_UNUSED, Elm_List_Data *sd) { Elm_Object_Item *it; Eina_List *l; EINA_LIST_FOREACH(sd->items, l, it) elm_wdg_item_translate(it); efl_ui_l10n_translation_update(efl_super(obj, MY_CLASS)); } EOLIAN static void _elm_list_elm_layout_sizing_eval(Eo *obj, Elm_List_Data *sd) { Evas_Coord vw = 0, vh = 0; Evas_Coord minw = 0, minh = 0, maxw = 0, maxh = 0, w = 0, h = 0, vmw = 0, vmh = 0; double xw = 0.0, yw = 0.0; ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd); if (!efl_finalized_get(obj)) return; //not constructed yet evas_object_size_hint_combined_min_get(sd->box, &minw, &minh); evas_object_size_hint_max_get(sd->box, &maxw, &maxh); evas_object_size_hint_weight_get(sd->box, &xw, &yw); elm_interface_scrollable_content_viewport_geometry_get (obj, NULL, NULL, &vw, &vh); if (xw > 0.0) { if ((minw > 0) && (vw < minw)) vw = minw; else if ((maxw > 0) && (vw > maxw)) vw = maxw; } else if (minw > 0) vw = minw; if (yw > 0.0) { if ((minh > 0) && (vh < minh)) vh = minh; else if ((maxh > 0) && (vh > maxh)) vh = maxh; } else if (minh > 0) vh = minh; evas_object_resize(sd->box, vw, vh); w = -1; h = -1; edje_object_size_min_calc (wd->resize_obj, &vmw, &vmh); if (sd->scr_minw) w = vmw + minw; if (sd->scr_minh) h = vmh + minh; evas_object_size_hint_max_get(obj, &maxw, &maxh); if ((maxw > 0) && (w > maxw)) w = maxw; if ((maxh > 0) && (h > maxh)) h = maxh; evas_object_size_hint_min_set(obj, w, h); } static void _elm_list_content_min_limit_cb(Evas_Object *obj, Eina_Bool w, Eina_Bool h) { ELM_LIST_DATA_GET(obj, sd); if ((sd->mode == ELM_LIST_LIMIT) || (sd->mode == ELM_LIST_EXPAND)) return; sd->scr_minw = !!w; sd->scr_minh = !!h; elm_layout_sizing_eval(obj); } static void _elm_list_mode_set_internal(Evas_Object *obj) { Elm_List_Data *sd = efl_data_scope_get(obj, MY_CLASS); if (sd->mode == ELM_LIST_LIMIT) { if (!sd->h_mode) { sd->scr_minw = EINA_TRUE; sd->scr_minh = EINA_FALSE; } else { sd->scr_minw = EINA_FALSE; sd->scr_minh = EINA_TRUE; } } else if (sd->mode == ELM_LIST_EXPAND) { sd->scr_minw = EINA_TRUE; sd->scr_minh = EINA_TRUE; } else if (sd->mode == ELM_LIST_COMPRESS) { sd->scr_minw = EINA_FALSE; sd->scr_minh = EINA_FALSE; } elm_layout_sizing_eval(obj); } static inline void _elm_list_walk(Evas_Object *obj, Elm_List_Data *sd) { if (sd->walking < 0) { ERR("ERROR: walking was negative. fixed!\n"); sd->walking = 0; } sd->walking++; efl_ref(obj); evas_object_ref(obj); } static inline void _elm_list_unwalk(Evas_Object *obj, Elm_List_Data *sd) { sd->walking--; if (sd->walking < 0) { ERR("ERROR: walking became negative. fixed!\n"); sd->walking = 0; } if (sd->walking) goto cleanup; if (sd->fix_pending) { sd->fix_pending = EINA_FALSE; _items_fix(obj); elm_layout_sizing_eval(obj); } cleanup: evas_object_unref(obj); efl_unref(obj); } static void _items_fix(Evas_Object *obj) { Evas_Coord minw[2] = { 0, 0 }, minh[2] = { 0, 0 }; const Eina_List *l; Elm_Object_Item *eo_it; Evas_Coord mw, mh; int i, redo = 0; Eina_Array walk; const char *style; const char *it_odd; const char *it_plain; const char *it_compress; const char *it_compress_odd; ELM_LIST_DATA_GET(obj, sd); style = elm_widget_style_get(obj); it_plain = sd->h_mode ? "h_item" : "item"; it_odd = sd->h_mode ? "h_item_odd" : "item_odd"; it_compress = sd->h_mode ? "h_item_compress" : "item_compress"; it_compress_odd = sd->h_mode ? "h_item_compress_odd" : "item_compress_odd"; if (sd->walking) { sd->fix_pending = EINA_TRUE; return; } _elm_list_walk(obj, sd); // watch out "return" before unwalk! sd->fixing_now = EINA_TRUE; eina_array_step_set(&walk, sizeof (walk), 8); EINA_LIST_FOREACH(sd->items, l, eo_it) { ELM_LIST_ITEM_DATA_GET(eo_it, it); if (!it) continue; if (it->deleted) continue; if (it->icon) { evas_object_size_hint_combined_min_get(it->icon, &mw, &mh); if (mw > minw[0]) minw[0] = mw; if (mh > minh[0]) minh[0] = mh; } if (it->end) { evas_object_size_hint_combined_min_get(it->end, &mw, &mh); if (mw > minw[1]) minw[1] = mw; if (mh > minh[1]) minh[1] = mh; } eina_array_push(&walk, efl_ref(eo_it)); } if ((minw[0] != sd->minw[0]) || (minw[1] != sd->minw[1]) || (minh[0] != sd->minh[0]) || (minh[1] != sd->minh[1])) { sd->minw[0] = minw[0]; sd->minw[1] = minw[1]; sd->minh[0] = minh[0]; sd->minh[1] = minh[1]; redo = 1; } i = 0; while ((eo_it = eina_array_pop(&walk))) { if (efl_invalidated_get(eo_it)) goto noneed; ELM_LIST_ITEM_DATA_GET(eo_it, it); if (!it) goto noneed; if (it->deleted) goto noneed; it->even = i & 0x1; if ((it->even != it->is_even) || (!it->fixed) || (redo)) { const char *stacking; if (it->is_separator) elm_widget_theme_object_set (obj, VIEW(it), "separator", sd->h_mode ? "vertical" : "horizontal", style); else if (sd->mode == ELM_LIST_COMPRESS) { if (it->even) elm_widget_theme_object_set (obj, VIEW(it), "list", it_compress, style); else elm_widget_theme_object_set (obj, VIEW(it), "list", it_compress_odd, style); } else { if (it->even) elm_widget_theme_object_set (obj, VIEW(it), "list", it_plain, style); else elm_widget_theme_object_set (obj, VIEW(it), "list", it_odd, style); } stacking = edje_object_data_get(VIEW(it), "stacking"); if (stacking) { if (!strcmp(stacking, "below")) evas_object_lower(VIEW(it)); else if (!strcmp(stacking, "above")) evas_object_raise(VIEW(it)); } if (!it->is_separator) { edje_object_part_text_escaped_set (VIEW(it), "elm.text", it->label); elm_wdg_item_part_text_custom_update(EO_OBJ(it)); if ((!it->icon) && (minh[0] > 0)) { 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(VIEW(it))); evas_object_color_set(it->end, 0, 0, 0, 0); it->dummy_end = EINA_TRUE; } if (eina_list_count(sd->items) == 1) { edje_object_signal_emit (VIEW(it), "elm,state,list,single", "elm"); } else if (l == sd->items) //1st item { edje_object_signal_emit (VIEW(it), "elm,state,list,first", "elm"); } else if (l == eina_list_last(sd->items)) { edje_object_signal_emit (VIEW(it), "elm,state,list,last", "elm"); } else { edje_object_signal_emit (VIEW(it), "elm,state,list,middle", "elm"); } } 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(VIEW(it)); if (it->deleted) goto noneed; mw = mh = -1; if (!it->is_separator) elm_coords_finger_size_adjust(1, &mw, 1, &mh); edje_object_size_min_restricted_calc (VIEW(it), &mw, &mh, mw, mh); /* FIXME: this fixed T179 but introduced T286. Temporarily disable these lines until it gets fixed correctly. Evas_Coord ew, eh; edje_object_parts_extends_calc (VIEW(it), NULL, NULL, &ew, &eh); mw = mw > ew ? mw : ew; mh = mh > eh ? mh : eh; */ evas_object_size_hint_min_set(VIEW(it), mw, mh); evas_object_show(VIEW(it)); } if ((it->selected) || (it->highlighted)) { const char *select_raise; // 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 (VIEW(it), "elm,state,selected", "elm"); if (it->deleted) goto noneed; select_raise = edje_object_data_get(VIEW(it), "selectraise"); if ((select_raise) && (!strcmp(select_raise, "on"))) evas_object_raise(VIEW(it)); } if (it->base->disabled) edje_object_signal_emit(VIEW(it), "elm,state,disabled", "elm"); it->fixed = EINA_TRUE; it->is_even = it->even; } if (it->icon) { evas_object_size_hint_min_set(it->icon, minw[0], minh[0]); 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]); edje_object_part_swallow (VIEW(it), "elm.swallow.end", it->end); } if (!it->is_separator) i++; noneed: efl_unref(eo_it); } sd->fixing_now = EINA_FALSE; _elm_list_unwalk(obj, sd); //focus highlight in_theme is set by list item theme. _elm_widget_item_highlight_in_theme( obj, elm_list_first_item_get(obj)); } static void _size_hints_changed_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED) { ELM_LIST_DATA_GET(data, sd); ELM_WIDGET_DATA_GET_OR_RETURN(data, wd); if (sd->delete_me) return; /* FIXME: Looks it updates items_fix() unnecessarily. when resize_obj, box finished sizing, then it can call _items_fix() one time at the end. */ if (sd->fixing_now) { if ((obj != wd->resize_obj) && (obj != sd->box)) return; } _items_fix(data); elm_layout_sizing_eval(data); } /* FIXME: take off later. maybe this show region coords belong in the * interface (new api functions, set/get)? */ static void _show_region_hook(void *data EINA_UNUSED, Evas_Object *obj, Eina_Rect r) { elm_interface_scrollable_content_region_set(obj, r.x, r.y, r.w, r.h); } EOLIAN static void _elm_list_efl_ui_widget_disabled_set(Eo *obj, Elm_List_Data *sd, Eina_Bool disabled) { efl_ui_widget_disabled_set(efl_super(obj, MY_CLASS), disabled); if (efl_ui_widget_disabled_get(obj)) { elm_widget_scroll_freeze_push(obj); elm_widget_scroll_hold_push(obj); /* FIXME: if we get to have a way to only un-highlight items * in the future, keeping them selected... */ _all_items_unselect(sd); } else { elm_widget_scroll_freeze_pop(obj); elm_widget_scroll_hold_pop(obj); } } static void _mirrored_set(Evas_Object *obj, Eina_Bool rtl) { Elm_Object_Item *eo_it; Eina_List *n; ELM_LIST_DATA_GET(obj, sd); efl_ui_mirrored_set(obj, rtl); EINA_LIST_FOREACH(sd->items, n, eo_it) { ELM_LIST_ITEM_DATA_GET(eo_it, it); edje_object_mirrored_set(VIEW(it), rtl); } } EOLIAN static Efl_Ui_Theme_Apply_Result _elm_list_efl_ui_widget_theme_apply(Eo *obj, Elm_List_Data *sd) { Elm_Object_Item *eo_it; Eina_List *n; Efl_Ui_Theme_Apply_Result int_ret = EFL_UI_THEME_APPLY_RESULT_FAIL; int_ret = efl_ui_widget_theme_apply(efl_super(obj, MY_CLASS)); if (!int_ret) return EFL_UI_THEME_APPLY_RESULT_FAIL; _mirrored_set(obj, efl_ui_mirrored_get(obj)); EINA_LIST_FOREACH(sd->items, n, eo_it) { ELM_LIST_ITEM_DATA_GET(eo_it, it); edje_object_scale_set (VIEW(it), efl_gfx_entity_scale_get(obj) * elm_config_scale_get()); it->fixed = EINA_FALSE; } _items_fix(obj); elm_layout_sizing_eval(obj); return int_ret; } static void _elm_list_item_focused(Elm_Object_Item *eo_it) { ELM_LIST_ITEM_DATA_GET(eo_it, it); ELM_LIST_DATA_GET_FROM_ITEM(it, sd); Evas_Object *win = elm_widget_top_get(WIDGET(it)); Evas_Coord x, y, w, h, sx, sy, sw, sh; const char *focus_raise; if ((!sd) || _is_no_select(it) || (eo_it == sd->focused_item)) return; evas_object_geometry_get(VIEW(it), &x, &y, &w, &h); evas_object_geometry_get(sd->hit_rect, &sx, &sy, &sw, &sh); if (!ELM_RECTS_INCLUDE(sx, sy, sw, sh, x, y, w, h)) { switch (_elm_config->focus_autoscroll_mode) { case ELM_FOCUS_AUTOSCROLL_MODE_SHOW: elm_list_item_show(eo_it); break; case ELM_FOCUS_AUTOSCROLL_MODE_BRING_IN: elm_list_item_bring_in(eo_it); break; default: break; } } sd->focused_item = eo_it; if (elm_win_focus_highlight_enabled_get(win) || _elm_config->win_auto_focus_enable) { edje_object_signal_emit (VIEW(it), "elm,state,focused", "elm"); } focus_raise = edje_object_data_get(VIEW(it), "focusraise"); if ((focus_raise) && (!strcmp(focus_raise, "on"))) evas_object_raise(VIEW(it)); efl_event_callback_legacy_call (WIDGET(it), ELM_LIST_EVENT_ITEM_FOCUSED, eo_it); if (_elm_config->atspi_mode) efl_access_state_changed_signal_emit(eo_it, EFL_ACCESS_STATE_FOCUSED, EINA_TRUE); } static void _elm_list_item_unfocused(Elm_Object_Item *eo_it) { ELM_LIST_ITEM_DATA_GET(eo_it, it); Evas_Object *obj = WIDGET(it); Evas_Object *win = elm_widget_top_get(obj); ELM_LIST_DATA_GET(obj, sd); if ((!sd) || (!sd->focused_item) || (eo_it != sd->focused_item)) return; if (_is_no_select(it)) return; if (elm_win_focus_highlight_enabled_get(win) || _elm_config->win_auto_focus_enable) { ELM_LIST_ITEM_DATA_GET(sd->focused_item, focus_it); edje_object_signal_emit (VIEW(focus_it), "elm,state,unfocused", "elm"); } sd->focused_item = NULL; efl_event_callback_legacy_call(obj, ELM_LIST_EVENT_ITEM_UNFOCUSED, eo_it); if (_elm_config->atspi_mode) efl_access_state_changed_signal_emit(eo_it, EFL_ACCESS_STATE_FOCUSED, EINA_FALSE); } /* * This function searches the nearest visible item based on the given item. * If the given item is in the list viewport, this returns the given item. * Or this searches other items and checks the nearest fully visible item * according to the given item's position. */ static Elm_List_Item_Data * _elm_list_nearest_visible_item_get(Evas_Object *obj, Elm_List_Item_Data *it) { Evas_Coord vx = 0, vy = 0, vw = 0, vh = 0; // list viewport geometry Evas_Coord ix = 0, iy = 0, iw = 0, ih = 0; // given item geometry Evas_Coord cx = 0, cy = 0, cw = 0, ch = 0; // candidate item geometry Eina_List *item_list = NULL; Elm_List_Item_Data *item = NULL; ELM_LIST_DATA_GET(obj, sd); Eina_Bool search_next = EINA_FALSE; if (!it) return NULL; evas_object_geometry_get(obj, &vx, &vy, &vw, &vh); evas_object_geometry_get(VIEW(it), &ix, &iy, &iw, &ih); if (ELM_RECTS_INCLUDE(vx, vy, vw, vh, ix, iy, iw, ih)) { if (!elm_object_item_disabled_get(EO_OBJ(it))) return it; else search_next = EINA_TRUE; } item_list = eina_list_data_find_list(sd->items, EO_OBJ(it)); if ((!sd->h_mode && (iy < vy)) || (sd->h_mode && (iw < vw)) || search_next) { while ((item_list = eina_list_next(item_list))) { item = efl_data_scope_get(eina_list_data_get(item_list), ELM_LIST_ITEM_CLASS); if (!item) continue; evas_object_geometry_get(VIEW(item), &cx, &cy, &cw, &ch); if (ELM_RECTS_INCLUDE(vx, vy, vw, vh, cx, cy, cw, ch) && !elm_object_item_disabled_get(EO_OBJ(item))) { return item; } } } else { while ((item_list = eina_list_prev(item_list))) { item = efl_data_scope_get(eina_list_data_get(item_list), ELM_LIST_ITEM_CLASS); if (!item) continue; evas_object_geometry_get(VIEW(item), &cx, &cy, &cw, &ch); if (ELM_RECTS_INCLUDE(vx, vy, vw, vh, cx, cy, cw, ch) && !elm_object_item_disabled_get(EO_OBJ(item))) { return item; } } } return it; } EOLIAN static Eina_Bool _elm_list_efl_ui_focus_object_on_focus_update(Eo *obj, Elm_List_Data *sd) { Eina_Bool int_ret = EINA_FALSE; Elm_Object_Item *eo_it = NULL; Eina_Bool is_sel = EINA_FALSE; int_ret = efl_ui_focus_object_on_focus_update(efl_super(obj, MY_CLASS)); if (!int_ret) return EINA_FALSE; if (elm_object_focus_get(obj) && sd->selected && !sd->last_selected_item) { Elm_Object_Item *sel = eina_list_data_get(sd->selected); sd->last_selected_item = efl_data_scope_get(sel, ELM_LIST_ITEM_CLASS); } if (!sd->items) return EINA_FALSE; if (elm_object_focus_get(obj) && !sd->mouse_down) { if (sd->last_focused_item) eo_it = sd->last_focused_item; else if (sd->last_selected_item) eo_it = sd->last_selected_item; else if (_elm_config->first_item_focus_on_first_focus_in) { eo_it = elm_list_first_item_get(obj); is_sel = EINA_TRUE; } if (eo_it) { ELM_LIST_ITEM_DATA_GET(eo_it, it); it = _elm_list_nearest_visible_item_get(obj, it); if (it) { if (!_elm_config->item_select_on_focus_disable && is_sel) elm_list_item_selected_set(EO_OBJ(it), EINA_TRUE); else _elm_list_item_focused(EO_OBJ(it)); } } } else { sd->last_focused_item = sd->focused_item; if (sd->focused_item) _elm_list_item_unfocused(sd->focused_item); } return EINA_TRUE; } EOLIAN static Eina_Bool _elm_list_efl_ui_widget_widget_sub_object_del(Eo *obj, Elm_List_Data *sd, Evas_Object *sobj) { const Eina_List *l; Elm_Object_Item *eo_it; Eina_Bool int_ret = EINA_FALSE; int_ret = elm_widget_sub_object_del(efl_super(obj, MY_CLASS), sobj); if (!int_ret) return EINA_FALSE; if ((sobj == sd->box) || (sobj == obj)) goto end; EINA_LIST_FOREACH(sd->items, l, eo_it) { ELM_LIST_ITEM_DATA_GET(eo_it, it); if ((sobj == it->icon) || (sobj == it->end)) { if (it->icon == sobj) it->icon = NULL; if (it->end == sobj) it->end = NULL; evas_object_event_callback_del_full (sobj, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _size_hints_changed_cb, obj); efl_del(eo_it); if (!sd->walking && efl_parent_get(obj)) { _items_fix(obj); elm_layout_sizing_eval(obj); } else sd->fix_pending = EINA_TRUE; break; } } end: return EINA_TRUE; } static void _item_highlight(Elm_List_Item_Data *it) { Elm_Object_Item *eo = EO_OBJ(it); Evas_Object *obj; const char *select_raise; if (efl_invalidated_get(eo)) return ; ELM_LIST_ITEM_CHECK_OR_RETURN(it); obj = WIDGET(it); ELM_LIST_DATA_GET(obj, sd); if (_is_no_select(it) || (it->highlighted) || (it->base->disabled)) return; efl_ref(EO_OBJ(it)); // This is done to delay the update of a theme change if items_fix get called _elm_list_walk(obj, sd); edje_object_signal_emit(VIEW(it), "elm,state,selected", "elm"); efl_event_callback_legacy_call(obj, ELM_LIST_EVENT_HIGHLIGHTED, EO_OBJ(it)); select_raise = edje_object_data_get(VIEW(it), "selectraise"); if ((select_raise) && (!strcmp(select_raise, "on"))) evas_object_raise(VIEW(it)); it->highlighted = EINA_TRUE; _elm_list_unwalk(obj, sd); efl_unref(EO_OBJ(it)); } static void _item_select(Elm_List_Item_Data *it) { Elm_Object_Item *eo = EO_OBJ(it); Evas_Object *obj; if (efl_invalidated_get(eo)) return ; ELM_LIST_ITEM_CHECK_OR_RETURN(it); obj = WIDGET(it); ELM_LIST_DATA_GET(obj, sd); Elm_Object_Item *eo_it = EO_OBJ(it); if (it->base->disabled || _is_no_select(it)) return; if (!sd->focus_on_selection_enabled) { if (it->icon && elm_object_widget_check(it->icon) && elm_object_focus_get(it->icon)) { elm_object_focus_set(obj, EINA_FALSE); elm_object_focus_set(obj, EINA_TRUE); } else if (it->end && elm_object_widget_check(it->end) && elm_object_focus_get(it->end)) { elm_object_focus_set(obj, EINA_FALSE); elm_object_focus_set(obj, EINA_TRUE); } } if (it->selected) { if (sd->select_mode == ELM_OBJECT_SELECT_MODE_ALWAYS) goto call; return; } _elm_list_item_content_focus_set(it, ELM_FOCUS_PREVIOUS, sd->h_mode); it->selected = EINA_TRUE; sd->selected = eina_list_append(sd->selected, eo_it); call: efl_ref(EO_OBJ(it)); _elm_list_walk(obj, sd); if (it->func) it->func((void *)WIDGET_ITEM_DATA_GET(eo_it), WIDGET(it), eo_it); efl_event_callback_legacy_call(obj, EFL_UI_EVENT_SELECTED, eo_it); if (_elm_config->atspi_mode) efl_access_state_changed_signal_emit(eo_it, EFL_ACCESS_STATE_SELECTED, EINA_TRUE); sd->last_selected_item = eo_it; _elm_list_unwalk(obj, sd); efl_unref(EO_OBJ(it)); } static void _item_unhighlight(Elm_List_Item_Data *it) { Elm_Object_Item *eo = EO_OBJ(it); Evas_Object *obj; const char *stacking, *select_raise; if (efl_invalidated_get(eo)) return ; ELM_LIST_ITEM_CHECK_OR_RETURN(it); obj = WIDGET(it); ELM_LIST_DATA_GET(obj, sd); // if ((!it->highlighted) || (it->base->disabled) || // (sd->select_mode == ELM_OBJECT_SELECT_MODE_NONE)) return; if (!it->highlighted) return; efl_ref(EO_OBJ(it)); _elm_list_walk(obj, sd); edje_object_signal_emit(VIEW(it), "elm,state,unselected", "elm"); efl_event_callback_legacy_call (obj, ELM_LIST_EVENT_UNHIGHLIGHTED, EO_OBJ(it)); stacking = edje_object_data_get(VIEW(it), "stacking"); select_raise = edje_object_data_get(VIEW(it), "selectraise"); if ((select_raise) && (!strcmp(select_raise, "on"))) { if ((stacking) && (!strcmp(stacking, "below"))) evas_object_lower(VIEW(it)); } it->highlighted = EINA_FALSE; _elm_list_unwalk(obj, sd); efl_unref(EO_OBJ(it)); } static void _item_unselect(Elm_List_Item_Data *it) { Elm_Object_Item *eo = EO_OBJ(it); Evas_Object *obj; if (efl_invalidated_get(eo)) return ; ELM_LIST_ITEM_CHECK_OR_RETURN(it); obj = WIDGET(it); ELM_LIST_DATA_GET(obj, sd); // if (it->base->disabled || (sd->select_mode == ELM_OBJECT_SELECT_MODE_NONE)) // return; efl_ref(eo); _elm_list_walk(obj, sd); if (sd->focus_on_selection_enabled) { if (it->icon) elm_object_focus_set(it->icon, EINA_FALSE); if (it->end) elm_object_focus_set(it->end, EINA_FALSE); } if (it->selected) { it->selected = EINA_FALSE; sd->selected = eina_list_remove(sd->selected, EO_OBJ(it)); if (!(it->base->disabled || (sd->select_mode == ELM_OBJECT_SELECT_MODE_NONE))) efl_event_callback_legacy_call (WIDGET(it), EFL_UI_EVENT_UNSELECTED, EO_OBJ(it)); if (_elm_config->atspi_mode) efl_access_state_changed_signal_emit(EO_OBJ(it), EFL_ACCESS_STATE_SELECTED, EINA_FALSE); } _elm_list_unwalk(obj, sd); efl_unref(eo); } static void _process_item_unselected_set(void *data, Elm_Object_Item *sel, Elm_List_Item_Data *it) { if (sel == data) return ; _item_unhighlight(it); _item_unselect(it); } static Eina_Bool _swipe_cancel(void *data) { Elm_List_Item_Data *it = data; ELM_LIST_ITEM_CHECK_OR_RETURN(it, ECORE_CALLBACK_CANCEL); ELM_LIST_DATA_GET_FROM_ITEM(it, sd); sd->swipe = EINA_FALSE; sd->movements = 0; return ECORE_CALLBACK_RENEW; } static void _edge_left_cb(Evas_Object *obj, void *data EINA_UNUSED) { efl_event_callback_legacy_call(obj, ELM_LIST_EVENT_EDGE_LEFT, NULL); } static void _edge_right_cb(Evas_Object *obj, void *data EINA_UNUSED) { efl_event_callback_legacy_call(obj, ELM_LIST_EVENT_EDGE_RIGHT, NULL); } static void _edge_top_cb(Evas_Object *obj, void *data EINA_UNUSED) { efl_event_callback_legacy_call(obj, ELM_LIST_EVENT_EDGE_TOP, NULL); } static void _edge_bottom_cb(Evas_Object *obj, void *data EINA_UNUSED) { efl_event_callback_legacy_call(obj, ELM_LIST_EVENT_EDGE_BOTTOM, NULL); } static Eina_Bool _long_press_cb(void *data) { Elm_List_Item_Data *it = data; Evas_Object *obj; ELM_LIST_ITEM_CHECK_OR_RETURN(it, ECORE_CALLBACK_CANCEL); obj = WIDGET(it); ELM_LIST_DATA_GET(obj, sd); it->long_timer = NULL; if (it->base->disabled) goto end; sd->longpressed = EINA_TRUE; efl_event_callback_legacy_call (WIDGET(it), EFL_UI_EVENT_LONGPRESSED, EO_OBJ(it)); end: return ECORE_CALLBACK_CANCEL; } static void _swipe_do(Elm_List_Item_Data *it) { int i, sum = 0; ELM_LIST_ITEM_CHECK_OR_RETURN(it); ELM_LIST_DATA_GET_FROM_ITEM(it, sd); sd->swipe = EINA_FALSE; for (i = 0; i < sd->movements; i++) { sum += sd->history[i].x; if (abs(sd->history[0].y - sd->history[i].y) > 10) return; } sum /= sd->movements; if (abs(sum - sd->history[0].x) <= 10) return; efl_event_callback_legacy_call (WIDGET(it), ELM_LIST_EVENT_SWIPE, EO_OBJ(it)); } static void _mouse_in_cb(void *data, Evas *evas EINA_UNUSED, Evas_Object *o EINA_UNUSED, void *event_info EINA_UNUSED) { Elm_List_Item_Data *it = data; if (!elm_object_item_disabled_get(EO_OBJ(it)) && (_elm_config->focus_move_policy == ELM_FOCUS_MOVE_POLICY_IN)) elm_object_item_focus_set(EO_OBJ(it), EINA_TRUE); } static void _mouse_move_cb(void *data, Evas *evas EINA_UNUSED, Evas_Object *o, void *event_info) { Evas_Object *obj; Elm_List_Item_Data *it = data; Evas_Event_Mouse_Move *ev = event_info; Evas_Coord x = 0, y = 0, w = 0, h = 0; ELM_LIST_ITEM_CHECK_OR_RETURN(it); obj = WIDGET(it); ELM_LIST_DATA_GET(obj, sd); efl_ref(EO_OBJ(it)); _elm_list_walk(obj, sd); evas_object_geometry_get(o, &x, &y, &w, &h); if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) { if (!sd->on_hold) { sd->on_hold = EINA_TRUE; ELM_SAFE_FREE(it->long_timer, ecore_timer_del); if (!sd->was_selected) { _item_unhighlight(it); _item_unselect(it); } } } else if (sd->mouse_down && ELM_RECTS_POINT_OUT(x, y, w, h, ev->cur.canvas.x, ev->cur.canvas.y)) { ELM_SAFE_FREE(it->long_timer, ecore_timer_del); if (!sd->was_selected) { _item_unhighlight(it); _item_unselect(it); } it->base->still_in = EINA_FALSE; } if (sd->movements == ELM_LIST_SWIPE_MOVES) { sd->swipe = EINA_TRUE; } else { sd->history[sd->movements].x = ev->cur.canvas.x; sd->history[sd->movements].y = ev->cur.canvas.y; if (abs((sd->history[sd->movements].x - sd->history[0].x)) > 40) { sd->swipe = EINA_TRUE; } else sd->movements++; } if (sd->swipe) ELM_SAFE_FREE(it->long_timer, ecore_timer_del); _elm_list_unwalk(obj, sd); efl_unref(EO_OBJ(it)); } static void _mouse_down_cb(void *data, Evas *evas EINA_UNUSED, Evas_Object *o EINA_UNUSED, void *event_info) { Evas_Event_Mouse_Down *ev = event_info; Elm_List_Item_Data *it = data; Evas_Object *obj; Evas_Coord x, y; ELM_LIST_ITEM_CHECK_OR_RETURN(it); obj = WIDGET(it); ELM_LIST_DATA_GET(obj, sd); if (ev->button == 3) { evas_object_geometry_get(obj, &x, &y, NULL, NULL); sd->dx = ev->canvas.x - x; sd->dy = ev->canvas.y - y; return; } if (ev->button != 1) return; if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) sd->on_hold = EINA_TRUE; else sd->on_hold = EINA_FALSE; if (sd->on_hold) return; sd->mouse_down = EINA_TRUE; sd->was_selected = it->selected; efl_ref(EO_OBJ(it)); _elm_list_walk(obj, sd); _item_highlight(it); sd->longpressed = EINA_FALSE; ecore_timer_del(it->long_timer); it->long_timer = ecore_timer_add (_elm_config->longpress_timeout, _long_press_cb, it); ecore_timer_del(it->swipe_timer); it->swipe_timer = ecore_timer_add(ELM_LIST_SWIPE_TIME, _swipe_cancel, it); /* Always call the callbacks last - the user may delete our context! */ if (ev->flags & EVAS_BUTTON_DOUBLE_CLICK) { efl_event_callback_legacy_call (WIDGET(it), EFL_UI_EVENT_CLICKED_DOUBLE, EO_OBJ(it)); efl_event_callback_legacy_call (WIDGET(it), ELM_LIST_EVENT_ACTIVATED, EO_OBJ(it)); } sd->swipe = EINA_FALSE; sd->movements = 0; it->base->still_in = EINA_TRUE; _elm_list_unwalk(obj, sd); efl_unref(EO_OBJ(it)); } static void _mouse_up_cb(void *data, Evas *evas EINA_UNUSED, Evas_Object *o EINA_UNUSED, void *event_info) { Evas_Object *obj; Elm_List_Item_Data *it = data; Evas_Event_Mouse_Up *ev = event_info; Evas_Coord x, y, dx, dy; ELM_LIST_ITEM_CHECK_OR_RETURN(it); obj = WIDGET(it); ELM_LIST_DATA_GET(obj, sd); if (ev->button == 3) { evas_object_geometry_get(obj, &x, &y, NULL, NULL); dx = sd->dx - (ev->canvas.x - x); dy = sd->dy - (ev->canvas.y - y); if (dx < 0) dx = -dx; if (dy < 0) dy = -dy; if ((dx < 5) && (dy < 5)) efl_event_callback_legacy_call (obj, EFL_UI_EVENT_CLICKED_RIGHT, EO_OBJ(it)); return; } if (ev->button != 1) return; if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) sd->on_hold = EINA_TRUE; else sd->on_hold = EINA_FALSE; sd->mouse_down = EINA_FALSE; ELM_SAFE_FREE(it->long_timer, ecore_timer_del); ELM_SAFE_FREE(it->swipe_timer, ecore_timer_del); if (sd->swipe) { if (!sd->was_selected) { _item_unhighlight(it); _item_unselect(it); } _swipe_do(data); sd->swipe = EINA_FALSE; sd->was_selected = EINA_FALSE; return; } if (sd->longpressed) { if (!sd->was_selected) { _item_unhighlight(it); _item_unselect(it); } sd->longpressed = EINA_FALSE; sd->was_selected = EINA_FALSE; return; } if (it->base->disabled) return; if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD || !it->base->still_in) return; efl_ref(EO_OBJ(it)); _elm_list_walk(obj, sd); if (sd->focused_item != EO_OBJ(it)) elm_object_item_focus_set(EO_OBJ(it), EINA_TRUE); if (sd->multi && ((sd->multi_select_mode != ELM_OBJECT_MULTI_SELECT_MODE_WITH_CONTROL) || (evas_key_modifier_is_set(ev->modifiers, "Control")))) { if (!it->selected) { _item_highlight(it); _item_select(it); } else { _item_unhighlight(it); _item_unselect(it); } } else { _items_safe_process(sd->selected, _process_item_unselected_set, EO_OBJ(it)); _item_highlight(it); _item_select(it); } _elm_list_unwalk(obj, sd); efl_unref(EO_OBJ(it)); } 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_DATA_GET(list, sd); Elm_Object_Item *it = elm_list_last_item_get(list); if (!_elm_config->item_select_on_focus_disable) elm_list_item_selected_set(it, EINA_TRUE); else elm_object_item_focus_set(it, EINA_TRUE); elm_layout_signal_emit(list, "elm,action,looping,left,end", "elm"); sd->item_looping_on = EINA_FALSE; } 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_DATA_GET(list, sd); Elm_Object_Item *it = elm_list_first_item_get(list); if (!_elm_config->item_select_on_focus_disable) elm_list_item_selected_set(it, EINA_TRUE); else elm_object_item_focus_set(it, EINA_TRUE); elm_layout_signal_emit(list, "elm,action,looping,right,end", "elm"); sd->item_looping_on = EINA_FALSE; } 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_DATA_GET(list, sd); Elm_Object_Item *it = elm_list_last_item_get(list); if (!_elm_config->item_select_on_focus_disable) elm_list_item_selected_set(it, EINA_TRUE); else elm_object_item_focus_set(it, EINA_TRUE); elm_layout_signal_emit(list, "elm,action,looping,up,end", "elm"); sd->item_looping_on = EINA_FALSE; } 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_DATA_GET(list, sd); Elm_Object_Item *it = elm_list_first_item_get(list); if (!_elm_config->item_select_on_focus_disable) elm_list_item_selected_set(it, EINA_TRUE); else elm_object_item_focus_set(it, EINA_TRUE); elm_layout_signal_emit(list, "elm,action,looping,down,end", "elm"); sd->item_looping_on = EINA_FALSE; } EOLIAN static void _elm_list_item_elm_widget_item_disable(Eo *eo_item EINA_UNUSED, Elm_List_Item_Data *item) { _item_unhighlight(item); _item_unselect(item); 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"); } EOLIAN static void _elm_list_item_elm_widget_item_part_content_set(Eo *eo_item EINA_UNUSED, Elm_List_Item_Data *item, const char *part, Evas_Object *content) { 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); } evas_object_del(*icon_p); *icon_p = content; if (VIEW(item)) { if ((!part) || !strcmp(part, "start")) edje_object_part_swallow(VIEW(item), "elm.swallow.icon", content); else edje_object_part_swallow(VIEW(item), "elm.swallow.end", content); } } EOLIAN static Evas_Object * _elm_list_item_elm_widget_item_part_content_get(const Eo *eo_item EINA_UNUSED, Elm_List_Item_Data *item, const char *part) { 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; } EOLIAN static Evas_Object * _elm_list_item_elm_widget_item_part_content_unset(Eo *eo_it EINA_UNUSED, Elm_List_Item_Data *item, const char *part) { if ((!part) || (!strcmp(part, "start"))) { Evas_Object *obj = item->icon; elm_wdg_item_part_content_set(eo_it, part, NULL); return obj; } else if (!strcmp(part, "end")) { Evas_Object *obj = item->end; elm_wdg_item_part_content_set(eo_it, part, NULL); return obj; } return NULL; } EOLIAN static void _elm_list_item_elm_widget_item_part_text_set(Eo *eo_list_it, Elm_List_Item_Data *list_it, const char *part, const char *text) { if (part && strcmp(part, "default")) { elm_wdg_item_part_text_custom_set(eo_list_it, part, text); edje_object_part_text_escaped_set(VIEW(list_it), part, text); 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); } EOLIAN static const char * _elm_list_item_elm_widget_item_part_text_get(const Eo *eo_it, Elm_List_Item_Data *it, const char *part) { if (part && strcmp(part, "default")) return elm_wdg_item_part_text_custom_get(eo_it, part); return it->label; } /* FIXME: this _item_del_pre_hook is called stupidly! To fix this, 1. it->walking concept should be adopted. 2. elm_widget_item_del() should be called instead of the combination of _elm_list_item_free() + elm_widget_item_free() */ EOLIAN static void _elm_list_item_elm_widget_item_del_pre(Eo *eo_item EINA_UNUSED, Elm_List_Item_Data *item) { Evas_Object *obj = WIDGET(item); ELM_LIST_DATA_GET(obj, sd); if (item->selected) { _item_unhighlight(item); _item_unselect(item); } item->deleted = EINA_TRUE; sd->items = eina_list_remove_list(sd->items, item->node); item->node = NULL; } EOLIAN static void _elm_list_item_elm_widget_item_signal_emit(Eo *eo_it EINA_UNUSED, Elm_List_Item_Data *it, const char *emission, const char *source) { edje_object_signal_emit(VIEW(it), emission, source); } EOLIAN static void _elm_list_item_elm_widget_item_item_focus_set(Eo *eo_it, Elm_List_Item_Data *it, Eina_Bool focused) { Evas_Object *obj = WIDGET(it); ELM_LIST_DATA_GET(obj, sd); if (focused) { sd->last_focused_item = eo_it; if (!elm_object_focus_get(obj)) elm_object_focus_set(obj, EINA_TRUE); if (!elm_object_focus_get(obj)) return; if (eo_it != sd->focused_item) { if (sd->focused_item) _elm_list_item_unfocused(sd->focused_item); _elm_list_item_focused(eo_it); } } else { if (!elm_object_focus_get(obj)) return; if (eo_it) _elm_list_item_unfocused(eo_it); } _elm_widget_focus_highlight_start(obj); } EOLIAN static Eina_Bool _elm_list_item_elm_widget_item_item_focus_get(const Eo *eo_it, Elm_List_Item_Data *it) { ELM_LIST_ITEM_CHECK_OR_RETURN(it, EINA_FALSE); Evas_Object *obj = WIDGET(it); ELM_LIST_CHECK(obj) EINA_FALSE; ELM_LIST_DATA_GET(obj, sd); if (eo_it == sd->focused_item) return EINA_TRUE; return EINA_FALSE; } EOLIAN static Efl_Access_State_Set _elm_list_item_efl_access_object_state_set_get(const Eo *eo_it, Elm_List_Item_Data *data EINA_UNUSED) { Efl_Access_State_Set ret; Eina_Bool sel; ret = efl_access_object_state_set_get(efl_super(eo_it, ELM_LIST_ITEM_CLASS)); if (elm_object_item_disabled_get(eo_it)) return ret; STATE_TYPE_SET(ret, EFL_ACCESS_STATE_SELECTABLE); sel = elm_obj_list_item_selected_get(eo_it); if (sel) STATE_TYPE_SET(ret, EFL_ACCESS_STATE_SELECTED); else STATE_TYPE_UNSET(ret, EFL_ACCESS_STATE_SELECTED); return ret; } EOLIAN static const char* _elm_list_item_efl_access_object_i18n_name_get(const Eo *eo_it, Elm_List_Item_Data *data) { const char *ret; ret = efl_access_object_i18n_name_get(efl_super(eo_it, ELM_LIST_ITEM_CLASS)); if (ret) return ret; return _elm_widget_item_accessible_plain_name_get(eo_it, data->label); } static char * _access_info_cb(void *data, Evas_Object *obj EINA_UNUSED) { Elm_List_Item_Data *it = (Elm_List_Item_Data *)data; const char *txt = NULL; if (!it) return NULL; if (!txt) txt = it->label; if (txt) return strdup(txt); return NULL; } static char * _access_state_cb(void *data, Evas_Object *obj EINA_UNUSED) { Elm_List_Item_Data *it = (Elm_List_Item_Data *)data; if (!it) return NULL; if (it->base->disabled) return strdup(E_("State: Disabled")); return NULL; } static void _access_on_highlight_cb(void *data) { Elm_Object_Item *it = data; if (!it) return; elm_list_item_bring_in(it); } static void _access_activate_cb(void *data EINA_UNUSED, Evas_Object *part_obj EINA_UNUSED, Elm_Object_Item *eo_it) { Evas_Object *obj; ELM_LIST_ITEM_DATA_GET(eo_it, it); ELM_LIST_ITEM_CHECK_OR_RETURN(it); obj = WIDGET(it); ELM_LIST_DATA_GET(obj, sd); efl_ref(eo_it); _elm_list_walk(obj, sd); if (sd->multi) { if (!it->selected) { _item_highlight(it); _item_select(it); } else { _item_unhighlight(it); _item_unselect(it); } } else { _items_safe_process(sd->selected, _process_item_unselected_set, eo_it); _item_highlight(it); _item_select(it); } _elm_list_unwalk(obj, sd); efl_unref(eo_it); } static void _access_widget_item_register(Elm_List_Item_Data *it, Eina_Bool is_access) { Elm_Access_Info *ai; if (!is_access) _elm_access_widget_item_unregister(it->base); else { _elm_access_widget_item_register(it->base); ai = _elm_access_info_get(it->base->access_obj); _elm_access_callback_set(ai, ELM_ACCESS_INFO, _access_info_cb, it); _elm_access_callback_set(ai, ELM_ACCESS_STATE, _access_state_cb, it); _elm_access_on_highlight_hook_set(ai, _access_on_highlight_cb, EO_OBJ(it)); _elm_access_activate_callback_set(ai, _access_activate_cb, EO_OBJ(it)); } } EOLIAN static Eo * _elm_list_item_efl_object_constructor(Eo *eo_it, Elm_List_Item_Data *it) { eo_it = efl_constructor(efl_super(eo_it, ELM_LIST_ITEM_CLASS)); it->base = efl_data_scope_get(eo_it, ELM_WIDGET_ITEM_CLASS); efl_access_object_role_set(eo_it, EFL_ACCESS_ROLE_LIST_ITEM); return eo_it; } static Elm_List_Item_Data * _item_new(Evas_Object *obj, const char *label, Evas_Object *icon, Evas_Object *end, Evas_Smart_Cb func, const void *data) { Eo *eo_it = efl_add(ELM_LIST_ITEM_CLASS, obj); if (!eo_it) return NULL; ELM_LIST_ITEM_DATA_GET(eo_it, it); it->label = eina_stringshare_add(label); it->icon = icon; it->end = end; it->func = func; WIDGET_ITEM_DATA_SET(EO_OBJ(it), data); VIEW_SET(it, edje_object_add(evas_object_evas_get(obj))); edje_object_update_hints_set(VIEW(it), 1); if (it->icon) efl_parent_set(it->icon, eo_it); if (it->end) efl_parent_set(it->end, eo_it); /* access */ if (_elm_config->access_mode == ELM_ACCESS_MODE_ON) _access_widget_item_register(it, EINA_TRUE); edje_object_mirrored_set(VIEW(it), efl_ui_mirrored_get(obj)); evas_object_event_callback_add (VIEW(it), EVAS_CALLBACK_MOUSE_DOWN, _mouse_down_cb, it); evas_object_event_callback_add (VIEW(it), EVAS_CALLBACK_MOUSE_UP, _mouse_up_cb, it); evas_object_event_callback_add (VIEW(it), EVAS_CALLBACK_MOUSE_MOVE, _mouse_move_cb, it); evas_object_event_callback_add (VIEW(it), EVAS_CALLBACK_MOUSE_IN, _mouse_in_cb, it); 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); edje_object_mirrored_set(VIEW(it), efl_ui_mirrored_get(obj)); if (it->icon) { elm_widget_sub_object_add(obj, it->icon); evas_object_event_callback_add (it->icon, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _size_hints_changed_cb, obj); efl_access_object_access_type_set(it->icon, EFL_ACCESS_TYPE_DISABLED); elm_widget_tree_unfocusable_set(it->icon, EINA_TRUE); } if (it->end) { elm_widget_sub_object_add(obj, it->end); evas_object_event_callback_add (it->end, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _size_hints_changed_cb, obj); efl_access_object_access_type_set(it->end, EFL_ACCESS_TYPE_DISABLED); elm_widget_tree_unfocusable_set(it->end, EINA_TRUE); } if (_elm_config->atspi_mode) efl_access_added(eo_it); return it; } static void _resize_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { elm_layout_sizing_eval(data); } static Eina_Bool _elm_list_smart_focus_next_enable = EINA_FALSE; EOLIAN static void _elm_list_efl_canvas_group_group_add(Eo *obj, Elm_List_Data *priv) { Evas_Coord minw, minh; ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd); efl_canvas_group_add(efl_super(obj, MY_CLASS)); elm_widget_sub_object_parent_add(obj); elm_widget_can_focus_set(obj, EINA_TRUE); priv->mode = ELM_LIST_SCROLL; if (!elm_layout_theme_set(obj, "list", "base", elm_widget_style_get(obj))) CRI("Failed to set layout!"); priv->hit_rect = evas_object_rectangle_add(evas_object_evas_get(obj)); evas_object_data_set(priv->hit_rect, "_elm_leaveme", obj); evas_object_smart_member_add(priv->hit_rect, obj); elm_widget_sub_object_add(obj, priv->hit_rect); /* common scroller hit rectangle setup */ evas_object_color_set(priv->hit_rect, 0, 0, 0, 0); evas_object_show(priv->hit_rect); evas_object_repeat_events_set(priv->hit_rect, EINA_TRUE); elm_interface_scrollable_edge_left_cb_set(obj, _edge_left_cb); elm_interface_scrollable_edge_right_cb_set(obj, _edge_right_cb); elm_interface_scrollable_edge_top_cb_set(obj, _edge_top_cb); elm_interface_scrollable_edge_bottom_cb_set(obj, _edge_bottom_cb); elm_interface_scrollable_content_min_limit_cb_set(obj, _elm_list_content_min_limit_cb); elm_interface_scrollable_objects_set(obj, wd->resize_obj, priv->hit_rect); /* the scrollable interface may set this */ evas_object_event_callback_add (wd->resize_obj, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _size_hints_changed_cb, obj); edje_object_size_min_calc (wd->resize_obj, &minw, &minh); evas_object_size_hint_min_set(obj, minw, minh); evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE, _resize_cb, obj); elm_interface_scrollable_bounce_allow_set(obj, EINA_FALSE, _elm_config->thumbscroll_bounce_enable); priv->box = elm_box_add(obj); evas_object_size_hint_weight_set(priv->box, EVAS_HINT_EXPAND, 0.0); evas_object_size_hint_align_set(priv->box, EVAS_HINT_FILL, 0.0); efl_access_object_access_type_set(priv->box, EFL_ACCESS_TYPE_DISABLED); /* FIXME: change this ugly code path later */ elm_widget_on_show_region_hook_set(priv->box, obj, _show_region_hook, NULL); elm_widget_sub_object_add(obj, priv->box); elm_interface_scrollable_content_set(obj, priv->box); 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); } EOLIAN static void _elm_list_efl_canvas_group_group_del(Eo *obj, Elm_List_Data *sd) { const Eina_List *l; Elm_Object_Item *eo_it; sd->delete_me = EINA_TRUE; EINA_LIST_FOREACH(sd->items, l, eo_it) { ELM_LIST_ITEM_DATA_GET(eo_it, it); if (it->icon) evas_object_event_callback_del (it->icon, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _size_hints_changed_cb); if (it->end) evas_object_event_callback_del (it->end, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _size_hints_changed_cb); } evas_object_event_callback_del (obj, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _size_hints_changed_cb); evas_object_event_callback_del (sd->box, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _size_hints_changed_cb); while (sd->items) /* will be removed from list in _elm_list_item_elm_widget_item_del_pre */ efl_del(eina_list_data_get(sd->items)); sd->selected = eina_list_free(sd->selected); efl_canvas_group_del(efl_super(obj, MY_CLASS)); } EOLIAN static void _elm_list_efl_gfx_entity_position_set(Eo *obj, Elm_List_Data *sd, Eina_Position2D pos) { if (_evas_object_intercept_call(obj, EVAS_OBJECT_INTERCEPT_CB_MOVE, 0, pos.x, pos.y)) return; efl_gfx_entity_position_set(efl_super(obj, MY_CLASS), pos); efl_gfx_entity_position_set(sd->hit_rect, pos); } EOLIAN static void _elm_list_efl_gfx_entity_size_set(Eo *obj, Elm_List_Data *sd, Eina_Size2D sz) { if (_evas_object_intercept_call(obj, EVAS_OBJECT_INTERCEPT_CB_RESIZE, 0, sz.w, sz.h)) return; efl_gfx_entity_size_set(efl_super(obj, MY_CLASS), sz); efl_gfx_entity_size_set(sd->hit_rect, sz); } EOLIAN static void _elm_list_efl_canvas_group_group_member_add(Eo *obj, Elm_List_Data *sd, Evas_Object *member) { efl_canvas_group_member_add(efl_super(obj, MY_CLASS), member); if (sd->hit_rect) evas_object_raise(sd->hit_rect); } EOLIAN static void _elm_list_efl_ui_widget_on_access_update(Eo *obj EINA_UNUSED, Elm_List_Data *sd, Eina_Bool acs) { Eina_List *elist = NULL; Elm_Object_Item *eo_it; _elm_list_smart_focus_next_enable = acs; EINA_LIST_FOREACH(sd->items, elist, eo_it) { ELM_LIST_ITEM_DATA_GET(eo_it, it); _access_widget_item_register(it, _elm_list_smart_focus_next_enable); } } EAPI Evas_Object * elm_list_add(Evas_Object *parent) { EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL); return elm_legacy_add(MY_CLASS, parent); } EOLIAN static Eo * _elm_list_efl_object_constructor(Eo *obj, Elm_List_Data *sd EINA_UNUSED) { obj = efl_constructor(efl_super(obj, MY_CLASS)); efl_canvas_object_type_set(obj, MY_CLASS_NAME_LEGACY); evas_object_smart_callbacks_descriptions_set(obj, _smart_callbacks); efl_access_object_role_set(obj, EFL_ACCESS_ROLE_LIST); legacy_efl_ui_focus_manager_widget_legacy_signals(obj, obj); return obj; } EOLIAN static void _elm_list_go(Eo *obj, Elm_List_Data *sd EINA_UNUSED) { _items_fix(obj); } EOLIAN static void _elm_list_multi_select_set(Eo *obj EINA_UNUSED, Elm_List_Data *sd, Eina_Bool multi) { sd->multi = multi; } EOLIAN static Eina_Bool _elm_list_multi_select_get(const Eo *obj EINA_UNUSED, Elm_List_Data *sd) { return sd->multi; } EOLIAN static void _elm_list_multi_select_mode_set(Eo *obj EINA_UNUSED, Elm_List_Data *sd, Elm_Object_Multi_Select_Mode mode) { if (mode >= ELM_OBJECT_MULTI_SELECT_MODE_MAX) return; if (sd->multi_select_mode != mode) sd->multi_select_mode = mode; } EOLIAN static Elm_Object_Multi_Select_Mode _elm_list_multi_select_mode_get(const Eo *obj EINA_UNUSED, Elm_List_Data *sd) { return sd->multi_select_mode; } EOLIAN static void _elm_list_mode_set(Eo *obj, Elm_List_Data *sd, Elm_List_Mode mode) { Elm_Object_Item *eo_it; Eina_List *n; if (sd->mode == mode) return; sd->mode = mode; _elm_list_mode_set_internal(obj); EINA_LIST_FOREACH(sd->items, n, eo_it) { ELM_LIST_ITEM_DATA_GET(eo_it, it); it->fixed = EINA_FALSE; } _items_fix(obj); } EOLIAN static Elm_List_Mode _elm_list_mode_get(const Eo *obj EINA_UNUSED, Elm_List_Data *sd) { return sd->mode; } EOLIAN static void _elm_list_horizontal_set(Eo *obj, Elm_List_Data *sd, Eina_Bool horizontal) { Eina_Bool bounce = _elm_config->thumbscroll_bounce_enable; horizontal = !!horizontal; if (sd->h_mode == horizontal) return; sd->h_mode = horizontal; elm_box_horizontal_set(sd->box, horizontal); if (horizontal) { evas_object_size_hint_weight_set(sd->box, 0.0, EVAS_HINT_EXPAND); evas_object_size_hint_align_set(sd->box, 0.0, EVAS_HINT_FILL); elm_interface_scrollable_bounce_allow_set(obj, bounce, EINA_FALSE); } else { evas_object_size_hint_weight_set(sd->box, EVAS_HINT_EXPAND, 0.0); evas_object_size_hint_align_set(sd->box, EVAS_HINT_FILL, 0.0); elm_interface_scrollable_bounce_allow_set(obj, EINA_FALSE, bounce); } } EOLIAN static Eina_Bool _elm_list_horizontal_get(const Eo *obj EINA_UNUSED, Elm_List_Data *sd) { return sd->h_mode; } EOLIAN static void _elm_list_select_mode_set(Eo *obj EINA_UNUSED, Elm_List_Data *sd, Elm_Object_Select_Mode mode) { if (mode >= ELM_OBJECT_SELECT_MODE_MAX) return; if (sd->select_mode != mode) sd->select_mode = mode; } EOLIAN static Elm_Object_Select_Mode _elm_list_select_mode_get(const Eo *obj EINA_UNUSED, Elm_List_Data *sd) { return sd->select_mode; } EAPI void elm_list_bounce_set(Evas_Object *obj, Eina_Bool h_bounce, Eina_Bool v_bounce) { ELM_LIST_CHECK(obj); elm_interface_scrollable_bounce_allow_set(obj, h_bounce, v_bounce); } EAPI void elm_list_bounce_get(const Evas_Object *obj, Eina_Bool *h_bounce, Eina_Bool *v_bounce) { ELM_LIST_CHECK(obj); elm_interface_scrollable_bounce_allow_get((Eo *) obj, 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_LIST_CHECK(obj); elm_interface_scrollable_policy_set(obj, policy_h, policy_v); } EOLIAN static void _elm_list_elm_interface_scrollable_policy_set(Eo *obj, Elm_List_Data *sd EINA_UNUSED, Elm_Scroller_Policy policy_h, Elm_Scroller_Policy policy_v) { if ((policy_h >= ELM_SCROLLER_POLICY_LAST) || (policy_v >= ELM_SCROLLER_POLICY_LAST)) return; elm_interface_scrollable_policy_set(efl_super(obj, MY_CLASS), 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_LIST_CHECK(obj); elm_interface_scrollable_policy_get((Eo *) obj, policy_h, policy_v); } static void _item_clear(void *data EINA_UNUSED, Elm_Object_Item *eo, Elm_List_Item_Data *it EINA_UNUSED) { efl_del(eo); } EOLIAN static void _elm_list_clear(Eo *obj, Elm_List_Data *sd) { if (!sd->items) return; sd->selected = eina_list_free(sd->selected); _items_safe_process(sd->items, _item_clear, NULL); _items_fix(obj); elm_layout_sizing_eval(obj); } EOLIAN static const Eina_List* _elm_list_items_get(const Eo *obj EINA_UNUSED, Elm_List_Data *sd) { return sd->items; } EOLIAN static Elm_Object_Item* _elm_list_selected_item_get(const Eo *obj EINA_UNUSED, Elm_List_Data *sd) { if (sd->selected) return sd->selected->data; else return NULL; } EOLIAN static const Eina_List* _elm_list_selected_items_get(const Eo *obj EINA_UNUSED, Elm_List_Data *sd) { return sd->selected; } EOLIAN static Elm_Object_Item* _elm_list_item_append(Eo *obj, Elm_List_Data *sd, const char *label, Evas_Object *icon, Evas_Object *end, Evas_Smart_Cb func, const void *data) { Elm_List_Item_Data *it; it = _item_new(obj, label, icon, end, func, data); sd->items = eina_list_append(sd->items, EO_OBJ(it)); it->node = eina_list_last(sd->items); elm_box_pack_end(sd->box, VIEW(it)); if (_elm_config->atspi_mode) efl_access_children_changed_added_signal_emit(obj, EO_OBJ(it)); return EO_OBJ(it); } EOLIAN static Elm_Object_Item* _elm_list_item_prepend(Eo *obj, Elm_List_Data *sd, const char *label, Evas_Object *icon, Evas_Object *end, Evas_Smart_Cb func, const void *data) { Elm_List_Item_Data *it; it = _item_new(obj, label, icon, end, func, data); sd->items = eina_list_prepend(sd->items, EO_OBJ(it)); it->node = sd->items; elm_box_pack_start(sd->box, VIEW(it)); if (_elm_config->atspi_mode) efl_access_children_changed_added_signal_emit(obj, EO_OBJ(it)); return EO_OBJ(it); } EOLIAN static Elm_Object_Item* _elm_list_item_insert_before(Eo *obj, Elm_List_Data *sd, Elm_Object_Item *eo_before, const char *label, Evas_Object *icon, Evas_Object *end, Evas_Smart_Cb func, const void *data) { Elm_List_Item_Data *it; EINA_SAFETY_ON_NULL_RETURN_VAL(eo_before, NULL); ELM_LIST_ITEM_DATA_GET(eo_before, before_it); ELM_LIST_ITEM_CHECK_OR_RETURN(before_it, NULL); if (!before_it->node) return NULL; it = _item_new(obj, label, icon, end, func, data); sd->items = eina_list_prepend_relative_list(sd->items, EO_OBJ(it), before_it->node); it->node = before_it->node->prev; elm_box_pack_before(sd->box, VIEW(it), VIEW(before_it)); if (_elm_config->atspi_mode) efl_access_children_changed_added_signal_emit(obj, EO_OBJ(it)); return EO_OBJ(it); } EOLIAN static Elm_Object_Item* _elm_list_item_insert_after(Eo *obj, Elm_List_Data *sd, Elm_Object_Item *eo_after, const char *label, Evas_Object *icon, Evas_Object *end, Evas_Smart_Cb func, const void *data) { Elm_List_Item_Data *it; EINA_SAFETY_ON_NULL_RETURN_VAL(eo_after, NULL); ELM_LIST_ITEM_DATA_GET(eo_after, after_it); ELM_LIST_ITEM_CHECK_OR_RETURN(after_it, NULL); if (!after_it->node) return NULL; it = _item_new(obj, label, icon, end, func, data); sd->items = eina_list_append_relative_list(sd->items, EO_OBJ(it), after_it->node); it->node = after_it->node->next; elm_box_pack_after(sd->box, VIEW(it), VIEW(after_it)); if (_elm_config->atspi_mode) efl_access_children_changed_added_signal_emit(obj, EO_OBJ(it)); return EO_OBJ(it); } EOLIAN static Elm_Object_Item* _elm_list_item_sorted_insert(Eo *obj, Elm_List_Data *sd, const char *label, Evas_Object *icon, Evas_Object *end, Evas_Smart_Cb func, const void *data, Eina_Compare_Cb cmp_func) { Eina_List *l; Elm_List_Item_Data *it; it = _item_new(obj, label, icon, end, func, data); sd->items = eina_list_sorted_insert(sd->items, cmp_func, EO_OBJ(it)); l = eina_list_data_find_list(sd->items, EO_OBJ(it)); l = eina_list_next(l); if (!l) { it->node = eina_list_last(sd->items); elm_box_pack_end(sd->box, VIEW(it)); } else { Elm_Object_Item *eo_before = eina_list_data_get(l); ELM_LIST_ITEM_DATA_GET(eo_before, before); it->node = before->node->prev; elm_box_pack_before(sd->box, VIEW(it), VIEW(before)); } if (_elm_config->atspi_mode) efl_access_children_changed_added_signal_emit(obj, EO_OBJ(it)); return EO_OBJ(it); } EOLIAN static void _elm_list_item_separator_set(Eo *eo_item, Elm_List_Item_Data *it, Eina_Bool setting) { ELM_LIST_ITEM_CHECK_OR_RETURN(it); it->is_separator = !!setting; if (it->is_separator) efl_access_object_role_set(eo_item, EFL_ACCESS_ROLE_SEPARATOR); else efl_access_object_role_set(eo_item, EFL_ACCESS_ROLE_LIST_ITEM); } EOLIAN static Eina_Bool _elm_list_item_separator_get(const Eo *eo_item EINA_UNUSED, Elm_List_Item_Data *it) { ELM_LIST_ITEM_CHECK_OR_RETURN(it, EINA_FALSE); return it->is_separator; } EOLIAN static void _elm_list_item_selected_set(Eo *eo_item, Elm_List_Item_Data *item, Eina_Bool selected) { Evas_Object *obj; ELM_LIST_ITEM_CHECK_OR_RETURN(item); obj = WIDGET(item); ELM_LIST_DATA_GET(obj, sd); selected = !!selected; if (item->selected == selected) return; efl_ref(eo_item); _elm_list_walk(obj, sd); if (selected) { if (!sd->multi) _items_safe_process(sd->selected, _process_item_unselected_set, NULL); _item_highlight(item); elm_object_item_focus_set(EO_OBJ(item), EINA_TRUE); _item_select(item); } else { _process_item_unselected_set(NULL, eo_item, item); } _elm_list_unwalk(obj, sd); efl_unref(eo_item); } EOLIAN static Eina_Bool _elm_list_item_selected_get(const Eo *eo_item EINA_UNUSED, Elm_List_Item_Data *it) { ELM_LIST_ITEM_CHECK_OR_RETURN(it, EINA_FALSE); return it->selected; } EOLIAN static void _elm_list_item_show(Eo *eo_it EINA_UNUSED, Elm_List_Item_Data *it) { Evas_Coord bx, by, bw, bh; Evas_Coord x, y, w, h; ELM_LIST_ITEM_CHECK_OR_RETURN(it); ELM_LIST_DATA_GET_FROM_ITEM(it, sd); evas_smart_objects_calculate(evas_object_evas_get(sd->box)); evas_object_geometry_get(sd->box, &bx, &by, &bw, &bh); evas_object_geometry_get(VIEW(it), &x, &y, &w, &h); x -= bx; y -= by; elm_interface_scrollable_content_region_show(WIDGET(it), x, y, w, h); } EOLIAN static void _elm_list_item_bring_in(Eo *eo_it EINA_UNUSED, Elm_List_Item_Data *it) { Evas_Coord bx, by, bw, bh; Evas_Coord x, y, w, h; ELM_LIST_ITEM_CHECK_OR_RETURN(it); ELM_LIST_DATA_GET_FROM_ITEM(it, sd); evas_smart_objects_calculate(evas_object_evas_get(sd->box)); evas_object_geometry_get(sd->box, &bx, &by, &bw, &bh); evas_object_geometry_get(VIEW(it), &x, &y, &w, &h); x -= bx; y -= by; elm_interface_scrollable_region_bring_in(WIDGET(it), x, y, w, h); } EOLIAN static Evas_Object * _elm_list_item_object_get(const Eo *eo_it EINA_UNUSED, Elm_List_Item_Data *it) { ELM_LIST_ITEM_CHECK_OR_RETURN(it, NULL); return VIEW(it); } EOLIAN static Elm_Object_Item * _elm_list_item_prev_get(const Eo *eo_item EINA_UNUSED, Elm_List_Item_Data *item) { if (item->node->prev) return item->node->prev->data; return NULL; } EOLIAN static Elm_Object_Item * _elm_list_item_next_get(const Eo *eo_item EINA_UNUSED, Elm_List_Item_Data *item) { if (item->node->next) return item->node->next->data; return NULL; } EOLIAN static Elm_Object_Item* _elm_list_first_item_get(const Eo *obj EINA_UNUSED, Elm_List_Data *sd) { if (!sd->items) return NULL; else return eina_list_data_get(sd->items); return NULL; } EOLIAN static Elm_Object_Item* _elm_list_last_item_get(const Eo *obj EINA_UNUSED, Elm_List_Data *sd) { if (!sd->items) return NULL; else return eina_list_data_get(eina_list_last(sd->items)); return NULL; } EOLIAN static Elm_Object_Item* _elm_list_at_xy_item_get(const Eo *obj EINA_UNUSED, Elm_List_Data *sd, Evas_Coord x, Evas_Coord y, int *posret) { Eina_List *l; Elm_Object_Item *eo_it; Evas_Coord lasty; evas_object_geometry_get(sd->hit_rect, &lasty, NULL, NULL, NULL); EINA_LIST_FOREACH(sd->items, l, eo_it) { ELM_LIST_ITEM_DATA_GET(eo_it, it); Evas_Coord itx, ity; Evas_Object *vit = VIEW(it); Evas_Coord vx, vy, vw, vh; evas_object_geometry_get(vit, &vx, &vy, &vw, &vh); itx = vx; ity = vy; if (ELM_RECTS_INTERSECT (itx, ity, vw, vh, x, y, 1, 1)) { if (posret) { if (y <= (ity + (vh / 4))) *posret = -1; else if (y >= (ity + vh - (vh / 4))) *posret = 1; else *posret = 0; } return EO_OBJ(it); } lasty = ity + vh; } if (posret) { if (y > lasty) *posret = 1; else *posret = -1; } return NULL; } EOLIAN static void _elm_list_focus_on_selection_set(Eo *obj EINA_UNUSED, Elm_List_Data *sd, Eina_Bool enabled) { sd->focus_on_selection_enabled = !!enabled; } EOLIAN static Eina_Bool _elm_list_focus_on_selection_get(const Eo *obj EINA_UNUSED, Elm_List_Data *sd) { return sd->focus_on_selection_enabled; } static Eina_Rect _elm_list_item_coordinates_adjust(Elm_List_Item_Data *it) { Evas_Coord ix, iy, iw, ih, vx, vy, vw, vh; elm_interface_scrollable_content_viewport_geometry_get(WIDGET(it), &vx, &vy, &vw, &vh); evas_object_geometry_get(VIEW(it), &ix, &iy, &iw, &ih); if (iy < vy) iy = vy; if ((iy + ih) > (vy + vh)) ih = (vy + vh - iy); if (ix < vx) ix = vx; if ((ix + iw) > (vx + vw)) iw = (vx + vw - ix); return EINA_RECT(ix, iy, iw, ih); } EOLIAN static Eina_Rect _elm_list_efl_ui_widget_focus_highlight_geometry_get(const Eo *obj, Elm_List_Data *sd) { Eina_Rect r = {}; if (sd->focused_item) { ELM_LIST_ITEM_DATA_GET(sd->focused_item, focus_it); r = _elm_list_item_coordinates_adjust(focus_it); elm_widget_focus_highlight_focus_part_geometry_get(VIEW(focus_it), &r.x, &r.y, &r.w, &r.h); } else { r = efl_gfx_entity_geometry_get(obj); } return r; } EOLIAN static Elm_Object_Item* _elm_list_elm_widget_item_container_focused_item_get(const Eo *obj EINA_UNUSED, Elm_List_Data *sd) { return sd->focused_item; } EOLIAN static void _elm_list_elm_interface_scrollable_item_loop_enabled_set(Eo *obj EINA_UNUSED, Elm_List_Data *sd, Eina_Bool enable) { sd->item_loop_enable = !!enable; } EOLIAN static Eina_Bool _elm_list_elm_interface_scrollable_item_loop_enabled_get(const Eo *obj EINA_UNUSED, Elm_List_Data *sd) { return sd->item_loop_enable; } static void _elm_list_class_constructor(Efl_Class *klass) { if (_elm_config->access_mode) _elm_list_smart_focus_next_enable = EINA_TRUE; evas_smart_legacy_type_register(MY_CLASS_NAME_LEGACY, klass); } EOLIAN const Efl_Access_Action_Data * _elm_list_efl_access_widget_action_elm_actions_get(const Eo *obj EINA_UNUSED, Elm_List_Data *pd EINA_UNUSED) { static Efl_Access_Action_Data atspi_actions[] = { { "move,prior", "move", "prior", _key_action_move}, { "move,next", "move", "next", _key_action_move}, { "move,left", "move", "left", _key_action_move}, { "move,left,multi", "move", "left_multi", _key_action_move}, { "move,right", "move", "right", _key_action_move}, { "move,right,multi", "move", "right_multi", _key_action_move}, { "move,up", "move", "up", _key_action_move}, { "move,up,multi", "move", "up_multi", _key_action_move}, { "move,down", "move", "down", _key_action_move}, { "move,down,multi", "move", "down_multi", _key_action_move}, { "move,first", "move", "first", _key_action_move}, { "move,last", "move", "last", _key_action_move}, { "select", "select", NULL, _key_action_select}, { "escape", "escape", NULL, _key_action_escape}, { NULL, NULL, NULL, NULL } }; return &atspi_actions[0]; } EOLIAN Eina_List* _elm_list_efl_access_object_access_children_get(const Eo *obj, Elm_List_Data *pd) { Eina_List *ret; ret = efl_access_object_access_children_get(efl_super(obj, ELM_LIST_CLASS)); return eina_list_merge(eina_list_clone(pd->items), ret); } EOLIAN int _elm_list_efl_access_selection_selected_children_count_get(const Eo *objm EINA_UNUSED, Elm_List_Data *pd) { return eina_list_count(pd->selected); } EOLIAN Eo* _elm_list_efl_access_selection_selected_child_get(const Eo *obj EINA_UNUSED, Elm_List_Data *pd, int child_idx) { return eina_list_nth(pd->selected, child_idx); } EOLIAN Eina_Bool _elm_list_efl_access_selection_child_select(Eo *obj EINA_UNUSED, Elm_List_Data *pd, int child_index) { if (pd->select_mode != ELM_OBJECT_SELECT_MODE_NONE) { Eo *item = eina_list_nth(pd->items, child_index); if (item) elm_list_item_selected_set(item, EINA_TRUE); return EINA_TRUE; } return EINA_FALSE; } EOLIAN Eina_Bool _elm_list_efl_access_selection_selected_child_deselect(Eo *obj EINA_UNUSED, Elm_List_Data *pd, int child_index) { Eo *item = eina_list_nth(pd->selected, child_index); if (item) { elm_list_item_selected_set(item, EINA_FALSE); return EINA_TRUE; } return EINA_FALSE; } EOLIAN Eina_Bool _elm_list_efl_access_selection_is_child_selected(Eo *obj EINA_UNUSED, Elm_List_Data *pd, int child_index) { Eo *item = eina_list_nth(pd->items, child_index); if (item) return elm_list_item_selected_get(item); return EINA_FALSE; } EOLIAN Eina_Bool _elm_list_efl_access_selection_all_children_select(Eo *obj EINA_UNUSED, Elm_List_Data *pd) { Eo *it; Eina_List *l; if (pd->select_mode == ELM_OBJECT_SELECT_MODE_NONE) return EINA_FALSE; EINA_LIST_FOREACH(pd->items, l, it) elm_list_item_selected_set(it, EINA_TRUE); return EINA_TRUE; } EOLIAN Eina_Bool _elm_list_efl_access_selection_access_selection_clear(Eo *obj EINA_UNUSED, Elm_List_Data *pd) { Eo *it; Eina_List *l; if (pd->select_mode == ELM_OBJECT_SELECT_MODE_NONE) return EINA_FALSE; EINA_LIST_FOREACH(pd->items, l, it) elm_list_item_selected_set(it, EINA_FALSE); return EINA_TRUE; } EOLIAN Eina_Bool _elm_list_efl_access_selection_child_deselect(Eo *obj EINA_UNUSED, Elm_List_Data *pd, int child_index) { Eo *item = eina_list_nth(pd->items, child_index); if (item) { elm_list_item_selected_set(item, EINA_FALSE); return EINA_TRUE; } return EINA_FALSE; } EOLIAN static Eina_Bool _elm_list_efl_ui_widget_focus_state_apply(Eo *obj, Elm_List_Data *pd EINA_UNUSED, Efl_Ui_Widget_Focus_State current_state, Efl_Ui_Widget_Focus_State *configured_state, Efl_Ui_Widget *redirect EINA_UNUSED) { return efl_ui_widget_focus_state_apply(efl_super(obj, MY_CLASS), current_state, configured_state, obj); } /* Standard widget overrides */ ELM_WIDGET_KEY_DOWN_DEFAULT_IMPLEMENT(elm_list, Elm_List_Data) /* Internal EO APIs and hidden overrides */ #define ELM_LIST_EXTRA_OPS \ ELM_LAYOUT_SIZING_EVAL_OPS(elm_list), \ EFL_CANVAS_GROUP_ADD_DEL_OPS(elm_list) #include "elm_list.eo.c" #include "elm_list_item.eo.c"