2 # include "elementary_config.h"
5 #define ELM_INTERFACE_ATSPI_ACCESSIBLE_PROTECTED
6 #define ELM_INTERFACE_ATSPI_COMPONENT_PROTECTED
7 #define ELM_INTERFACE_ATSPI_WIDGET_ACTION_PROTECTED
8 #define ELM_INTERFACE_ATSPI_SELECTION_PROTECTED
9 //TIZEN_ONLY(20160329): list: enhance accessibility scroll and highlight (02c20ee39a0ebbe67b9e1491ccfc46dd681821c9)
10 #define ELM_INTERFACE_ATSPI_COMPONENT_PROTECTED
12 #define ELM_WIDGET_ITEM_PROTECTED
14 #include <Elementary.h>
17 #include "elm_widget_list.h"
18 #include "elm_interface_scrollable.h"
20 #define MY_CLASS ELM_LIST_CLASS
22 #define MY_CLASS_NAME "Elm_List"
23 #define MY_CLASS_NAME_LEGACY "elm_list"
25 #define ELM_LIST_SWIPE_TIME 0.4
27 static const char SIG_ACTIVATED[] = "activated";
28 static const char SIG_CLICKED_DOUBLE[] = "clicked,double";
29 static const char SIG_CLICKED_RIGHT[] = "clicked,right";
30 static const char SIG_SELECTED[] = "selected";
31 static const char SIG_UNSELECTED[] = "unselected";
32 static const char SIG_LONGPRESSED[] = "longpressed";
33 static const char SIG_EDGE_TOP[] = "edge,top";
34 static const char SIG_EDGE_BOTTOM[] = "edge,bottom";
35 static const char SIG_EDGE_LEFT[] = "edge,left";
36 static const char SIG_EDGE_RIGHT[] = "edge,right";
37 static const char SIG_SWIPE[] = "swipe";
38 static const char SIG_HIGHLIGHTED[] = "highlighted";
39 static const char SIG_UNHIGHLIGHTED[] = "unhighlighted";
40 static const char SIG_ITEM_FOCUSED[] = "item,focused";
41 static const char SIG_ITEM_UNFOCUSED[] = "item,unfocused";
42 static const Evas_Smart_Cb_Description _smart_callbacks[] = {
44 {SIG_CLICKED_DOUBLE, ""},
45 {SIG_CLICKED_RIGHT, ""},
48 {SIG_LONGPRESSED, ""},
50 {SIG_EDGE_BOTTOM, ""},
54 {SIG_HIGHLIGHTED, ""},
55 {SIG_UNHIGHLIGHTED, ""},
56 {SIG_ITEM_FOCUSED, ""},
57 {SIG_ITEM_UNFOCUSED, ""},
58 {SIG_WIDGET_LANG_CHANGED, ""}, /**< handled by elm_widget */
59 {SIG_WIDGET_ACCESS_CHANGED, ""}, /**< handled by elm_widget */
60 {SIG_LAYOUT_FOCUSED, ""}, /**< handled by elm_layout */
61 {SIG_LAYOUT_UNFOCUSED, ""}, /**< handled by elm_layout */
65 static void _size_hints_changed_cb(void *, Evas *, Evas_Object *, void *);
66 static void _mouse_up_cb(void *, Evas *, Evas_Object *, void *);
67 static void _mouse_down_cb(void *, Evas *, Evas_Object *, void *);
68 static void _mouse_move_cb(void *, Evas *, Evas_Object *, void *);
69 static void _mouse_in_cb(void *, Evas *, Evas_Object *, void *);
70 static void _items_fix(Evas_Object *);
72 static Eina_Bool _key_action_move(Evas_Object *obj, const char *params);
73 static Eina_Bool _key_action_select(Evas_Object *obj, const char *params);
74 static Eina_Bool _key_action_escape(Evas_Object *obj, const char *params);
77 static const Elm_Action key_actions[] = {
78 {"move", _key_action_move},
79 {"select", _key_action_select},
80 {"escape", _key_action_escape},
85 _is_no_select(Elm_List_Item_Data *it)
87 ELM_LIST_DATA_GET_FROM_ITEM(it, sd);
89 if ((sd->select_mode == ELM_OBJECT_SELECT_MODE_NONE) ||
90 (sd->select_mode == ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY))
96 _elm_list_item_free(Elm_List_Item_Data *it)
98 ELM_LIST_DATA_GET_FROM_ITEM(it, sd);
99 Elm_Object_Item *eo_it = it?EO_OBJ(it):NULL;
101 if (sd->focused_item == eo_it)
102 sd->focused_item = NULL;
103 if (sd->last_focused_item == eo_it)
104 sd->last_focused_item = NULL;
105 if (sd->last_selected_item == eo_it)
106 sd->last_selected_item = NULL;
109 evas_object_event_callback_del_full
110 (VIEW(it), EVAS_CALLBACK_MOUSE_DOWN, _mouse_down_cb, it);
111 evas_object_event_callback_del_full
112 (VIEW(it), EVAS_CALLBACK_MOUSE_UP, _mouse_up_cb, it);
113 evas_object_event_callback_del_full
114 (VIEW(it), EVAS_CALLBACK_MOUSE_MOVE, _mouse_move_cb, it);
115 evas_object_event_callback_del_full
116 (VIEW(it), EVAS_CALLBACK_MOUSE_IN, _mouse_in_cb, it);
119 evas_object_event_callback_del_full
120 (it->icon, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
121 _size_hints_changed_cb, WIDGET(it));
124 evas_object_event_callback_del_full
125 (it->end, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
126 _size_hints_changed_cb, WIDGET(it));
128 ELM_SAFE_FREE(it->label, eina_stringshare_del);
129 ELM_SAFE_FREE(it->swipe_timer, ecore_timer_del);
130 ELM_SAFE_FREE(it->long_timer, ecore_timer_del);
131 ELM_SAFE_FREE(it->icon, evas_object_del);
132 ELM_SAFE_FREE(it->end, evas_object_del);
136 _item_multi_select_up(Elm_List_Data *sd)
138 Elm_Object_Item *prev;
140 if (!sd->selected) return EINA_FALSE;
141 if (!sd->multi) return EINA_FALSE;
143 prev = elm_list_item_prev(sd->last_selected_item);
146 if (!elm_object_item_disabled_get(prev)) break;
147 prev = elm_list_item_prev(prev);
149 if (!prev) return EINA_TRUE;
151 if (elm_list_item_selected_get(prev))
153 elm_list_item_selected_set(sd->last_selected_item, EINA_FALSE);
154 sd->last_selected_item = prev;
158 elm_list_item_selected_set(prev, EINA_TRUE);
164 _item_multi_select_down(Elm_List_Data *sd)
166 Elm_Object_Item *next;
168 if (!sd->selected) return EINA_FALSE;
169 if (!sd->multi) return EINA_FALSE;
171 next = elm_list_item_next(sd->last_selected_item);
174 if (!elm_object_item_disabled_get(next)) break;
175 next = elm_list_item_next(next);
177 if (!next) return EINA_TRUE;
179 if (elm_list_item_selected_get(next))
181 elm_list_item_selected_set(sd->last_selected_item, EINA_FALSE);
182 sd->last_selected_item = next;
186 elm_list_item_selected_set(next, EINA_TRUE);
192 _all_items_unselect(Elm_List_Data *sd)
194 if (!sd->selected) return EINA_FALSE;
197 elm_list_item_selected_set
198 (sd->selected->data, EINA_FALSE);
204 _item_single_select_up(Elm_List_Data *sd)
206 Elm_Object_Item *prev;
209 prev = eina_list_data_get(eina_list_last(sd->items));
211 prev = elm_list_item_prev(sd->last_selected_item);
215 if (!elm_object_item_disabled_get(prev)) break;
216 prev = elm_list_item_prev(prev);
219 if (!prev) return EINA_FALSE;
221 _all_items_unselect(sd);
223 elm_list_item_selected_set(prev, EINA_TRUE);
229 _item_single_select_down(Elm_List_Data *sd)
231 Elm_Object_Item *next;
234 next = eina_list_data_get(sd->items);
236 next = elm_list_item_next(sd->last_selected_item);
240 if (!elm_object_item_disabled_get(next)) break;
241 next = elm_list_item_next(next);
244 if (!next) return EINA_FALSE;
246 _all_items_unselect(sd);
248 elm_list_item_selected_set(next, EINA_TRUE);
254 _elm_list_item_content_focus_set(Elm_List_Item_Data *it, Elm_Focus_Direction dir,
257 if (!it) return EINA_FALSE;
258 ELM_LIST_DATA_GET_FROM_ITEM(it, sd);
260 if (!sd->focus_on_selection_enabled) return EINA_FALSE;
261 if ((h_mode && (dir != ELM_FOCUS_UP) && (dir != ELM_FOCUS_DOWN)) ||
262 (!h_mode && (dir != ELM_FOCUS_LEFT) && (dir != ELM_FOCUS_RIGHT)))
266 Evas_Object *focus_chain[2];
267 Evas_Object *focused = NULL;
270 if (it->icon && elm_object_widget_check(it->icon) && elm_object_focus_allow_get(it->icon))
271 focus_chain[focus_objs++] = it->icon;
272 if (it->end && elm_object_widget_check(it->end) && elm_object_focus_allow_get(it->end))
273 focus_chain[focus_objs++] = it->end;
278 for (idx = 0; idx < focus_objs; idx++)
280 if (elm_object_focus_get(focus_chain[idx]))
282 focused = focus_chain[idx];
289 elm_object_focus_set(focus_chain[0], EINA_TRUE);
293 if (dir != ELM_FOCUS_PREVIOUS)
295 Evas_Object *nextfocus;
296 Elm_Object_Item *nextfocus_item;
297 if (elm_widget_focus_next_get(focused, dir, &nextfocus, &nextfocus_item))
300 elm_object_item_focus_set(nextfocus_item, EINA_TRUE);
302 elm_object_focus_set(nextfocus, EINA_TRUE);
306 idx += ((dir == ELM_FOCUS_UP) || (dir == ELM_FOCUS_LEFT)) ? -1 : 1;
307 if (idx < 0) idx = focus_objs - 1;
308 if (idx >= focus_objs) idx = 0;
309 focused = focus_chain[idx];
312 elm_object_focus_set(focused, EINA_TRUE);
316 static Elm_Object_Item *
317 _next_item_get(Elm_List_Data *sd, Elm_Object_Item *eo_cur, Elm_Focus_Direction dir)
319 Eina_List *list = NULL;
320 Elm_Object_Item *eo_it = NULL;
322 list = eina_list_data_find_list(sd->items, eo_cur);
323 if (!list) return NULL;
324 if ((!sd->h_mode && (dir == ELM_FOCUS_UP)) ||
325 ((sd->h_mode) && (dir == ELM_FOCUS_LEFT)))
326 eo_it = eina_list_data_get(eina_list_prev(list));
327 else if (((!sd->h_mode) && (dir == ELM_FOCUS_DOWN)) ||
328 ((sd->h_mode) && (dir == ELM_FOCUS_RIGHT)))
329 eo_it = eina_list_data_get(eina_list_next(list));
335 _item_focused_next(Evas_Object *obj, Elm_Focus_Direction dir)
337 ELM_LIST_DATA_GET_OR_RETURN_VAL(obj, sd, EINA_FALSE);
338 Elm_Object_Item *eo_it = NULL;
340 if (sd->focused_item)
341 eo_it = _next_item_get(sd, sd->focused_item, dir);
344 elm_object_item_disabled_get(eo_it))
346 eo_it = _next_item_get(sd, eo_it, dir);
351 elm_object_item_focus_set(eo_it, EINA_TRUE);
359 _elm_list_elm_widget_event_direction(Evas_Object *obj, Elm_Focus_Direction dir, Eina_Bool multi)
361 Elm_Object_Item *eo_it = NULL;
362 ELM_LIST_DATA_GET(obj, sd);
363 Eina_Bool ret = EINA_FALSE;
366 Eina_Bool focus_only = EINA_FALSE;
368 // check if the content can get the focus by direction key
369 ELM_LIST_ITEM_DATA_GET(elm_object_focused_item_get(obj) , it);
370 if (_elm_list_item_content_focus_set(it, dir, sd->h_mode))
373 if ((sd->h_mode && (dir != ELM_FOCUS_LEFT) && (dir != ELM_FOCUS_RIGHT)) ||
374 (!sd->h_mode && (dir != ELM_FOCUS_UP) && (dir != ELM_FOCUS_DOWN)))
377 // get content size and viewport size
378 if ((dir == ELM_FOCUS_LEFT) || (dir == ELM_FOCUS_RIGHT))
381 elm_interface_scrollable_content_viewport_geometry_get
382 (NULL, NULL, &v, NULL),
383 elm_interface_scrollable_content_size_get(&min, NULL));
388 elm_interface_scrollable_content_viewport_geometry_get
389 (NULL, NULL, NULL, &v),
390 elm_interface_scrollable_content_size_get(NULL, &min));
393 // move focus or selection according to the configuration
394 focus_only = _elm_config->item_select_on_focus_disable;
396 ret = _item_focused_next(obj, dir);
401 if ((dir == ELM_FOCUS_LEFT) || (dir == ELM_FOCUS_UP))
402 ret = _item_multi_select_up(sd);
404 ret = _item_multi_select_down(sd);
408 if ((dir == ELM_FOCUS_LEFT) || (dir == ELM_FOCUS_UP))
409 ret = _item_single_select_up(sd);
411 ret = _item_single_select_down(sd);
417 // handle item loop feature
418 if (sd->item_loop_enable && !sd->item_looping_on)
422 if (dir == ELM_FOCUS_LEFT)
424 elm_layout_signal_emit(obj, "elm,action,looping,left", "elm");
425 sd->item_looping_on = EINA_TRUE;
427 else if (dir == ELM_FOCUS_RIGHT)
429 elm_layout_signal_emit(obj, "elm,action,looping,right", "elm");
430 sd->item_looping_on = EINA_TRUE;
432 else if (dir == ELM_FOCUS_UP)
434 elm_layout_signal_emit(obj, "elm,action,looping,up", "elm");
435 sd->item_looping_on = EINA_TRUE;
437 else if (dir == ELM_FOCUS_DOWN)
439 elm_layout_signal_emit(obj, "elm,action,looping,down", "elm");
440 sd->item_looping_on = EINA_TRUE;
445 if ((dir == ELM_FOCUS_LEFT) || (dir == ELM_FOCUS_UP))
446 eo_it = elm_list_last_item_get(obj);
448 eo_it = elm_list_first_item_get(obj);
451 elm_object_item_focus_set(eo_it, EINA_TRUE);
453 elm_list_item_selected_set(eo_it, EINA_TRUE);
457 else if (sd->item_looping_on)
463 static Eina_Bool _key_action_move(Evas_Object *obj, const char *params)
465 ELM_LIST_DATA_GET(obj, sd);
466 const char *dir = params;
472 Evas_Coord step_x = 0;
473 Evas_Coord step_y = 0;
474 Evas_Coord page_x = 0;
475 Evas_Coord page_y = 0;
476 Elm_Object_Item *it = NULL;
479 elm_interface_scrollable_content_pos_get(&x, &y),
480 elm_interface_scrollable_step_size_get(&step_x, &step_y),
481 elm_interface_scrollable_page_size_get(&page_x, &page_y),
482 elm_interface_scrollable_content_viewport_geometry_get
483 (NULL, NULL, &v_w, &v_h));
485 _elm_widget_focus_auto_show(obj);
486 /* TODO: fix logic for horizontal mode */
487 if (!strcmp(dir, "left"))
489 if (_elm_list_elm_widget_event_direction(obj, ELM_FOCUS_LEFT, EINA_FALSE))
494 else if (!strcmp(dir, "left_multi"))
496 if (_elm_list_elm_widget_event_direction(obj, ELM_FOCUS_LEFT, EINA_TRUE))
501 else if (!strcmp(dir, "right"))
503 if (_elm_list_elm_widget_event_direction(obj, ELM_FOCUS_RIGHT, EINA_FALSE))
508 else if (!strcmp(dir, "right_multi"))
510 if (_elm_list_elm_widget_event_direction(obj, ELM_FOCUS_RIGHT, EINA_TRUE))
515 else if (!strcmp(dir, "up"))
517 if (_elm_list_elm_widget_event_direction(obj, ELM_FOCUS_UP, EINA_FALSE))
522 else if (!strcmp(dir, "up_multi"))
524 if (_elm_list_elm_widget_event_direction(obj, ELM_FOCUS_UP, EINA_TRUE))
529 else if (!strcmp(dir, "down"))
531 if (_elm_list_elm_widget_event_direction(obj, ELM_FOCUS_DOWN, EINA_FALSE))
536 else if (!strcmp(dir, "down_multi"))
538 if (_elm_list_elm_widget_event_direction(obj, ELM_FOCUS_DOWN, EINA_TRUE))
543 else if (!strcmp(dir, "first"))
545 it = eina_list_data_get(sd->items);
548 elm_list_item_selected_set(it, EINA_TRUE);
554 else if (!strcmp(dir, "last"))
556 it = eina_list_data_get(eina_list_last(sd->items));
559 elm_list_item_selected_set(it, EINA_TRUE);
565 else if (!strcmp(dir, "prior"))
570 x -= -(page_x * v_w) / 100;
577 y -= -(page_y * v_h) / 100;
582 else if (!strcmp(dir, "next"))
587 x += -(page_x * v_w) / 100;
594 y += -(page_y * v_h) / 100;
599 else return EINA_FALSE;
601 eo_do(obj, elm_interface_scrollable_content_pos_set(x, y, EINA_TRUE));
605 static Eina_Bool _key_action_select(Evas_Object *obj, const char *params EINA_UNUSED)
607 ELM_LIST_DATA_GET(obj, sd);
608 Elm_Object_Item *eo_it = NULL;
610 if (!_elm_config->item_select_on_focus_disable &&
611 (!sd->multi) && (sd->selected))
612 eo_it = elm_list_selected_item_get(obj);
614 eo_it = elm_object_focused_item_get(obj);
615 elm_list_item_selected_set(eo_it, EINA_TRUE);
618 ELM_LIST_ITEM_DATA_GET(eo_it, it);
619 eo_do(WIDGET(it), eo_event_callback_call
620 (ELM_LIST_EVENT_ACTIVATED, eo_it));
626 static Eina_Bool _key_action_escape(Evas_Object *obj, const char *params EINA_UNUSED)
628 ELM_LIST_DATA_GET(obj, sd);
630 if (!_all_items_unselect(sd)) return EINA_FALSE;
634 EOLIAN static Eina_Bool
635 _elm_list_elm_widget_event(Eo *obj, Elm_List_Data *sd, Evas_Object *src, Evas_Callback_Type type, void *event_info)
638 Evas_Event_Key_Down *ev = event_info;
640 if (type != EVAS_CALLBACK_KEY_DOWN) return EINA_FALSE;
641 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE;
642 if (!sd->items) return EINA_FALSE;
644 if (!_elm_config_key_binding_call(obj, ev, key_actions))
647 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
651 EOLIAN static Eina_Bool
652 _elm_list_elm_widget_translate(Eo *obj EINA_UNUSED, Elm_List_Data *sd)
657 EINA_LIST_FOREACH(sd->items, l, it)
658 eo_do(it, elm_wdg_item_translate());
660 eo_do_super(obj, MY_CLASS, elm_obj_widget_translate());
666 _elm_list_deletions_process(Elm_List_Data *sd)
668 Elm_List_Item_Data *it;
670 sd->walking++; // avoid nested deletion and also _sub_del() items_fix
672 EINA_LIST_FREE(sd->to_delete, it)
674 sd->items = eina_list_remove_list(sd->items, it->node);
676 /* issuing free because of "locking" item del pre hook */
677 _elm_list_item_free(it);
685 _elm_list_elm_layout_sizing_eval(Eo *obj, Elm_List_Data *sd)
687 Evas_Coord vw = 0, vh = 0;
688 Evas_Coord minw = 0, minh = 0, maxw = 0, maxh = 0, w = 0, h = 0, vmw = 0, vmh = 0;
689 double xw = 0.0, yw = 0.0;
691 ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
693 evas_object_size_hint_min_get(sd->box, &minw, &minh);
694 evas_object_size_hint_max_get(sd->box, &maxw, &maxh);
695 evas_object_size_hint_weight_get(sd->box, &xw, &yw);
697 eo_do(obj, elm_interface_scrollable_content_viewport_geometry_get
698 (NULL, NULL, &vw, &vh));
701 if ((minw > 0) && (vw < minw)) vw = minw;
702 else if ((maxw > 0) && (vw > maxw))
709 if ((minh > 0) && (vh < minh)) vh = minh;
710 else if ((maxh > 0) && (vh > maxh))
716 evas_object_resize(sd->box, vw, vh);
720 edje_object_size_min_calc
721 (wd->resize_obj, &vmw, &vmh);
723 if (sd->scr_minw) w = vmw + minw;
724 if (sd->scr_minh) h = vmh + minh;
726 evas_object_size_hint_max_get(obj, &maxw, &maxh);
727 if ((maxw > 0) && (w > maxw))
729 if ((maxh > 0) && (h > maxh))
732 evas_object_size_hint_min_set(obj, w, h);
736 _elm_list_content_min_limit_cb(Evas_Object *obj,
740 ELM_LIST_DATA_GET(obj, sd);
742 if ((sd->mode == ELM_LIST_LIMIT) ||
743 (sd->mode == ELM_LIST_EXPAND)) return;
747 elm_layout_sizing_eval(obj);
751 _elm_list_mode_set_internal(Evas_Object *obj)
753 Elm_List_Data *sd = eo_data_scope_get(obj, MY_CLASS);
754 if (sd->mode == ELM_LIST_LIMIT)
758 sd->scr_minw = EINA_TRUE;
759 sd->scr_minh = EINA_FALSE;
763 sd->scr_minw = EINA_FALSE;
764 sd->scr_minh = EINA_TRUE;
767 else if (sd->mode == ELM_LIST_EXPAND)
769 sd->scr_minw = EINA_TRUE;
770 sd->scr_minh = EINA_TRUE;
774 sd->scr_minw = EINA_FALSE;
775 sd->scr_minh = EINA_FALSE;
778 elm_layout_sizing_eval(obj);
782 _elm_list_walk(Elm_List_Data *sd)
786 ERR("ERROR: walking was negative. fixed!\n");
793 _elm_list_unwalk(Evas_Object *obj, Elm_List_Data *sd)
798 ERR("ERROR: walking became negative. fixed!\n");
806 _elm_list_deletions_process(sd);
810 sd->fix_pending = EINA_FALSE;
812 elm_layout_sizing_eval(obj);
817 _items_fix(Evas_Object *obj)
819 Evas_Coord minw[2] = { 0, 0 }, minh[2] = { 0, 0 };
821 Elm_Object_Item *eo_it;
827 const char *it_plain;
828 const char *it_compress;
829 const char *it_compress_odd;
831 ELM_LIST_DATA_GET(obj, sd);
833 style = elm_widget_style_get(obj);
834 it_plain = sd->h_mode ? "h_item" : "item";
835 it_odd = sd->h_mode ? "h_item_odd" : "item_odd";
836 it_compress = sd->h_mode ? "h_item_compress" : "item_compress";
837 it_compress_odd = sd->h_mode ? "h_item_compress_odd" : "item_compress_odd";
841 sd->fix_pending = EINA_TRUE;
845 evas_object_ref(obj);
846 _elm_list_walk(sd); // watch out "return" before unwalk!
848 EINA_LIST_FOREACH(sd->items, l, eo_it)
850 ELM_LIST_ITEM_DATA_GET(eo_it, it);
852 if (it->deleted) continue;
855 evas_object_size_hint_min_get(it->icon, &mw, &mh);
856 if (mw > minw[0]) minw[0] = mw;
857 if (mh > minh[0]) minh[0] = mh;
861 evas_object_size_hint_min_get(it->end, &mw, &mh);
862 if (mw > minw[1]) minw[1] = mw;
863 if (mh > minh[1]) minh[1] = mh;
867 if ((minw[0] != sd->minw[0]) || (minw[1] != sd->minw[1]) ||
868 (minh[0] != sd->minh[0]) || (minh[1] != sd->minh[1]))
870 sd->minw[0] = minw[0];
871 sd->minw[1] = minw[1];
872 sd->minh[0] = minh[0];
873 sd->minh[1] = minh[1];
878 EINA_LIST_FOREACH(sd->items, l, eo_it)
880 ELM_LIST_ITEM_DATA_GET(eo_it, it);
886 if ((it->even != it->is_even) || (!it->fixed) || (redo))
888 const char *stacking;
890 if (it->is_separator)
891 elm_widget_theme_object_set
892 (obj, VIEW(it), "separator", sd->h_mode ?
893 "vertical" : "horizontal", style);
894 else if (sd->mode == ELM_LIST_COMPRESS)
897 elm_widget_theme_object_set
898 (obj, VIEW(it), "list", it_compress, style);
900 elm_widget_theme_object_set
901 (obj, VIEW(it), "list", it_compress_odd, style);
906 elm_widget_theme_object_set
907 (obj, VIEW(it), "list", it_plain, style);
909 elm_widget_theme_object_set
910 (obj, VIEW(it), "list", it_odd, style);
912 stacking = edje_object_data_get(VIEW(it), "stacking");
915 if (!strcmp(stacking, "below"))
916 evas_object_lower(VIEW(it));
917 else if (!strcmp(stacking, "above"))
918 evas_object_raise(VIEW(it));
921 if (!it->is_separator)
923 edje_object_part_text_escaped_set
924 (VIEW(it), "elm.text", it->label);
925 eo_do(EO_OBJ(it), elm_wdg_item_part_text_custom_update());
927 if ((!it->icon) && (minh[0] > 0))
929 it->icon = evas_object_rectangle_add
930 (evas_object_evas_get(VIEW(it)));
931 evas_object_color_set(it->icon, 0, 0, 0, 0);
932 it->dummy_icon = EINA_TRUE;
934 if ((!it->end) && (minh[1] > 0))
936 it->end = evas_object_rectangle_add
937 (evas_object_evas_get(VIEW(it)));
938 evas_object_color_set(it->end, 0, 0, 0, 0);
939 it->dummy_end = EINA_TRUE;
943 evas_object_size_hint_min_set(it->icon, minw[0], minh[0]);
944 evas_object_size_hint_max_set(it->icon, 99999, 99999);
945 edje_object_part_swallow
946 (VIEW(it), "elm.swallow.icon", it->icon);
950 evas_object_size_hint_min_set(it->end, minw[1], minh[1]);
951 evas_object_size_hint_max_set(it->end, 99999, 99999);
952 edje_object_part_swallow
953 (VIEW(it), "elm.swallow.end", it->end);
955 if (eina_list_count(sd->items) == 1)
957 edje_object_signal_emit
958 (VIEW(it), "elm,state,list,single", "elm");
960 else if (l == sd->items) //1st item
962 edje_object_signal_emit
963 (VIEW(it), "elm,state,list,first", "elm");
965 else if (l == eina_list_last(sd->items))
967 edje_object_signal_emit
968 (VIEW(it), "elm,state,list,last", "elm");
972 edje_object_signal_emit
973 (VIEW(it), "elm,state,list,middle", "elm");
978 // this may call up user and it may modify the list item
979 // but we're safe as we're flagged as walking.
980 // just don't process further
981 edje_object_message_signal_process(VIEW(it));
985 if (!it->is_separator)
986 elm_coords_finger_size_adjust(1, &mw, 1, &mh);
987 edje_object_size_min_restricted_calc
988 (VIEW(it), &mw, &mh, mw, mh);
990 FIXME: this fixed T179 but introduced T286.
991 Temporarily disable these lines until it gets fixed correctly.
993 edje_object_parts_extends_calc
994 (VIEW(it), NULL, NULL, &ew, &eh);
995 mw = mw > ew ? mw : ew;
996 mh = mh > eh ? mh : eh;
998 evas_object_size_hint_min_set(VIEW(it), mw, mh);
999 evas_object_show(VIEW(it));
1001 if ((it->selected) || (it->highlighted))
1003 const char *select_raise;
1005 // this may call up user and it may modify the list item
1006 // but we're safe as we're flagged as walking.
1007 // just don't process further
1008 edje_object_signal_emit
1009 (VIEW(it), "elm,state,selected", "elm");
1013 select_raise = edje_object_data_get(VIEW(it), "selectraise");
1014 if ((select_raise) && (!strcmp(select_raise, "on")))
1015 evas_object_raise(VIEW(it));
1017 if (it->base->disabled)
1018 edje_object_signal_emit(VIEW(it), "elm,state,disabled", "elm");
1020 it->fixed = EINA_TRUE;
1021 it->is_even = it->even;
1024 if (!it->is_separator)
1028 _elm_list_mode_set_internal(obj);
1029 _elm_list_unwalk(obj, sd);
1031 //focus highlight in_theme is set by list item theme.
1032 _elm_widget_item_highlight_in_theme(
1033 obj, elm_list_first_item_get(obj));
1035 evas_object_unref(obj);
1039 _size_hints_changed_cb(void *data,
1040 Evas *e EINA_UNUSED,
1041 Evas_Object *obj EINA_UNUSED,
1042 void *event_info EINA_UNUSED)
1044 ELM_LIST_DATA_GET(data, sd);
1045 if (sd->delete_me) return;
1048 elm_layout_sizing_eval(data);
1051 /* FIXME: take off later. maybe this show region coords belong in the
1052 * interface (new api functions, set/get)? */
1054 _show_region_hook(void *data EINA_UNUSED,
1057 Evas_Coord x, y, w, h;
1059 elm_widget_show_region_get(obj, &x, &y, &w, &h);
1060 eo_do(obj, elm_interface_scrollable_content_region_set(x, y, w, h));
1063 EOLIAN static Eina_Bool
1064 _elm_list_elm_widget_disable(Eo *obj, Elm_List_Data *sd)
1066 Eina_Bool int_ret = EINA_FALSE;
1067 eo_do_super(obj, MY_CLASS, int_ret = elm_obj_widget_disable());
1068 if (!int_ret) return EINA_FALSE;
1070 if (elm_widget_disabled_get(obj))
1072 elm_widget_scroll_freeze_push(obj);
1073 elm_widget_scroll_hold_push(obj);
1074 /* FIXME: if we get to have a way to only un-highlight items
1075 * in the future, keeping them selected... */
1076 _all_items_unselect(sd);
1080 elm_widget_scroll_freeze_pop(obj);
1081 elm_widget_scroll_hold_pop(obj);
1088 _mirrored_set(Evas_Object *obj,
1091 Elm_Object_Item *eo_it;
1094 ELM_LIST_DATA_GET(obj, sd);
1096 eo_do(obj, elm_interface_scrollable_mirrored_set(rtl));
1098 EINA_LIST_FOREACH(sd->items, n, eo_it)
1100 ELM_LIST_ITEM_DATA_GET(eo_it, it);
1101 edje_object_mirrored_set(VIEW(it), rtl);
1105 EOLIAN static Eina_Bool
1106 _elm_list_elm_widget_theme_apply(Eo *obj, Elm_List_Data *sd)
1108 Elm_Object_Item *eo_it;
1111 Eina_Bool int_ret = EINA_FALSE;
1112 eo_do_super(obj, MY_CLASS, int_ret = elm_obj_widget_theme_apply());
1113 if (!int_ret) return EINA_FALSE;
1115 _mirrored_set(obj, elm_widget_mirrored_get(obj));
1117 EINA_LIST_FOREACH(sd->items, n, eo_it)
1119 ELM_LIST_ITEM_DATA_GET(eo_it, it);
1120 edje_object_scale_set
1121 (VIEW(it), elm_widget_scale_get(obj) * elm_config_scale_get());
1122 it->fixed = EINA_FALSE;
1127 elm_layout_sizing_eval(obj);
1133 _elm_list_item_focused(Elm_Object_Item *eo_it)
1135 ELM_LIST_ITEM_DATA_GET(eo_it, it);
1136 ELM_LIST_DATA_GET_FROM_ITEM(it, sd);
1137 Evas_Coord x, y, w, h, sx, sy, sw, sh;
1138 const char *focus_raise;
1140 if ((!sd) || _is_no_select(it) ||
1141 (eo_it == sd->focused_item))
1143 evas_object_geometry_get(VIEW(it), &x, &y, &w, &h);
1144 evas_object_geometry_get(sd->hit_rect, &sx, &sy, &sw, &sh);
1145 if (!ELM_RECTS_INCLUDE(sx, sy, sw, sh, x, y, w, h))
1147 switch (_elm_config->focus_autoscroll_mode)
1149 case ELM_FOCUS_AUTOSCROLL_MODE_SHOW:
1150 elm_list_item_show(eo_it);
1152 case ELM_FOCUS_AUTOSCROLL_MODE_BRING_IN:
1153 elm_list_item_bring_in(eo_it);
1159 sd->focused_item = eo_it;
1160 if (elm_widget_focus_highlight_enabled_get(WIDGET(it)) || _elm_config->win_auto_focus_enable)
1162 edje_object_signal_emit
1163 (VIEW(it), "elm,state,focused", "elm");
1165 focus_raise = edje_object_data_get(VIEW(it), "focusraise");
1166 if ((focus_raise) && (!strcmp(focus_raise, "on")))
1167 evas_object_raise(VIEW(it));
1168 eo_do(WIDGET(it), eo_event_callback_call
1169 (ELM_LIST_EVENT_ITEM_FOCUSED, eo_it));
1170 if (_elm_config->atspi_mode)
1171 elm_interface_atspi_accessible_state_changed_signal_emit(eo_it, ELM_ATSPI_STATE_FOCUSED, EINA_TRUE);
1175 _elm_list_item_unfocused(Elm_Object_Item *eo_it)
1177 ELM_LIST_ITEM_DATA_GET(eo_it, it);
1178 Evas_Object *obj = WIDGET(it);
1179 ELM_LIST_DATA_GET(obj, sd);
1181 if ((!sd) || (!sd->focused_item) ||
1182 (eo_it != sd->focused_item))
1185 if (_is_no_select(it))
1188 if (elm_widget_focus_highlight_enabled_get(obj) || _elm_config->win_auto_focus_enable)
1190 ELM_LIST_ITEM_DATA_GET(sd->focused_item, focus_it);
1191 edje_object_signal_emit
1192 (VIEW(focus_it), "elm,state,unfocused", "elm");
1195 sd->focused_item = NULL;
1196 eo_do(obj, eo_event_callback_call(ELM_LIST_EVENT_ITEM_UNFOCUSED, eo_it));
1197 if (_elm_config->atspi_mode)
1198 elm_interface_atspi_accessible_state_changed_signal_emit(eo_it, ELM_ATSPI_STATE_FOCUSED, EINA_FALSE);
1202 * This function searches the nearest visible item based on the given item.
1203 * If the given item is in the list viewport, this returns the given item.
1204 * Or this searches other items and checks the nearest fully visible item
1205 * according to the given item's position.
1207 static Elm_List_Item_Data *
1208 _elm_list_nearest_visible_item_get(Evas_Object *obj, Elm_List_Item_Data *it)
1210 Evas_Coord vx = 0, vy = 0, vw = 0, vh = 0; // list viewport geometry
1211 Evas_Coord ix = 0, iy = 0, iw = 0, ih = 0; // given item geometry
1212 Evas_Coord cx = 0, cy = 0, cw = 0, ch = 0; // candidate item geometry
1213 Eina_List *item_list = NULL;
1214 Elm_List_Item_Data *item = NULL;
1215 ELM_LIST_DATA_GET(obj, sd);
1216 Eina_Bool search_next = EINA_FALSE;
1218 if (!it) return NULL;
1220 evas_object_geometry_get(obj, &vx, &vy, &vw, &vh);
1221 evas_object_geometry_get(VIEW(it), &ix, &iy, &iw, &ih);
1223 if (ELM_RECTS_INCLUDE(vx, vy, vw, vh, ix, iy, iw, ih))
1225 if (!elm_object_item_disabled_get(EO_OBJ(it)))
1228 search_next = EINA_TRUE;
1231 item_list = eina_list_data_find_list(sd->items, EO_OBJ(it));
1233 if ((!sd->h_mode && (iy < vy)) ||
1234 (sd->h_mode && (iw < vw)) ||
1237 while ((item_list = eina_list_next(item_list)))
1239 item = eo_data_scope_get(eina_list_data_get(item_list), ELM_LIST_ITEM_CLASS);
1240 if (!item) continue;
1241 evas_object_geometry_get(VIEW(item), &cx, &cy, &cw, &ch);
1242 if (ELM_RECTS_INCLUDE(vx, vy, vw, vh, cx, cy, cw, ch) &&
1243 !elm_object_item_disabled_get(EO_OBJ(item)))
1251 while ((item_list = eina_list_prev(item_list)))
1253 item = eo_data_scope_get(eina_list_data_get(item_list), ELM_LIST_ITEM_CLASS);
1254 if (!item) continue;
1255 evas_object_geometry_get(VIEW(item), &cx, &cy, &cw, &ch);
1256 if (ELM_RECTS_INCLUDE(vx, vy, vw, vh, cx, cy, cw, ch) &&
1257 !elm_object_item_disabled_get(EO_OBJ(item)))
1267 EOLIAN static Eina_Bool
1268 _elm_list_elm_widget_on_focus(Eo *obj, Elm_List_Data *sd, Elm_Object_Item *item EINA_UNUSED)
1270 Eina_Bool int_ret = EINA_FALSE;
1271 Elm_Object_Item *eo_it = NULL;
1272 Eina_Bool is_sel = EINA_FALSE;
1274 eo_do_super(obj, MY_CLASS, int_ret = elm_obj_widget_on_focus(NULL));
1275 if (!int_ret) return EINA_FALSE;
1277 if (elm_widget_focus_get(obj) && sd->selected && !sd->last_selected_item)
1279 Elm_Object_Item *sel = eina_list_data_get(sd->selected);
1280 sd->last_selected_item = eo_data_scope_get(sel, ELM_LIST_ITEM_CLASS);
1283 if (!sd->items) return EINA_FALSE;
1285 if (elm_widget_focus_get(obj) && !sd->mouse_down)
1287 if (sd->last_focused_item)
1288 eo_it = sd->last_focused_item;
1289 else if (sd->last_selected_item)
1290 eo_it = sd->last_selected_item;
1291 else if (_elm_config->first_item_focus_on_first_focus_in)
1293 eo_it = elm_list_first_item_get(obj);
1299 ELM_LIST_ITEM_DATA_GET(eo_it, it);
1300 it = _elm_list_nearest_visible_item_get(obj, it);
1303 if (!_elm_config->item_select_on_focus_disable && is_sel)
1304 elm_list_item_selected_set(EO_OBJ(it), EINA_TRUE);
1306 elm_object_item_focus_set(EO_OBJ(it), EINA_TRUE);
1312 sd->last_focused_item = sd->focused_item;
1313 if (sd->focused_item)
1314 _elm_list_item_unfocused(sd->focused_item);
1319 EOLIAN static Eina_Bool
1320 _elm_list_elm_widget_sub_object_del(Eo *obj, Elm_List_Data *sd, Evas_Object *sobj)
1323 Elm_Object_Item *eo_it;
1325 Eina_Bool int_ret = EINA_FALSE;
1326 eo_do_super(obj, MY_CLASS, int_ret = elm_obj_widget_sub_object_del(sobj));
1327 if (!int_ret) return EINA_FALSE;
1329 if ((sobj == sd->box) || (sobj == obj)) goto end;
1331 EINA_LIST_FOREACH(sd->items, l, eo_it)
1333 ELM_LIST_ITEM_DATA_GET(eo_it, it);
1334 if ((sobj == it->icon) || (sobj == it->end))
1336 if (it->icon == sobj) it->icon = NULL;
1337 if (it->end == sobj) it->end = NULL;
1338 evas_object_event_callback_del_full
1339 (sobj, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _size_hints_changed_cb,
1344 elm_layout_sizing_eval(obj);
1347 sd->fix_pending = EINA_TRUE;
1357 _item_highlight(Elm_List_Item_Data *it)
1360 const char *select_raise;
1362 ELM_LIST_ITEM_CHECK_OR_RETURN(it);
1364 ELM_LIST_DATA_GET(obj, sd);
1366 if (_is_no_select(it) ||
1367 (it->highlighted) || (it->base->disabled))
1370 evas_object_ref(obj);
1373 edje_object_signal_emit(VIEW(it), "elm,state,selected", "elm");
1374 eo_do(obj, eo_event_callback_call(ELM_LIST_EVENT_HIGHLIGHTED, EO_OBJ(it)));
1375 select_raise = edje_object_data_get(VIEW(it), "selectraise");
1376 if ((select_raise) && (!strcmp(select_raise, "on")))
1377 evas_object_raise(VIEW(it));
1378 it->highlighted = EINA_TRUE;
1379 _elm_list_unwalk(obj, sd);
1380 evas_object_unref(obj);
1384 _item_select(Elm_List_Item_Data *it)
1388 ELM_LIST_ITEM_CHECK_OR_RETURN(it);
1390 ELM_LIST_DATA_GET(obj, sd);
1391 Elm_Object_Item *eo_it = EO_OBJ(it);
1393 if (it->base->disabled || _is_no_select(it))
1395 if (!sd->focus_on_selection_enabled)
1397 if (it->icon && elm_object_widget_check(it->icon) &&
1398 elm_object_focus_get(it->icon))
1400 elm_object_focus_set(obj, EINA_FALSE);
1401 elm_object_focus_set(obj, EINA_TRUE);
1403 else if (it->end && elm_object_widget_check(it->end) &&
1404 elm_object_focus_get(it->end))
1406 elm_object_focus_set(obj, EINA_FALSE);
1407 elm_object_focus_set(obj, EINA_TRUE);
1412 if (sd->select_mode == ELM_OBJECT_SELECT_MODE_ALWAYS) goto call;
1416 _elm_list_item_content_focus_set(it, ELM_FOCUS_PREVIOUS, sd->h_mode);
1418 it->selected = EINA_TRUE;
1419 sd->selected = eina_list_append(sd->selected, eo_it);
1422 evas_object_ref(obj);
1425 if (it->func) it->func((void *)WIDGET_ITEM_DATA_GET(eo_it), WIDGET(it), eo_it);
1426 eo_do(obj, eo_event_callback_call(EVAS_SELECTABLE_INTERFACE_EVENT_SELECTED, eo_it));
1427 if (_elm_config->atspi_mode)
1428 elm_interface_atspi_accessible_state_changed_signal_emit(eo_it, ELM_ATSPI_STATE_SELECTED, EINA_TRUE);
1429 sd->last_selected_item = eo_it;
1431 _elm_list_unwalk(obj, sd);
1432 evas_object_unref(obj);
1436 _item_unhighlight(Elm_List_Item_Data *it)
1439 const char *stacking, *select_raise;
1441 ELM_LIST_ITEM_CHECK_OR_RETURN(it);
1443 ELM_LIST_DATA_GET(obj, sd);
1445 // if ((!it->highlighted) || (it->base->disabled) ||
1446 // (sd->select_mode == ELM_OBJECT_SELECT_MODE_NONE)) return;
1447 if (!it->highlighted) return;
1449 evas_object_ref(obj);
1452 edje_object_signal_emit(VIEW(it), "elm,state,unselected", "elm");
1453 eo_do(obj, eo_event_callback_call
1454 (ELM_LIST_EVENT_UNHIGHLIGHTED, EO_OBJ(it)));
1455 stacking = edje_object_data_get(VIEW(it), "stacking");
1456 select_raise = edje_object_data_get(VIEW(it), "selectraise");
1457 if ((select_raise) && (!strcmp(select_raise, "on")))
1459 if ((stacking) && (!strcmp(stacking, "below")))
1460 evas_object_lower(VIEW(it));
1462 it->highlighted = EINA_FALSE;
1464 _elm_list_unwalk(obj, sd);
1465 evas_object_unref(obj);
1469 _item_unselect(Elm_List_Item_Data *it)
1473 ELM_LIST_ITEM_CHECK_OR_RETURN(it);
1475 ELM_LIST_DATA_GET(obj, sd);
1477 // if (it->base->disabled || (sd->select_mode == ELM_OBJECT_SELECT_MODE_NONE))
1480 evas_object_ref(obj);
1483 if (sd->focus_on_selection_enabled)
1485 if (it->icon) elm_object_focus_set(it->icon, EINA_FALSE);
1486 if (it->end) elm_object_focus_set(it->end, EINA_FALSE);
1491 it->selected = EINA_FALSE;
1492 sd->selected = eina_list_remove(sd->selected, EO_OBJ(it));
1493 if (!(it->base->disabled ||
1494 (sd->select_mode == ELM_OBJECT_SELECT_MODE_NONE)))
1495 eo_do(WIDGET(it), eo_event_callback_call
1496 (EVAS_SELECTABLE_INTERFACE_EVENT_UNSELECTED, EO_OBJ(it)));
1497 if (_elm_config->atspi_mode)
1498 elm_interface_atspi_accessible_state_changed_signal_emit(EO_OBJ(it), ELM_ATSPI_STATE_SELECTED, EINA_FALSE);
1501 _elm_list_unwalk(obj, sd);
1502 evas_object_unref(obj);
1506 _swipe_cancel(void *data)
1508 Elm_List_Item_Data *it = data;
1510 ELM_LIST_ITEM_CHECK_OR_RETURN(it, ECORE_CALLBACK_CANCEL);
1511 ELM_LIST_DATA_GET_FROM_ITEM(it, sd);
1513 sd->swipe = EINA_FALSE;
1516 return ECORE_CALLBACK_RENEW;
1520 _edge_left_cb(Evas_Object *obj,
1521 void *data EINA_UNUSED)
1523 eo_do(obj, eo_event_callback_call(ELM_LIST_EVENT_EDGE_LEFT, NULL));
1527 _edge_right_cb(Evas_Object *obj,
1528 void *data EINA_UNUSED)
1530 eo_do(obj, eo_event_callback_call(ELM_LIST_EVENT_EDGE_RIGHT, NULL));
1534 _edge_top_cb(Evas_Object *obj,
1535 void *data EINA_UNUSED)
1537 eo_do(obj, eo_event_callback_call(ELM_LIST_EVENT_EDGE_TOP, NULL));
1541 _edge_bottom_cb(Evas_Object *obj,
1542 void *data EINA_UNUSED)
1544 eo_do(obj, eo_event_callback_call(ELM_LIST_EVENT_EDGE_BOTTOM, NULL));
1548 _long_press_cb(void *data)
1550 Elm_List_Item_Data *it = data;
1553 ELM_LIST_ITEM_CHECK_OR_RETURN(it, ECORE_CALLBACK_CANCEL);
1555 ELM_LIST_DATA_GET(obj, sd);
1557 it->long_timer = NULL;
1558 if (it->base->disabled) goto end;
1560 sd->longpressed = EINA_TRUE;
1561 eo_do(WIDGET(it), eo_event_callback_call
1562 (EVAS_CLICKABLE_INTERFACE_EVENT_LONGPRESSED, EO_OBJ(it)));
1565 return ECORE_CALLBACK_CANCEL;
1569 _swipe_do(Elm_List_Item_Data *it)
1573 ELM_LIST_ITEM_CHECK_OR_RETURN(it);
1574 ELM_LIST_DATA_GET_FROM_ITEM(it, sd);
1576 sd->swipe = EINA_FALSE;
1577 for (i = 0; i < sd->movements; i++)
1579 sum += sd->history[i].x;
1580 if (abs(sd->history[0].y - sd->history[i].y) > 10) return;
1583 sum /= sd->movements;
1584 if (abs(sum - sd->history[0].x) <= 10) return;
1586 eo_do(WIDGET(it), eo_event_callback_call
1587 (ELM_LIST_EVENT_SWIPE, EO_OBJ(it)));
1591 _mouse_in_cb(void *data,
1592 Evas *evas EINA_UNUSED,
1593 Evas_Object *o EINA_UNUSED,
1594 void *event_info EINA_UNUSED)
1596 Elm_List_Item_Data *it = data;
1597 if (!elm_object_item_disabled_get(EO_OBJ(it)) &&
1598 (_elm_config->focus_move_policy == ELM_FOCUS_MOVE_POLICY_IN))
1599 elm_object_item_focus_set(EO_OBJ(it), EINA_TRUE);
1603 _mouse_move_cb(void *data,
1604 Evas *evas EINA_UNUSED,
1609 Elm_List_Item_Data *it = data;
1610 Evas_Event_Mouse_Move *ev = event_info;
1611 Evas_Coord x = 0, y = 0, w = 0, h = 0;
1613 ELM_LIST_ITEM_CHECK_OR_RETURN(it);
1615 ELM_LIST_DATA_GET(obj, sd);
1617 evas_object_ref(obj);
1620 evas_object_geometry_get(o, &x, &y, &w, &h);
1622 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
1626 sd->on_hold = EINA_TRUE;
1627 ELM_SAFE_FREE(it->long_timer, ecore_timer_del);
1628 if (!sd->was_selected)
1630 _item_unhighlight(it);
1635 else if (ELM_RECTS_POINT_OUT(x, y, w, h, ev->cur.canvas.x, ev->cur.canvas.y))
1637 ELM_SAFE_FREE(it->long_timer, ecore_timer_del);
1638 if (!sd->was_selected)
1640 _item_unhighlight(it);
1643 it->base->still_in = EINA_FALSE;
1646 if (sd->movements == ELM_LIST_SWIPE_MOVES)
1648 sd->swipe = EINA_TRUE;
1652 sd->history[sd->movements].x = ev->cur.canvas.x;
1653 sd->history[sd->movements].y = ev->cur.canvas.y;
1654 if (abs((sd->history[sd->movements].x - sd->history[0].x)) > 40)
1656 sd->swipe = EINA_TRUE;
1662 ELM_SAFE_FREE(it->long_timer, ecore_timer_del);
1663 _elm_list_unwalk(obj, sd);
1664 evas_object_unref(obj);
1668 _mouse_down_cb(void *data,
1669 Evas *evas EINA_UNUSED,
1670 Evas_Object *o EINA_UNUSED,
1673 Evas_Event_Mouse_Down *ev = event_info;
1674 Elm_List_Item_Data *it = data;
1678 ELM_LIST_ITEM_CHECK_OR_RETURN(it);
1680 ELM_LIST_DATA_GET(obj, sd);
1682 if (ev->button == 3)
1684 evas_object_geometry_get(obj, &x, &y, NULL, NULL);
1685 sd->dx = ev->canvas.x - x;
1686 sd->dy = ev->canvas.y - y;
1690 if (ev->button != 1) return;
1691 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) sd->on_hold = EINA_TRUE;
1692 else sd->on_hold = EINA_FALSE;
1694 if (sd->on_hold) return;
1695 sd->mouse_down = EINA_TRUE;
1696 sd->was_selected = it->selected;
1698 evas_object_ref(obj);
1701 _item_highlight(it);
1702 sd->longpressed = EINA_FALSE;
1703 ecore_timer_del(it->long_timer);
1704 it->long_timer = ecore_timer_add
1705 (_elm_config->longpress_timeout, _long_press_cb, it);
1706 ecore_timer_del(it->swipe_timer);
1707 it->swipe_timer = ecore_timer_add(ELM_LIST_SWIPE_TIME, _swipe_cancel, it);
1709 /* Always call the callbacks last - the user may delete our context! */
1710 if (ev->flags & EVAS_BUTTON_DOUBLE_CLICK)
1712 eo_do(WIDGET(it), eo_event_callback_call
1713 (EVAS_CLICKABLE_INTERFACE_EVENT_CLICKED_DOUBLE, EO_OBJ(it)));
1714 eo_do(WIDGET(it), eo_event_callback_call
1715 (ELM_LIST_EVENT_ACTIVATED, EO_OBJ(it)));
1717 sd->swipe = EINA_FALSE;
1719 it->base->still_in = EINA_TRUE;
1721 _elm_list_unwalk(obj, sd);
1722 evas_object_unref(obj);
1726 _mouse_up_cb(void *data,
1727 Evas *evas EINA_UNUSED,
1728 Evas_Object *o EINA_UNUSED,
1732 Elm_List_Item_Data *it = data;
1733 Evas_Event_Mouse_Up *ev = event_info;
1734 Evas_Coord x, y, dx, dy;
1736 ELM_LIST_ITEM_CHECK_OR_RETURN(it);
1738 ELM_LIST_DATA_GET(obj, sd);
1740 if (ev->button == 3)
1742 evas_object_geometry_get(obj, &x, &y, NULL, NULL);
1743 dx = sd->dx - (ev->canvas.x - x);
1744 dy = sd->dy - (ev->canvas.y - y);
1745 if (dx < 0) dx = -dx;
1746 if (dy < 0) dy = -dy;
1747 if ((dx < 5) && (dy < 5))
1748 eo_do(obj, eo_event_callback_call
1749 (EVAS_CLICKABLE_INTERFACE_EVENT_CLICKED_RIGHT, EO_OBJ(it)));
1753 if (ev->button != 1) return;
1754 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) sd->on_hold = EINA_TRUE;
1755 else sd->on_hold = EINA_FALSE;
1757 sd->mouse_down = EINA_FALSE;
1758 ELM_SAFE_FREE(it->long_timer, ecore_timer_del);
1759 ELM_SAFE_FREE(it->swipe_timer, ecore_timer_del);
1762 if (!sd->was_selected)
1764 _item_unhighlight(it);
1768 sd->swipe = EINA_FALSE;
1769 sd->was_selected = EINA_FALSE;
1772 if (sd->longpressed)
1774 if (!sd->was_selected)
1776 _item_unhighlight(it);
1779 sd->longpressed = EINA_FALSE;
1780 sd->was_selected = EINA_FALSE;
1784 if (it->base->disabled)
1786 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD || !it->base->still_in)
1789 evas_object_ref(obj);
1792 if (sd->focused_item != EO_OBJ(it))
1793 elm_object_item_focus_set(EO_OBJ(it), EINA_TRUE);
1796 ((sd->multi_select_mode != ELM_OBJECT_MULTI_SELECT_MODE_WITH_CONTROL) ||
1797 (evas_key_modifier_is_set(ev->modifiers, "Control"))))
1801 _item_highlight(it);
1806 _item_unhighlight(it);
1814 while (sd->selected)
1816 Elm_Object_Item *eo_it2 = sd->selected->data;
1817 ELM_LIST_ITEM_DATA_GET(eo_it2, it2);
1818 sd->selected = eina_list_remove_list
1819 (sd->selected, sd->selected);
1820 _item_unhighlight(it2);
1821 _item_unselect(it2);
1823 _item_highlight(it);
1828 const Eina_List *l, *l_next;
1829 Elm_Object_Item *eo_it2;
1831 EINA_LIST_FOREACH_SAFE(sd->selected, l, l_next, eo_it2)
1832 if (eo_it2 != EO_OBJ(it))
1834 ELM_LIST_ITEM_DATA_GET(eo_it2, it2);
1835 _item_unhighlight(it2);
1836 _item_unselect(it2);
1838 _item_highlight(it);
1843 _elm_list_unwalk(obj, sd);
1844 evas_object_unref(obj);
1848 _elm_list_looping_left_cb(void *data,
1849 Evas_Object *obj EINA_UNUSED,
1850 const char *emission EINA_UNUSED,
1851 const char *source EINA_UNUSED)
1853 Evas_Object *list = data;
1855 ELM_LIST_DATA_GET(list, sd);
1857 Elm_Object_Item *it = elm_list_last_item_get(list);
1858 if (!_elm_config->item_select_on_focus_disable)
1859 elm_list_item_selected_set(it, EINA_TRUE);
1861 elm_object_item_focus_set(it, EINA_TRUE);
1862 elm_layout_signal_emit(list, "elm,action,looping,left,end", "elm");
1863 sd->item_looping_on = EINA_FALSE;
1867 _elm_list_looping_right_cb(void *data,
1868 Evas_Object *obj EINA_UNUSED,
1869 const char *emission EINA_UNUSED,
1870 const char *source EINA_UNUSED)
1872 Evas_Object *list = data;
1874 ELM_LIST_DATA_GET(list, sd);
1876 Elm_Object_Item *it = elm_list_first_item_get(list);
1877 if (!_elm_config->item_select_on_focus_disable)
1878 elm_list_item_selected_set(it, EINA_TRUE);
1880 elm_object_item_focus_set(it, EINA_TRUE);
1881 elm_layout_signal_emit(list, "elm,action,looping,right,end", "elm");
1882 sd->item_looping_on = EINA_FALSE;
1886 _elm_list_looping_up_cb(void *data,
1887 Evas_Object *obj EINA_UNUSED,
1888 const char *emission EINA_UNUSED,
1889 const char *source EINA_UNUSED)
1891 Evas_Object *list = data;
1893 ELM_LIST_DATA_GET(list, sd);
1895 Elm_Object_Item *it = elm_list_last_item_get(list);
1896 if (!_elm_config->item_select_on_focus_disable)
1897 elm_list_item_selected_set(it, EINA_TRUE);
1899 elm_object_item_focus_set(it, EINA_TRUE);
1900 elm_layout_signal_emit(list, "elm,action,looping,up,end", "elm");
1901 sd->item_looping_on = EINA_FALSE;
1905 _elm_list_looping_down_cb(void *data,
1906 Evas_Object *obj EINA_UNUSED,
1907 const char *emission EINA_UNUSED,
1908 const char *source EINA_UNUSED)
1910 Evas_Object *list = data;
1912 ELM_LIST_DATA_GET(list, sd);
1914 Elm_Object_Item *it = elm_list_first_item_get(list);
1915 if (!_elm_config->item_select_on_focus_disable)
1916 elm_list_item_selected_set(it, EINA_TRUE);
1918 elm_object_item_focus_set(it, EINA_TRUE);
1919 elm_layout_signal_emit(list, "elm,action,looping,down,end", "elm");
1920 sd->item_looping_on = EINA_FALSE;
1924 _elm_list_item_elm_widget_item_disable(Eo *eo_item EINA_UNUSED, Elm_List_Item_Data *item)
1926 _item_unhighlight(item);
1927 _item_unselect(item);
1928 if (item->base->disabled)
1929 edje_object_signal_emit(VIEW(item), "elm,state,disabled", "elm");
1931 edje_object_signal_emit(VIEW(item), "elm,state,enabled", "elm");
1935 _elm_list_item_elm_widget_item_part_content_set(Eo *eo_item EINA_UNUSED, Elm_List_Item_Data *item,
1937 Evas_Object *content)
1939 Evas_Object **icon_p = NULL;
1940 Eina_Bool dummy = EINA_FALSE;
1942 if ((!part) || (!strcmp(part, "start")))
1944 icon_p = &(item->icon);
1945 dummy = item->dummy_icon;
1946 if (!content) item->dummy_icon = EINA_TRUE;
1947 else item->dummy_icon = EINA_FALSE;
1949 else if (!strcmp(part, "end"))
1951 icon_p = &(item->end);
1952 dummy = item->dummy_end;
1953 if (!content) item->dummy_end = EINA_TRUE;
1954 else item->dummy_end = EINA_FALSE;
1959 if (content == *icon_p) return;
1960 if ((dummy) && (!content)) return;
1961 if (dummy) evas_object_del(*icon_p);
1965 evas_object_rectangle_add(evas_object_evas_get(WIDGET(item)));
1966 evas_object_color_set(content, 0, 0, 0, 0);
1968 evas_object_del(*icon_p);
1973 if ((!part) || !strcmp(part, "start"))
1974 edje_object_part_swallow(VIEW(item), "elm.swallow.icon", content);
1976 edje_object_part_swallow(VIEW(item), "elm.swallow.end", content);
1980 EOLIAN static Evas_Object *
1981 _elm_list_item_elm_widget_item_part_content_get(Eo *eo_item EINA_UNUSED, Elm_List_Item_Data *item,
1984 if ((!part) || (!strcmp(part, "start")))
1986 if (item->dummy_icon) return NULL;
1989 else if (!strcmp(part, "end"))
1991 if (item->dummy_end) return NULL;
1998 EOLIAN static Evas_Object *
1999 _elm_list_item_elm_widget_item_part_content_unset(Eo *eo_it EINA_UNUSED, Elm_List_Item_Data *item,
2002 if ((!part) || (!strcmp(part, "start")))
2004 Evas_Object *obj = item->icon;
2005 eo_do(eo_it, elm_wdg_item_part_content_set(part, NULL));
2008 else if (!strcmp(part, "end"))
2010 Evas_Object *obj = item->end;
2011 eo_do(eo_it, elm_wdg_item_part_content_set(part, NULL));
2019 _elm_list_item_elm_widget_item_part_text_set(Eo *eo_list_it, Elm_List_Item_Data *list_it,
2023 if (part && strcmp(part, "default"))
2025 eo_do(eo_list_it, elm_wdg_item_part_text_custom_set(part, text));
2026 edje_object_part_text_escaped_set(VIEW(list_it), part, text);
2029 if (!eina_stringshare_replace(&list_it->label, text)) return;
2031 edje_object_part_text_escaped_set(VIEW(list_it), "elm.text", text);
2034 EOLIAN static const char *
2035 _elm_list_item_elm_widget_item_part_text_get(Eo *eo_it, Elm_List_Item_Data *it,
2039 if (part && strcmp(part, "default"))
2040 return eo_do_ret(eo_it, ret, elm_wdg_item_part_text_custom_get(part));
2044 /* FIXME: this _item_del_pre_hook is never been called at all!
2046 1. it->walking concept should be adopted.
2047 2. elm_widget_item_del() should be called instead of the combination of
2048 _elm_list_item_free() + elm_widget_item_free()
2050 EOLIAN static Eina_Bool
2051 _elm_list_item_elm_widget_item_del_pre(Eo *eo_item EINA_UNUSED, Elm_List_Item_Data *item)
2053 Evas_Object *obj = WIDGET(item);
2055 ELM_LIST_DATA_GET(obj, sd);
2059 _item_unhighlight(item);
2060 _item_unselect(item);
2063 if (sd->walking > 0)
2065 if (item->deleted) return EINA_FALSE;
2066 item->deleted = EINA_TRUE;
2067 sd->to_delete = eina_list_append(sd->to_delete, item);
2071 sd->items = eina_list_remove_list(sd->items, item->node);
2073 evas_object_ref(obj);
2076 _elm_list_item_free(item);
2078 _elm_list_unwalk(obj, sd);
2079 evas_object_unref(obj);
2084 EOLIAN static void _elm_list_item_elm_widget_item_signal_emit(Eo *eo_it EINA_UNUSED, Elm_List_Item_Data *it,
2085 const char *emission,
2088 edje_object_signal_emit(VIEW(it), emission, source);
2092 _elm_list_item_elm_widget_item_focus_set(Eo *eo_it, Elm_List_Item_Data *it, Eina_Bool focused)
2094 Evas_Object *obj = WIDGET(it);
2095 ELM_LIST_DATA_GET(obj, sd);
2099 sd->last_focused_item = eo_it;
2100 if (!elm_object_focus_get(obj))
2101 elm_object_focus_set(obj, EINA_TRUE);
2103 if (!elm_widget_focus_get(obj))
2106 if (eo_it != sd->focused_item)
2108 if (sd->focused_item)
2109 _elm_list_item_unfocused(sd->focused_item);
2110 _elm_list_item_focused(eo_it);
2115 if (!elm_widget_focus_get(obj))
2118 _elm_list_item_unfocused(eo_it);
2120 _elm_widget_focus_highlight_start(obj);
2123 EOLIAN static Eina_Bool
2124 _elm_list_item_elm_widget_item_focus_get(Eo *eo_it, Elm_List_Item_Data *it)
2126 ELM_LIST_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
2127 Evas_Object *obj = WIDGET(it);
2128 ELM_LIST_CHECK(obj) EINA_FALSE;
2129 ELM_LIST_DATA_GET(obj, sd);
2131 if (eo_it == sd->focused_item)
2136 EOLIAN static Elm_Atspi_State_Set
2137 _elm_list_item_elm_interface_atspi_accessible_state_set_get(Eo *eo_it, Elm_List_Item_Data *data EINA_UNUSED)
2139 Elm_Atspi_State_Set ret;
2142 eo_do_super(eo_it, ELM_LIST_ITEM_CLASS, ret = elm_interface_atspi_accessible_state_set_get());
2144 if (elm_object_item_disabled_get(eo_it))
2147 STATE_TYPE_SET(ret, ELM_ATSPI_STATE_SELECTABLE);
2149 eo_do(eo_it, sel = elm_obj_list_item_selected_get());
2151 STATE_TYPE_SET(ret, ELM_ATSPI_STATE_SELECTED);
2153 STATE_TYPE_UNSET(ret, ELM_ATSPI_STATE_SELECTED);
2159 _elm_list_item_elm_interface_atspi_accessible_name_get(Eo *eo_it EINA_UNUSED, Elm_List_Item_Data *data)
2161 return data->label ? strdup(data->label) : NULL;
2164 EOLIAN static Eina_List*
2165 _elm_list_item_elm_interface_atspi_accessible_children_get(Eo *eo_it EINA_UNUSED, Elm_List_Item_Data *data)
2167 Eina_List *ret = NULL;
2169 if (data->icon && eo_isa(data->icon, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN))
2170 ret = eina_list_append(ret, data->icon);
2171 if (data->end && eo_isa(data->end, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN))
2172 ret = eina_list_append(ret, data->end);
2177 EOLIAN static Eina_Bool
2178 _elm_list_item_elm_interface_atspi_component_highlight_clear(Eo *eo_it, Elm_List_Item_Data *it)
2180 elm_object_accessibility_highlight_set(VIEW(it), EINA_FALSE);
2186 _access_info_cb(void *data, Evas_Object *obj EINA_UNUSED)
2188 Elm_List_Item_Data *it = (Elm_List_Item_Data *)data;
2189 const char *txt = NULL;
2190 if (!it) return NULL;
2192 if (!txt) txt = it->label;
2193 if (txt) return strdup(txt);
2199 _access_state_cb(void *data, Evas_Object *obj EINA_UNUSED)
2201 Elm_List_Item_Data *it = (Elm_List_Item_Data *)data;
2202 if (!it) return NULL;
2204 if (it->base->disabled)
2205 return strdup(E_("State: Disabled"));
2211 _access_on_highlight_cb(void *data)
2213 Elm_Object_Item *it = data;
2216 elm_list_item_bring_in(it);
2220 _access_activate_cb(void *data EINA_UNUSED,
2221 Evas_Object *part_obj EINA_UNUSED,
2222 Elm_Object_Item *eo_it)
2226 ELM_LIST_ITEM_DATA_GET(eo_it, it);
2227 ELM_LIST_ITEM_CHECK_OR_RETURN(it);
2230 ELM_LIST_DATA_GET(obj, sd);
2232 evas_object_ref(obj);
2239 _item_highlight(it);
2244 _item_unhighlight(it);
2252 while (sd->selected)
2254 Elm_Object_Item *eo_sel = sd->selected->data;
2255 ELM_LIST_ITEM_DATA_GET(eo_sel, sel);
2256 _item_unhighlight(sel);
2257 _item_unselect(sel);
2259 _item_highlight(it);
2264 const Eina_List *l, *l_next;
2265 Elm_Object_Item *eo_it2;
2267 EINA_LIST_FOREACH_SAFE(sd->selected, l, l_next, eo_it2)
2268 if (eo_it2 != EO_OBJ(it))
2270 ELM_LIST_ITEM_DATA_GET(eo_it2, it2);
2271 _item_unhighlight(it2);
2272 _item_unselect(it2);
2274 _item_highlight(it);
2279 _elm_list_unwalk(obj, sd);
2280 evas_object_unref(obj);
2284 _access_widget_item_register(Elm_List_Item_Data *it, Eina_Bool is_access)
2286 Elm_Access_Info *ai;
2288 if (!is_access) _elm_access_widget_item_unregister(it->base);
2291 _elm_access_widget_item_register(it->base);
2293 ai = _elm_access_info_get(it->base->access_obj);
2295 _elm_access_callback_set(ai, ELM_ACCESS_INFO, _access_info_cb, it);
2296 _elm_access_callback_set(ai, ELM_ACCESS_STATE, _access_state_cb, it);
2297 _elm_access_on_highlight_hook_set(ai, _access_on_highlight_cb, EO_OBJ(it));
2298 _elm_access_activate_callback_set(ai, _access_activate_cb, EO_OBJ(it));
2303 _elm_list_item_eo_base_constructor(Eo *eo_it, Elm_List_Item_Data *it)
2305 eo_it = eo_do_super_ret(eo_it, ELM_LIST_ITEM_CLASS, eo_it, eo_constructor());
2306 it->base = eo_data_scope_get(eo_it, ELM_WIDGET_ITEM_CLASS);
2307 eo_do(eo_it, elm_interface_atspi_accessible_role_set(ELM_ATSPI_ROLE_LIST_ITEM));
2312 static Elm_List_Item_Data *
2313 _item_new(Evas_Object *obj,
2320 Eo *eo_it = eo_add(ELM_LIST_ITEM_CLASS, obj);
2321 if (!eo_it) return NULL;
2322 ELM_LIST_ITEM_DATA_GET(eo_it, it);
2324 it->label = eina_stringshare_add(label);
2328 WIDGET_ITEM_DATA_SET(EO_OBJ(it), data);
2330 VIEW(it) = edje_object_add(evas_object_evas_get(obj));
2332 if (_elm_config->atspi_mode)
2334 if (it->icon) eo_do(it->icon, elm_interface_atspi_accessible_parent_set(eo_it));
2335 if (it->end) eo_do(it->end, elm_interface_atspi_accessible_parent_set(eo_it));
2339 if (_elm_config->access_mode == ELM_ACCESS_MODE_ON)
2340 _access_widget_item_register(it, EINA_TRUE);
2342 edje_object_mirrored_set(VIEW(it), elm_widget_mirrored_get(obj));
2343 evas_object_event_callback_add
2344 (VIEW(it), EVAS_CALLBACK_MOUSE_DOWN, _mouse_down_cb, it);
2345 evas_object_event_callback_add
2346 (VIEW(it), EVAS_CALLBACK_MOUSE_UP, _mouse_up_cb, it);
2347 evas_object_event_callback_add
2348 (VIEW(it), EVAS_CALLBACK_MOUSE_MOVE, _mouse_move_cb, it);
2349 evas_object_event_callback_add
2350 (VIEW(it), EVAS_CALLBACK_MOUSE_IN, _mouse_in_cb, it);
2351 evas_object_size_hint_weight_set
2352 (VIEW(it), EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
2353 evas_object_size_hint_align_set(VIEW(it), EVAS_HINT_FILL, EVAS_HINT_FILL);
2354 edje_object_mirrored_set(VIEW(it), elm_widget_mirrored_get(obj));
2358 eo_do(it->icon, elm_interface_atspi_accessible_parent_set(eo_it));
2359 elm_widget_sub_object_add(obj, it->icon);
2360 evas_object_event_callback_add
2361 (it->icon, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _size_hints_changed_cb,
2366 eo_do(it->end, elm_interface_atspi_accessible_parent_set(eo_it));
2367 elm_widget_sub_object_add(obj, it->end);
2368 evas_object_event_callback_add
2369 (it->end, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _size_hints_changed_cb,
2373 if (_elm_config->atspi_mode)
2374 elm_interface_atspi_accessible_added(eo_it);
2380 _resize_cb(void *data,
2381 Evas *e EINA_UNUSED,
2382 Evas_Object *obj EINA_UNUSED,
2383 void *event_info EINA_UNUSED)
2385 elm_layout_sizing_eval(data);
2388 static Eina_Bool _elm_list_smart_focus_next_enable = EINA_FALSE;
2390 EOLIAN static Eina_Bool
2391 _elm_list_elm_widget_focus_next_manager_is(Eo *obj EINA_UNUSED, Elm_List_Data *sd EINA_UNUSED)
2393 return _elm_list_smart_focus_next_enable;
2396 EOLIAN static Eina_Bool
2397 _elm_list_elm_widget_focus_direction_manager_is(Eo *obj EINA_UNUSED, Elm_List_Data *sd EINA_UNUSED)
2402 EOLIAN static Eina_Bool
2403 _elm_list_elm_widget_focus_next(Eo *obj, Elm_List_Data *sd, Elm_Focus_Direction dir, Evas_Object **next, Elm_Object_Item **next_item)
2405 Eina_List *items = NULL;
2406 Eina_List *elist = NULL;
2407 Elm_Object_Item *eo_it;
2409 if (_elm_config->access_mode != ELM_ACCESS_MODE_ON) return EINA_FALSE;
2411 EINA_LIST_FOREACH(sd->items, elist, eo_it)
2413 ELM_LIST_ITEM_DATA_GET(eo_it, it);
2414 items = eina_list_append(items, it->base->access_obj);
2415 if (it->icon) items = eina_list_append(items, it->icon);
2416 if (it->end) items = eina_list_append(items, it->end);
2419 return elm_widget_focus_list_next_get
2420 (obj, items, eina_list_data_get, dir, next, next_item);
2424 _elm_list_evas_object_smart_add(Eo *obj, Elm_List_Data *priv)
2426 Evas_Coord minw, minh;
2428 ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
2430 eo_do_super(obj, MY_CLASS, evas_obj_smart_add());
2431 elm_widget_sub_object_parent_add(obj);
2433 elm_widget_can_focus_set(obj, EINA_TRUE);
2435 priv->mode = ELM_LIST_SCROLL;
2437 if (!elm_layout_theme_set(obj, "list", "base", elm_widget_style_get(obj)))
2438 CRI("Failed to set layout!");
2440 priv->hit_rect = evas_object_rectangle_add(evas_object_evas_get(obj));
2441 evas_object_data_set(priv->hit_rect, "_elm_leaveme", obj);
2442 evas_object_smart_member_add(priv->hit_rect, obj);
2443 elm_widget_sub_object_add(obj, priv->hit_rect);
2445 /* common scroller hit rectangle setup */
2446 evas_object_color_set(priv->hit_rect, 0, 0, 0, 0);
2447 evas_object_show(priv->hit_rect);
2448 evas_object_repeat_events_set(priv->hit_rect, EINA_TRUE);
2451 elm_interface_scrollable_edge_left_cb_set(_edge_left_cb),
2452 elm_interface_scrollable_edge_right_cb_set(_edge_right_cb),
2453 elm_interface_scrollable_edge_top_cb_set(_edge_top_cb),
2454 elm_interface_scrollable_edge_bottom_cb_set(_edge_bottom_cb),
2455 elm_interface_scrollable_content_min_limit_cb_set(_elm_list_content_min_limit_cb),
2456 elm_interface_scrollable_objects_set(wd->resize_obj, priv->hit_rect));
2458 /* the scrollable interface may set this */
2459 evas_object_event_callback_add
2460 (wd->resize_obj, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
2461 _size_hints_changed_cb, obj);
2463 edje_object_size_min_calc
2464 (wd->resize_obj, &minw, &minh);
2465 evas_object_size_hint_min_set(obj, minw, minh);
2466 evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE, _resize_cb, obj);
2468 eo_do(obj, elm_interface_scrollable_bounce_allow_set(EINA_FALSE, _elm_config->thumbscroll_bounce_enable));
2470 priv->box = elm_box_add(obj);
2471 evas_object_size_hint_weight_set(priv->box, EVAS_HINT_EXPAND, 0.0);
2472 evas_object_size_hint_align_set(priv->box, EVAS_HINT_FILL, 0.0);
2474 /* FIXME: change this ugly code path later */
2475 elm_widget_on_show_region_hook_set(priv->box, _show_region_hook, obj);
2476 elm_widget_sub_object_add(obj, priv->box);
2478 eo_do(obj, elm_interface_scrollable_content_set(priv->box));
2479 evas_object_event_callback_add
2480 (priv->box, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
2481 _size_hints_changed_cb, obj);
2483 edje_object_signal_callback_add(wd->resize_obj, "elm,looping,left,done", "elm", _elm_list_looping_left_cb, obj);
2484 edje_object_signal_callback_add(wd->resize_obj, "elm,looping,right,done", "elm", _elm_list_looping_right_cb, obj);
2485 edje_object_signal_callback_add(wd->resize_obj, "elm,looping,up,done", "elm", _elm_list_looping_up_cb, obj);
2486 edje_object_signal_callback_add(wd->resize_obj, "elm,looping,down,done", "elm", _elm_list_looping_down_cb, obj);
2490 _elm_list_evas_object_smart_del(Eo *obj, Elm_List_Data *sd)
2493 Elm_Object_Item *eo_it;
2496 ERR("ERROR: list deleted while walking.\n");
2498 sd->delete_me = EINA_TRUE;
2499 EINA_LIST_FOREACH(sd->items, l, eo_it)
2501 ELM_LIST_ITEM_DATA_GET(eo_it, it);
2503 evas_object_event_callback_del
2504 (it->icon, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
2505 _size_hints_changed_cb);
2507 evas_object_event_callback_del
2508 (it->end, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
2509 _size_hints_changed_cb);
2512 evas_object_event_callback_del
2513 (obj, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
2514 _size_hints_changed_cb);
2515 evas_object_event_callback_del
2516 (sd->box, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _size_hints_changed_cb);
2520 EINA_LIST_FREE(sd->items, eo_it)
2522 ELM_LIST_ITEM_DATA_GET(eo_it, it);
2523 /* issuing free because of "locking" item del pre hook */
2524 _elm_list_item_free(it);
2529 _elm_list_unwalk(obj, sd);
2532 ERR("ERROR: leaking nodes!\n");
2534 sd->selected = eina_list_free(sd->selected);
2536 eo_do_super(obj, MY_CLASS, evas_obj_smart_del());
2540 _elm_list_evas_object_smart_move(Eo *obj, Elm_List_Data *sd, Evas_Coord x, Evas_Coord y)
2542 eo_do_super(obj, MY_CLASS, evas_obj_smart_move(x, y));
2544 evas_object_move(sd->hit_rect, x, y);
2548 _elm_list_evas_object_smart_resize(Eo *obj, Elm_List_Data *sd, Evas_Coord w, Evas_Coord h)
2550 eo_do_super(obj, MY_CLASS, evas_obj_smart_resize(w, h));
2552 evas_object_resize(sd->hit_rect, w, h);
2556 _elm_list_evas_object_smart_member_add(Eo *obj, Elm_List_Data *sd, Evas_Object *member)
2558 eo_do_super(obj, MY_CLASS, evas_obj_smart_member_add(member));
2561 evas_object_raise(sd->hit_rect);
2565 _elm_list_elm_widget_access(Eo *obj EINA_UNUSED, Elm_List_Data *sd, Eina_Bool acs)
2567 Eina_List *elist = NULL;
2568 Elm_Object_Item *eo_it;
2569 _elm_list_smart_focus_next_enable = acs;
2571 EINA_LIST_FOREACH(sd->items, elist, eo_it)
2573 ELM_LIST_ITEM_DATA_GET(eo_it, it);
2574 _access_widget_item_register(it, _elm_list_smart_focus_next_enable);
2579 elm_list_add(Evas_Object *parent)
2581 EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
2582 Evas_Object *obj = eo_add(MY_CLASS, parent);
2587 _elm_list_eo_base_constructor(Eo *obj, Elm_List_Data *sd EINA_UNUSED)
2589 obj = eo_do_super_ret(obj, MY_CLASS, obj, eo_constructor());
2591 evas_obj_type_set(MY_CLASS_NAME_LEGACY),
2592 evas_obj_smart_callbacks_descriptions_set(_smart_callbacks),
2593 elm_interface_atspi_accessible_role_set(ELM_ATSPI_ROLE_LIST));
2599 _elm_list_go(Eo *obj, Elm_List_Data *sd EINA_UNUSED)
2605 _elm_list_multi_select_set(Eo *obj EINA_UNUSED, Elm_List_Data *sd, Eina_Bool multi)
2610 EOLIAN static Eina_Bool
2611 _elm_list_multi_select_get(Eo *obj EINA_UNUSED, Elm_List_Data *sd)
2617 _elm_list_multi_select_mode_set(Eo *obj EINA_UNUSED, Elm_List_Data *sd, Elm_Object_Multi_Select_Mode mode)
2619 if (mode >= ELM_OBJECT_MULTI_SELECT_MODE_MAX)
2622 if (sd->multi_select_mode != mode)
2623 sd->multi_select_mode = mode;
2626 EOLIAN static Elm_Object_Multi_Select_Mode
2627 _elm_list_multi_select_mode_get(Eo *obj EINA_UNUSED, Elm_List_Data *sd)
2629 return sd->multi_select_mode;
2633 _elm_list_mode_set(Eo *obj, Elm_List_Data *sd, Elm_List_Mode mode)
2635 Elm_Object_Item *eo_it;
2638 if (sd->mode == mode)
2643 _elm_list_mode_set_internal(obj);
2645 EINA_LIST_FOREACH(sd->items, n, eo_it)
2647 ELM_LIST_ITEM_DATA_GET(eo_it, it);
2648 it->fixed = EINA_FALSE;
2653 EOLIAN static Elm_List_Mode
2654 _elm_list_mode_get(Eo *obj EINA_UNUSED, Elm_List_Data *sd)
2660 _elm_list_horizontal_set(Eo *obj, Elm_List_Data *sd, Eina_Bool horizontal)
2662 Eina_Bool bounce = _elm_config->thumbscroll_bounce_enable;
2664 horizontal = !!horizontal;
2666 if (sd->h_mode == horizontal)
2669 sd->h_mode = horizontal;
2670 elm_box_horizontal_set(sd->box, horizontal);
2674 evas_object_size_hint_weight_set(sd->box, 0.0, EVAS_HINT_EXPAND);
2675 evas_object_size_hint_align_set(sd->box, 0.0, EVAS_HINT_FILL);
2676 eo_do(obj, elm_interface_scrollable_bounce_allow_set(bounce, EINA_FALSE));
2680 evas_object_size_hint_weight_set(sd->box, EVAS_HINT_EXPAND, 0.0);
2681 evas_object_size_hint_align_set(sd->box, EVAS_HINT_FILL, 0.0);
2682 eo_do(obj, elm_interface_scrollable_bounce_allow_set(EINA_FALSE, bounce));
2685 _elm_list_mode_set_internal(obj);
2688 EOLIAN static Eina_Bool
2689 _elm_list_horizontal_get(Eo *obj EINA_UNUSED, Elm_List_Data *sd)
2695 _elm_list_select_mode_set(Eo *obj EINA_UNUSED, Elm_List_Data *sd, Elm_Object_Select_Mode mode)
2697 if (mode >= ELM_OBJECT_SELECT_MODE_MAX)
2700 if (sd->select_mode != mode)
2701 sd->select_mode = mode;
2704 EOLIAN static Elm_Object_Select_Mode
2705 _elm_list_select_mode_get(Eo *obj EINA_UNUSED, Elm_List_Data *sd)
2707 return sd->select_mode;
2711 elm_list_bounce_set(Evas_Object *obj,
2715 ELM_LIST_CHECK(obj);
2717 eo_do(obj, elm_interface_scrollable_bounce_allow_set(h_bounce, v_bounce));
2721 elm_list_bounce_get(const Evas_Object *obj,
2722 Eina_Bool *h_bounce,
2723 Eina_Bool *v_bounce)
2725 ELM_LIST_CHECK(obj);
2727 eo_do((Eo *) obj, elm_interface_scrollable_bounce_allow_get(h_bounce, v_bounce));
2731 elm_list_scroller_policy_set(Evas_Object *obj,
2732 Elm_Scroller_Policy policy_h,
2733 Elm_Scroller_Policy policy_v)
2735 ELM_LIST_CHECK(obj);
2736 eo_do(obj, elm_interface_scrollable_policy_set(policy_h, policy_v));
2740 _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)
2742 if ((policy_h >= ELM_SCROLLER_POLICY_LAST) ||
2743 (policy_v >= ELM_SCROLLER_POLICY_LAST))
2746 eo_do_super(obj, MY_CLASS, elm_interface_scrollable_policy_set(policy_h, policy_v));
2750 elm_list_scroller_policy_get(const Evas_Object *obj,
2751 Elm_Scroller_Policy *policy_h,
2752 Elm_Scroller_Policy *policy_v)
2754 ELM_LIST_CHECK(obj);
2755 eo_do((Eo *) obj, elm_interface_scrollable_policy_get(policy_h, policy_v));
2759 _elm_list_clear(Eo *obj, Elm_List_Data *sd)
2761 Elm_Object_Item *eo_it;
2763 if (!sd->items) return;
2765 sd->selected = eina_list_free(sd->selected);
2767 if (sd->walking > 0)
2771 EINA_LIST_FOREACH(sd->items, n, eo_it)
2773 ELM_LIST_ITEM_DATA_GET(eo_it, it);
2774 if (it->deleted) continue;
2775 it->deleted = EINA_TRUE;
2776 sd->to_delete = eina_list_append(sd->to_delete, it);
2781 evas_object_ref(obj);
2785 EINA_LIST_FREE(sd->items, eo_it)
2787 ELM_LIST_ITEM_DATA_GET(eo_it, it);
2788 /* issuing free because of "locking" item del pre hook */
2789 _elm_list_item_free(it);
2793 _elm_list_unwalk(obj, sd);
2796 elm_layout_sizing_eval(obj);
2798 evas_object_unref(obj);
2801 EOLIAN static const Eina_List*
2802 _elm_list_items_get(Eo *obj EINA_UNUSED, Elm_List_Data *sd)
2807 EOLIAN static Elm_Object_Item*
2808 _elm_list_selected_item_get(Eo *obj EINA_UNUSED, Elm_List_Data *sd)
2810 if (sd->selected) return sd->selected->data;
2814 EOLIAN static const Eina_List*
2815 _elm_list_selected_items_get(Eo *obj EINA_UNUSED, Elm_List_Data *sd)
2817 return sd->selected;
2820 EOLIAN static Elm_Object_Item*
2821 _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)
2823 Elm_List_Item_Data *it;
2825 it = _item_new(obj, label, icon, end, func, data);
2827 sd->items = eina_list_append(sd->items, EO_OBJ(it));
2828 it->node = eina_list_last(sd->items);
2829 elm_box_pack_end(sd->box, VIEW(it));
2831 if (_elm_config->atspi_mode)
2832 elm_interface_atspi_accessible_children_changed_added_signal_emit(obj, EO_OBJ(it));
2837 EOLIAN static Elm_Object_Item*
2838 _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)
2840 Elm_List_Item_Data *it;
2842 it = _item_new(obj, label, icon, end, func, data);
2844 sd->items = eina_list_prepend(sd->items, EO_OBJ(it));
2845 it->node = sd->items;
2846 elm_box_pack_start(sd->box, VIEW(it));
2848 if (_elm_config->atspi_mode)
2849 elm_interface_atspi_accessible_children_changed_added_signal_emit(obj, EO_OBJ(it));
2854 EOLIAN static Elm_Object_Item*
2855 _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)
2857 Elm_List_Item_Data *it;
2858 EINA_SAFETY_ON_NULL_RETURN_VAL(eo_before, NULL);
2859 ELM_LIST_ITEM_DATA_GET(eo_before, before_it);
2861 ELM_LIST_ITEM_CHECK_OR_RETURN(before_it, NULL);
2863 if (!before_it->node) return NULL;
2865 it = _item_new(obj, label, icon, end, func, data);
2866 sd->items = eina_list_prepend_relative_list(sd->items, EO_OBJ(it), before_it->node);
2867 it->node = before_it->node->prev;
2868 elm_box_pack_before(sd->box, VIEW(it), VIEW(before_it));
2870 if (_elm_config->atspi_mode)
2871 elm_interface_atspi_accessible_children_changed_added_signal_emit(obj, EO_OBJ(it));
2876 EOLIAN static Elm_Object_Item*
2877 _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)
2879 Elm_List_Item_Data *it;
2880 EINA_SAFETY_ON_NULL_RETURN_VAL(eo_after, NULL);
2881 ELM_LIST_ITEM_DATA_GET(eo_after, after_it);
2883 ELM_LIST_ITEM_CHECK_OR_RETURN(after_it, NULL);
2885 if (!after_it->node) return NULL;
2887 it = _item_new(obj, label, icon, end, func, data);
2888 sd->items = eina_list_append_relative_list(sd->items, EO_OBJ(it), after_it->node);
2889 it->node = after_it->node->next;
2890 elm_box_pack_after(sd->box, VIEW(it), VIEW(after_it));
2892 if (_elm_config->atspi_mode)
2893 elm_interface_atspi_accessible_children_changed_added_signal_emit(obj, EO_OBJ(it));
2898 EOLIAN static Elm_Object_Item*
2899 _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)
2902 Elm_List_Item_Data *it;
2904 it = _item_new(obj, label, icon, end, func, data);
2906 sd->items = eina_list_sorted_insert(sd->items, cmp_func, EO_OBJ(it));
2907 l = eina_list_data_find_list(sd->items, EO_OBJ(it));
2908 l = eina_list_next(l);
2911 it->node = eina_list_last(sd->items);
2912 elm_box_pack_end(sd->box, VIEW(it));
2916 Elm_Object_Item *eo_before = eina_list_data_get(l);
2917 ELM_LIST_ITEM_DATA_GET(eo_before, before);
2919 it->node = before->node->prev;
2920 elm_box_pack_before(sd->box, VIEW(it), VIEW(before));
2923 if (_elm_config->atspi_mode)
2924 elm_interface_atspi_accessible_children_changed_added_signal_emit(obj, EO_OBJ(it));
2930 _elm_list_item_separator_set(Eo *eo_item, Elm_List_Item_Data *it, Eina_Bool setting)
2932 ELM_LIST_ITEM_CHECK_OR_RETURN(it);
2934 it->is_separator = !!setting;
2936 if (it->is_separator)
2937 eo_do(eo_item, elm_interface_atspi_accessible_role_set(ELM_ATSPI_ROLE_SEPARATOR));
2939 eo_do(eo_item, elm_interface_atspi_accessible_role_set(ELM_ATSPI_ROLE_LIST_ITEM));
2942 EOLIAN static Eina_Bool
2943 _elm_list_item_separator_get(Eo *eo_item EINA_UNUSED, Elm_List_Item_Data *it)
2945 ELM_LIST_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
2947 return it->is_separator;
2951 _elm_list_item_selected_set(Eo *eo_item EINA_UNUSED, Elm_List_Item_Data *item,
2956 ELM_LIST_ITEM_CHECK_OR_RETURN(item);
2958 ELM_LIST_DATA_GET(obj, sd);
2960 selected = !!selected;
2961 if (item->selected == selected) return;
2963 evas_object_ref(obj);
2970 while (sd->selected)
2972 Elm_Object_Item *eo_sel = sd->selected->data;
2973 ELM_LIST_ITEM_DATA_GET(eo_sel, sel);
2974 _item_unhighlight(sel);
2975 _item_unselect(sel);
2978 _item_highlight(item);
2979 elm_object_item_focus_set(EO_OBJ(item), EINA_TRUE);
2984 _item_unhighlight(item);
2985 _item_unselect(item);
2988 _elm_list_unwalk(obj, sd);
2989 evas_object_unref(obj);
2992 EOLIAN static Eina_Bool
2993 _elm_list_item_selected_get(Eo *eo_item EINA_UNUSED, Elm_List_Item_Data *it)
2995 ELM_LIST_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
2997 return it->selected;
3001 _elm_list_item_show(Eo *eo_it EINA_UNUSED, Elm_List_Item_Data *it)
3003 Evas_Coord bx, by, bw, bh;
3004 Evas_Coord x, y, w, h;
3006 ELM_LIST_ITEM_CHECK_OR_RETURN(it);
3007 ELM_LIST_DATA_GET_FROM_ITEM(it, sd);
3009 evas_smart_objects_calculate(evas_object_evas_get(sd->box));
3010 evas_object_geometry_get(sd->box, &bx, &by, &bw, &bh);
3011 evas_object_geometry_get(VIEW(it), &x, &y, &w, &h);
3015 eo_do(WIDGET(it), elm_interface_scrollable_content_region_show(x, y, w, h));
3019 _elm_list_item_bring_in(Eo *eo_it EINA_UNUSED, Elm_List_Item_Data *it)
3021 Evas_Coord bx, by, bw, bh;
3022 Evas_Coord x, y, w, h;
3024 ELM_LIST_ITEM_CHECK_OR_RETURN(it);
3025 ELM_LIST_DATA_GET_FROM_ITEM(it, sd);
3027 evas_smart_objects_calculate(evas_object_evas_get(sd->box));
3028 evas_object_geometry_get(sd->box, &bx, &by, &bw, &bh);
3029 evas_object_geometry_get(VIEW(it), &x, &y, &w, &h);
3033 eo_do(WIDGET(it), elm_interface_scrollable_region_bring_in(x, y, w, h));
3036 EOLIAN static Evas_Object *
3037 _elm_list_item_object_get(Eo *eo_it EINA_UNUSED, Elm_List_Item_Data *it)
3039 ELM_LIST_ITEM_CHECK_OR_RETURN(it, NULL);
3044 EOLIAN static Elm_Object_Item *
3045 _elm_list_item_prev_get(Eo *eo_item EINA_UNUSED, Elm_List_Item_Data *item)
3047 if (item->node->prev)
3048 return item->node->prev->data;
3052 EOLIAN static Elm_Object_Item *
3053 _elm_list_item_next_get(Eo *eo_item EINA_UNUSED, Elm_List_Item_Data *item)
3055 if (item->node->next)
3056 return item->node->next->data;
3060 EOLIAN static Elm_Object_Item*
3061 _elm_list_first_item_get(Eo *obj EINA_UNUSED, Elm_List_Data *sd)
3063 if (!sd->items) return NULL;
3065 return eina_list_data_get(sd->items);
3069 EOLIAN static Elm_Object_Item*
3070 _elm_list_last_item_get(Eo *obj EINA_UNUSED, Elm_List_Data *sd)
3072 if (!sd->items) return NULL;
3074 return eina_list_data_get(eina_list_last(sd->items));
3078 EOLIAN static Elm_Object_Item*
3079 _elm_list_at_xy_item_get(const Eo *obj EINA_UNUSED, Elm_List_Data *sd, Evas_Coord x, Evas_Coord y, int *posret)
3082 Elm_Object_Item *eo_it;
3084 evas_object_geometry_get(sd->hit_rect, &lasty, NULL, NULL, NULL);
3086 EINA_LIST_FOREACH(sd->items, l, eo_it)
3088 ELM_LIST_ITEM_DATA_GET(eo_it, it);
3089 Evas_Coord itx, ity;
3090 Evas_Object *vit = VIEW(it);
3091 Evas_Coord vx, vy, vw, vh;
3092 evas_object_geometry_get(vit, &vx, &vy, &vw, &vh);
3096 if (ELM_RECTS_INTERSECT
3097 (itx, ity, vw, vh, x, y, 1, 1))
3101 if (y <= (ity + (vh / 4))) *posret = -1;
3102 else if (y >= (ity + vh - (vh / 4)))
3115 if (y > lasty) *posret = 1;
3123 _elm_list_focus_on_selection_set(Eo *obj EINA_UNUSED, Elm_List_Data *sd, Eina_Bool enabled)
3125 sd->focus_on_selection_enabled = !!enabled;
3128 EOLIAN static Eina_Bool
3129 _elm_list_focus_on_selection_get(Eo *obj EINA_UNUSED, Elm_List_Data *sd)
3131 return sd->focus_on_selection_enabled;
3135 _elm_list_item_coordinates_adjust(Elm_List_Item_Data *it,
3141 ELM_LIST_DATA_GET_FROM_ITEM(it, sd);
3143 Evas_Coord ix, iy, iw, ih, vx, vy, vw, vh;
3145 evas_object_geometry_get(sd->hit_rect, &vx, &vy, &vw, &vh);
3146 evas_object_geometry_get(VIEW(it), &ix, &iy, &iw, &ih);
3153 if (ELM_RECTS_X_AXIS_OUT(ix, iy, iw, ih, vx, vy, vw, vh))
3160 if (ELM_RECTS_Y_AXIS_OUT(ix, iy, iw, ih, vx, vy, vw, vh))
3168 _elm_list_elm_widget_focus_highlight_geometry_get(const Eo *obj EINA_UNUSED, Elm_List_Data *sd, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h)
3170 if (sd->focused_item)
3172 ELM_LIST_ITEM_DATA_GET(sd->focused_item, focus_it);
3173 _elm_list_item_coordinates_adjust(focus_it, x, y, w, h);
3174 elm_widget_focus_highlight_focus_part_geometry_get(VIEW(focus_it), x, y, w, h);
3178 EOLIAN static Elm_Object_Item*
3179 _elm_list_elm_widget_focused_item_get(Eo *obj EINA_UNUSED, Elm_List_Data *sd)
3181 return sd->focused_item;
3185 _elm_list_elm_widget_item_loop_enabled_set(Eo *obj EINA_UNUSED, Elm_List_Data *sd, Eina_Bool enable)
3187 sd->item_loop_enable = !!enable;
3190 EOLIAN static Eina_Bool
3191 _elm_list_elm_widget_item_loop_enabled_get(Eo *obj EINA_UNUSED, Elm_List_Data *sd)
3193 return sd->item_loop_enable;
3197 _elm_list_class_constructor(Eo_Class *klass)
3199 if (_elm_config->access_mode)
3200 _elm_list_smart_focus_next_enable = EINA_TRUE;
3202 evas_smart_legacy_type_register(MY_CLASS_NAME_LEGACY, klass);
3205 EOLIAN const Elm_Atspi_Action *
3206 _elm_list_elm_interface_atspi_widget_action_elm_actions_get(Eo *obj EINA_UNUSED, Elm_List_Data *pd EINA_UNUSED)
3208 static Elm_Atspi_Action atspi_actions[] = {
3209 { "move,prior", "move", "prior", _key_action_move},
3210 { "move,next", "move", "next", _key_action_move},
3211 { "move,left", "move", "left", _key_action_move},
3212 { "move,left,multi", "move", "left_multi", _key_action_move},
3213 { "move,right", "move", "right", _key_action_move},
3214 { "move,right,multi", "move", "right_multi", _key_action_move},
3215 { "move,up", "move", "up", _key_action_move},
3216 { "move,up,multi", "move", "up_multi", _key_action_move},
3217 { "move,down", "move", "down", _key_action_move},
3218 { "move,down,multi", "move", "down_multi", _key_action_move},
3219 { "move,first", "move", "first", _key_action_move},
3220 { "move,last", "move", "last", _key_action_move},
3221 { "select", "select", NULL, _key_action_select},
3222 { "escape", "escape", NULL, _key_action_escape},
3223 { NULL, NULL, NULL, NULL }
3225 return &atspi_actions[0];
3229 _elm_list_elm_interface_atspi_accessible_children_get(Eo *eo_item EINA_UNUSED, Elm_List_Data *pd)
3231 return eina_list_clone(pd->items);
3235 _elm_list_elm_interface_atspi_selection_selected_children_count_get(Eo *objm EINA_UNUSED, Elm_List_Data *pd)
3237 return eina_list_count(pd->selected);
3241 _elm_list_elm_interface_atspi_selection_selected_child_get(Eo *obj EINA_UNUSED, Elm_List_Data *pd, int child_idx)
3243 return eina_list_nth(pd->selected, child_idx);
3247 _elm_list_elm_interface_atspi_selection_child_select(Eo *obj EINA_UNUSED, Elm_List_Data *pd, int child_index)
3249 if (pd->select_mode != ELM_OBJECT_SELECT_MODE_NONE)
3251 Eo *item = eina_list_nth(pd->items, child_index);
3253 elm_list_item_selected_set(item, EINA_TRUE);
3260 _elm_list_elm_interface_atspi_selection_selected_child_deselect(Eo *obj EINA_UNUSED, Elm_List_Data *pd, int child_index)
3262 Eo *item = eina_list_nth(pd->selected, child_index);
3265 elm_list_item_selected_set(item, EINA_FALSE);
3272 _elm_list_elm_interface_atspi_selection_is_child_selected(Eo *obj EINA_UNUSED, Elm_List_Data *pd, int child_index)
3274 Eo *item = eina_list_nth(pd->items, child_index);
3276 return elm_list_item_selected_get(item);
3282 _elm_list_elm_interface_atspi_selection_all_children_select(Eo *obj EINA_UNUSED, Elm_List_Data *pd)
3287 if (pd->select_mode == ELM_OBJECT_SELECT_MODE_NONE)
3290 EINA_LIST_FOREACH(pd->items, l, it)
3291 elm_list_item_selected_set(it, EINA_TRUE);
3297 _elm_list_elm_interface_atspi_selection_clear(Eo *obj EINA_UNUSED, Elm_List_Data *pd)
3302 if (pd->select_mode == ELM_OBJECT_SELECT_MODE_NONE)
3305 EINA_LIST_FOREACH(pd->items, l, it)
3306 elm_list_item_selected_set(it, EINA_FALSE);
3312 _elm_list_elm_interface_atspi_selection_child_deselect(Eo *obj EINA_UNUSED, Elm_List_Data *pd, int child_index)
3314 Eo *item = eina_list_nth(pd->items, child_index);
3317 elm_list_item_selected_set(item, EINA_FALSE);
3323 //TIZEN_ONLY(20160329): list: enhance accessibility scroll and highlight (02c20ee39a0ebbe67b9e1491ccfc46dd681821c9)
3324 static int _is_item_in_viewport(int viewport_y, int viewport_h, int obj_y, int obj_h)
3326 if ((obj_y + obj_h/2) < viewport_y)
3328 else if ((obj_y + obj_h/2) > viewport_y + viewport_h)
3333 static Eina_Bool _atspi_enabled()
3336 Eina_Bool ret = EINA_FALSE;
3337 if (_elm_config->atspi_mode && (bridge = _elm_atspi_bridge_get()))
3338 eo_do(bridge, ret = elm_obj_atspi_bridge_connected_get());
3343 _elm_list_elm_interface_scrollable_content_pos_set(Eo *obj EINA_UNUSED, Elm_List_Data *pd, Evas_Coord x, Evas_Coord y, Eina_Bool sig)
3345 if (!_atspi_enabled())
3347 eo_do_super(obj, MY_CLASS, elm_interface_scrollable_content_pos_set(x,y,sig));
3351 int old_x, old_y, delta_y;
3352 eo_do_super(obj, MY_CLASS, elm_interface_scrollable_content_pos_get(&old_x,&old_y));
3353 eo_do_super(obj, MY_CLASS, elm_interface_scrollable_content_pos_set(x,y,sig));
3354 delta_y = old_y - y;
3356 //check if highlighted item is list descendant
3357 Evas_Object *win = elm_widget_top_get(obj);
3358 Evas_Object * highlighted_obj = _elm_win_accessibility_highlight_get(win);
3359 Evas_Object * parent = highlighted_obj;
3360 if (eo_isa(highlighted_obj, ELM_WIDGET_CLASS))
3362 while ((parent = elm_widget_parent_get(parent)))
3366 else if (eo_isa(highlighted_obj, EDJE_OBJECT_CLASS))
3368 while ((parent = evas_object_smart_parent_get(parent)))
3375 int obj_x, obj_y, w, h, hx, hy, hw, hh;
3376 evas_object_geometry_get(obj, &obj_x, &obj_y, &w, &h);
3378 evas_object_geometry_get(highlighted_obj, &hx, &hy, &hw, &hh);
3380 Elm_List_Item_Data *next_previous_item = NULL;
3381 int viewport_position_result = _is_item_in_viewport(obj_y, h, hy, hh);
3382 //only highlight if move direction is correct
3383 //sometimes highlighted item is brought in and it does not fit viewport
3384 //however content goes to the viewport position so soon it will
3385 //meet _is_item_in_viewport condition
3387 if ((viewport_position_result < 0 && delta_y > 0) ||
3388 (viewport_position_result > 0 && delta_y < 0))
3392 Eina_Bool traverse_direction = viewport_position_result > 0;
3393 l = traverse_direction ? pd->items: eina_list_last(pd->items);
3397 item = eina_list_data_get(l);
3398 ELM_LIST_ITEM_DATA_GET(item, it_data);
3399 next_previous_item = it_data;
3400 evas_object_geometry_get(VIEW(next_previous_item), &hx, &hy, &hw, &hh);
3402 if (_is_item_in_viewport(obj_y, h, hy, hh) == 0)
3405 next_previous_item = NULL;
3407 l = traverse_direction ? eina_list_next(l): eina_list_prev(l);
3410 if (next_previous_item)
3411 eo_do(EO_OBJ(next_previous_item), elm_interface_atspi_component_highlight_grab());
3415 EOLIAN static Eina_Bool
3416 _elm_list_item_elm_interface_atspi_component_highlight_grab(Eo *eo_it, Elm_List_Item_Data *it)
3418 Evas_Coord wy, wh, x, y, w, h, bx, by, bw, bh;
3419 ELM_LIST_DATA_GET_OR_RETURN_VAL(WIDGET(it), sd, EINA_FALSE);
3422 evas_object_geometry_get(WIDGET(it), NULL, &wy, NULL, &wh);
3423 evas_object_geometry_get(VIEW(it), &x, &y, &w, &h);
3424 int res = _is_item_in_viewport(wy, wh, y, h);
3428 evas_object_geometry_get(sd->box, &bx, &by, &bw, &bh);
3429 evas_smart_objects_calculate(evas_object_evas_get(sd->box));
3435 eo_do(WIDGET(it), elm_interface_scrollable_content_region_show(x, y, w, h));
3440 eo_do(WIDGET(it), elm_interface_scrollable_content_region_show(x, y, w, h));
3444 elm_list_item_show(eo_it);
3446 eo_do_super(eo_it, ELM_LIST_ITEM_CLASS, ret = elm_interface_atspi_component_highlight_grab());
3451 #include "elm_list.eo.c"
3452 #include "elm_list_item.eo.c"