1 #ifdef HAVE_CONFIG_H
2 # include "elementary_config.h"
3 #endif
4
5 #include <fnmatch.h>
6
7 #define EFL_ACCESS_OBJECT_PROTECTED
8 #define EFL_ACCESS_SELECTION_PROTECTED
9 #define EFL_ACCESS_WIDGET_ACTION_PROTECTED
10 #define ELM_WIDGET_ITEM_PROTECTED
11 #define EFL_UI_FOCUS_COMPOSITION_PROTECTED
12
13 #include <Elementary.h>
14 #include <Elementary_Cursor.h>
15
16 #include "elm_priv.h"
17 #include "elm_widget_genlist.h"
18 #include "elm_interface_scrollable.h"
19 #include "elm_pan_eo.h"
20 #include "efl_ui_focus_parent_provider_gen_eo.h"
21 #include "efl_ui_focus_composition_adapter.eo.h"
22 #include "elm_genlist_item_eo.h"
23 #include "elm_genlist_pan_eo.h"
24 #include "elm_genlist_eo.h"
25
26 #define MY_PAN_CLASS ELM_GENLIST_PAN_CLASS
27
28 #define MY_PAN_CLASS_NAME "Elm_Genlist_Pan"
29 #define MY_PAN_CLASS_NAME_LEGACY "elm_genlist_pan"
30
31 #define MY_CLASS ELM_GENLIST_CLASS
32
33 #define MY_CLASS_NAME "Elm_Genlist"
34 #define MY_CLASS_NAME_LEGACY "elm_genlist"
35
36 // internally allocated
37 #define CLASS_ALLOCATED 0x3a70f11f
38
39 #define MAX_ITEMS_PER_BLOCK 32
40 #define REORDER_EFFECT_TIME 0.5
41 #define MULTI_DOWN_TIME 1.0
42 #define SWIPE_TIME 0.4
43 #define SCR_HOLD_TIME 0.1
44 #define ITEM_QUEUE_MAX 128
45
46 #define ERR_ABORT(_msg) \
47 do { \
48 ERR(_msg); \
49 if (getenv("ELM_ERROR_ABORT")) abort(); \
50 } while (0)
51
52 #define ELM_PRIV_GENLIST_SIGNALS(cmd) \
53 cmd(SIG_ACTIVATED, "activated", "") \
54 cmd(SIG_CLICKED_DOUBLE, "clicked,double", "") \
55 cmd(SIG_CLICKED_RIGHT, "clicked,right", "") \
56 cmd(SIG_SELECTED, "selected", "") \
57 cmd(SIG_UNSELECTED, "unselected", "") \
58 cmd(SIG_EXPANDED, "expanded", "") \
59 cmd(SIG_CONTRACTED, "contracted", "") \
60 cmd(SIG_EXPAND_REQUEST, "expand,request", "") \
61 cmd(SIG_CONTRACT_REQUEST, "contract,request", "") \
62 cmd(SIG_REALIZED, "realized", "") \
63 cmd(SIG_UNREALIZED, "unrealized", "") \
64 cmd(SIG_DRAG_START_UP, "drag,start,up", "") \
65 cmd(SIG_DRAG_START_DOWN, "drag,start,down", "") \
66 cmd(SIG_DRAG_START_LEFT, "drag,start,left", "") \
67 cmd(SIG_DRAG_START_RIGHT, "drag,start,right", "") \
68 cmd(SIG_DRAG_STOP, "drag,stop", "") \
69 cmd(SIG_DRAG, "drag", "") \
70 cmd(SIG_LONGPRESSED, "longpressed", "") \
71 cmd(SIG_SCROLL, "scroll", "") \
72 cmd(SIG_SCROLL_ANIM_START, "scroll,anim,start", "") \
73 cmd(SIG_SCROLL_ANIM_STOP, "scroll,anim,stop", "") \
74 cmd(SIG_SCROLL_DRAG_START, "scroll,drag,start", "") \
75 cmd(SIG_SCROLL_DRAG_STOP, "scroll,drag,stop", "") \
76 cmd(SIG_EDGE_TOP, "edge,top", "") \
77 cmd(SIG_EDGE_BOTTOM, "edge,bottom", "") \
78 cmd(SIG_EDGE_LEFT, "edge,left", "") \
79 cmd(SIG_EDGE_RIGHT, "edge,right", "") \
80 cmd(SIG_VBAR_DRAG, "vbar,drag", "") \
81 cmd(SIG_VBAR_PRESS, "vbar,press", "") \
82 cmd(SIG_VBAR_UNPRESS, "vbar,unpress", "") \
83 cmd(SIG_HBAR_DRAG, "hbar,drag", "") \
84 cmd(SIG_HBAR_PRESS, "hbar,press", "") \
85 cmd(SIG_HBAR_UNPRESS, "hbar,unpress", "") \
86 cmd(SIG_MULTI_SWIPE_LEFT, "multi,swipe,left", "") \
87 cmd(SIG_MULTI_SWIPE_RIGHT, "multi,swipe,right", "") \
88 cmd(SIG_MULTI_SWIPE_UP, "multi,swipe,up", "") \
89 cmd(SIG_MULTI_SWIPE_DOWN, "multi,swipe,down", "") \
90 cmd(SIG_MULTI_PINCH_OUT, "multi,pinch,out", "") \
91 cmd(SIG_MULTI_PINCH_IN, "multi,pinch,in", "") \
92 cmd(SIG_SWIPE, "swipe", "") \
93 cmd(SIG_MOVED, "moved", "") \
94 cmd(SIG_MOVED_AFTER, "moved,after", "") \
95 cmd(SIG_MOVED_BEFORE, "moved,before", "") \
96 cmd(SIG_INDEX_UPDATE, "index,update", "") \
97 cmd(SIG_TREE_EFFECT_FINISHED , "tree,effect,finished", "") \
98 cmd(SIG_HIGHLIGHTED, "highlighted", "") \
99 cmd(SIG_UNHIGHLIGHTED, "unhighlighted", "") \
100 cmd(SIG_ITEM_FOCUSED, "item,focused", "") \
101 cmd(SIG_ITEM_UNFOCUSED, "item,unfocused", "") \
102 cmd(SIG_PRESSED, "pressed", "") \
103 cmd(SIG_RELEASED, "released", "") \
104 cmd(SIG_FILTER_DONE, "filter,done", "")
105
106 ELM_PRIV_GENLIST_SIGNALS(ELM_PRIV_STATIC_VARIABLE_DECLARE);
107
108 static const Evas_Smart_Cb_Description _smart_callbacks[] = {
109 ELM_PRIV_GENLIST_SIGNALS(ELM_PRIV_SMART_CALLBACKS_DESC)
110 {SIG_WIDGET_LANG_CHANGED, ""}, /**< handled by elm_widget */
111 {SIG_WIDGET_ACCESS_CHANGED, ""}, /**< handled by elm_widget */
112 {SIG_LAYOUT_FOCUSED, ""}, /**< handled by elm_layout */
113 {SIG_LAYOUT_UNFOCUSED, ""}, /**< handled by elm_layout */
114
115 {NULL, NULL}
116 };
117 #undef ELM_PRIV_GENLIST_SIGNALS
118
119 /* edje signals internally used */
120 static const char SIGNAL_ENABLED[] = "elm,state,enabled";
121 static const char SIGNAL_DISABLED[] = "elm,state,disabled";
122 static const char SIGNAL_SELECTED[] = "elm,state,selected";
123 static const char SIGNAL_UNSELECTED[] = "elm,state,unselected";
124 static const char SIGNAL_EXPANDED[] = "elm,state,expanded";
125 static const char SIGNAL_CONTRACTED[] = "elm,state,contracted";
126 static const char SIGNAL_FLIP_ENABLED[] = "elm,state,flip,enabled";
127 static const char SIGNAL_FLIP_DISABLED[] = "elm,state,flip,disabled";
128 static const char SIGNAL_DECORATE_ENABLED[] = "elm,state,decorate,enabled";
129 static const char SIGNAL_DECORATE_DISABLED[] = "elm,state,decorate,disabled";
130 static const char SIGNAL_DECORATE_ENABLED_EFFECT[] = "elm,state,decorate,enabled,effect";
131 static const char SIGNAL_REORDER_ENABLED[] = "elm,state,reorder,enabled";
132 static const char SIGNAL_REORDER_DISABLED[] = "elm,state,reorder,disabled";
133 static const char SIGNAL_REORDER_MODE_SET[] = "elm,state,reorder,mode_set";
134 static const char SIGNAL_REORDER_MODE_UNSET[] = "elm,state,reorder,mode_unset";
135 static const char SIGNAL_CONTRACT_FLIP[] = "elm,state,contract_flip";
136 static const char SIGNAL_SHOW[] = "elm,state,show";
137 static const char SIGNAL_HIDE[] = "elm,state,hide";
138 static const char SIGNAL_FLIP_ITEM[] = "elm,action,flip_item";
139 static const char SIGNAL_ODD[] = "elm,state,odd";
140 static const char SIGNAL_EVEN[] = "elm,state,even";
141 static const char SIGNAL_FOCUSED[] = "elm,state,focused";
142 static const char SIGNAL_UNFOCUSED[] = "elm,state,unfocused";
143 static const char SIGNAL_LIST_SINGLE[] = "elm,state,list,single";
144 static const char SIGNAL_LIST_FIRST[] = "elm,state,list,first";
145 static const char SIGNAL_LIST_LAST[] = "elm,state,list,last";
146 static const char SIGNAL_LIST_MIDDLE[] = "elm,state,list,middle";
147 static const char SIGNAL_GROUP_SINGLE[] = "elm,state,group,single";
148 static const char SIGNAL_GROUP_FIRST[] = "elm,state,group,first";
149 static const char SIGNAL_GROUP_LAST[] = "elm,state,group,last";
150 static const char SIGNAL_GROUP_MIDDLE[] = "elm,state,group,middle";
151
152 static void _item_unrealize(Elm_Gen_Item *it);
153 static Eina_Bool _item_select(Elm_Gen_Item *it);
154 static void _item_unselect(Elm_Gen_Item *it);
155 static void _item_highlight(Elm_Gen_Item *it);
156 static Eina_Bool _key_action_move(Evas_Object *obj, const char *params);
157 static Eina_Bool _key_action_select(Evas_Object *obj, const char *params);
158 static Eina_Bool _key_action_escape(Evas_Object *obj, const char *params);
159 static void _calc_job(void *data);
160 static void _update_job(void *data);
161 static Eina_Bool _item_block_recalc(Item_Block *itb, int in, Eina_Bool qadd);
162 static void _item_mouse_callbacks_add(Elm_Gen_Item *it, Evas_Object *view);
163 static void _item_mouse_callbacks_del(Elm_Gen_Item *it, Evas_Object *view);
164 static void _access_activate_cb(void *data EINA_UNUSED,
165 Evas_Object *part_obj EINA_UNUSED,
166 Elm_Object_Item *item);
167 static void _decorate_item_set(Elm_Gen_Item *);
168 static void _internal_elm_genlist_clear(Evas_Object *obj);
169 static Eina_Bool _item_filtered_get(Elm_Gen_Item *it, Elm_Genlist_Data *sd);
170
171 static void _elm_genlist_tree_effect_stop(Elm_Genlist_Data *sd);
172 static Eina_Bool _elm_genlist_tree_effect_setup(Elm_Genlist_Data *sd);
173
174 static void _item_expanded_set_noevent(Elm_Gen_Item *it, Eina_Bool expanded);
175
176 static Eina_Bool _item_process(Elm_Genlist_Data *sd, Elm_Gen_Item *it);
177 static void _item_process_post(Elm_Genlist_Data *sd, Elm_Gen_Item *it);
178
179 static const Elm_Action key_actions[] = {
180 {"move", _key_action_move},
181 {"select", _key_action_select},
182 {"escape", _key_action_escape},
183 {NULL, NULL}
184 };
185
186 static void
_size_cache_free(void * data)187 _size_cache_free(void *data)
188 {
189 if(data) free(data);
190 }
191
192 static Eina_Bool
_is_no_select(Elm_Gen_Item * it)193 _is_no_select(Elm_Gen_Item *it)
194 {
195 ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
196
197 if ((sd->select_mode == ELM_OBJECT_SELECT_MODE_NONE) ||
198 (sd->select_mode == ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY) ||
199 (it->select_mode == ELM_OBJECT_SELECT_MODE_NONE) ||
200 (it->select_mode == ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY))
201 return EINA_TRUE;
202 return EINA_FALSE;
203 }
204
205 EOLIAN static void
_elm_genlist_pan_elm_pan_pos_set(Eo * obj,Elm_Genlist_Pan_Data * psd,Evas_Coord x,Evas_Coord y)206 _elm_genlist_pan_elm_pan_pos_set(Eo *obj, Elm_Genlist_Pan_Data *psd, Evas_Coord x, Evas_Coord y)
207 {
208 Item_Block *itb;
209
210 Elm_Genlist_Data *sd = psd->wsd;
211
212 if ((x == sd->pan_x) && (y == sd->pan_y)) return;
213 sd->pan_x = x;
214 sd->pan_y = y;
215
216 EINA_INLIST_FOREACH(sd->blocks, itb)
217 {
218 if ((itb->y + itb->h) > y)
219 {
220 Elm_Gen_Item *it;
221 Eina_List *l2;
222
223 EINA_LIST_FOREACH(itb->items, l2, it)
224 {
225 if ((itb->y + it->y) >= y)
226 {
227 sd->anchor_item = it;
228 sd->anchor_y = -(itb->y + it->y - y);
229 goto done;
230 }
231 }
232 }
233 }
234 done:
235 if (!sd->reorder_move_animator) evas_object_smart_changed(obj);
236 }
237
238 EOLIAN static void
_elm_genlist_pan_elm_pan_pos_get(const Eo * obj EINA_UNUSED,Elm_Genlist_Pan_Data * psd,Evas_Coord * x,Evas_Coord * y)239 _elm_genlist_pan_elm_pan_pos_get(const Eo *obj EINA_UNUSED, Elm_Genlist_Pan_Data *psd, Evas_Coord *x, Evas_Coord *y)
240 {
241 if (x) *x = psd->wsd->pan_x;
242 if (y) *y = psd->wsd->pan_y;
243 }
244
245 EOLIAN static void
_elm_genlist_pan_elm_pan_pos_max_get(const Eo * obj,Elm_Genlist_Pan_Data * psd,Evas_Coord * x,Evas_Coord * y)246 _elm_genlist_pan_elm_pan_pos_max_get(const Eo *obj, Elm_Genlist_Pan_Data *psd, Evas_Coord *x, Evas_Coord *y)
247 {
248 Evas_Coord ow, oh;
249
250 evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
251 ow = psd->wsd->minw - ow;
252 if (ow < 0) ow = 0;
253 oh = psd->wsd->minh - oh;
254 if (oh < 0) oh = 0;
255 if (x) *x = ow;
256 if (y) *y = oh;
257 }
258
259 EOLIAN static void
_elm_genlist_pan_elm_pan_pos_min_get(const Eo * obj EINA_UNUSED,Elm_Genlist_Pan_Data * _pd EINA_UNUSED,Evas_Coord * x,Evas_Coord * y)260 _elm_genlist_pan_elm_pan_pos_min_get(const Eo *obj EINA_UNUSED, Elm_Genlist_Pan_Data *_pd EINA_UNUSED, Evas_Coord *x, Evas_Coord *y)
261 {
262 if (x) *x = 0;
263 if (y) *y = 0;
264 }
265
266 EOLIAN static void
_elm_genlist_pan_elm_pan_content_size_get(const Eo * obj EINA_UNUSED,Elm_Genlist_Pan_Data * psd,Evas_Coord * w,Evas_Coord * h)267 _elm_genlist_pan_elm_pan_content_size_get(const Eo *obj EINA_UNUSED, Elm_Genlist_Pan_Data *psd, Evas_Coord *w, Evas_Coord *h)
268 {
269 if (w) *w = psd->wsd->minw;
270 if (h) *h = psd->wsd->minh;
271 }
272
273 EOLIAN static void
_elm_genlist_pan_efl_canvas_group_group_del(Eo * obj,Elm_Genlist_Pan_Data * psd)274 _elm_genlist_pan_efl_canvas_group_group_del(Eo *obj, Elm_Genlist_Pan_Data *psd)
275 {
276 ecore_job_del(psd->resize_job);
277
278 efl_canvas_group_del(efl_super(obj, MY_PAN_CLASS));
279 }
280
281 EOLIAN static void
_elm_genlist_pan_efl_gfx_entity_position_set(Eo * obj,Elm_Genlist_Pan_Data * psd,Eina_Position2D pos)282 _elm_genlist_pan_efl_gfx_entity_position_set(Eo *obj, Elm_Genlist_Pan_Data *psd, Eina_Position2D pos)
283 {
284 if (_evas_object_intercept_call(obj, EVAS_OBJECT_INTERCEPT_CB_MOVE, 0, pos.x, pos.y))
285 return;
286
287 efl_gfx_entity_position_set(efl_super(obj, MY_PAN_CLASS), pos);
288
289 psd->wsd->pan_changed = EINA_TRUE;
290 evas_object_smart_changed(obj);
291 }
292
293 static void
_elm_genlist_pan_smart_resize_job(void * data)294 _elm_genlist_pan_smart_resize_job(void *data)
295 {
296 ELM_GENLIST_PAN_DATA_GET(data, psd);
297
298 elm_layout_sizing_eval(psd->wobj);
299 psd->resize_job = NULL;
300 }
301
302 EOLIAN static void
_elm_genlist_pan_efl_gfx_entity_size_set(Eo * obj,Elm_Genlist_Pan_Data * psd,Eina_Size2D size)303 _elm_genlist_pan_efl_gfx_entity_size_set(Eo *obj, Elm_Genlist_Pan_Data *psd, Eina_Size2D size)
304 {
305 Elm_Genlist_Data *sd = psd->wsd;
306 Eina_Size2D old;
307
308 if (_evas_object_intercept_call(obj, EVAS_OBJECT_INTERCEPT_CB_RESIZE, 0, size.w, size.h))
309 return;
310
311 old = efl_gfx_entity_size_get(obj);
312 if ((old.w == size.w) && (old.h == size.h)) goto super; // should already be intercepted above
313 if ((sd->mode == ELM_LIST_COMPRESS) && (old.w != size.w))
314 {
315 /* fix me later */
316 ecore_job_del(psd->resize_job);
317 psd->resize_job =
318 ecore_job_add(_elm_genlist_pan_smart_resize_job, obj);
319 }
320 sd->pan_changed = EINA_TRUE;
321 evas_object_smart_changed(obj);
322 // if the width changed we may have to resize content if scrollbar went
323 // away or appeared to queue a job to deal with it. it should settle in
324 // the end to a steady-state
325 if (old.w != size.w)
326 efl_canvas_group_change(sd->obj);
327
328 super:
329 efl_gfx_entity_size_set(efl_super(obj, MY_PAN_CLASS), size);
330 }
331
332 static void
_item_text_realize(Elm_Gen_Item * it,Evas_Object * target,Eina_List ** source,const char * parts)333 _item_text_realize(Elm_Gen_Item *it,
334 Evas_Object *target,
335 Eina_List **source,
336 const char *parts)
337 {
338 const Eina_List *l;
339 const char *key;
340 char *s;
341 char buf[256];
342
343 if (!it->itc->func.text_get) return;
344
345 if (!(*source))
346 *source = elm_widget_stringlist_get
347 (edje_object_data_get(target, "texts"));
348 EINA_LIST_FOREACH(*source, l, key)
349 {
350 if (parts && fnmatch(parts, key, FNM_PERIOD)) continue;
351
352 s = it->itc->func.text_get
353 ((void *)WIDGET_ITEM_DATA_GET(EO_OBJ(it)), WIDGET(it), key);
354 if (s)
355 {
356 edje_object_part_text_escaped_set(target, key, s);
357 free(s);
358
359 snprintf(buf, sizeof(buf), "elm,state,%s,visible", key);
360 edje_object_signal_emit(target, buf, "elm");
361 }
362 else
363 {
364 edje_object_part_text_set(target, key, "");
365 }
366 if (_elm_config->atspi_mode)
367 efl_access_i18n_name_changed_signal_emit(EO_OBJ(it));
368 }
369 }
370
371 static void
_widget_calculate_recursive(Eo * obj)372 _widget_calculate_recursive(Eo *obj)
373 {
374 Elm_Widget_Smart_Data *pd = NULL;
375 Evas_Object *child;
376
377 if (!efl_isa(obj, EFL_UI_WIDGET_CLASS)) return;
378
379 pd = efl_data_scope_get(obj, EFL_UI_WIDGET_CLASS);
380 if (!pd || !pd->resize_obj)
381 return;
382
383 if (!efl_canvas_group_need_recalculate_get(obj))
384 {
385 if (!efl_isa(pd->resize_obj, EFL_CANVAS_GROUP_CLASS) ||
386 !efl_canvas_group_need_recalculate_get(pd->resize_obj))
387 return;
388 }
389
390 for (unsigned int i = 0; i < eina_array_count(pd->children); ++i)
391 {
392 child = eina_array_data_get(pd->children, i);
393 _widget_calculate_recursive(child);
394 }
395
396 efl_canvas_group_calculate(obj);
397 }
398
399 static void
_item_content_realize(Elm_Gen_Item * it,Evas_Object * target,Eina_List ** contents,const char * src,const char * parts,Eina_Bool calc)400 _item_content_realize(Elm_Gen_Item *it,
401 Evas_Object *target,
402 Eina_List **contents,
403 const char *src,
404 const char *parts,
405 Eina_Bool calc)
406 {
407 Evas_Object *content;
408 char buf[256];
409 Eina_List *source;
410 const char *key;
411
412 ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
413
414 if (!parts)
415 {
416 EINA_LIST_FREE(*contents, content)
417 evas_object_del(content);
418 }
419 if ((!it->itc->func.content_get) &&
420 ((it->itc->version < 3) || (!it->itc->func.reusable_content_get))) return;
421
422 source = elm_widget_stringlist_get(edje_object_data_get(target, src));
423
424 EINA_LIST_FREE(source, key)
425 {
426 if (parts && fnmatch(parts, key, FNM_PERIOD))
427 continue;
428
429 Evas_Object *old = NULL;
430 old = edje_object_part_swallow_get(target, key);
431
432 // Reuse content by popping from the cache
433 content = NULL;
434 if (it->itc->func.reusable_content_get)
435 content = it->itc->func.reusable_content_get(
436 (void *)WIDGET_ITEM_DATA_GET(EO_OBJ(it)), WIDGET(it), key, old);
437 if (!content)
438 {
439 // Call the content get
440 if (it->itc->func.content_get)
441 content = it->itc->func.content_get
442 ((void *)WIDGET_ITEM_DATA_GET(EO_OBJ(it)), WIDGET(it), key);
443 if (!content) goto out;
444 }
445
446 if (content != old)
447 {
448 eina_hash_add(sd->content_item_map, &content, it->base->eo_obj);
449 // FIXME: Genlist item doesn't update its size when the size of
450 // content is changed, so deferred calculation for content should
451 // be performed before realization.
452 if (efl_isa(content, EFL_UI_WIDGET_CLASS))
453 {
454 ELM_WIDGET_DATA_GET_OR_RETURN(content, wd);
455
456 // FIXME : Layout need sizing eval before group calculate
457 if (efl_class_get(content) == EFL_UI_LAYOUT_BASE_CLASS)
458 elm_layout_sizing_eval(content);
459
460 _widget_calculate_recursive(content);
461 }
462
463 if (!edje_object_part_swallow(target, key, content))
464 {
465 ERR("%s (%p) can not be swallowed into %s",
466 evas_object_type_get(content), content, key);
467 evas_object_del(content);
468 goto out;
469 }
470 elm_widget_sub_object_add(WIDGET(it), content);
471
472 if (elm_widget_is(content))
473 {
474 elm_widget_tree_unfocusable_set(content, it->item->unfocusable);
475 if (!calc && (!it->item->unfocusable))
476 _elm_widget_full_eval(content);
477 }
478 }
479 *contents = eina_list_append(*contents, content);
480
481 if (elm_wdg_item_disabled_get(EO_OBJ(it)))
482 elm_widget_disabled_set(content, EINA_TRUE);
483
484 snprintf(buf, sizeof(buf), "elm,state,%s,visible", key);
485 edje_object_signal_emit(target, buf, "elm");
486 out:
487 if (old && content != old)
488 {
489 *contents = eina_list_remove(*contents, old);
490 evas_object_del(old);
491 eina_hash_del_by_key(sd->content_item_map, &old);
492 }
493 }
494 }
495
496 static void
_item_state_realize(Elm_Gen_Item * it,Evas_Object * target,const char * parts)497 _item_state_realize(Elm_Gen_Item *it, Evas_Object *target, const char *parts)
498 {
499 Eina_List *src;
500 const char *key;
501 char buf[4096];
502
503 if (!it->itc->func.state_get) return;
504
505 src = elm_widget_stringlist_get(edje_object_data_get(target, "states"));
506 EINA_LIST_FREE(src, key)
507 {
508 if (parts && fnmatch(parts, key, FNM_PERIOD)) continue;
509
510 Eina_Bool on = it->itc->func.state_get
511 ((void *)WIDGET_ITEM_DATA_GET(EO_OBJ(it)), WIDGET(it), key);
512
513 if (on)
514 {
515 snprintf(buf, sizeof(buf), "elm,state,%s,active", key);
516 edje_object_signal_emit(target, buf, "elm");
517 }
518 else
519 {
520 snprintf(buf, sizeof(buf), "elm,state,%s,passive", key);
521 edje_object_signal_emit(target, buf, "elm");
522 }
523 }
524 edje_object_message_signal_process(target);
525 }
526
527 /**
528 * Apply the right style for the created item view.
529 */
530 static void
_view_style_update(Elm_Gen_Item * it,Evas_Object * view,const char * style)531 _view_style_update(Elm_Gen_Item *it, Evas_Object *view, const char *style)
532 {
533 char buf[1024];
534 const char *stacking_even;
535 const char *stacking;
536 ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
537
538 // FIXME: There exists
539 // item, item_compress, item_odd, item_compress_odd,
540 // tree, tree_compress, tree_odd, tree_odd_compress
541 // But those used case by case. :-(
542 // Anyway, belows codes are for backward..
543 if (it->decorate_it_set)
544 {
545 // item, item_compress, item_odd, item_compress_odd
546 strncpy(buf, "item", sizeof(buf));
547 if (sd->mode == ELM_LIST_COMPRESS)
548 strncat(buf, "_compress", sizeof(buf) - strlen(buf) - 1);
549
550 if (it->item->order_num_in & 0x1)
551 strncat(buf, "_odd", sizeof(buf) - strlen(buf) - 1);
552 strncat(buf, "/", sizeof(buf) - strlen(buf) - 1);
553 strncat(buf, style, sizeof(buf) - strlen(buf) - 1);
554 }
555 else
556 {
557 // item, item_compress, tree, tree_compress
558 if (it->item->type & ELM_GENLIST_ITEM_TREE)
559 snprintf(buf, sizeof(buf), "tree%s/%s",
560 sd->mode == ELM_LIST_COMPRESS ? "_compress" :
561 "", style ? : "default");
562 else
563 snprintf(buf, sizeof(buf), "item%s/%s",
564 sd->mode == ELM_LIST_COMPRESS ? "_compress" :
565 "",style ? : "default");
566 }
567
568 Eina_Error th_ret =
569 elm_widget_theme_object_set(WIDGET(it), view, "genlist", buf,
570 elm_widget_style_get(WIDGET(it)));
571 if (th_ret == EFL_UI_THEME_APPLY_ERROR_GENERIC)
572 {
573 ERR("%s is not a valid genlist item style. "
574 "Automatically falls back into default style.",
575 style);
576 elm_widget_theme_object_set
577 (WIDGET(it), view, "genlist", "item/default", "default");
578 }
579
580 edje_object_mirrored_set(view, efl_ui_mirrored_get(WIDGET(it)));
581 edje_object_scale_set(view, efl_gfx_entity_scale_get(WIDGET(it))
582 * elm_config_scale_get());
583
584 stacking_even = edje_object_data_get(view, "stacking_even");
585 if (!stacking_even) stacking_even = "above";
586 it->item->stacking_even = !!strcmp("above", stacking_even);
587
588 stacking = edje_object_data_get(view, "stacking");
589 if (!stacking) stacking = "yes";
590 it->item->nostacking = !!strcmp("yes", stacking);
591 }
592
593 /**
594 * Create a VIEW(it) during _item_realize()
595 */
596 static Evas_Object *
_view_create(Elm_Gen_Item * it,const char * style)597 _view_create(Elm_Gen_Item *it, const char *style)
598 {
599 Evas_Object *view = edje_object_add(evas_object_evas_get(WIDGET(it)));
600 evas_object_smart_member_add(view, it->item->wsd->pan_obj);
601 elm_widget_sub_object_add(WIDGET(it), view);
602 edje_object_scale_set(view, efl_gfx_entity_scale_get(WIDGET(it)) *
603 elm_config_scale_get());
604
605 _view_style_update(it, view, style);
606 return view;
607 }
608
609 static void
_view_clear(Evas_Object * view,Eina_List ** texts,Eina_List ** contents)610 _view_clear(Evas_Object *view, Eina_List **texts, Eina_List **contents)
611 {
612 const char *part;
613 Evas_Object *c;
614 const Eina_List *l;
615
616 EINA_LIST_FOREACH(*texts, l, part)
617 edje_object_part_text_set(view, part, NULL);
618 ELM_SAFE_FREE(*texts, elm_widget_stringlist_free);
619
620 if (contents)
621 {
622 EINA_LIST_FREE(*contents, c)
623 evas_object_del(c);
624 }
625 }
626
627 static void
_item_scroll(Elm_Genlist_Data * sd)628 _item_scroll(Elm_Genlist_Data *sd)
629 {
630 Evas_Coord gith = 0;
631 Elm_Gen_Item *it = NULL;
632 Evas_Coord ow, oh, dx = 0, dy = 0, dw = 0, dh = 0;
633
634 if (!sd->show_item) return;
635
636 evas_object_geometry_get(sd->pan_obj, NULL, NULL, &ow, &oh);
637 it = sd->show_item;
638 dx = it->x + it->item->block->x;
639 dy = it->y + it->item->block->y;
640 dw = it->item->block->w;
641 dh = oh;
642
643 if (dw < 1) return;
644 if (ow < 1 || oh < 1) return;
645
646 switch (sd->scroll_to_type)
647 {
648 case ELM_GENLIST_ITEM_SCROLLTO_TOP:
649 if (it->item->group_item) gith = it->item->group_item->item->h;
650 dy -= gith;
651 break;
652
653 case ELM_GENLIST_ITEM_SCROLLTO_MIDDLE:
654 dy += ((it->item->h / 2) - (oh / 2));
655 break;
656
657 case ELM_GENLIST_ITEM_SCROLLTO_BOTTOM:
658 dy += (it->item->h - oh);
659 break;
660
661 case ELM_GENLIST_ITEM_SCROLLTO_IN:
662 default:
663 if ((sd->expanded_item) &&
664 ((sd->show_item->y + sd->show_item->item->block->y
665 + sd->show_item->item->h) -
666 (sd->expanded_item->y + sd->expanded_item->item->block->y) > oh))
667 {
668 it = sd->expanded_item;
669 if (it->item->group_item) gith = it->item->group_item->item->h;
670 dx = it->x + it->item->block->x;
671 dy = it->y + it->item->block->y - gith;
672 dw = it->item->block->w;
673 }
674 else
675 {
676 if ((it->item->group_item) &&
677 (sd->pan_y > (it->y + it->item->block->y)))
678 gith = it->item->group_item->item->h;
679 dy -= gith;
680 dh = it->item->h;
681 }
682 break;
683 }
684 if (sd->bring_in)
685 elm_interface_scrollable_region_bring_in(sd->obj, dx, dy, dw, dh);
686 else
687 elm_interface_scrollable_content_region_show
688 (sd->obj, dx, dy, dw, dh);
689
690 it->item->show_me = EINA_FALSE;
691 sd->show_item = NULL;
692 sd->auto_scroll_enabled = EINA_FALSE;
693 sd->check_scroll = EINA_FALSE;
694 }
695
696 static void
_elm_genlist_item_unrealize(Elm_Gen_Item * it,Eina_Bool calc)697 _elm_genlist_item_unrealize(Elm_Gen_Item *it,
698 Eina_Bool calc)
699 {
700 Evas *e;
701 if (!it->realized) return;
702 if (it->item->wsd->reorder_it == it)
703 {
704 WRN("reordering item should not be unrealized");
705 return;
706 }
707
708 e = evas_object_evas_get(WIDGET(it));
709 evas_event_freeze(e);
710
711 ELM_SAFE_FREE(it->long_timer, ecore_timer_del);
712
713 _view_clear(VIEW(it), &(it->texts), NULL);
714 ELM_SAFE_FREE(it->item_focus_chain, eina_list_free);
715
716 elm_wdg_item_track_cancel(EO_OBJ(it));
717
718 if (!calc)
719 {
720 efl_event_callback_legacy_call(WIDGET(it), ELM_GENLIST_EVENT_UNREALIZED, EO_OBJ(it));
721 if (it->base->func.unrealized) it->base->func.unrealized(EO_OBJ(it));
722 }
723
724 _item_unrealize(it);
725
726 evas_event_thaw(e);
727 evas_event_thaw_eval(e);
728 }
729
730 static void
_item_block_unrealize(Item_Block * itb)731 _item_block_unrealize(Item_Block *itb)
732 {
733 Elm_Gen_Item *it;
734 const Eina_List *l;
735 Eina_Bool dragging = EINA_FALSE;
736 Evas *e;
737
738 if (!itb->realized) return;
739 e = evas_object_evas_get((itb->sd)->obj);
740 evas_event_freeze(e);
741
742 EINA_LIST_FOREACH(itb->items, l, it)
743 {
744 if (itb->must_recalc || !(it->item->type & ELM_GENLIST_ITEM_GROUP))
745 {
746 if (it->dragging)
747 {
748 dragging = EINA_TRUE;
749 it->want_unrealize = EINA_TRUE;
750 }
751 else if (it != itb->sd->pin_item)
752 _elm_genlist_item_unrealize(it, EINA_FALSE);
753 }
754 }
755 if (!dragging)
756 {
757 Eina_List *n;
758
759 itb->realized = EINA_FALSE;
760 itb->want_unrealize = EINA_TRUE;
761
762 efl_ui_focus_manager_calc_unregister(itb->sd->obj, itb->adapter);
763 efl_del(itb->adapter);
764 itb->adapter = NULL;
765
766 EINA_LIST_FOREACH(itb->items, n, it)
767 {
768 efl_ui_focus_manager_calc_unregister(itb->sd->obj, EO_OBJ(it));
769 }
770 }
771 else
772 itb->want_unrealize = EINA_FALSE;
773 evas_event_thaw(e);
774 evas_event_thaw_eval(e);
775 }
776
777 static Eina_Bool
_must_recalc_idler(void * data)778 _must_recalc_idler(void *data)
779 {
780 ELM_GENLIST_DATA_GET(data, sd);
781
782 efl_canvas_group_change(sd->obj);
783 sd->must_recalc_idler = NULL;
784 return ECORE_CALLBACK_CANCEL;
785 }
786
787 static void
_calc_job(void * data)788 _calc_job(void *data)
789 {
790 int in = 0;
791 Item_Block *itb, *chb = NULL;
792 Elm_Genlist_Data *sd = data;
793 Eina_Bool minw_change = EINA_FALSE;
794 Eina_Bool did_must_recalc = EINA_FALSE;
795 Evas_Coord minw = -1, minh = 0, y = 0, ow = 0, vw = 0;
796 Evas *e;
797
798 sd->need_calc = EINA_FALSE;
799 evas_object_geometry_get(sd->pan_obj, NULL, NULL, &ow, &sd->h);
800 if (sd->mode == ELM_LIST_COMPRESS)
801 elm_interface_scrollable_content_viewport_geometry_get
802 (sd->obj, NULL, NULL, &vw, NULL);
803
804 if (sd->w != ow) sd->w = ow;
805
806 e = evas_object_evas_get(sd->obj);
807 evas_event_freeze(e);
808 EINA_INLIST_FOREACH(sd->blocks, itb)
809 {
810 Eina_Bool show_me = EINA_FALSE;
811
812 itb->num = in;
813 show_me = itb->show_me;
814 itb->show_me = EINA_FALSE;
815 if (chb)
816 {
817 if (itb->realized) _item_block_unrealize(itb);
818 }
819 if ((itb->changed) || ((itb->must_recalc) && (!did_must_recalc)))
820 {
821 if (itb->must_recalc)
822 {
823 Eina_List *l;
824 Elm_Gen_Item *it;
825
826 EINA_LIST_FOREACH(itb->items, l, it)
827 it->item->mincalcd = EINA_FALSE;
828 itb->changed = EINA_TRUE;
829 did_must_recalc = EINA_TRUE;
830 if (itb->realized) _item_block_unrealize(itb);
831 itb->must_recalc = EINA_FALSE;
832 }
833 show_me = _item_block_recalc(itb, in, EINA_FALSE);
834 chb = itb;
835 }
836 itb->y = y;
837 itb->x = 0;
838 minh += itb->minh;
839 if (minw < itb->minw)
840 {
841 minw = itb->minw;
842 if (minw != -1)
843 minw_change = EINA_TRUE;
844 }
845 if ((sd->mode == ELM_LIST_COMPRESS) && (minw > vw))
846 {
847 minw = vw;
848 minw_change = EINA_TRUE;
849 }
850 itb->w = minw;
851 itb->h = itb->minh;
852 y += itb->h;
853 in += itb->vis_count;
854 if ((show_me) && (sd->show_item) && (!sd->show_item->item->queued))
855 sd->check_scroll = EINA_TRUE;
856 }
857 if (minw_change)
858 {
859 EINA_INLIST_FOREACH(sd->blocks, itb)
860 {
861 itb->minw = minw;
862 itb->w = itb->minw;
863 }
864 }
865 if ((chb) && (EINA_INLIST_GET(chb)->next))
866 {
867 EINA_INLIST_FOREACH(EINA_INLIST_GET(chb)->next, itb)
868 {
869 if (itb->realized) _item_block_unrealize(itb);
870 }
871 }
872 sd->realminw = minw;
873 if (minw < sd->w) minw = sd->w;
874 if ((minw != sd->minw) || (minh != sd->minh))
875 {
876 sd->minw = minw;
877 sd->minh = minh;
878 efl_event_callback_legacy_call
879 (sd->pan_obj, ELM_PAN_EVENT_CHANGED, NULL);
880 elm_layout_sizing_eval(sd->obj);
881 if (sd->reorder_it)
882 {
883 Elm_Gen_Item *it;
884 it = sd->reorder_it;
885 it->item->w = minw;
886 }
887 if ((sd->anchor_item) && (sd->anchor_item->item->block)
888 && (!sd->auto_scroll_enabled))
889 {
890 Elm_Gen_Item *it;
891 Evas_Coord it_y;
892
893 it = sd->anchor_item;
894 it_y = sd->anchor_y;
895 elm_interface_scrollable_content_pos_set
896 (sd->obj, sd->pan_x, it->item->block->y
897 + it->y + it_y, EINA_TRUE);
898 sd->anchor_item = it;
899 sd->anchor_y = it_y;
900 }
901 }
902 if (did_must_recalc)
903 {
904 if (!sd->must_recalc_idler)
905 sd->must_recalc_idler = ecore_idler_add(_must_recalc_idler, sd->obj);
906 }
907 if (!sd->show_item) sd->check_scroll = EINA_FALSE;
908 if (sd->check_scroll)
909 {
910 if (EINA_INLIST_GET(sd->show_item) == sd->items->last)
911 sd->scroll_to_type = ELM_GENLIST_ITEM_SCROLLTO_IN;
912
913 if ((sd->show_item) && (sd->show_item->item->block))
914 _item_scroll(sd);
915 }
916
917 evas_object_smart_changed(sd->pan_obj);
918 evas_event_thaw(e);
919 evas_event_thaw_eval(e);
920 }
921
922 EOLIAN static void
_elm_genlist_efl_canvas_group_group_calculate(Eo * obj,Elm_Genlist_Data * sd)923 _elm_genlist_efl_canvas_group_group_calculate(Eo *obj, Elm_Genlist_Data *sd)
924 {
925 Evas_Coord minw = -1, minh = -1, maxw = -1, maxh = -1;
926 Evas_Coord vmw = 0, vmh = 0;
927
928 ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
929
930 if (sd->on_sub_del) return;;
931
932 evas_object_size_hint_combined_min_get(obj, &minw, NULL);
933 evas_object_size_hint_max_get(obj, &maxw, &maxh);
934
935 edje_object_size_min_calc(wd->resize_obj, &vmw, &vmh);
936
937 if (sd->mode == ELM_LIST_COMPRESS)
938 {
939 Evas_Coord vw = 0, vh = 0;
940
941 elm_interface_scrollable_content_viewport_geometry_get
942 (obj, NULL, NULL, &vw, &vh);
943 if ((vw != 0) && (vw != sd->prev_viewport_w))
944 {
945 Item_Block *itb;
946
947 sd->prev_viewport_w = vw;
948 /* Free all buckets for updaing changed width */
949 eina_hash_free_buckets(sd->size_caches);
950
951 EINA_INLIST_FOREACH(sd->blocks, itb)
952 {
953 itb->must_recalc = EINA_TRUE;
954 }
955 sd->need_calc = EINA_TRUE;
956 }
957 minw = vmw;
958 minh = vmh;
959 }
960 else
961 sd->need_calc = EINA_TRUE;
962 if (sd->need_calc)
963 _calc_job(sd);
964
965 if (sd->scr_minw)
966 {
967 maxw = -1;
968 minw = vmw + sd->realminw;
969 }
970 else
971 {
972 minw = vmw;
973 }
974 if (sd->scr_minh)
975 {
976 maxh = -1;
977 minh = vmh + sd->minh;
978 }
979 else
980 {
981 minw = vmw;
982 minh = vmh;
983 }
984
985 if ((maxw > 0) && (minw > maxw))
986 minw = maxw;
987 if ((maxh > 0) && (minh > maxh))
988 minh = maxh;
989
990 evas_object_size_hint_min_set(obj, minw, minh);
991 evas_object_size_hint_max_set(obj, maxw, maxh);
992 }
993
994 static void
_content_min_limit_cb(Evas_Object * obj,Eina_Bool w,Eina_Bool h)995 _content_min_limit_cb(Evas_Object *obj,
996 Eina_Bool w,
997 Eina_Bool h)
998 {
999 ELM_GENLIST_DATA_GET(obj, sd);
1000
1001 if ((sd->mode == ELM_LIST_LIMIT) ||
1002 (sd->mode == ELM_LIST_EXPAND)) return;
1003 sd->scr_minw = !!w;
1004 sd->scr_minh = !!h;
1005
1006 elm_layout_sizing_eval(obj);
1007 }
1008
1009 static void
_item_contract_emit(Elm_Object_Item * eo_it)1010 _item_contract_emit(Elm_Object_Item *eo_it)
1011 {
1012 ELM_GENLIST_ITEM_DATA_GET(eo_it, it);
1013 Elm_Object_Item *eo_it2;
1014 Eina_List *l;
1015
1016 //XXX: for compat
1017 edje_object_signal_emit(VIEW(it), SIGNAL_CONTRACT_FLIP, "");
1018 edje_object_signal_emit(VIEW(it), SIGNAL_CONTRACT_FLIP, "elm");
1019 it->item->tree_effect_finished = EINA_FALSE;
1020
1021 EINA_LIST_FOREACH(it->item->items, l, eo_it2)
1022 if (eo_it2) _item_contract_emit(eo_it2);
1023 }
1024
1025 static int
_item_tree_effect_before(Elm_Gen_Item * it)1026 _item_tree_effect_before(Elm_Gen_Item *it)
1027 {
1028 Elm_Object_Item *eo_it2;
1029 Eina_List *l;
1030 ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
1031
1032 EINA_LIST_FOREACH(it->item->items, l, eo_it2)
1033 {
1034 ELM_GENLIST_ITEM_DATA_GET(eo_it2, it2);
1035 if (it2->parent && (it == it2->parent))
1036 {
1037 if (!it2->realized)
1038 it2->item->tree_effect_hide_me = EINA_TRUE;
1039 if (sd->move_effect_mode ==
1040 ELM_GENLIST_TREE_EFFECT_EXPAND)
1041 {
1042 //XXX: for compat
1043 edje_object_signal_emit(VIEW(it2), SIGNAL_HIDE, "");
1044 edje_object_signal_emit(VIEW(it2), SIGNAL_HIDE, "elm");
1045 }
1046 else if (sd->move_effect_mode ==
1047 ELM_GENLIST_TREE_EFFECT_CONTRACT)
1048 _item_contract_emit(eo_it2);
1049 }
1050 }
1051 return ECORE_CALLBACK_CANCEL;
1052 }
1053
1054 /* returns true if change occurred */
1055 static Eina_Bool
_item_position(Elm_Gen_Item * it,Evas_Object * view,Evas_Coord it_x,Evas_Coord it_y)1056 _item_position(Elm_Gen_Item *it,
1057 Evas_Object *view,
1058 Evas_Coord it_x,
1059 Evas_Coord it_y)
1060 {
1061 Eina_Position2D pos;
1062 if (!it) return EINA_FALSE;
1063 if (!view) return EINA_FALSE;
1064 ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
1065 Evas *e = evas_object_evas_get(sd->obj);
1066
1067 evas_event_freeze(e);
1068 pos = efl_gfx_entity_position_get(view);
1069 efl_gfx_entity_geometry_set(view, EINA_RECT(it_x, it_y, it->item->w, it->item->h));
1070 evas_object_show(view);
1071 evas_event_thaw(e);
1072 evas_event_thaw_eval(e);
1073 return (pos.x != it_x) || (pos.y != it_y);
1074 }
1075
1076 static void
_item_tree_effect(Elm_Genlist_Data * sd,int y)1077 _item_tree_effect(Elm_Genlist_Data *sd,
1078 int y)
1079 {
1080 Elm_Gen_Item *expanded_next_it;
1081 Elm_Object_Item *eo_it;
1082
1083 expanded_next_it = sd->expanded_next_item;
1084
1085 if (sd->move_effect_mode == ELM_GENLIST_TREE_EFFECT_EXPAND)
1086 {
1087 eo_it = elm_genlist_item_prev_get(EO_OBJ(expanded_next_it));
1088 while (eo_it)
1089 {
1090 ELM_GENLIST_ITEM_DATA_GET(eo_it, it);
1091 if (it->item->expanded_depth <=
1092 expanded_next_it->item->expanded_depth) break;
1093 if (it->item->scrl_y &&
1094 (it->item->scrl_y <= expanded_next_it->item->old_scrl_y + y)
1095 && (it->item->expanded_depth >
1096 expanded_next_it->item->expanded_depth))
1097 {
1098 if (!it->item->tree_effect_finished)
1099 {
1100 //XXX: for compat
1101 edje_object_signal_emit(VIEW(it), "flip_item", "");
1102 edje_object_signal_emit(VIEW(it), SIGNAL_FLIP_ITEM,
1103 "elm");
1104 _item_position
1105 (it, VIEW(it), it->item->scrl_x, it->item->scrl_y);
1106 it->item->tree_effect_finished = EINA_TRUE;
1107 }
1108 }
1109 eo_it = elm_genlist_item_prev_get(eo_it);
1110 }
1111 }
1112 else if (sd->move_effect_mode == ELM_GENLIST_TREE_EFFECT_CONTRACT)
1113 {
1114 eo_it = elm_genlist_item_prev_get(EO_OBJ(expanded_next_it));
1115 while (eo_it)
1116 {
1117 ELM_GENLIST_ITEM_DATA_GET(eo_it, it);
1118 if ((it->item->scrl_y > expanded_next_it->item->old_scrl_y + y) &&
1119 (it->item->expanded_depth >
1120 expanded_next_it->item->expanded_depth))
1121 {
1122 if (!it->item->tree_effect_finished)
1123 {
1124 //XXX: for compat
1125 edje_object_signal_emit(VIEW(it), SIGNAL_HIDE, "");
1126 edje_object_signal_emit(VIEW(it), SIGNAL_HIDE, "elm");
1127 it->item->tree_effect_finished = EINA_TRUE;
1128 }
1129 }
1130 else
1131 break;
1132 eo_it = elm_genlist_item_prev_get(eo_it);
1133 }
1134 }
1135 }
1136
1137 static void
_item_sub_items_clear(Elm_Gen_Item * it)1138 _item_sub_items_clear(Elm_Gen_Item *it)
1139 {
1140 Eina_List *tl = NULL, *l;
1141 Elm_Object_Item *eo_it2;
1142
1143 ELM_GENLIST_ITEM_CHECK_OR_RETURN(it);
1144
1145 EINA_LIST_FOREACH(it->item->items, l, eo_it2)
1146 tl = eina_list_append(tl, eo_it2);
1147 EINA_LIST_FREE(tl, eo_it2)
1148 efl_del(eo_it2);
1149 }
1150
1151 static void
_item_auto_scroll(Elm_Genlist_Data * sd)1152 _item_auto_scroll(Elm_Genlist_Data *sd)
1153 {
1154 Elm_Object_Item *eo_tmp_item = NULL;
1155
1156 if ((sd->expanded_item) && (sd->auto_scroll_enabled))
1157 {
1158 eo_tmp_item = eina_list_data_get
1159 (eina_list_last(sd->expanded_item->item->items));
1160 if (!eo_tmp_item) return;
1161 ELM_GENLIST_ITEM_DATA_GET(eo_tmp_item, tmp_item);
1162 sd->show_item = tmp_item;
1163 sd->bring_in = EINA_TRUE;
1164 sd->scroll_to_type = ELM_GENLIST_ITEM_SCROLLTO_IN;
1165 if ((sd->show_item->item->queued) || (!sd->show_item->item->mincalcd))
1166 {
1167 sd->show_item->item->show_me = EINA_TRUE;
1168 sd->auto_scroll_enabled = EINA_FALSE;
1169 }
1170 else
1171 _item_scroll(sd);
1172 }
1173 }
1174
1175 static void
_item_tree_effect_finish(Elm_Genlist_Data * sd)1176 _item_tree_effect_finish(Elm_Genlist_Data *sd)
1177 {
1178 Elm_Object_Item *eo_it = NULL;
1179 const Eina_List *l;
1180 Item_Block *itb;
1181 Elm_Gen_Item *it1;
1182 Evas_Coord y = 0;
1183
1184 if (sd->tree_effect_animator)
1185 {
1186 if (sd->move_effect_mode == ELM_GENLIST_TREE_EFFECT_CONTRACT)
1187 _item_sub_items_clear(sd->expanded_item);
1188
1189 EINA_LIST_FOREACH(sd->expanded_item->item->items, l, eo_it)
1190 {
1191 ELM_GENLIST_ITEM_DATA_GET(eo_it, it);
1192 it->item->tree_effect_finished = EINA_TRUE;
1193 it->item->old_scrl_y = it->item->scrl_y;
1194 if (it->item->wsd->move_effect_mode ==
1195 ELM_GENLIST_TREE_EFFECT_EXPAND)
1196 {
1197 //XXX: for compat
1198 edje_object_signal_emit(VIEW(it), SIGNAL_SHOW, "");
1199 edje_object_signal_emit(VIEW(it), SIGNAL_SHOW, "elm");
1200 }
1201 }
1202 if (sd->move_effect_mode ==
1203 ELM_GENLIST_TREE_EFFECT_EXPAND)
1204 {
1205 EINA_INLIST_FOREACH(sd->blocks, itb)
1206 {
1207 EINA_LIST_FOREACH(itb->items, l, it1)
1208 {
1209 if (it1->item->scrl_y <= y)
1210 {
1211 it1->item->scrl_y = y + it1->item->h;
1212 _elm_genlist_item_unrealize(it1, EINA_FALSE);
1213 }
1214 y = it1->item->scrl_y;
1215 }
1216 }
1217 }
1218 }
1219
1220 _item_auto_scroll(sd);
1221 evas_object_lower(sd->event_block_rect);
1222 evas_object_hide(sd->event_block_rect);
1223 sd->move_effect_mode = ELM_GENLIST_TREE_EFFECT_NONE;
1224 sd->move_items = eina_list_free(sd->move_items);
1225
1226 efl_event_callback_legacy_call(sd->pan_obj, ELM_PAN_EVENT_CHANGED, NULL);
1227 efl_event_callback_legacy_call
1228 (sd->obj, ELM_GENLIST_EVENT_TREE_EFFECT_FINISHED, NULL);
1229 evas_object_smart_changed(sd->pan_obj);
1230
1231 _elm_genlist_tree_effect_stop(sd);
1232 }
1233
1234 static void
_item_restack(Elm_Gen_Item * it)1235 _item_restack(Elm_Gen_Item *it)
1236 {
1237 ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
1238
1239 if (it->item->nostacking) return;
1240 if ((it->item->order_num_in & 0x1) ^ it->item->stacking_even)
1241 {
1242 if (it->deco_all_view) evas_object_stack_below(it->deco_all_view, sd->stack[0]);
1243 else if (it->item->deco_it_view) evas_object_stack_below(it->item->deco_it_view, sd->stack[0]);
1244 else evas_object_stack_below(VIEW(it), sd->stack[0]);
1245 }
1246 else
1247 {
1248 if (it->deco_all_view) evas_object_stack_above(it->deco_all_view, sd->stack[0]);
1249 else if (it->item->deco_it_view) evas_object_stack_above(it->item->deco_it_view, sd->stack[0]);
1250 else evas_object_stack_above(VIEW(it), sd->stack[0]);
1251 }
1252 }
1253
1254 static void
_elm_genlist_item_position_state_update(Elm_Gen_Item * it)1255 _elm_genlist_item_position_state_update(Elm_Gen_Item *it)
1256 {
1257 unsigned idx = it->item->order_num_in;
1258
1259 if (!VIEW(it) && !it->deco_all_view) return;
1260 ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
1261
1262 _item_restack(it);
1263
1264 if (idx & 0x1)
1265 {
1266 edje_object_signal_emit(VIEW(it), SIGNAL_ODD, "elm");
1267 if (it->deco_all_view)
1268 edje_object_signal_emit(it->deco_all_view, SIGNAL_ODD, "elm");
1269 }
1270 else
1271 {
1272 edje_object_signal_emit(VIEW(it), SIGNAL_EVEN, "elm");
1273 if (it->deco_all_view)
1274 edje_object_signal_emit(it->deco_all_view, SIGNAL_EVEN, "elm");
1275 }
1276
1277 if (sd->item_count == 1)
1278 {
1279 edje_object_signal_emit(VIEW(it), SIGNAL_LIST_SINGLE, "elm");
1280 if (it->deco_all_view)
1281 edje_object_signal_emit(it->deco_all_view, SIGNAL_LIST_SINGLE, "elm");
1282 }
1283 else if (idx == 0)
1284 {
1285 edje_object_signal_emit(VIEW(it), SIGNAL_LIST_FIRST, "elm");
1286 if (it->deco_all_view)
1287 edje_object_signal_emit(it->deco_all_view, SIGNAL_LIST_FIRST, "elm");
1288 }
1289 else if (idx == sd->item_count - 1)
1290 {
1291 edje_object_signal_emit(VIEW(it), SIGNAL_LIST_LAST, "elm");
1292 if (it->deco_all_view)
1293 edje_object_signal_emit(it->deco_all_view, SIGNAL_LIST_LAST, "elm");
1294 }
1295 else if (idx > 0)
1296 {
1297 edje_object_signal_emit(VIEW(it), SIGNAL_LIST_MIDDLE, "elm");
1298 if (it->deco_all_view)
1299 edje_object_signal_emit(it->deco_all_view, SIGNAL_LIST_MIDDLE, "elm");
1300 }
1301
1302 if (it->parent)
1303 {
1304 unsigned first_idx = it->parent->item->order_num_in + 1;
1305 unsigned count = eina_list_count(it->parent->item->items);
1306
1307 if (count == 1)
1308 {
1309 edje_object_signal_emit(VIEW(it), SIGNAL_GROUP_SINGLE, "elm");
1310 if (it->deco_all_view)
1311 edje_object_signal_emit(it->deco_all_view, SIGNAL_GROUP_SINGLE,
1312 "elm");
1313 }
1314 else if (idx == first_idx)
1315 {
1316 edje_object_signal_emit(VIEW(it), SIGNAL_GROUP_FIRST, "elm");
1317 if (it->deco_all_view)
1318 edje_object_signal_emit(it->deco_all_view, SIGNAL_GROUP_FIRST,
1319 "elm");
1320 }
1321 else if (EO_OBJ(it) == eina_list_data_get(eina_list_last(it->parent->item->items)))
1322 {
1323 edje_object_signal_emit(VIEW(it), SIGNAL_GROUP_LAST, "elm");
1324 if (it->deco_all_view)
1325 edje_object_signal_emit(it->deco_all_view, SIGNAL_GROUP_LAST,
1326 "elm");
1327 }
1328 else if (idx > first_idx)
1329 {
1330 edje_object_signal_emit(VIEW(it), SIGNAL_GROUP_MIDDLE, "elm");
1331 if (it->deco_all_view)
1332 edje_object_signal_emit(it->deco_all_view, SIGNAL_GROUP_MIDDLE,
1333 "elm");
1334 }
1335 }
1336 }
1337
1338 static void
_item_order_update(Elm_Gen_Item * it,int index,Eina_Bool process)1339 _item_order_update(Elm_Gen_Item *it, int index, Eina_Bool process)
1340 {
1341 it->item->order_num_in = index;
1342 _elm_genlist_item_position_state_update(it);
1343
1344 if (process) edje_object_message_signal_process(VIEW(it));
1345 }
1346
1347 static void
_elm_genlist_item_state_update(Elm_Gen_Item * it)1348 _elm_genlist_item_state_update(Elm_Gen_Item *it)
1349 {
1350 if (it->selected)
1351 {
1352 edje_object_signal_emit(VIEW(it), SIGNAL_SELECTED, "elm");
1353 if (it->deco_all_view)
1354 edje_object_signal_emit
1355 (it->deco_all_view, SIGNAL_SELECTED, "elm");
1356 }
1357 if (elm_wdg_item_disabled_get(EO_OBJ(it)))
1358 {
1359 edje_object_signal_emit(VIEW(it), SIGNAL_DISABLED, "elm");
1360 if (it->deco_all_view)
1361 edje_object_signal_emit
1362 (it->deco_all_view, SIGNAL_DISABLED, "elm");
1363 }
1364 if (it->item->expanded)
1365 {
1366 edje_object_signal_emit(VIEW(it), SIGNAL_EXPANDED, "elm");
1367 if (it->deco_all_view)
1368 edje_object_signal_emit
1369 (it->deco_all_view, SIGNAL_EXPANDED, "elm");
1370 }
1371 }
1372
1373 static void
_view_inflate(Evas_Object * view,Elm_Gen_Item * it,Eina_List ** sources,Eina_List ** contents,Eina_Bool calc)1374 _view_inflate(Evas_Object *view, Elm_Gen_Item *it, Eina_List **sources, Eina_List **contents, Eina_Bool calc)
1375 {
1376 if (!view) return;
1377 if (sources) _item_text_realize(it, view, sources, NULL);
1378 if (contents) _item_content_realize(it, view, contents, "contents", NULL, calc);
1379 _item_state_realize(it, view, NULL);
1380 }
1381
1382 static void
_elm_genlist_item_index_update(Elm_Gen_Item * it)1383 _elm_genlist_item_index_update(Elm_Gen_Item *it)
1384 {
1385 if (it->position_update || it->item->block->position_update)
1386 {
1387 efl_event_callback_legacy_call
1388 (WIDGET(it), ELM_GENLIST_EVENT_INDEX_UPDATE, EO_OBJ(it));
1389 it->position_update = EINA_FALSE;
1390 }
1391 }
1392
1393 static void
_decorate_all_item_position(Elm_Gen_Item * it,int itx,int ity)1394 _decorate_all_item_position(Elm_Gen_Item *it,
1395 int itx,
1396 int ity)
1397 {
1398 if ((!it) || (!it->item->wsd->decorate_all_mode)) return;
1399 efl_gfx_entity_geometry_set(it->deco_all_view, EINA_RECT(itx, ity, it->item->w, it->item->h));
1400 }
1401
1402 static void
_decorate_all_item_realize(Elm_Gen_Item * it,Eina_Bool effect_on)1403 _decorate_all_item_realize(Elm_Gen_Item *it,
1404 Eina_Bool effect_on)
1405 {
1406 char buf[1024];
1407 const char *stacking;
1408 const char *stacking_even;
1409
1410 if (!it) return;
1411 ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
1412
1413 if (it->item->decorate_all_item_realized) return;
1414
1415 it->deco_all_view = edje_object_add(evas_object_evas_get(WIDGET(it)));
1416 edje_object_scale_set(it->deco_all_view, efl_gfx_entity_scale_get(WIDGET(it)) *
1417 elm_config_scale_get());
1418 evas_object_smart_member_add(it->deco_all_view, sd->pan_obj);
1419 elm_widget_sub_object_add(WIDGET(it), it->deco_all_view);
1420
1421 if (it->item->type & ELM_GENLIST_ITEM_TREE)
1422 strncpy(buf, "tree", sizeof(buf));
1423 else strncpy(buf, "item", sizeof(buf));
1424 if (sd->mode == ELM_LIST_COMPRESS)
1425 strncat(buf, "_compress", sizeof(buf) - strlen(buf) - 1);
1426
1427 strncat(buf, "/", sizeof(buf) - strlen(buf) - 1);
1428 strncat(buf, it->itc->decorate_all_item_style, sizeof(buf) - strlen(buf) - 1);
1429
1430 elm_widget_theme_object_set(WIDGET(it), it->deco_all_view, "genlist", buf,
1431 elm_widget_style_get(WIDGET(it)));
1432
1433 stacking_even = edje_object_data_get(VIEW(it), "stacking_even");
1434 if (!stacking_even) stacking_even = "above";
1435 it->item->stacking_even = !!strcmp("above", stacking_even);
1436
1437 stacking = edje_object_data_get(VIEW(it), "stacking");
1438 if (!stacking) stacking = "yes";
1439 it->item->nostacking = !!strcmp("yes", stacking);
1440
1441 edje_object_mirrored_set
1442 (it->deco_all_view, efl_ui_mirrored_get(WIDGET(it)));
1443
1444 _elm_genlist_item_position_state_update(it);
1445 _elm_genlist_item_state_update(it);
1446
1447 if (it->item->wsd->reorder_mode)
1448 {
1449 edje_object_signal_emit(it->deco_all_view, SIGNAL_REORDER_MODE_UNSET,
1450 "elm");
1451 }
1452
1453 if (effect_on)
1454 edje_object_signal_emit
1455 (it->deco_all_view, SIGNAL_DECORATE_ENABLED_EFFECT, "elm");
1456 else
1457 edje_object_signal_emit
1458 (it->deco_all_view, SIGNAL_DECORATE_ENABLED, "elm");
1459
1460 _item_mouse_callbacks_del(it, VIEW(it));
1461 _item_mouse_callbacks_add(it, it->deco_all_view);
1462
1463 if (it->flipped)
1464 edje_object_signal_emit
1465 (it->deco_all_view, SIGNAL_FLIP_ENABLED, "elm");
1466 _view_inflate(it->deco_all_view, it, NULL, &(it->item->deco_all_contents), EINA_FALSE);
1467 edje_object_part_swallow
1468 (it->deco_all_view, "elm.swallow.decorate.content", VIEW(it));
1469
1470 _decorate_all_item_position(it, it->item->scrl_x, it->item->scrl_y);
1471 evas_object_show(it->deco_all_view);
1472
1473 if (it->selected)
1474 edje_object_signal_emit(it->deco_all_view, SIGNAL_SELECTED, "elm");
1475
1476 it->item->decorate_all_item_realized = EINA_TRUE;
1477 it->want_unrealize = EINA_FALSE;
1478 }
1479
1480 //-- tree expand/contract signal handle routine --//
1481 static void
_expand_toggle_signal_cb(void * data,Evas_Object * obj EINA_UNUSED,const char * emission EINA_UNUSED,const char * source EINA_UNUSED)1482 _expand_toggle_signal_cb(void *data,
1483 Evas_Object *obj EINA_UNUSED,
1484 const char *emission EINA_UNUSED,
1485 const char *source EINA_UNUSED)
1486 {
1487 Elm_Gen_Item *it = data;
1488
1489 if (it->item->expanded)
1490 efl_event_callback_legacy_call(WIDGET(it), ELM_GENLIST_EVENT_CONTRACT_REQUEST, EO_OBJ(it));
1491 else
1492 efl_event_callback_legacy_call(WIDGET(it), ELM_GENLIST_EVENT_EXPAND_REQUEST, EO_OBJ(it));
1493 }
1494
1495 static void
_expand_signal_cb(void * data,Evas_Object * obj EINA_UNUSED,const char * emission EINA_UNUSED,const char * source EINA_UNUSED)1496 _expand_signal_cb(void *data,
1497 Evas_Object *obj EINA_UNUSED,
1498 const char *emission EINA_UNUSED,
1499 const char *source EINA_UNUSED)
1500 {
1501 Elm_Gen_Item *it = data;
1502
1503 if (!it->item->expanded)
1504 efl_event_callback_legacy_call(WIDGET(it), ELM_GENLIST_EVENT_EXPAND_REQUEST, EO_OBJ(it));
1505 }
1506
1507 static void
_contract_signal_cb(void * data,Evas_Object * obj EINA_UNUSED,const char * emission EINA_UNUSED,const char * source EINA_UNUSED)1508 _contract_signal_cb(void *data,
1509 Evas_Object *obj EINA_UNUSED,
1510 const char *emission EINA_UNUSED,
1511 const char *source EINA_UNUSED)
1512 {
1513 Elm_Gen_Item *it = data;
1514
1515 if (it->item->expanded)
1516 efl_event_callback_legacy_call(WIDGET(it), ELM_GENLIST_EVENT_CONTRACT_REQUEST, EO_OBJ(it));
1517 }
1518
1519 //-- item cache handle routine --//
1520 // push item cache into caches
1521 static Eina_Bool
_item_cache_push(Elm_Genlist_Data * sd,Item_Cache * itc)1522 _item_cache_push(Elm_Genlist_Data *sd, Item_Cache *itc)
1523 {
1524 if (!itc || (sd->item_cache_max <= 0))
1525 return EINA_FALSE;
1526
1527 sd->item_cache_count++;
1528 sd->item_cache =
1529 eina_inlist_prepend(sd->item_cache, EINA_INLIST_GET(itc));
1530
1531 return EINA_TRUE;
1532 }
1533
1534 // pop item cache from caches
1535 static Item_Cache *
_item_cache_pop(Elm_Genlist_Data * sd,Item_Cache * itc)1536 _item_cache_pop(Elm_Genlist_Data *sd, Item_Cache *itc)
1537 {
1538 if (!itc || (!sd->item_cache) ||
1539 (sd->item_cache_count <= 0))
1540 return NULL;
1541
1542 sd->item_cache =
1543 eina_inlist_remove (sd->item_cache, EINA_INLIST_GET(itc));
1544 sd->item_cache_count--;
1545
1546 return itc;
1547 }
1548
1549 // free one item cache
1550 static void
_item_cache_free(Item_Cache * itc)1551 _item_cache_free(Item_Cache *itc)
1552 {
1553 Evas_Object *c;
1554
1555 if (!itc) return;
1556
1557 evas_object_del(itc->spacer);
1558 /* does not exist if cache item has just been reused */
1559 if (itc->base_view)
1560 {
1561 Evas_Object *view = itc->base_view;
1562 efl_wref_del(itc->base_view, &itc->base_view);
1563 efl_del(view);
1564 itc->base_view = NULL;
1565 }
1566 itc->item_class = NULL;
1567 EINA_LIST_FREE(itc->contents, c)
1568 {
1569 evas_object_del(c);
1570 }
1571 ELM_SAFE_FREE(itc, free);
1572 }
1573
1574 // clean up item cache by removing overflowed caches
1575 static void
_item_cache_clean(Elm_Genlist_Data * sd)1576 _item_cache_clean(Elm_Genlist_Data *sd)
1577 {
1578 Evas *e;
1579
1580 if (!sd->obj) return;
1581 e = evas_object_evas_get(sd->obj);
1582 evas_event_freeze(e);
1583
1584 while ((sd->item_cache) && (sd->item_cache_count > sd->item_cache_max))
1585 {
1586 Item_Cache *itc =
1587 EINA_INLIST_CONTAINER_GET(sd->item_cache->last, Item_Cache);
1588 _item_cache_free(_item_cache_pop(sd, itc));
1589 }
1590 evas_event_thaw(e);
1591 evas_event_thaw_eval(e);
1592 }
1593
1594 // empty all item caches
1595 static void
_item_cache_zero(Elm_Genlist_Data * sd)1596 _item_cache_zero(Elm_Genlist_Data *sd)
1597 {
1598 int pmax = sd->item_cache_max;
1599
1600 sd->item_cache_max = 0;
1601 _item_cache_clean(sd);
1602 sd->item_cache_max = pmax;
1603 }
1604
1605 // add an item to item cache
1606 static Eina_Bool
_item_cache_add(Elm_Gen_Item * it,Eina_List * contents)1607 _item_cache_add(Elm_Gen_Item *it, Eina_List *contents)
1608 {
1609 if (it->item->nocache_once || it->item->nocache) return EINA_FALSE;
1610
1611 Item_Cache *itc = NULL;
1612 ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
1613 Evas_Object *obj = sd->obj;
1614 Evas_Object *win = efl_provider_find(obj, EFL_UI_WIN_CLASS);
1615 Evas *e = evas_object_evas_get(obj);
1616
1617 evas_event_freeze(e);
1618
1619 if (sd->item_cache_max > 0)
1620 itc = ELM_NEW(Item_Cache);
1621
1622 if (!_item_cache_push(sd, itc))
1623 {
1624 if (itc) ELM_SAFE_FREE(itc, free);
1625
1626 evas_event_thaw(e);
1627 evas_event_thaw_eval(e);
1628 return EINA_FALSE;
1629 }
1630 itc->spacer = it->spacer;
1631 efl_wref_add(VIEW(it), &itc->base_view);
1632 itc->item_class = it->itc;
1633 itc->contents = contents;
1634 if (it->item->type & ELM_GENLIST_ITEM_TREE)
1635 {
1636 itc->tree = 1;
1637 if (it->item->expanded)
1638 edje_object_signal_emit(itc->base_view, SIGNAL_CONTRACTED, "elm");
1639 }
1640
1641 if (it->selected)
1642 edje_object_signal_emit(itc->base_view, SIGNAL_UNSELECTED, "elm");
1643 if (elm_wdg_item_disabled_get(EO_OBJ(it)))
1644 edje_object_signal_emit(itc->base_view, SIGNAL_ENABLED, "elm");
1645 if ((EO_OBJ(it) == sd->focused_item) &&
1646 (elm_win_focus_highlight_enabled_get(win) || _elm_config->win_auto_focus_enable))
1647 edje_object_signal_emit(itc->base_view, SIGNAL_UNFOCUSED, "elm");
1648
1649 ELM_SAFE_FREE(it->long_timer, ecore_timer_del);
1650 ELM_SAFE_FREE(it->item->swipe_timer, ecore_timer_del);
1651
1652 // FIXME: other callbacks?
1653 edje_object_signal_callback_del_full
1654 (itc->base_view, "elm,action,expand,toggle", "elm",
1655 _expand_toggle_signal_cb, it);
1656 edje_object_signal_callback_del_full
1657 (itc->base_view, "elm,action,expand", "elm", _expand_signal_cb, it);
1658 edje_object_signal_callback_del_full
1659 (itc->base_view, "elm,action,contract", "elm", _contract_signal_cb, it);
1660 _item_mouse_callbacks_del(it, itc->base_view);
1661
1662 edje_object_mirrored_set(itc->base_view,
1663 efl_ui_mirrored_get(WIDGET(it)));
1664 edje_object_scale_set(itc->base_view,
1665 efl_gfx_entity_scale_get(WIDGET(it))
1666 * elm_config_scale_get());
1667
1668 it->spacer = NULL;
1669 efl_wref_del(it->base->view, &it->base->view);
1670 VIEW(it) = NULL;
1671 evas_object_hide(itc->base_view);
1672 // lower eocalloverhead - no need to do this
1673 // evas_object_move(itc->base_view, -9999, -9999);
1674
1675 _item_cache_clean(sd);
1676
1677 evas_event_thaw(e);
1678 evas_event_thaw_eval(e);
1679
1680 return EINA_TRUE;
1681 }
1682
1683 // find an item from item cache and remove it from the cache
1684 static Eina_Bool
_item_cache_find(Elm_Gen_Item * it)1685 _item_cache_find(Elm_Gen_Item *it)
1686 {
1687 if (it->item->nocache_once || it->item->nocache) return EINA_FALSE;
1688
1689 Item_Cache *itc = NULL;
1690 Eina_Inlist *l;
1691 Eina_Bool tree = 0;
1692 ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
1693
1694 if (it->item->type & ELM_GENLIST_ITEM_TREE) tree = 1;
1695 EINA_INLIST_FOREACH_SAFE(sd->item_cache, l, itc)
1696 {
1697 Evas_Object *obj;
1698
1699 if ((itc->tree == tree) &&
1700 (((!it->itc) && (!itc->item_class)) ||
1701 (it->itc && itc->item_class &&
1702 (it->itc == itc->item_class))))
1703 {
1704 itc = _item_cache_pop(sd, itc);
1705 if (!itc) continue;
1706
1707 it->spacer = itc->spacer;
1708 VIEW_SET(it, itc->base_view);
1709 itc->spacer = NULL;
1710 efl_wref_del(itc->base_view, &itc->base_view);
1711 itc->base_view = NULL;
1712 EINA_LIST_FREE(itc->contents, obj)
1713 {
1714 if (elm_widget_is(obj))
1715 elm_widget_tree_unfocusable_set(obj, it->item->unfocusable);
1716 evas_object_show(obj);
1717 }
1718 itc->contents = NULL;
1719 _item_cache_free(itc);
1720 return EINA_TRUE;
1721 }
1722 }
1723 return EINA_FALSE;
1724 }
1725
1726 static Eina_List *
_content_cache_add(Elm_Gen_Item * it,Eina_List ** cache)1727 _content_cache_add(Elm_Gen_Item *it, Eina_List **cache)
1728 {
1729 ELM_GENLIST_DATA_GET_FROM_ITEM(it, pd);
1730 Evas_Object *content = NULL;
1731 EINA_LIST_FREE(it->contents, content)
1732 {
1733 *cache = eina_list_append(*cache, content);
1734 eina_hash_del_by_key(pd->content_item_map, &content);
1735 if (elm_widget_is(content)) elm_widget_tree_unfocusable_set(content, EINA_TRUE);
1736 evas_object_hide(content);
1737 }
1738
1739 return *cache;
1740 }
1741
1742 static char *
_access_info_cb(void * data,Evas_Object * obj EINA_UNUSED)1743 _access_info_cb(void *data, Evas_Object *obj EINA_UNUSED)
1744 {
1745 char *ret;
1746 Eina_Strbuf *buf;
1747
1748 Elm_Gen_Item *it = (Elm_Gen_Item *)data;
1749 ELM_GENLIST_ITEM_CHECK_OR_RETURN(it, NULL);
1750
1751 buf = eina_strbuf_new();
1752
1753 if (it->itc->func.text_get)
1754 {
1755 const Eina_List *l;
1756 const char *key;
1757
1758 if (!(it->texts)) it->texts =
1759 elm_widget_stringlist_get(edje_object_data_get(VIEW(it), "texts"));
1760
1761 EINA_LIST_FOREACH(it->texts, l, key)
1762 {
1763 char *s = it->itc->func.text_get
1764 ((void *)WIDGET_ITEM_DATA_GET(EO_OBJ(it)), WIDGET(it), key);
1765
1766 if (s)
1767 {
1768 if (eina_strbuf_length_get(buf) > 0) eina_strbuf_append(buf, ", ");
1769 eina_strbuf_append(buf, s);
1770 free(s);
1771 }
1772 }
1773 }
1774
1775 ret = eina_strbuf_string_steal(buf);
1776 eina_strbuf_free(buf);
1777 return ret;
1778 }
1779
1780 static char *
_access_state_cb(void * data,Evas_Object * obj EINA_UNUSED)1781 _access_state_cb(void *data, Evas_Object *obj EINA_UNUSED)
1782 {
1783 Elm_Gen_Item *it = (Elm_Gen_Item *)data;
1784 ELM_GENLIST_ITEM_CHECK_OR_RETURN(it, NULL);
1785
1786 if (it->base->disabled)
1787 return strdup(E_("State: Disabled"));
1788
1789 return NULL;
1790 }
1791
1792 static void
_access_on_highlight_cb(void * data)1793 _access_on_highlight_cb(void *data)
1794 {
1795 Evas_Coord x, y, w, h;
1796 Evas_Coord sx, sy, sw, sh;
1797 Elm_Gen_Item *it = (Elm_Gen_Item *)data;
1798 ELM_GENLIST_ITEM_CHECK_OR_RETURN(it);
1799
1800 evas_object_geometry_get(it->base->view, &x, &y, &w, &h);
1801 // XXX There would be a reason.
1802 if ((w == 0) && (h == 0)) return;
1803
1804 evas_object_geometry_get(it->base->widget, &sx, &sy, &sw, &sh);
1805 if ((x < sx) || (y < sy) || ((x + w) > (sx + sw)) || ((y + h) > (sy + sh)))
1806 elm_genlist_item_bring_in(EO_OBJ(it),
1807 ELM_GENLIST_ITEM_SCROLLTO_IN);
1808 }
1809
1810 static void
_access_widget_item_register(Elm_Gen_Item * it)1811 _access_widget_item_register(Elm_Gen_Item *it)
1812 {
1813 Elm_Access_Info *ai;
1814
1815 _elm_access_widget_item_register(it->base);
1816
1817 ai = _elm_access_info_get(it->base->access_obj);
1818
1819 _elm_access_callback_set(ai, ELM_ACCESS_INFO, _access_info_cb, it);
1820 _elm_access_callback_set(ai, ELM_ACCESS_STATE, _access_state_cb, it);
1821 _elm_access_on_highlight_hook_set(ai, _access_on_highlight_cb, it);
1822 _elm_access_activate_callback_set(ai, _access_activate_cb, EO_OBJ(it));
1823 }
1824
1825 static void
_elm_genlist_item_focus_update(Elm_Gen_Item * it)1826 _elm_genlist_item_focus_update(Elm_Gen_Item *it)
1827 {
1828 const char *focus_raise;
1829 Evas_Object *obj = WIDGET(it);
1830 Evas_Object *win = efl_provider_find(obj, EFL_UI_WIN_CLASS);
1831 ELM_GENLIST_DATA_GET(obj, sd);
1832
1833 if (elm_win_focus_highlight_enabled_get(win)
1834 || _elm_config->win_auto_focus_enable)
1835 edje_object_signal_emit(VIEW(it), SIGNAL_FOCUSED, "elm");
1836
1837 focus_raise = edje_object_data_get(VIEW(it), "focusraise");
1838 if ((focus_raise) && (!strcmp(focus_raise, "on")))
1839 {
1840 Elm_Gen_Item *git;
1841 Eina_List *l;
1842
1843 evas_object_raise(VIEW(it));
1844 EINA_LIST_FOREACH(sd->group_items, l, git)
1845 {
1846 if (git->realized) evas_object_raise(VIEW(git));
1847 }
1848 }
1849 }
1850
1851 static void
_item_realize(Elm_Gen_Item * it,const int index,Eina_Bool calc)1852 _item_realize(Elm_Gen_Item *it, const int index, Eina_Bool calc)
1853 {
1854 const char *treesize;
1855 Item_Size *size = NULL;
1856 int tsize = 20;
1857 int in = index;
1858 ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
1859
1860 if (it->realized)
1861 {
1862 if (it->item->order_num_in != in)
1863 {
1864 _item_order_update(it, in, EINA_TRUE);
1865 _elm_genlist_item_index_update(it);
1866 }
1867 return;
1868 }
1869
1870 if (sd->tree_effect_enabled ||
1871 (!_item_cache_find(it)))
1872 {
1873 VIEW_SET(it, _view_create(it, it->itc->item_style));
1874 if (it->item->nocache_once)
1875 it->item->nocache_once = EINA_FALSE;
1876 }
1877
1878 /* access */
1879 if (_elm_config->access_mode) _access_widget_item_register(it);
1880
1881 _item_order_update(it, in, EINA_FALSE);
1882
1883 if (sd->reorder_mode)
1884 edje_object_signal_emit(VIEW(it), SIGNAL_REORDER_MODE_SET, "elm");
1885 else
1886 edje_object_signal_emit(VIEW(it), SIGNAL_REORDER_MODE_UNSET, "elm");
1887
1888 treesize = edje_object_data_get(VIEW(it), "treesize");
1889 if (treesize) tsize = atoi(treesize);
1890
1891 if (edje_object_part_exists(VIEW(it), "elm.swallow.pad"))
1892 {
1893 if (!it->spacer && treesize)
1894 {
1895 it->spacer =
1896 evas_object_rectangle_add(evas_object_evas_get(WIDGET(it)));
1897 evas_object_color_set(it->spacer, 0, 0, 0, 0);
1898 elm_widget_sub_object_add(WIDGET(it), it->spacer);
1899 }
1900
1901 evas_object_size_hint_min_set
1902 (it->spacer, (it->item->expanded_depth * tsize) *
1903 elm_config_scale_get(), 1);
1904 edje_object_part_swallow(VIEW(it), "elm.swallow.pad", it->spacer);
1905 }
1906 else
1907 {
1908 ELM_SAFE_FREE(it->spacer, evas_object_del);
1909 }
1910
1911 if (!calc)
1912 {
1913 edje_object_signal_callback_add
1914 (VIEW(it), "elm,action,expand,toggle", "elm",
1915 _expand_toggle_signal_cb, it);
1916 edje_object_signal_callback_add
1917 (VIEW(it), "elm,action,expand", "elm", _expand_signal_cb, it);
1918 edje_object_signal_callback_add
1919 (VIEW(it), "elm,action,contract", "elm", _contract_signal_cb, it);
1920 _item_mouse_callbacks_add(it, VIEW(it));
1921
1922 if ((sd->decorate_all_mode) && (!it->deco_all_view) &&
1923 (it->item->type != ELM_GENLIST_ITEM_GROUP) &&
1924 (it->itc->decorate_all_item_style))
1925 _decorate_all_item_realize(it, EINA_FALSE);
1926
1927 _elm_genlist_item_state_update(it);
1928 _elm_genlist_item_index_update(it);
1929
1930 if (EO_OBJ(it) == sd->focused_item)
1931 {
1932 _elm_genlist_item_focus_update(it);
1933 _elm_widget_item_highlight_in_theme(WIDGET(it), EO_OBJ(it));
1934 _elm_widget_highlight_in_theme_update(WIDGET(it));
1935 _elm_widget_focus_highlight_start(WIDGET(it));
1936 }
1937 }
1938
1939 size = eina_hash_find(sd->size_caches, &(it->itc));
1940 /* homogeneous genlist shortcut */
1941 if ((calc) && (sd->homogeneous) && (!it->item->mincalcd) && size)
1942 {
1943 it->item->w = it->item->minw = size->minw;
1944 it->item->h = it->item->minh = size->minh;
1945 size->expanded_depth = it->item->expanded_depth;
1946 it->item->mincalcd = EINA_TRUE;
1947 }
1948 else
1949 {
1950 if (eina_list_count(it->contents) != 0)
1951 ERR_ABORT("If you see this error, please notify us and we"
1952 "will fix it");
1953
1954 _view_inflate(VIEW(it), it, &it->texts, &it->contents, calc);
1955 if (it->has_contents != (!!it->contents))
1956 it->item->mincalcd = EINA_FALSE;
1957 it->has_contents = !!it->contents;
1958 if (it->flipped)
1959 {
1960 edje_object_signal_emit(VIEW(it), SIGNAL_FLIP_ENABLED, "elm");
1961 _item_content_realize(it, VIEW(it), &it->item->flip_contents,
1962 "flips", NULL, EINA_FALSE);
1963 }
1964
1965 /* access: unregister item which have no text and content */
1966 if (_elm_config->access_mode && !it->texts && !it->contents)
1967 _elm_access_widget_item_unregister(it->base);
1968
1969 if (!it->item->mincalcd)
1970 {
1971 if (sd->homogeneous && size)
1972 {
1973 it->item->w = it->item->minw = size->minw;
1974 it->item->h = it->item->minh = size->minh;
1975 it->item->mincalcd = EINA_TRUE;
1976 if (it->item->block->realized)
1977 it->item->w = it->item->block->w;
1978 }
1979 else
1980 {
1981 Evas_Coord mw = -1, mh = -1;
1982
1983 if (it->select_mode != ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY)
1984 elm_coords_finger_size_adjust(1, &mw, 1, &mh);
1985 if (sd->mode == ELM_LIST_COMPRESS)
1986 mw = sd->prev_viewport_w;
1987 // Process signal for proper size calc with text and content visible.
1988 edje_object_message_signal_process(VIEW(it));
1989 edje_object_size_min_restricted_calc(VIEW(it), &mw, &mh, mw, mh);
1990 it->item->w = it->item->minw = mw;
1991 it->item->h = it->item->minh = mh;
1992 it->item->mincalcd = EINA_TRUE;
1993
1994 if (sd->homogeneous)
1995 {
1996 if (size)
1997 eina_hash_del_by_key(sd->size_caches, &(it->itc));
1998
1999 size = ELM_NEW(Item_Size);
2000 size->itc = it->itc;
2001 size->expanded_depth = it->item->expanded_depth;
2002 size->minw = mw;
2003 size->minh = mh;
2004 eina_hash_add(sd->size_caches, &(it->itc), size);
2005 }
2006 }
2007 }
2008 if (!calc) evas_object_show(VIEW(it));
2009 }
2010
2011 if (it->tooltip.content_cb)
2012 {
2013 elm_wdg_item_tooltip_content_cb_set(EO_OBJ(it), it->tooltip.content_cb, it->tooltip.data, NULL);
2014 elm_wdg_item_tooltip_style_set(EO_OBJ(it), it->tooltip.style);
2015 elm_wdg_item_tooltip_window_mode_set(EO_OBJ(it), it->tooltip.free_size);
2016 }
2017
2018 if (it->mouse_cursor)
2019 elm_wdg_item_cursor_set(EO_OBJ(it), it->mouse_cursor);
2020
2021 it->realized = EINA_TRUE;
2022 it->want_unrealize = EINA_FALSE;
2023
2024 if (!calc)
2025 {
2026 if (it->item->tree_effect_hide_me)
2027 {
2028 if (sd->move_effect_mode
2029 != ELM_GENLIST_TREE_EFFECT_NONE)
2030 {
2031 //XXX: for compat
2032 edje_object_signal_emit(VIEW(it), SIGNAL_HIDE, "");
2033 edje_object_signal_emit(VIEW(it), SIGNAL_HIDE, "elm");
2034 }
2035 it->item->tree_effect_hide_me = EINA_FALSE;
2036 }
2037
2038 if (it->item->type == ELM_GENLIST_ITEM_NONE)
2039 {
2040 Evas_Object* eobj;
2041 Eina_List* l;
2042 EINA_LIST_FOREACH(it->contents, l, eobj)
2043 if (elm_widget_is(eobj) && elm_object_focus_allow_get(eobj))
2044 it->item_focus_chain = eina_list_append
2045 (it->item_focus_chain, eobj);
2046
2047 }
2048
2049 if (it->item->type == ELM_GENLIST_ITEM_TREE)
2050 {
2051 Evas_Object* t_eobj;
2052 Eina_List* tl;
2053 EINA_LIST_FOREACH(it->contents, tl, t_eobj)
2054 if (elm_widget_is(t_eobj) && elm_object_focus_allow_get(t_eobj))
2055 it->item_focus_chain = eina_list_append
2056 (it->item_focus_chain, t_eobj);
2057
2058 }
2059
2060 efl_event_callback_legacy_call(WIDGET(it), ELM_GENLIST_EVENT_REALIZED, EO_OBJ(it));
2061 if (it->base->func.realized) it->base->func.realized(EO_OBJ(it));
2062 }
2063
2064 //Send a signal so that an item changes its style according to its expand depth
2065 if (it->item->expanded_depth > 0)
2066 {
2067 char buf[126];
2068 snprintf(buf, sizeof(buf), "elm,state,expanded_depth,%d",
2069 it->item->expanded_depth);
2070 edje_object_signal_emit(VIEW(it), buf, "elm");
2071 }
2072
2073 if ((!calc) && (sd->decorate_all_mode) &&
2074 (it->item->type != ELM_GENLIST_ITEM_GROUP))
2075 {
2076 if (it->itc->decorate_all_item_style)
2077 {
2078 if (!it->deco_all_view)
2079 _decorate_all_item_realize(it, EINA_FALSE);
2080 edje_object_message_signal_process(it->deco_all_view);
2081 }
2082 }
2083
2084 if (it->decorate_it_set) _decorate_item_set(it);
2085
2086 edje_object_message_signal_process(VIEW(it));
2087
2088 if (sd->focus_on_realization == it)
2089 {
2090 _elm_widget_item_highlight_in_theme(WIDGET(it), EO_OBJ(it));
2091 _elm_widget_highlight_in_theme_update(WIDGET(it));
2092 _elm_widget_focus_highlight_start(WIDGET(it));
2093 efl_ui_focus_manager_focus_set(WIDGET(it), EO_OBJ(it));
2094 sd->focus_on_realization = NULL;
2095 }
2096 }
2097
2098 static void
_tree_effect_animator_cb(void * data,const Efl_Event * event EINA_UNUSED)2099 _tree_effect_animator_cb(void *data, const Efl_Event *event EINA_UNUSED)
2100 {
2101 int in = 0;
2102 const Eina_List *l;
2103 int y = 0, dy = 0, dh = 0;
2104 double effect_duration = 0.3, t;
2105 ELM_GENLIST_DATA_GET(data, sd);
2106 Eina_Bool end = EINA_FALSE, vis = EINA_TRUE;
2107 Evas_Coord ox, oy, ow, oh, cvx, cvy, cvw, cvh;
2108 Elm_Gen_Item *it = NULL, *it2, *expanded_next_it;
2109 Elm_Object_Item *eo_it = NULL, *eo_it2;
2110
2111 t = ((0.0 > (t = ecore_time_get() - sd->start_time)) ? 0.0 : t);
2112 evas_object_geometry_get(sd->pan_obj, &ox, &oy, &ow, &oh);
2113 evas_output_viewport_get
2114 (evas_object_evas_get(sd->pan_obj), &cvx, &cvy, &cvw, &cvh);
2115 if (t > effect_duration) end = EINA_TRUE;
2116
2117 // Below while statement is needed, when the genlist is resized.
2118 it2 = sd->expanded_item;
2119 eo_it2 = EO_OBJ(it2);
2120 while (eo_it2 && vis)
2121 {
2122 it2 = efl_data_scope_get(eo_it2, ELM_GENLIST_ITEM_CLASS);
2123 evas_object_move(VIEW(it2), it2->item->scrl_x, it2->item->scrl_y);
2124 vis = (ELM_RECTS_INTERSECT(it2->item->scrl_x, it2->item->scrl_y,
2125 it2->item->w, it2->item->h, cvx, cvy, cvw,
2126 cvh));
2127 eo_it2 = elm_genlist_item_prev_get(eo_it2);
2128 }
2129
2130 if (sd->expanded_next_item)
2131 {
2132 expanded_next_it = sd->expanded_next_item;
2133
2134 /* move items */
2135 EINA_LIST_FOREACH(sd->move_items, l, it)
2136 {
2137 if (sd->move_effect_mode == ELM_GENLIST_TREE_EFFECT_EXPAND)
2138 {
2139 expanded_next_it->item->old_scrl_y =
2140 sd->expanded_item->item->old_scrl_y
2141 + sd->expanded_item->item->h;
2142 if (expanded_next_it->item->scrl_y <=
2143 expanded_next_it->item->old_scrl_y) /* did not
2144 * calculate
2145 * next item
2146 * position */
2147 expanded_next_it->item->scrl_y = cvy + cvh;
2148
2149 dy = ((expanded_next_it->item->scrl_y >= (cvy + cvh)) ?
2150 cvy + cvh : expanded_next_it->item->scrl_y) -
2151 expanded_next_it->item->old_scrl_y;
2152 }
2153 else if (sd->move_effect_mode == ELM_GENLIST_TREE_EFFECT_CONTRACT)
2154 {
2155 if (expanded_next_it->item->scrl_y >
2156 expanded_next_it->item->old_scrl_y) /* did not
2157 * calculate
2158 * next item
2159 * position */
2160 expanded_next_it->item->old_scrl_y = cvy + cvh;
2161
2162 if (expanded_next_it->item->old_scrl_y > (cvy + cvh))
2163 {
2164 dy = (sd->expanded_item->item->scrl_y +
2165 sd->expanded_item->item->h) - cvy + cvh;
2166 expanded_next_it->item->old_scrl_y = cvy + cvh;
2167 }
2168 else
2169 {
2170 dy = (sd->expanded_item->item->scrl_y +
2171 sd->expanded_item->item->h) -
2172 expanded_next_it->item->old_scrl_y;
2173 }
2174 }
2175
2176 if (t <= effect_duration)
2177 {
2178 y = ((1 - (1 - (t / effect_duration)) *
2179 (1 - (t / effect_duration))) * dy);
2180 }
2181 else
2182 {
2183 end = EINA_TRUE;
2184 y = dy;
2185 }
2186
2187 if (!it->realized && !it->item->queued)
2188 _item_realize(it, in, 0);
2189 if (!it->hide) in++;
2190
2191 if (it != expanded_next_it)
2192 {
2193 it->item->old_scrl_y =
2194 expanded_next_it->item->old_scrl_y +
2195 expanded_next_it->item->h + dh;
2196
2197 dh += it->item->h;
2198 }
2199
2200 if ((it->item->old_scrl_y + y) < (cvy + cvh))
2201 _item_position(it, VIEW(it), it->item->scrl_x,
2202 it->item->old_scrl_y + y);
2203 }
2204 /* tree effect */
2205 _item_tree_effect(sd, y);
2206 }
2207 else
2208 {
2209 int expanded_item_num = 0;
2210 int num = 0;
2211
2212 if (sd->expanded_item)
2213 eo_it = elm_genlist_item_next_get(EO_OBJ(sd->expanded_item));
2214
2215 eo_it2 = eo_it;
2216 while (eo_it2)
2217 {
2218 expanded_item_num++;
2219 eo_it2 = elm_genlist_item_next_get(eo_it2);
2220 }
2221
2222 while (eo_it)
2223 {
2224 it = efl_data_scope_get(eo_it, ELM_GENLIST_ITEM_CLASS);
2225 num++;
2226 if (sd->expanded_item->item->expanded_depth >=
2227 it->item->expanded_depth) break;
2228 if (sd->move_effect_mode == ELM_GENLIST_TREE_EFFECT_EXPAND)
2229 {
2230 if (!it->item->tree_effect_finished)
2231 {
2232 if (t >= (((num - 1) * effect_duration) /
2233 expanded_item_num))
2234 {
2235 //XXX: for compat
2236 edje_object_signal_emit(VIEW(it), "flip_item", "");
2237 edje_object_signal_emit(VIEW(it), SIGNAL_FLIP_ITEM,
2238 "elm");
2239 _item_position(it, VIEW(it), it->item->scrl_x,
2240 it->item->scrl_y);
2241 it->item->tree_effect_finished = EINA_TRUE;
2242 }
2243 }
2244 }
2245 eo_it = elm_genlist_item_next_get(eo_it);
2246 }
2247 }
2248
2249 if (end)
2250 {
2251 _item_tree_effect_finish(sd);
2252 _elm_genlist_tree_effect_stop(sd);
2253 }
2254 }
2255
2256 static void
_group_items_recalc(void * data)2257 _group_items_recalc(void *data)
2258 {
2259 Eina_List *l;
2260 Elm_Gen_Item *git;
2261 Elm_Genlist_Data *sd = data;
2262 Evas_Coord vy;
2263 Evas *e = evas_object_evas_get(sd->obj);
2264
2265 evas_event_freeze(e);
2266 EINA_LIST_FOREACH(sd->group_items, l, git)
2267 {
2268 if (git->item->want_realize)
2269 {
2270 if (!git->realized) _item_realize(git, git->item->order_num_in, EINA_FALSE);
2271 if (sd->pin_item && git == sd->pin_item->item->group_item &&
2272 sd->pin_item->item->scrl_y <= (git->item->scrl_y + git->item->h))
2273 {
2274 elm_interface_scrollable_content_viewport_geometry_get
2275 (sd->obj, NULL, &vy, NULL, NULL);
2276 if ((git->item->scrl_y + git->item->h) > vy)
2277 {
2278 sd->pin_item->item->scrl_y = git->item->scrl_y + git->item->h;
2279 evas_object_move(VIEW(sd->pin_item),
2280 sd->pin_item->item->scrl_x, sd->pin_item->item->scrl_y);
2281 }
2282 }
2283 else if (sd->pin_item && sd->pin_item_top && git != sd->pin_item->item->group_item &&
2284 (git->item->scrl_y < (sd->pin_item->item->scrl_y + sd->pin_item->item->h)))
2285 git->item->scrl_y = sd->pin_item->item->scrl_y + sd->pin_item->item->h;
2286
2287 efl_gfx_entity_geometry_set(VIEW(git), EINA_RECT(git->item->scrl_x, git->item->scrl_y, sd->minw, git->item->h));
2288 evas_object_stack_above(VIEW(git), sd->stack[1]);
2289 evas_object_show(VIEW(git));
2290 }
2291 else if (!git->item->want_realize && git->realized)
2292 {
2293 if (!git->dragging)
2294 _elm_genlist_item_unrealize(git, EINA_FALSE);
2295 }
2296 }
2297 evas_event_thaw(e);
2298 evas_event_thaw_eval(e);
2299 }
2300
2301 static Eina_Bool
_reorder_move_animator_cb(void * data)2302 _reorder_move_animator_cb(void *data)
2303 {
2304 double t;
2305 Elm_Gen_Item *it = data;
2306 Eina_Bool down = EINA_FALSE;
2307 ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
2308 int y, dy = it->item->h / 10 * elm_config_scale_get(), diff;
2309
2310 t = ((0.0 > (t = ecore_loop_time_get()
2311 - sd->start_time)) ? 0.0 : t);
2312
2313 if (t <= REORDER_EFFECT_TIME)
2314 y = (1 * sin((t / REORDER_EFFECT_TIME) * (M_PI / 2)) * dy);
2315 else y = dy;
2316
2317 diff = abs(it->item->old_scrl_y - it->item->scrl_y);
2318 if (diff < dy) y = diff;
2319 else if (diff > it->item->h) y = diff / 2;
2320
2321 if (it->item->old_scrl_y < it->item->scrl_y)
2322 {
2323 it->item->old_scrl_y += y;
2324 down = EINA_TRUE;
2325 }
2326 else if (it->item->old_scrl_y > it->item->scrl_y)
2327 {
2328 it->item->old_scrl_y -= y;
2329 down = EINA_FALSE;
2330 }
2331
2332 if (it->deco_all_view)
2333 _item_position
2334 (it, it->deco_all_view, it->item->scrl_x, it->item->old_scrl_y);
2335 else
2336 _item_position(it, VIEW(it), it->item->scrl_x, it->item->old_scrl_y);
2337 _group_items_recalc(sd);
2338
2339 if ((sd->reorder_pan_move) ||
2340 (down && it->item->old_scrl_y >= it->item->scrl_y) ||
2341 (!down && it->item->old_scrl_y <= it->item->scrl_y))
2342 {
2343 it->item->old_scrl_y = it->item->scrl_y;
2344 it->item->move_effect_enabled = EINA_FALSE;
2345 sd->reorder_move_animator = NULL;
2346 return ECORE_CALLBACK_CANCEL;
2347 }
2348
2349 return ECORE_CALLBACK_RENEW;
2350 }
2351
2352 static int
_reorder_item_space_get(Elm_Gen_Item * it)2353 _reorder_item_space_get(Elm_Gen_Item *it)
2354 {
2355 ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
2356 Elm_Gen_Item *reorder_it = sd->reorder_it;
2357 Evas_Coord rox, roy, row, roh, oy, oh;
2358 Eina_Bool top = EINA_FALSE;
2359
2360 if (!reorder_it) return 0;
2361
2362 evas_object_geometry_get(sd->pan_obj, NULL, &oy, NULL, &oh);
2363 evas_object_geometry_get
2364 (sd->VIEW(reorder_it), &rox, &roy, &row, &roh);
2365
2366 if ((sd->reorder_start_y < it->item->block->y) &&
2367 (roy - oy + (roh / 2) >= it->item->block->y - sd->pan_y))
2368 {
2369 it->item->block->reorder_offset =
2370 sd->reorder_it->item->h * -1;
2371 if (it->item->block->count == 1)
2372 sd->reorder_rel = it;
2373 }
2374 else if ((sd->reorder_start_y >= it->item->block->y) &&
2375 (roy - oy + (roh / 2) <= it->item->block->y - sd->pan_y))
2376 {
2377 it->item->block->reorder_offset = sd->reorder_it->item->h;
2378 }
2379 else
2380 it->item->block->reorder_offset = 0;
2381
2382 it->item->scrl_y += it->item->block->reorder_offset;
2383
2384 top = (ELM_RECTS_INTERSECT
2385 (it->item->scrl_x, it->item->scrl_y, it->item->w, it->item->h,
2386 rox, roy + (roh / 2), row, 1));
2387 if (top)
2388 {
2389 sd->reorder_rel = it;
2390 it->item->scrl_y += sd->reorder_it->item->h;
2391 return sd->reorder_it->item->h;
2392 }
2393 else
2394 return 0;
2395 }
2396
2397 static void
_pin_item_recalc(Elm_Gen_Item * it)2398 _pin_item_recalc(Elm_Gen_Item *it)
2399 {
2400 Evas_Coord vx, vy, vw, vh;
2401 ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
2402
2403 sd->pin_item_top = EINA_FALSE;
2404 elm_interface_scrollable_content_viewport_geometry_get
2405 (sd->obj, &vx, &vy, &vw, &vh);
2406 if (it->item->scrl_x < vx)
2407 it->item->scrl_x = vx;
2408 else if (it->item->scrl_x + it->item->w > vx + vw)
2409 it->item->scrl_x = vx + vw - it->item->w;
2410
2411 if (it->item->scrl_y < vy)
2412 {
2413 sd->pin_item_top = EINA_TRUE;
2414 it->item->scrl_y = vy;
2415 }
2416 else if (it->item->scrl_y + it->item->h > vy + vh)
2417 it->item->scrl_y = vy + vh - it->item->h;
2418
2419 efl_gfx_entity_geometry_set(VIEW(it), EINA_RECT(it->item->scrl_x, it->item->scrl_y, it->item->w, it->item->h));
2420 evas_object_show(VIEW(it));
2421 }
2422
2423 static void
_item_block_position(Item_Block * itb,const int blk_idx)2424 _item_block_position(Item_Block *itb, const int blk_idx)
2425 {
2426 Elm_Gen_Item *it;
2427 Elm_Gen_Item *git;
2428 const Eina_List *l;
2429 Eina_Bool vis = EINA_FALSE;
2430 Evas_Coord y = 0, ox, oy, ow, oh, cvx, cvy, cvw, cvh;
2431 Elm_Genlist_Data *sd = NULL;
2432 int vis_count = 0;
2433 Evas *e = evas_object_evas_get((itb->sd)->obj);
2434
2435 evas_event_freeze(e);
2436 evas_object_geometry_get(itb->sd->pan_obj, &ox, &oy, &ow, &oh);
2437 evas_output_viewport_get(e, &cvx, &cvy, &cvw, &cvh);
2438
2439 EINA_LIST_FOREACH(itb->items, l, it)
2440 {
2441 sd = it->item->wsd;
2442 if (sd->reorder_it == it) continue;
2443
2444 if (it->itc->func.filter_get)
2445 _item_filtered_get(it, sd);
2446 if (it->hide)
2447 {
2448 if (it->realized) evas_object_hide(VIEW(it));
2449 continue;
2450 }
2451 it->x = 0;
2452 it->y = y;
2453 it->item->w = itb->w;
2454 it->item->scrl_x = itb->x + it->x - sd->pan_x + ox;
2455 it->item->scrl_y = itb->y + it->y - sd->pan_y + oy;
2456
2457 vis = (ELM_RECTS_INTERSECT
2458 (it->item->scrl_x, it->item->scrl_y, it->item->w, it->item->h,
2459 cvx, cvy, cvw, cvh));
2460 if (!(it->item->type & ELM_GENLIST_ITEM_GROUP))
2461 {
2462 if ((itb->realized) && (!it->realized))
2463 {
2464 if (vis) _item_realize(it, blk_idx + vis_count, EINA_FALSE);
2465 }
2466 if ((blk_idx + vis_count) != it->item->order_num_in)
2467 {
2468 _item_order_update(it, blk_idx + vis_count, EINA_TRUE);
2469 }
2470 if (it->realized)
2471 {
2472 if (vis || it->dragging)
2473 {
2474 if (sd->reorder_mode)
2475 y += _reorder_item_space_get(it);
2476 git = it->item->group_item;
2477 if (git)
2478 {
2479 if (git->item->scrl_y < oy)
2480 git->item->scrl_y = oy;
2481 if ((git->item->scrl_y + git->item->h) >
2482 (it->item->scrl_y + it->item->h))
2483 git->item->scrl_y = (it->item->scrl_y +
2484 it->item->h) - git->item->h;
2485 git->item->scrl_x = it->item->scrl_x;
2486 git->item->want_realize = EINA_TRUE;
2487 }
2488 if ((sd->reorder_it) &&
2489 (it->item->old_scrl_y != it->item->scrl_y))
2490 {
2491 if (!it->item->move_effect_enabled)
2492 {
2493 it->item->move_effect_enabled = EINA_TRUE;
2494 sd->reorder_move_animator =
2495 ecore_evas_animator_add(e,
2496 _reorder_move_animator_cb, it);
2497 }
2498 }
2499 if (!it->item->move_effect_enabled)
2500 {
2501 if ((sd->decorate_all_mode) &&
2502 (it->itc->decorate_all_item_style))
2503 _decorate_all_item_position
2504 (it, it->item->scrl_x, it->item->scrl_y);
2505 else
2506 {
2507 if (!sd->tree_effect_enabled ||
2508 (sd->move_effect_mode ==
2509 ELM_GENLIST_TREE_EFFECT_NONE) ||
2510 ((sd->move_effect_mode !=
2511 ELM_GENLIST_TREE_EFFECT_NONE) &&
2512 (it->item->old_scrl_y ==
2513 it->item->scrl_y)))
2514 {
2515 if (it->item->deco_it_view)
2516 _item_position
2517 (it, it->item->deco_it_view,
2518 it->item->scrl_x,
2519 it->item->scrl_y);
2520 else
2521 _item_position
2522 (it, VIEW(it), it->item->scrl_x,
2523 it->item->scrl_y);
2524 }
2525 }
2526 it->item->old_scrl_y = it->item->scrl_y;
2527 }
2528 }
2529 else
2530 {
2531 if (!sd->tree_effect_animator && (it != sd->pin_item))
2532 _elm_genlist_item_unrealize(it, EINA_FALSE);
2533 }
2534 }
2535 }
2536 else
2537 {
2538 if (vis) it->item->want_realize = EINA_TRUE;
2539 }
2540 y += it->item->h;
2541 vis_count++;
2542
2543 if (it == sd->pin_item)
2544 _pin_item_recalc(it);
2545 }
2546
2547 evas_event_thaw(e);
2548 evas_event_thaw_eval(e);
2549 }
2550
2551 static inline void
_flush_block_order(Elm_Genlist_Data * sd)2552 _flush_block_order(Elm_Genlist_Data *sd)
2553 {
2554 Item_Block *itb;
2555 Eina_List *blocks = NULL;
2556
2557 EINA_INLIST_FOREACH(sd->blocks, itb)
2558 {
2559 if (itb->adapter)
2560 blocks = eina_list_append(blocks, itb->adapter);
2561 }
2562
2563 efl_ui_focus_manager_calc_update_order(sd->obj, sd->obj, blocks);
2564 }
2565
2566 static void
_item_block_realize(Item_Block * itb)2567 _item_block_realize(Item_Block *itb)
2568 {
2569 Elm_Gen_Item *it;
2570 Eina_List *n;
2571
2572 if (itb->realized) return;
2573
2574 itb->realized = EINA_TRUE;
2575 itb->want_unrealize = EINA_FALSE;
2576
2577 if (!itb->adapter)
2578 {
2579 itb->adapter = efl_add(EFL_UI_FOCUS_COMPOSITION_ADAPTER_CLASS, itb->sd->obj);
2580 efl_ui_focus_composition_adapter_focus_manager_parent_set(itb->adapter, itb->sd->obj);
2581 efl_ui_focus_composition_adapter_focus_manager_object_set(itb->adapter, itb->sd->obj);
2582 efl_ui_focus_manager_calc_register_logical(itb->sd->obj, itb->adapter, itb->sd->obj, NULL);
2583 _flush_block_order(itb->sd);
2584 }
2585
2586 EINA_LIST_FOREACH(itb->items, n, it)
2587 {
2588 efl_ui_focus_manager_calc_register_logical(itb->sd->obj, EO_OBJ(it), itb->adapter, NULL);
2589 }
2590 }
2591
2592 static Eina_Bool
_elm_genlist_tree_effect_setup(Elm_Genlist_Data * sd)2593 _elm_genlist_tree_effect_setup(Elm_Genlist_Data *sd)
2594 {
2595 if (!sd->tree_effect_animator)
2596 {
2597 _item_tree_effect_before(sd->expanded_item);
2598 evas_object_raise(sd->event_block_rect);
2599 evas_object_stack_below(sd->event_block_rect, sd->stack[1]);
2600 evas_object_show(sd->event_block_rect);
2601 sd->start_time = ecore_time_get();
2602 efl_event_callback_add(sd->obj, EFL_CANVAS_OBJECT_EVENT_ANIMATOR_TICK, _tree_effect_animator_cb, sd->obj);
2603 sd->tree_effect_animator = 1;
2604 return EINA_TRUE;
2605 }
2606 return EINA_FALSE;
2607 }
2608
2609 static void
_elm_genlist_tree_effect_stop(Elm_Genlist_Data * sd)2610 _elm_genlist_tree_effect_stop(Elm_Genlist_Data *sd)
2611 {
2612 if (sd->tree_effect_animator)
2613 {
2614 sd->tree_effect_animator = 0;
2615 efl_event_callback_del(sd->obj, EFL_CANVAS_OBJECT_EVENT_ANIMATOR_TICK, _tree_effect_animator_cb, sd->obj);
2616 }
2617 }
2618
2619 EOLIAN static void
_elm_genlist_pan_efl_canvas_group_group_calculate(Eo * obj,Elm_Genlist_Pan_Data * psd)2620 _elm_genlist_pan_efl_canvas_group_group_calculate(Eo *obj, Elm_Genlist_Pan_Data *psd)
2621 {
2622 Evas_Coord ox, oy, ow, oh, cvx, cvy, cvw, cvh;
2623 Evas_Coord vx = 0, vy = 0, vw = 0, vh = 0;
2624 Elm_Gen_Item *git;
2625 Item_Block *itb;
2626 Eina_List *l;
2627 int in = 0;
2628 Evas *e = evas_object_evas_get(obj);;
2629
2630 Elm_Genlist_Data *sd = psd->wsd;
2631
2632 efl_canvas_group_need_recalculate_set(obj, EINA_FALSE);
2633 evas_event_freeze(e);
2634
2635 if (sd->pan_changed)
2636 {
2637 _calc_job(sd);
2638 sd->pan_changed = EINA_FALSE;
2639 }
2640
2641 evas_object_geometry_get(obj, &ox, &oy, &ow, &oh);
2642 evas_output_viewport_get(e, &cvx, &cvy, &cvw, &cvh);
2643
2644 if (sd->tree_effect_enabled &&
2645 (sd->move_effect_mode != ELM_GENLIST_TREE_EFFECT_NONE))
2646 {
2647 _elm_genlist_tree_effect_setup(sd);
2648 }
2649
2650 EINA_INLIST_FOREACH(sd->blocks, itb)
2651 {
2652 itb->w = sd->minw;
2653 if (ELM_RECTS_INTERSECT(itb->x - sd->pan_x + ox,
2654 itb->y - sd->pan_y + oy,
2655 itb->w, itb->h,
2656 cvx, cvy, cvw, cvh))
2657 {
2658 if ((!itb->realized) || (itb->changed))
2659 _item_block_realize(itb);
2660 _item_block_position(itb, in);
2661 }
2662 else
2663 {
2664 if (itb->realized) _item_block_unrealize(itb);
2665 if (sd->pin_item && itb == sd->pin_item->item->block)
2666 {
2667 if (!sd->pin_item->realized)
2668 _item_realize(sd->pin_item, sd->pin_item->item->order_num_in, EINA_FALSE);
2669 sd->pin_item->item->w = itb->w;
2670 sd->pin_item->item->scrl_x = itb->x - sd->pan_x + ox;
2671 sd->pin_item->item->scrl_y = itb->y - sd->pan_y + oy;
2672 _pin_item_recalc(sd->pin_item);
2673 }
2674 }
2675 in += itb->vis_count;
2676 }
2677 if ((!sd->reorder_it) || (sd->reorder_pan_move))
2678 _group_items_recalc(sd);
2679 if ((sd->reorder_mode) && (sd->reorder_it))
2680 {
2681 if (sd->pan_y != sd->reorder_old_pan_y)
2682 sd->reorder_pan_move = EINA_TRUE;
2683 else sd->reorder_pan_move = EINA_FALSE;
2684
2685 evas_object_raise(sd->VIEW(reorder_it));
2686 evas_object_stack_below(sd->VIEW(reorder_it), sd->stack[1]);
2687 sd->reorder_old_pan_y = sd->pan_y;
2688 sd->start_time = ecore_loop_time_get();
2689 }
2690
2691 if (!sd->tree_effect_enabled ||
2692 (sd->move_effect_mode == ELM_GENLIST_TREE_EFFECT_NONE))
2693 _item_auto_scroll(sd);
2694
2695 elm_interface_scrollable_content_pos_get((sd)->obj, &vx, &vy);
2696 elm_interface_scrollable_content_viewport_geometry_get
2697 ((sd)->obj, NULL, NULL, &vw, &vh);
2698
2699 if (sd->reorder_fast == 1)
2700 elm_interface_scrollable_content_region_show((sd)->obj, vx, vy - 10, vw, vh);
2701 else if (sd->reorder_fast == -1)
2702 elm_interface_scrollable_content_region_show((sd)->obj, vx, vy + 10, vw, vh);
2703
2704 if (sd->focused_item && !sd->item_loop_enable)
2705 _elm_widget_focus_highlight_start(psd->wobj);
2706
2707 EINA_LIST_FOREACH(sd->group_items, l, git)
2708 {
2709 git->item->want_realize = EINA_FALSE;
2710 if (git->realized) evas_object_raise(VIEW(git));
2711 }
2712
2713 if (sd->pin_item)
2714 evas_object_raise(VIEW(sd->pin_item));
2715 //update item before the render to prevent delayed update by job.
2716 if (sd->update_job)
2717 {
2718 ELM_SAFE_FREE(sd->update_job, ecore_job_del);
2719 _update_job(sd->obj);
2720 }
2721
2722 evas_event_thaw(e);
2723 evas_event_thaw_eval(e);
2724
2725 efl_event_callback_legacy_call
2726 (psd->wobj, ELM_INTERFACE_SCROLLABLE_EVENT_CHANGED, NULL);
2727 }
2728
2729 EOLIAN static void
_elm_genlist_pan_efl_object_destructor(Eo * obj,Elm_Genlist_Pan_Data * psd)2730 _elm_genlist_pan_efl_object_destructor(Eo *obj, Elm_Genlist_Pan_Data *psd)
2731 {
2732 efl_data_unref(psd->wobj, psd->wsd);
2733 efl_destructor(efl_super(obj, MY_PAN_CLASS));
2734 }
2735
2736 EOLIAN static void
_elm_genlist_pan_class_constructor(Efl_Class * klass)2737 _elm_genlist_pan_class_constructor(Efl_Class *klass)
2738 {
2739 evas_smart_legacy_type_register(MY_PAN_CLASS_NAME_LEGACY, klass);
2740 }
2741
2742 static Eina_Bool
_item_multi_select_up(Elm_Genlist_Data * sd)2743 _item_multi_select_up(Elm_Genlist_Data *sd)
2744 {
2745 Elm_Object_Item *eo_prev;
2746
2747 if (!sd->selected) return EINA_FALSE;
2748 if (!sd->multi) return EINA_FALSE;
2749
2750 eo_prev = elm_genlist_item_prev_get(sd->last_selected_item);
2751 while (eo_prev)
2752 {
2753 ELM_GENLIST_ITEM_DATA_GET(eo_prev, prev);
2754 if ((!_is_no_select(prev)) &&
2755 (!elm_object_item_disabled_get(eo_prev)) && (!prev->hide))
2756 break;
2757 eo_prev = EO_OBJ(ELM_GEN_ITEM_PREV(prev));
2758 }
2759 if (!eo_prev) return EINA_TRUE;
2760
2761 if (elm_genlist_item_selected_get(eo_prev))
2762 {
2763 elm_genlist_item_selected_set(sd->last_selected_item, EINA_FALSE);
2764 sd->last_selected_item = eo_prev;
2765 }
2766 else
2767 {
2768 elm_genlist_item_selected_set(eo_prev, EINA_TRUE);
2769 }
2770 return EINA_TRUE;
2771 }
2772
2773 static Eina_Bool
_item_multi_select_down(Elm_Genlist_Data * sd)2774 _item_multi_select_down(Elm_Genlist_Data *sd)
2775 {
2776 Elm_Object_Item *eo_next;
2777
2778 if (!sd->selected) return EINA_FALSE;
2779 if (!sd->multi) return EINA_FALSE;
2780
2781 eo_next = elm_genlist_item_next_get(sd->last_selected_item);
2782 while ((eo_next))
2783 {
2784 ELM_GENLIST_ITEM_DATA_GET(eo_next, next);
2785 if ((!_is_no_select(next)) &&
2786 (!elm_object_item_disabled_get(eo_next)) && (!next->hide))
2787 break;
2788 eo_next = EO_OBJ(ELM_GEN_ITEM_NEXT(next));
2789 }
2790 if (!eo_next) return EINA_TRUE;
2791
2792 if (elm_genlist_item_selected_get(eo_next))
2793 {
2794 elm_genlist_item_selected_set(sd->last_selected_item, EINA_FALSE);
2795 sd->last_selected_item = eo_next;
2796 }
2797 else
2798 {
2799 elm_genlist_item_selected_set(eo_next, EINA_TRUE);
2800 }
2801
2802 return EINA_TRUE;
2803 }
2804
2805 static Eina_Bool
_all_items_deselect(Elm_Genlist_Data * sd)2806 _all_items_deselect(Elm_Genlist_Data *sd)
2807 {
2808 if (!sd->selected) return EINA_FALSE;
2809
2810 sd->deselecting = eina_list_clone(sd->selected);
2811 while (sd->deselecting)
2812 {
2813 Elm_Object_Item *it = eina_list_data_get(sd->deselecting);
2814
2815 sd->deselecting = eina_list_remove_list(sd->deselecting, sd->deselecting);
2816 elm_genlist_item_selected_set(it, EINA_FALSE);
2817 }
2818
2819 return EINA_TRUE;
2820 }
2821
2822 static Eina_Bool
_item_single_select_up(Elm_Genlist_Data * sd)2823 _item_single_select_up(Elm_Genlist_Data *sd)
2824 {
2825 Elm_Gen_Item *prev = NULL;
2826
2827 if (!sd->selected)
2828 prev = ELM_GEN_ITEM_FROM_INLIST(sd->items->last);
2829 else
2830 {
2831 Elm_Object_Item *eo_prev = elm_genlist_item_prev_get
2832 (sd->last_selected_item);
2833 prev = efl_data_scope_get(eo_prev, ELM_GENLIST_ITEM_CLASS);
2834 }
2835
2836 while (prev)
2837 {
2838 if ((!_is_no_select(prev)) &&
2839 (!elm_object_item_disabled_get(EO_OBJ(prev))) && (!prev->hide))
2840 break;
2841 prev = ELM_GEN_ITEM_PREV(prev);
2842 }
2843
2844 if (!prev) return EINA_FALSE;
2845
2846 _all_items_deselect(sd);
2847
2848 elm_genlist_item_selected_set(EO_OBJ(prev), EINA_TRUE);
2849 return EINA_TRUE;
2850 }
2851
2852 static Eina_Bool
_item_single_select_down(Elm_Genlist_Data * sd)2853 _item_single_select_down(Elm_Genlist_Data *sd)
2854 {
2855 Elm_Gen_Item *next = NULL;
2856 Elm_Object_Item *eo_next = NULL;
2857
2858 if (!sd->selected)
2859 next = ELM_GEN_ITEM_FROM_INLIST(sd->items);
2860 else
2861 {
2862 eo_next = elm_genlist_item_next_get(sd->last_selected_item);
2863 next = efl_data_scope_get(eo_next, ELM_GENLIST_ITEM_CLASS);
2864 }
2865
2866 while (next)
2867 {
2868 if ((!_is_no_select(next)) &&
2869 (!elm_object_item_disabled_get(EO_OBJ(next))) && (!next->hide))
2870 break;
2871 next = ELM_GEN_ITEM_NEXT(next);
2872 }
2873
2874 if (!next) return EINA_FALSE;
2875
2876 _all_items_deselect(sd);
2877
2878 elm_genlist_item_selected_set(EO_OBJ(next), EINA_TRUE);
2879
2880 return EINA_TRUE;
2881 }
2882
2883 static void
_elm_genlist_item_focused(Elm_Object_Item * eo_it)2884 _elm_genlist_item_focused(Elm_Object_Item *eo_it)
2885 {
2886 ELM_GENLIST_ITEM_DATA_GET(eo_it, it);
2887 Evas_Object *obj = WIDGET(it);
2888 ELM_GENLIST_DATA_GET(obj, sd);
2889
2890 if (_is_no_select(it) ||
2891 (eo_it == sd->focused_item) ||
2892 (elm_wdg_item_disabled_get(eo_it)))
2893 return;
2894
2895 if (it != sd->pin_item)
2896 {
2897 switch (_elm_config->focus_autoscroll_mode)
2898 {
2899 case ELM_FOCUS_AUTOSCROLL_MODE_SHOW:
2900 elm_genlist_item_show(eo_it,
2901 ELM_GENLIST_ITEM_SCROLLTO_IN);
2902 break;
2903 case ELM_FOCUS_AUTOSCROLL_MODE_BRING_IN:
2904 elm_genlist_item_bring_in(eo_it,
2905 ELM_GENLIST_ITEM_SCROLLTO_IN);
2906 break;
2907 default:
2908 break;
2909 }
2910 }
2911
2912 sd->focused_item = eo_it;
2913
2914 if (it->realized)
2915 _elm_genlist_item_focus_update(it);
2916 efl_event_callback_legacy_call(obj, ELM_GENLIST_EVENT_ITEM_FOCUSED, eo_it);
2917 if (_elm_config->atspi_mode)
2918 efl_access_state_changed_signal_emit(eo_it, EFL_ACCESS_STATE_TYPE_FOCUSED, EINA_TRUE);
2919 }
2920
2921 static void
_elm_genlist_item_unfocused(Elm_Object_Item * eo_it)2922 _elm_genlist_item_unfocused(Elm_Object_Item *eo_it)
2923 {
2924 if (!eo_it) return;
2925
2926 ELM_GENLIST_ITEM_DATA_GET(eo_it, it);
2927 Evas_Object *obj = WIDGET(it);
2928 Evas_Object *win = efl_provider_find(obj, EFL_UI_WIN_CLASS);
2929 ELM_GENLIST_DATA_GET(obj, sd);
2930
2931 if (_is_no_select(it))
2932 return;
2933
2934 if ((!sd->focused_item) ||
2935 (eo_it != sd->focused_item))
2936 return;
2937
2938 if (elm_win_focus_highlight_enabled_get(win))
2939 {
2940 ELM_GENLIST_ITEM_DATA_GET(sd->focused_item, focus_it);
2941 edje_object_signal_emit(VIEW(focus_it), SIGNAL_UNFOCUSED, "elm");
2942 }
2943
2944 sd->focused_item = NULL;
2945 efl_event_callback_legacy_call(obj, ELM_GENLIST_EVENT_ITEM_UNFOCUSED, eo_it);
2946 if (_elm_config->atspi_mode)
2947 efl_access_state_changed_signal_emit(eo_it, EFL_ACCESS_STATE_TYPE_FOCUSED, EINA_FALSE);
2948 }
2949
2950 static Eina_Bool
_item_focused_next(Evas_Object * obj,Elm_Focus_Direction dir)2951 _item_focused_next(Evas_Object *obj, Elm_Focus_Direction dir)
2952 {
2953 ELM_GENLIST_DATA_GET(obj, sd);
2954 Elm_Gen_Item *next;
2955 Elm_Object_Item *eo_next;
2956 Elm_Object_Item *eo_first_item;
2957 Elm_Object_Item *eo_last_item;
2958
2959 if (!sd->focused_item)
2960 {
2961 if (dir == ELM_FOCUS_UP)
2962 next = ELM_GEN_ITEM_FROM_INLIST(sd->items->last);
2963 else if (dir == ELM_FOCUS_DOWN)
2964 next = ELM_GEN_ITEM_FROM_INLIST(sd->items);
2965 else
2966 return EINA_FALSE;
2967
2968 while ((next) &&
2969 ((elm_wdg_item_disabled_get(EO_OBJ(next))) ||
2970 (_is_no_select(next))))
2971 if (!next->hide) next = ELM_GEN_ITEM_NEXT(next);
2972 }
2973 else
2974 {
2975 ELM_GENLIST_ITEM_DATA_GET(sd->focused_item, focus_it);
2976 if (dir == ELM_FOCUS_UP)
2977 {
2978 eo_first_item = elm_genlist_first_item_get(WIDGET(focus_it));
2979 if (eo_first_item == sd->focused_item) return EINA_FALSE;
2980 eo_next = elm_genlist_item_prev_get(sd->focused_item);
2981 next = efl_data_scope_get(eo_next, ELM_GENLIST_ITEM_CLASS);
2982
2983 while ((next) &&
2984 ((elm_wdg_item_disabled_get(eo_next)) ||
2985 (_is_no_select(next))))
2986 {
2987 eo_next = elm_genlist_item_prev_get(eo_next);
2988 next = efl_data_scope_get(eo_next, ELM_GENLIST_ITEM_CLASS);
2989 }
2990 }
2991 else if (dir == ELM_FOCUS_DOWN)
2992 {
2993 eo_last_item = elm_genlist_last_item_get(WIDGET(focus_it));
2994 if (eo_last_item == sd->focused_item) return EINA_FALSE;
2995 eo_next = elm_genlist_item_next_get(sd->focused_item);
2996 next = efl_data_scope_get(eo_next, ELM_GENLIST_ITEM_CLASS);
2997
2998 while ((next) &&
2999 ((elm_wdg_item_disabled_get(eo_next)) ||
3000 (_is_no_select(next))))
3001 {
3002 eo_next = elm_genlist_item_next_get(eo_next);
3003 next = efl_data_scope_get(eo_next, ELM_GENLIST_ITEM_CLASS);
3004 }
3005 }
3006 else
3007 return EINA_FALSE;
3008
3009 if (!next) return EINA_FALSE;
3010 }
3011
3012 elm_object_item_focus_set(EO_OBJ(next), EINA_TRUE);
3013
3014 return EINA_TRUE;
3015 }
3016
3017 static void
_elm_genlist_item_content_focus_set(Elm_Gen_Item * it,Elm_Focus_Direction dir)3018 _elm_genlist_item_content_focus_set(Elm_Gen_Item *it, Elm_Focus_Direction dir)
3019 {
3020 Evas_Object *focused_obj = NULL;
3021 Eina_List *l;
3022 if (!it) return;
3023
3024 if (!it->item->wsd->focus_on_selection_enabled) return;
3025
3026 if (!it->item_focus_chain)
3027 {
3028 elm_object_focus_set(VIEW(it), EINA_TRUE);
3029 return;
3030 }
3031
3032 EINA_LIST_FOREACH(it->item_focus_chain, l, focused_obj)
3033 if (elm_object_focus_get(focused_obj)) break;
3034
3035 /* FOCUS-FIXME
3036 if (focused_obj && (dir != ELM_FOCUS_PREVIOUS))
3037 {
3038 Evas_Object *nextfocus;
3039 Elm_Object_Item *nextfocus_item;
3040 if (efl_ui_widget_focus_next_get(focused_obj, dir, &nextfocus, &nextfocus_item))
3041 {
3042 if (nextfocus_item)
3043 elm_object_item_focus_set(nextfocus_item, EINA_TRUE);
3044 else
3045 elm_object_focus_set(nextfocus, EINA_TRUE);
3046 return;
3047 }
3048 }
3049 */
3050
3051 if (!l) l = it->item_focus_chain;
3052
3053 if (dir == ELM_FOCUS_RIGHT)
3054 {
3055 l = eina_list_next(l);
3056 if (!l) l = it->item_focus_chain;
3057 }
3058 else if (dir == ELM_FOCUS_LEFT)
3059 {
3060 l = eina_list_prev(l);
3061 if (!l) l = eina_list_last(it->item_focus_chain);
3062 }
3063
3064 elm_object_focus_set(eina_list_data_get(l), EINA_TRUE);
3065 }
3066
3067 static Eina_Bool
_key_action_move_dir(Evas_Object * obj,Elm_Focus_Direction dir,Eina_Bool multi)3068 _key_action_move_dir(Evas_Object *obj, Elm_Focus_Direction dir, Eina_Bool multi)
3069 {
3070 ELM_GENLIST_DATA_GET(obj, sd);
3071 Elm_Object_Item *it = NULL;
3072 Eina_Bool ret = EINA_FALSE;
3073 Evas_Coord v = 0;
3074 Evas_Coord min = 0;
3075 Eina_Bool focus_only = EINA_FALSE;
3076
3077 // get content size and viewport size
3078 elm_interface_scrollable_content_viewport_geometry_get
3079 (obj, NULL, NULL, NULL, &v);
3080 elm_interface_scrollable_content_size_get(obj, NULL, &min);
3081
3082 if (_elm_config->item_select_on_focus_disable)
3083 {
3084 ret = _item_focused_next(obj, dir);
3085 }
3086 else
3087 {
3088 if (multi)
3089 {
3090 if (dir == ELM_FOCUS_UP)
3091 ret = _item_multi_select_up(sd);
3092 else if (dir == ELM_FOCUS_DOWN)
3093 ret = _item_multi_select_down(sd);
3094 }
3095 else
3096 {
3097 if ((sd->focused_item) && (dir == ELM_FOCUS_UP))
3098 ret = _item_single_select_up(sd);
3099 else if (dir == ELM_FOCUS_DOWN)
3100 ret = _item_single_select_down(sd);
3101 }
3102 }
3103 if (ret)
3104 return EINA_TRUE;
3105
3106 focus_only = _elm_config->item_select_on_focus_disable;
3107 // handle item loop feature
3108 if (sd->item_loop_enable && !sd->item_looping_on)
3109 {
3110 if (min < v)
3111 {
3112 if (dir == ELM_FOCUS_UP)
3113 {
3114 elm_layout_signal_emit(obj, "elm,action,looping,up", "elm");
3115 sd->item_looping_on = EINA_TRUE;
3116 }
3117 else if (dir == ELM_FOCUS_DOWN)
3118 {
3119 elm_layout_signal_emit(obj, "elm,action,looping,down", "elm");
3120 sd->item_looping_on = EINA_TRUE;
3121 }
3122 }
3123 else
3124 {
3125 if (dir == ELM_FOCUS_UP)
3126 {
3127 it = elm_genlist_last_item_get(obj);
3128 ELM_GENLIST_ITEM_DATA_GET(it, gen_it);
3129 while (_is_no_select(gen_it) || elm_wdg_item_disabled_get(it))
3130 it = elm_genlist_item_prev_get(it);
3131 }
3132 else if (dir == ELM_FOCUS_DOWN)
3133 {
3134 it = elm_genlist_first_item_get(obj);
3135 ELM_GENLIST_ITEM_DATA_GET(it, gen_it);
3136 while (_is_no_select(gen_it) || elm_wdg_item_disabled_get(it))
3137 it = elm_genlist_item_next_get(it);
3138 }
3139
3140 if (it && focus_only)
3141 elm_object_item_focus_set(it, EINA_TRUE);
3142 else if (it)
3143 elm_genlist_item_selected_set(it, EINA_TRUE);
3144 }
3145 return EINA_TRUE;
3146 }
3147 else if (sd->item_looping_on)
3148 return EINA_TRUE;
3149
3150 return EINA_FALSE;
3151 }
3152
3153 static Eina_Bool
_key_action_move(Evas_Object * obj,const char * params)3154 _key_action_move(Evas_Object *obj, const char *params)
3155 {
3156 ELM_GENLIST_DATA_GET(obj, sd);
3157 const char *dir = params;
3158
3159 Evas_Coord x = 0;
3160 Evas_Coord y = 0;
3161 Evas_Coord v_w = 0;
3162 Evas_Coord v_h = 0;
3163 Evas_Coord step_x = 0;
3164 Evas_Coord step_y = 0;
3165 Evas_Coord page_x = 0;
3166 Evas_Coord page_y = 0;
3167 Elm_Object_Item *it = NULL;
3168 Evas_Coord pan_max_x = 0, pan_max_y = 0;
3169
3170 if (!sd->items) return EINA_FALSE;
3171 elm_interface_scrollable_content_pos_get(obj, &x, &y);
3172 elm_interface_scrollable_step_size_get(obj, &step_x, &step_y);
3173 elm_interface_scrollable_page_size_get(obj, &page_x, &page_y);
3174 elm_interface_scrollable_content_viewport_geometry_get
3175 (obj, NULL, NULL, &v_w, &v_h);
3176
3177 _elm_widget_focus_auto_show(obj);
3178
3179 if (!strcmp(dir, "up_multi"))
3180 {
3181 if (_key_action_move_dir(obj, ELM_FOCUS_UP, EINA_TRUE)) return EINA_TRUE;
3182 else if (_key_action_move_dir(obj, ELM_FOCUS_UP, EINA_FALSE)) return EINA_TRUE;
3183 else return EINA_FALSE;
3184 }
3185 else if (!strcmp(dir, "down_multi"))
3186 {
3187 if (_key_action_move_dir(obj, ELM_FOCUS_DOWN, EINA_TRUE)) return EINA_TRUE;
3188 else if (_key_action_move_dir(obj, ELM_FOCUS_DOWN, EINA_FALSE)) return EINA_TRUE;
3189 else return EINA_FALSE;
3190 }
3191 else if (!strcmp(dir, "first"))
3192 {
3193 it = elm_genlist_first_item_get(obj);
3194 if (it)
3195 {
3196 if (_elm_config->item_select_on_focus_disable)
3197 {
3198 elm_object_item_focus_set(it, EINA_TRUE);
3199 elm_genlist_item_show(it, ELM_GENLIST_ITEM_SCROLLTO_TOP);
3200 }
3201 else
3202 {
3203 elm_genlist_item_selected_set(it, EINA_TRUE);
3204 }
3205 return EINA_TRUE;
3206 }
3207 }
3208 else if (!strcmp(dir, "last"))
3209 {
3210 it = elm_genlist_last_item_get(obj);
3211 if (it)
3212 {
3213 if (_elm_config->item_select_on_focus_disable)
3214 {
3215 elm_object_item_focus_set(it, EINA_TRUE);
3216 elm_genlist_item_show(it, ELM_GENLIST_ITEM_SCROLLTO_BOTTOM);
3217 }
3218 else
3219 {
3220 elm_genlist_item_selected_set(it, EINA_TRUE);
3221 }
3222 return EINA_TRUE;
3223 }
3224 }
3225 else if (!strcmp(dir, "prior"))
3226 {
3227 if (page_y < 0)
3228 y -= -(page_y * v_h) / 100;
3229 else
3230 y -= page_y;
3231 }
3232 else if (!strcmp(dir, "next"))
3233 {
3234 if (page_y < 0)
3235 y += -(page_y * v_h) / 100;
3236 else
3237 y += page_y;
3238 }
3239 else return EINA_FALSE;
3240
3241 elm_obj_pan_pos_max_get(sd->pan_obj, &pan_max_x, &pan_max_y);
3242 if (x < 0)
3243 x = 0;
3244 else if (x > pan_max_x)
3245 x = pan_max_x;
3246 if (y < 0)
3247 y = 0;
3248 else if (y > pan_max_y)
3249 y = pan_max_y;
3250
3251 elm_interface_scrollable_content_pos_set(obj, x, y, EINA_TRUE);
3252
3253 return EINA_TRUE;
3254 }
3255
3256 static Eina_Bool
_key_action_select(Evas_Object * obj,const char * params)3257 _key_action_select(Evas_Object *obj, const char *params)
3258 {
3259 Elm_Object_Item *eo_it = NULL;
3260
3261 ELM_GENLIST_DATA_GET(obj, sd);
3262 if (!sd->items) return EINA_FALSE;
3263
3264 eo_it = elm_object_focused_item_get(obj);
3265 if (!eo_it) return EINA_TRUE;
3266 elm_genlist_item_expanded_set(eo_it, !elm_genlist_item_expanded_get(eo_it));
3267 ELM_GENLIST_ITEM_DATA_GET(eo_it, it);
3268
3269 if (sd->multi &&
3270 ((sd->multi_select_mode != ELM_OBJECT_MULTI_SELECT_MODE_WITH_CONTROL) ||
3271 (!strcmp(params, "multi"))))
3272 {
3273 if (!it->selected)
3274 {
3275 _item_highlight(it);
3276 if (_item_select(it)) goto deleted;
3277 }
3278 else
3279 _item_unselect(it);
3280 }
3281 else
3282 {
3283 if (!it->selected)
3284 {
3285 while (sd->selected)
3286 {
3287 Elm_Object_Item *eo_sel = sd->selected->data;
3288 Elm_Gen_Item *sel = efl_data_scope_get(eo_sel, ELM_GENLIST_ITEM_CLASS);
3289 _item_unselect(sel);
3290 }
3291 }
3292 else
3293 {
3294 const Eina_List *l, *l_next;
3295 Elm_Object_Item *eo_it2;
3296
3297 EINA_LIST_FOREACH_SAFE(sd->selected, l, l_next, eo_it2)
3298 {
3299 ELM_GENLIST_ITEM_DATA_GET(eo_it2, it2);
3300 if (it2 != it)
3301 _item_unselect(it2);
3302 }
3303 }
3304 _item_highlight(it);
3305 if (_item_select(it)) goto deleted;
3306 }
3307
3308 efl_event_callback_legacy_call(WIDGET(it), ELM_GENLIST_EVENT_ACTIVATED, EO_OBJ(it));
3309
3310 return EINA_TRUE;
3311
3312 deleted:
3313 return EINA_FALSE;
3314 }
3315
3316 static Eina_Bool
_key_action_escape(Evas_Object * obj,const char * params EINA_UNUSED)3317 _key_action_escape(Evas_Object *obj, const char *params EINA_UNUSED)
3318 {
3319 ELM_GENLIST_DATA_GET(obj, sd);
3320
3321 if (!_all_items_deselect(sd)) return EINA_FALSE;
3322 return EINA_TRUE;
3323 }
3324
3325 EOLIAN static Eina_Bool
_elm_genlist_efl_ui_widget_widget_sub_object_add(Eo * obj,Elm_Genlist_Data * _pd EINA_UNUSED,Evas_Object * sobj)3326 _elm_genlist_efl_ui_widget_widget_sub_object_add(Eo *obj, Elm_Genlist_Data *_pd EINA_UNUSED, Evas_Object *sobj)
3327 {
3328 /* skipping layout's code, which registers size hint changing
3329 * callback on sub objects. this is here because items'
3330 * content_get() routines may change hints on the objects after
3331 * creation, thus issuing TOO MANY sizing_eval()'s here. they are
3332 * not needed at here anyway, so let's skip listening to those
3333 * hints changes */
3334 return elm_widget_sub_object_add(efl_cast(obj, EFL_UI_WIDGET_CLASS), sobj);
3335 }
3336
3337 EOLIAN static Eina_Bool
_elm_genlist_efl_ui_widget_widget_sub_object_del(Eo * obj,Elm_Genlist_Data * sd,Evas_Object * sobj)3338 _elm_genlist_efl_ui_widget_widget_sub_object_del(Eo *obj, Elm_Genlist_Data *sd, Evas_Object *sobj)
3339 {
3340 Eina_Bool int_ret = EINA_FALSE;
3341
3342 /* XXX: hack -- also skipping sizing recalculation on
3343 * sub-object-del. genlist's crazy code paths (like groups and
3344 * such) seem to issue a whole lot of deletions and Evas bitches
3345 * about too many recalculations */
3346 sd->on_sub_del = EINA_TRUE;
3347 int_ret = elm_widget_sub_object_del(efl_super(obj, MY_CLASS), sobj);
3348 sd->on_sub_del = EINA_FALSE;
3349 return int_ret;
3350 }
3351
3352 /*
3353 * This function searches the nearest visible item based on the given item.
3354 * If the given item is in the genlist viewport, this returns the given item.
3355 * Or this searches the realized items and checks the nearest fully visible item
3356 * according to the given item's position.
3357 */
3358 static Elm_Object_Item *
_elm_genlist_nearest_visible_item_get(Evas_Object * obj,Elm_Object_Item * eo_it)3359 _elm_genlist_nearest_visible_item_get(Evas_Object *obj, Elm_Object_Item *eo_it)
3360 {
3361 Evas_Coord vx = 0, vy = 0, vw = 0, vh = 0; // genlist viewport geometry
3362 Evas_Coord ix = 0, iy = 0, iw = 0, ih = 0; // given item geometry
3363 Evas_Coord cx = 0, cy = 0, cw = 0, ch = 0; // candidate item geometry
3364 Eina_List *item_list = NULL, *l = NULL;
3365 Elm_Object_Item *first_item, *eo_item = NULL;
3366 ELM_GENLIST_DATA_GET(obj, sd);
3367 Eina_Bool search_next = EINA_FALSE;
3368
3369 if (!eo_it) return NULL;
3370 ELM_GENLIST_ITEM_DATA_GET(eo_it, it);
3371
3372 evas_object_geometry_get(sd->pan_obj, &vx, &vy, &vw, &vh);
3373
3374 if (it->realized)
3375 {
3376 evas_object_geometry_get(VIEW(it), &ix, &iy, &iw, &ih);
3377
3378 if (ELM_RECTS_INCLUDE(vx, vy, vw, vh, ix, iy, iw, ih))
3379 {
3380 if (!elm_object_item_disabled_get(eo_it))
3381 return eo_it;
3382 else
3383 search_next = EINA_TRUE;
3384 }
3385 }
3386
3387 item_list = elm_genlist_realized_items_get(obj);
3388 /* if first realized item is before parameter item then parameter item is
3389 * off viewport towards bottom: start at end of list */
3390 first_item = eina_list_data_get(item_list);
3391 ELM_GENLIST_ITEM_DATA_GET(first_item, first_it);
3392
3393 if ((iy < vy) || search_next || (!first_it) || (first_it->position > it->position))
3394 {
3395 EINA_LIST_FOREACH(item_list, l, eo_item)
3396 {
3397 ELM_GENLIST_ITEM_DATA_GET(eo_item, item);
3398 evas_object_geometry_get(VIEW(item), &cx, &cy, &cw, &ch);
3399 if (ELM_RECTS_INCLUDE(vx, vy, vw, vh, cx, cy, cw, ch) &&
3400 !elm_object_item_disabled_get(eo_item))
3401 {
3402 eina_list_free(item_list);
3403 return eo_item;
3404 }
3405 }
3406 }
3407 else
3408 {
3409 EINA_LIST_REVERSE_FOREACH(item_list, l, eo_item)
3410 {
3411 ELM_GENLIST_ITEM_DATA_GET(eo_item, item);
3412 evas_object_geometry_get(VIEW(item), &cx, &cy, &cw, &ch);
3413 if (ELM_RECTS_INCLUDE(vx, vy, vw, vh, cx, cy, cw, ch) &&
3414 !elm_object_item_disabled_get(eo_item))
3415 {
3416 eina_list_free(item_list);
3417 return eo_item;
3418 }
3419 }
3420 }
3421 eina_list_free(item_list);
3422
3423 return it->realized ? eo_it : NULL;
3424 }
3425
3426 EOLIAN static void
_elm_genlist_efl_ui_focus_manager_setup_on_first_touch(Eo * obj,Elm_Genlist_Data * sd,Efl_Ui_Focus_Direction direction EINA_UNUSED,Efl_Ui_Focus_Object * entry EINA_UNUSED)3427 _elm_genlist_efl_ui_focus_manager_setup_on_first_touch(Eo *obj, Elm_Genlist_Data *sd, Efl_Ui_Focus_Direction direction EINA_UNUSED, Efl_Ui_Focus_Object *entry EINA_UNUSED)
3428 {
3429 Elm_Object_Item *eo_it = NULL;
3430 Eina_Bool is_sel = EINA_FALSE;
3431
3432 if (!sd->items)
3433 {
3434 efl_ui_focus_manager_setup_on_first_touch(efl_super(obj, MY_CLASS), direction, entry);
3435 }
3436 else
3437 {
3438 if (sd->last_focused_item)
3439 eo_it = sd->last_focused_item;
3440 else if (sd->last_selected_item)
3441 eo_it = sd->last_selected_item;
3442 else if (_elm_config->first_item_focus_on_first_focus_in)
3443 {
3444 eo_it = elm_genlist_first_item_get(obj);
3445 is_sel = EINA_TRUE;
3446 }
3447
3448 while (eo_it)
3449 {
3450 ELM_GENLIST_ITEM_DATA_GET(eo_it, it);
3451 if ((!_is_no_select(it)) && (!elm_object_item_disabled_get(eo_it)))
3452 break;
3453 eo_it = EO_OBJ(ELM_GEN_ITEM_NEXT(it));
3454 }
3455
3456 if (eo_it)
3457 {
3458 eo_it = _elm_genlist_nearest_visible_item_get(obj, eo_it);
3459 if (eo_it)
3460 {
3461 if (!_elm_config->item_select_on_focus_disable && is_sel)
3462 elm_genlist_item_selected_set(eo_it, EINA_TRUE);
3463 else
3464 elm_object_item_focus_set(eo_it, EINA_TRUE);
3465 _elm_widget_focus_highlight_start(obj);
3466 //set it again in the manager, there might be the case that the manager focus history and internal item foused logic are in different states
3467 if (efl_ui_focus_manager_request_subchild(obj, eo_it))
3468 efl_ui_focus_manager_focus_set(obj, eo_it);
3469 }
3470 }
3471 else
3472 {
3473 //Just set evas focus on the genlist itself, events will pass on and a other element will be taken
3474 efl_ui_focus_object_focus_set(obj, EINA_TRUE);
3475 }
3476 }
3477 }
3478
3479 EOLIAN static Efl_Ui_Focus_Object*
_elm_genlist_efl_ui_focus_manager_manager_focus_get(const Eo * obj,EINA_UNUSED Elm_Genlist_Data * pd)3480 _elm_genlist_efl_ui_focus_manager_manager_focus_get(const Eo *obj, EINA_UNUSED Elm_Genlist_Data *pd)
3481 {
3482 Eo *focused_obj = efl_ui_focus_manager_focus_get(efl_super(obj, MY_CLASS));
3483 Eo *registered_manager = efl_ui_focus_object_focus_manager_get(obj);
3484
3485 if (!focused_obj && efl_ui_focus_manager_redirect_get(registered_manager))
3486 return (Efl_Ui_Focus_Object*) obj;
3487
3488 return focused_obj;
3489 }
3490
3491 static Efl_Ui_Focus_Object*
_select_candidate(Eo * obj,EINA_UNUSED Elm_Genlist_Data * pd,Efl_Ui_Focus_Direction direction)3492 _select_candidate(Eo *obj, EINA_UNUSED Elm_Genlist_Data *pd, Efl_Ui_Focus_Direction direction)
3493 {
3494 Elm_Object_Item *first = elm_genlist_first_item_get(obj);
3495 Elm_Object_Item *last = elm_genlist_last_item_get(obj);
3496
3497 switch(direction)
3498 {
3499 case EFL_UI_FOCUS_DIRECTION_DOWN:
3500 case EFL_UI_FOCUS_DIRECTION_RIGHT:
3501 elm_object_item_focus_set(first, EINA_TRUE);
3502 return obj;
3503 break;
3504 case EFL_UI_FOCUS_DIRECTION_UP:
3505 case EFL_UI_FOCUS_DIRECTION_LEFT:
3506 elm_object_item_focus_set(last, EINA_TRUE);
3507 return obj;
3508 break;
3509 case EFL_UI_FOCUS_DIRECTION_NEXT:
3510 case EFL_UI_FOCUS_DIRECTION_PREVIOUS:
3511 //do not go further with logical movement
3512 return NULL;
3513 break;
3514 default:
3515 ERR("Uncaught focus direction");
3516 return NULL;
3517 break;
3518 }
3519 }
3520
3521 EOLIAN static Efl_Ui_Focus_Object*
_elm_genlist_efl_ui_focus_manager_move(Eo * obj,Elm_Genlist_Data * pd,Efl_Ui_Focus_Direction direction)3522 _elm_genlist_efl_ui_focus_manager_move(Eo *obj, Elm_Genlist_Data *pd, Efl_Ui_Focus_Direction direction)
3523 {
3524 if (efl_ui_focus_manager_focus_get(obj) == obj)
3525 {
3526 return _select_candidate(obj, pd, direction);
3527 }
3528 else
3529 {
3530 return efl_ui_focus_manager_move(efl_super(obj, MY_CLASS), direction);
3531 }
3532 }
3533
3534 EOLIAN static Eina_Bool
_elm_genlist_efl_ui_focus_object_on_focus_update(Eo * obj,Elm_Genlist_Data * sd)3535 _elm_genlist_efl_ui_focus_object_on_focus_update(Eo *obj, Elm_Genlist_Data *sd)
3536 {
3537 Eina_Bool int_ret = EINA_FALSE;
3538
3539 int_ret = efl_ui_focus_object_on_focus_update(efl_super(obj, MY_CLASS));
3540 if (!int_ret) return EINA_FALSE;
3541
3542 if (efl_ui_focus_object_focus_get(obj) && (sd->items) && (sd->selected) &&
3543 (!sd->last_selected_item))
3544 {
3545 sd->last_selected_item = eina_list_data_get(sd->selected);
3546 }
3547
3548 return EINA_TRUE;
3549 }
3550
3551 static Eina_Bool _elm_genlist_smart_focus_next_enable = EINA_FALSE;
3552
3553 static void
_mirrored_set(Evas_Object * obj,Eina_Bool rtl)3554 _mirrored_set(Evas_Object *obj,
3555 Eina_Bool rtl)
3556 {
3557 ELM_GENLIST_DATA_GET(obj, sd);
3558
3559 _item_cache_zero(sd);
3560 efl_ui_mirrored_set(obj, rtl);
3561 }
3562
3563 EOLIAN static Eina_Error
_elm_genlist_efl_ui_widget_theme_apply(Eo * obj,Elm_Genlist_Data * sd)3564 _elm_genlist_efl_ui_widget_theme_apply(Eo *obj, Elm_Genlist_Data *sd)
3565 {
3566 Item_Block *itb;
3567 Eina_Error int_ret = EFL_UI_THEME_APPLY_ERROR_GENERIC;
3568 Eina_List *l;
3569 Elm_Gen_Item *it;
3570 Evas *e;
3571
3572 int_ret = efl_ui_widget_theme_apply(efl_super(obj, MY_CLASS));
3573 if (int_ret == EFL_UI_THEME_APPLY_ERROR_GENERIC) return int_ret;
3574
3575 elm_interface_scrollable_reset_signals(obj);
3576 e = evas_object_evas_get(obj);
3577 evas_event_freeze(e);
3578 _mirrored_set(obj, efl_ui_mirrored_get(obj));
3579
3580 eina_hash_free_buckets(sd->size_caches);
3581 sd->minw = sd->minh = sd->realminw = 0;
3582
3583 EINA_INLIST_FOREACH(sd->blocks, itb)
3584 {
3585 if (itb->realized) _item_block_unrealize(itb);
3586 EINA_LIST_FOREACH(itb->items, l, it)
3587 it->item->mincalcd = EINA_FALSE;
3588
3589 itb->changed = EINA_TRUE;
3590 }
3591 if (sd->obj && efl_finalized_get(obj))
3592 efl_canvas_group_change(sd->obj);
3593 elm_layout_sizing_eval(obj);
3594 evas_event_thaw(e);
3595 evas_event_thaw_eval(e);
3596
3597 return int_ret;
3598 }
3599
3600 /* FIXME: take off later. maybe this show region coords belong in the
3601 * interface (new api functions, set/get)? */
3602 static void
_show_region_hook(void * data EINA_UNUSED,Evas_Object * obj,Eina_Rect r)3603 _show_region_hook(void *data EINA_UNUSED, Evas_Object *obj, Eina_Rect r)
3604 {
3605 ELM_GENLIST_DATA_GET_OR_RETURN(obj, sd);
3606
3607 //x & y are screen coordinates, Add with pan coordinates
3608 r.x += sd->pan_x;
3609 r.y += sd->pan_y;
3610 elm_interface_scrollable_content_region_show(obj, r.x, r.y, r.w, r.h);
3611 }
3612
3613 static void
_item_highlight(Elm_Gen_Item * it)3614 _item_highlight(Elm_Gen_Item *it)
3615 {
3616 const char *selectraise;
3617 ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
3618
3619 if (_is_no_select(it) ||
3620 (!sd->highlight) ||
3621 (it->highlighted) || elm_wdg_item_disabled_get(EO_OBJ(it)) ||
3622 (it->item->deco_it_view))
3623 return;
3624
3625 edje_object_signal_emit(VIEW(it), SIGNAL_SELECTED, "elm");
3626 if (it->deco_all_view)
3627 edje_object_signal_emit(it->deco_all_view, SIGNAL_SELECTED, "elm");
3628 efl_event_callback_legacy_call(WIDGET(it), ELM_GENLIST_EVENT_HIGHLIGHTED, EO_OBJ(it));
3629
3630 selectraise = edje_object_data_get(VIEW(it), "selectraise");
3631 if ((selectraise) && (!strcmp(selectraise, "on")))
3632 {
3633 if (it->deco_all_view) evas_object_stack_below(it->deco_all_view, sd->stack[1]);
3634 else evas_object_stack_below(VIEW(it), sd->stack[1]);
3635 if ((it->item->group_item) && (it->item->group_item->realized))
3636 evas_object_stack_above(it->item->VIEW(group_item), sd->stack[1]);
3637 if (sd->pin_item && sd->pin_item->realized)
3638 evas_object_stack_above(VIEW(sd->pin_item), sd->stack[1]);
3639 }
3640 it->highlighted = EINA_TRUE;
3641 }
3642
3643 static void
_item_unhighlight(Elm_Gen_Item * it)3644 _item_unhighlight(Elm_Gen_Item *it)
3645 {
3646 if (!it->highlighted) return;
3647
3648 edje_object_signal_emit(VIEW(it), SIGNAL_UNSELECTED, "elm");
3649 efl_event_callback_legacy_call(WIDGET(it), ELM_GENLIST_EVENT_UNHIGHLIGHTED, EO_OBJ(it));
3650 if (it->deco_all_view)
3651 edje_object_signal_emit(it->deco_all_view, SIGNAL_UNSELECTED, "elm");
3652 _item_restack(it);
3653 it->highlighted = EINA_FALSE;
3654 }
3655
3656 static void
_item_block_position_update(Eina_Inlist * list,int idx)3657 _item_block_position_update(Eina_Inlist *list,
3658 int idx)
3659 {
3660 Item_Block *tmp;
3661
3662 EINA_INLIST_FOREACH(list, tmp)
3663 {
3664 tmp->position = idx++;
3665 tmp->position_update = EINA_TRUE;
3666 }
3667 }
3668
3669 static void
_item_position_update(Eina_List * list,int idx)3670 _item_position_update(Eina_List *list,
3671 int idx)
3672 {
3673 Elm_Gen_Item *it;
3674 Eina_List *l;
3675
3676 EINA_LIST_FOREACH(list, l, it)
3677 {
3678 it->position = idx++;
3679 it->position_update = EINA_TRUE;
3680 }
3681 }
3682
3683 static void
_item_block_merge(Item_Block * left,Item_Block * right)3684 _item_block_merge(Item_Block *left,
3685 Item_Block *right)
3686 {
3687 Eina_List *l;
3688 Elm_Gen_Item *it2;
3689
3690 EINA_LIST_FOREACH(right->items, l, it2)
3691 {
3692 if (right->realized)
3693 efl_ui_focus_manager_calc_unregister(right->sd->obj, EO_OBJ(it2));
3694 it2->item->block = left;
3695 left->count++;
3696 left->changed = EINA_TRUE;
3697 if (left->realized)
3698 efl_ui_focus_manager_calc_register_logical(right->sd->obj, EO_OBJ(it2), left->adapter, NULL);
3699 }
3700 left->items = eina_list_merge(left->items, right->items);
3701 }
3702
3703 static void
_item_block_del(Elm_Gen_Item * it)3704 _item_block_del(Elm_Gen_Item *it)
3705 {
3706 Eina_Inlist *il;
3707 Item_Block *itb = it->item->block;
3708 Eina_Bool block_changed = EINA_FALSE;
3709 ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
3710
3711 itb->items = eina_list_remove(itb->items, it);
3712 itb->count--;
3713 itb->changed = EINA_TRUE;
3714 efl_canvas_group_change(sd->pan_obj);
3715 efl_canvas_group_change(sd->obj);
3716 if (itb->realized) efl_ui_focus_manager_calc_unregister(itb->sd->obj, EO_OBJ(it));
3717 if (itb->count < 1)
3718 {
3719 Item_Block *itbn;
3720
3721 il = EINA_INLIST_GET(itb);
3722 itbn = (Item_Block *)(il->next);
3723 if (it->parent)
3724 {
3725 it->parent->item->items =
3726 eina_list_remove(it->parent->item->items, EO_OBJ(it));
3727 if (!it->parent->item->items)
3728 sd->top_level_parent_items--;
3729 }
3730 else
3731 {
3732 _item_block_position_update(il->next, itb->position);
3733 sd->blocks = eina_inlist_remove(sd->blocks, il);
3734 }
3735 free(itb);
3736 if (itbn) itbn->changed = EINA_TRUE;
3737 }
3738 else
3739 {
3740 if (itb->count < (sd->max_items_per_block / 2))
3741 {
3742 Item_Block *itbp;
3743 Item_Block *itbn;
3744
3745 il = EINA_INLIST_GET(itb);
3746 itbp = (Item_Block *)(il->prev);
3747 itbn = (Item_Block *)(il->next);
3748
3749 /* merge block with previous */
3750 if ((itbp) &&
3751 ((itbp->count + itb->count) <
3752 (sd->max_items_per_block +
3753 (sd->max_items_per_block / 2))))
3754 {
3755 _item_block_merge(itbp, itb);
3756 _item_block_position_update
3757 (EINA_INLIST_GET(itb)->next, itb->position);
3758 sd->blocks = eina_inlist_remove
3759 (sd->blocks, EINA_INLIST_GET(itb));
3760 free(itb);
3761 block_changed = EINA_TRUE;
3762 }
3763 /* merge block with next */
3764 else if ((itbn) &&
3765 ((itbn->count + itb->count) <
3766 (sd->max_items_per_block +
3767 (sd->max_items_per_block / 2))))
3768 {
3769 _item_block_merge(itb, itbn);
3770 _item_block_position_update
3771 (EINA_INLIST_GET(itbn)->next, itbn->position);
3772 sd->blocks =
3773 eina_inlist_remove(sd->blocks, EINA_INLIST_GET(itbn));
3774 free(itbn);
3775 block_changed = EINA_TRUE;
3776 }
3777 }
3778 }
3779
3780 if (block_changed)
3781 {
3782 sd->pan_changed = EINA_TRUE;
3783 evas_object_smart_changed(sd->pan_obj);
3784 }
3785 }
3786
3787 static void
_decorate_all_item_unrealize(Elm_Gen_Item * it)3788 _decorate_all_item_unrealize(Elm_Gen_Item *it)
3789 {
3790 if ((!it) || (!it->item->decorate_all_item_realized)) return;
3791
3792 edje_object_part_unswallow(it->deco_all_view, VIEW(it));
3793 evas_object_smart_member_add(VIEW(it), it->item->wsd->pan_obj);
3794 elm_widget_sub_object_add(WIDGET(it), VIEW(it));
3795 _elm_genlist_item_position_state_update(it);
3796 _elm_genlist_item_state_update(it);
3797
3798 if (it->item->wsd->reorder_mode)
3799 {
3800 edje_object_signal_emit(VIEW(it), SIGNAL_REORDER_MODE_SET, "elm");
3801 edje_object_signal_emit(it->deco_all_view, SIGNAL_REORDER_MODE_UNSET,
3802 "elm");
3803 }
3804
3805 _view_clear(it->deco_all_view, &(it->item->deco_all_texts),
3806 &(it->item->deco_all_contents));
3807
3808 edje_object_signal_emit(VIEW(it), SIGNAL_DECORATE_DISABLED, "elm");
3809
3810 edje_object_message_signal_process(it->deco_all_view);
3811 _item_mouse_callbacks_del(it, it->deco_all_view);
3812 _item_mouse_callbacks_add(it, VIEW(it));
3813
3814 ELM_SAFE_FREE(it->deco_all_view, evas_object_del);
3815
3816 it->item->decorate_all_item_realized = EINA_FALSE;
3817 }
3818
3819 static void
_elm_genlist_item_del_not_serious(Elm_Gen_Item * it)3820 _elm_genlist_item_del_not_serious(Elm_Gen_Item *it)
3821 {
3822 ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
3823 Elm_Object_Item *eo_it = EO_OBJ(it);
3824
3825 elm_wdg_item_pre_notify_del(eo_it);
3826
3827 if (it->selected)
3828 {
3829 sd->selected = eina_list_remove(sd->selected, EO_OBJ(it));
3830 if (sd->deselecting)
3831 sd->deselecting = eina_list_remove(sd->deselecting, it);
3832 }
3833 if (sd->last_focused_item == eo_it)
3834 sd->last_focused_item = NULL;
3835 if (sd->focused_item == eo_it)
3836 sd->focused_item = NULL;
3837 if (sd->last_selected_item == eo_it)
3838 sd->last_selected_item = NULL;
3839 if (sd->mode_item == it)
3840 sd-> mode_item = NULL;
3841
3842 if (it->itc->func.del)
3843 it->itc->func.del((void *)WIDGET_ITEM_DATA_GET(EO_OBJ(it)), WIDGET(it));
3844 }
3845
3846 static void
_elm_genlist_item_del_serious(Elm_Gen_Item * it)3847 _elm_genlist_item_del_serious(Elm_Gen_Item *it)
3848 {
3849 ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
3850
3851 sd->item_count--;
3852 _elm_genlist_item_del_not_serious(it);
3853
3854 sd->items = eina_inlist_remove(sd->items, EINA_INLIST_GET(it));
3855 if (it->tooltip.del_cb)
3856 it->tooltip.del_cb((void *)it->tooltip.data, WIDGET(it), it);
3857 ELM_SAFE_FREE(it->long_timer, ecore_timer_del);
3858 if (it->item->type & ELM_GENLIST_ITEM_GROUP)
3859 sd->group_items = eina_list_remove(sd->group_items, it);
3860
3861 ELM_SAFE_FREE(sd->state, eina_inlist_sorted_state_free);
3862 efl_canvas_group_change(sd->pan_obj);
3863 efl_canvas_group_change(sd->obj);
3864
3865 ELM_SAFE_FREE(it->item, free);
3866 }
3867
3868 static void
_item_del(Elm_Gen_Item * it)3869 _item_del(Elm_Gen_Item *it)
3870 {
3871 Evas *e;
3872 Evas_Object *obj = WIDGET(it);
3873 ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
3874
3875 e = evas_object_evas_get(obj);
3876 evas_event_freeze(e);
3877
3878 if (it->item->rel_revs)
3879 {
3880 Elm_Gen_Item *tmp;
3881 EINA_LIST_FREE(it->item->rel_revs, tmp)
3882 {
3883 if (tmp->item->queued && !(tmp->base)->on_deletion)
3884 {
3885 tmp->item->queued = EINA_FALSE;
3886 sd->queue = eina_list_remove(sd->queue, tmp);
3887 if (_item_process(sd, tmp))
3888 _item_process_post(sd, tmp);
3889 }
3890 tmp->item->rel = NULL;
3891 }
3892 }
3893 if (it->item->rel)
3894 {
3895 it->item->rel->item->rel_revs =
3896 eina_list_remove(it->item->rel->item->rel_revs, it);
3897 }
3898 elm_genlist_item_subitems_clear(EO_OBJ(it));
3899 if (sd->show_item == it) sd->show_item = NULL;
3900 if (sd->pin_item == it) sd->pin_item = NULL;
3901 if (it->realized) _elm_genlist_item_unrealize(it, EINA_FALSE);
3902 if (it->item->decorate_all_item_realized) _decorate_all_item_unrealize(it);
3903 if (it->item->block) _item_block_del(it);
3904 if (it->item->queued)
3905 sd->queue = eina_list_remove(sd->queue, it);
3906 if (sd->anchor_item == it)
3907 {
3908 sd->anchor_item = ELM_GEN_ITEM_NEXT(it);
3909 if (!sd->anchor_item)
3910 sd->anchor_item =
3911 ELM_GEN_ITEM_PREV(it);
3912 }
3913 if (sd->expanded_item == it)
3914 {
3915 if (sd->tree_effect_animator)
3916 {
3917 _item_tree_effect_finish(sd);
3918 _elm_genlist_tree_effect_stop(sd);
3919 }
3920 sd->expanded_item = NULL;
3921 sd->move_effect_mode = ELM_GENLIST_TREE_EFFECT_NONE;
3922 }
3923 if (sd->expanded_next_item == it) sd->expanded_next_item = NULL;
3924 if (sd->move_items) sd->move_items = eina_list_remove(sd->move_items, it);
3925 if (it->parent)
3926 {
3927 it->parent->item->items = eina_list_remove(it->parent->item->items, EO_OBJ(it));
3928 if (!it->parent->item->items)
3929 sd->top_level_parent_items--;
3930 }
3931 ELM_SAFE_FREE(it->item->swipe_timer, ecore_timer_del);
3932 _elm_genlist_item_del_serious(it);
3933
3934 if (it->itc->refcount <= 1 && eina_hash_find(sd->size_caches, &(it->itc)))
3935 eina_hash_del_by_key(sd->size_caches, it->itc);
3936 elm_genlist_item_class_unref((Elm_Genlist_Item_Class *)it->itc);
3937 evas_event_thaw(e);
3938 evas_event_thaw_eval(e);
3939 if (!sd->queue) _item_scroll(sd);
3940 }
3941
3942 static void
_item_unselect(Elm_Gen_Item * it)3943 _item_unselect(Elm_Gen_Item *it)
3944 {
3945 ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
3946
3947 _item_unhighlight(it); /* unhighlight the item first */
3948 if (!it->selected) return; /* then check whether the item is selected */
3949
3950 if (it->item->wsd->focus_on_selection_enabled)
3951 {
3952 Evas_Object* eobj;
3953 Eina_List* l;
3954 EINA_LIST_FOREACH(it->item_focus_chain, l, eobj)
3955 elm_object_focus_set(eobj, EINA_FALSE);
3956 }
3957
3958 it->selected = EINA_FALSE;
3959 sd->selected = eina_list_remove(sd->selected, EO_OBJ(it));
3960 evas_object_smart_callback_call
3961 (WIDGET(it), "unselected", EO_OBJ(it));
3962 if (_elm_config->atspi_mode)
3963 efl_access_state_changed_signal_emit(EO_OBJ(it), EFL_ACCESS_STATE_TYPE_SELECTED, EINA_FALSE);
3964 }
3965
3966 static void
_item_mouse_in_cb(void * data,Evas * evas EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)3967 _item_mouse_in_cb(void *data,
3968 Evas *evas EINA_UNUSED,
3969 Evas_Object *obj EINA_UNUSED,
3970 void *event_info EINA_UNUSED)
3971 {
3972 Elm_Gen_Item *it = data;
3973 if (!elm_object_item_disabled_get(EO_OBJ(it)) &&
3974 (_elm_config->focus_move_policy == ELM_FOCUS_MOVE_POLICY_IN))
3975 elm_object_item_focus_set(EO_OBJ(it), EINA_TRUE);
3976 }
3977
3978 static void
_item_mouse_move_cb(void * data,Evas * evas EINA_UNUSED,Evas_Object * obj,void * event_info)3979 _item_mouse_move_cb(void *data,
3980 Evas *evas EINA_UNUSED,
3981 Evas_Object *obj,
3982 void *event_info)
3983 {
3984 Elm_Gen_Item *it = data;
3985 Evas_Event_Mouse_Move *ev = event_info;
3986 Evas_Coord ox, oy, ow, oh, it_scrl_y, y_pos;
3987 Evas_Coord minw = 0, minh = 0, x, y, w, h, dx, dy, adx, ady;
3988 ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
3989 Elm_Object_Item *eo_it = EO_OBJ(it);
3990
3991 evas_object_geometry_get(obj, &x, &y, &w, &h);
3992 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
3993 {
3994 if (!sd->on_hold)
3995 {
3996 sd->on_hold = EINA_TRUE;
3997 if ((!sd->wasselected) && (!it->flipped))
3998 _item_unselect(it);
3999 }
4000 }
4001 else if (it->down && ELM_RECTS_POINT_OUT(x, y, w, h, ev->cur.canvas.x, ev->cur.canvas.y) &&
4002 !sd->reorder_it)
4003 {
4004 ELM_SAFE_FREE(it->long_timer, ecore_timer_del);
4005 if ((!sd->wasselected) && (!it->flipped))
4006 _item_unselect(it);
4007 it->base->still_in = EINA_FALSE;
4008 }
4009
4010 if (sd->multi_touched)
4011 {
4012 sd->cur_x = ev->cur.canvas.x;
4013 sd->cur_y = ev->cur.canvas.y;
4014 return;
4015 }
4016 if ((it->dragging) && (it->down))
4017 {
4018 if (sd->movements == SWIPE_MOVES)
4019 sd->swipe = EINA_TRUE;
4020 else
4021 {
4022 sd->history[sd->movements].x = ev->cur.canvas.x;
4023 sd->history[sd->movements].y = ev->cur.canvas.y;
4024 if (abs((sd->history[sd->movements].x -
4025 sd->history[0].x)) > 40)
4026 sd->swipe = EINA_TRUE;
4027 else
4028 sd->movements++;
4029 }
4030 ELM_SAFE_FREE(it->long_timer, ecore_timer_del);
4031 evas_object_smart_callback_call(WIDGET(it), "drag", eo_it);
4032 return;
4033 }
4034 if ((!it->down) || (sd->longpressed))
4035 {
4036 ELM_SAFE_FREE(it->long_timer, ecore_timer_del);
4037 if ((sd->reorder_mode) && (sd->reorder_it))
4038 {
4039 Eina_Bool changed;
4040 evas_object_geometry_get(sd->pan_obj, &ox, &oy, &ow, &oh);
4041
4042 if (ev->cur.canvas.y < (oy + (sd->reorder_it->item->h / 2)))
4043 sd->reorder_fast = 1;
4044 else if (ev->cur.canvas.y > (oy + oh - (sd->reorder_it->item->h / 2)))
4045 sd->reorder_fast = -1;
4046 else sd->reorder_fast = 0;
4047
4048 it_scrl_y = ev->cur.canvas.y - sd->reorder_it->dy;
4049
4050 if (!sd->reorder_start_y)
4051 sd->reorder_start_y = it->item->block->y + it->y;
4052
4053 if (it_scrl_y < oy)
4054 y_pos = oy;
4055 else if (it_scrl_y + sd->reorder_it->item->h > oy + oh)
4056 y_pos = oy + oh - sd->reorder_it->item->h;
4057 else
4058 y_pos = it_scrl_y;
4059
4060 if (it->deco_all_view)
4061 changed = _item_position(it, it->deco_all_view, it->item->scrl_x, y_pos);
4062 else
4063 changed = _item_position(it, VIEW(it), it->item->scrl_x, y_pos);
4064
4065 efl_canvas_group_change(sd->obj);
4066 if (changed)
4067 efl_canvas_group_change(sd->pan_obj);
4068 }
4069 return;
4070 }
4071 if (it->select_mode != ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY)
4072 elm_coords_finger_size_adjust(1, &minw, 1, &minh);
4073
4074 evas_object_geometry_get(obj, &x, &y, &w, &h);
4075 x = ev->cur.canvas.x - x;
4076 y = ev->cur.canvas.y - y;
4077 dx = x - it->dx;
4078 adx = dx;
4079 if (adx < 0) adx = -dx;
4080
4081 dy = y - it->dy;
4082 ady = dy;
4083 if (ady < 0) ady = -dy;
4084
4085 minw /= 2;
4086 minh /= 2;
4087
4088 // gah! annoying drag detection - leave this alone
4089 if (h < w)
4090 {
4091 if (minw < h) minw = h;
4092 if (minh < h) minh = h;
4093 }
4094 else
4095 {
4096 if (minw < w) minw = w;
4097 if (minh < w) minh = w;
4098 }
4099 if (minw < 5) minw = 5;
4100 if (minh < 5) minh = 5;
4101
4102 if ((adx > minw) || (ady > minh))
4103 {
4104 it->dragging = EINA_TRUE;
4105 ELM_SAFE_FREE(it->long_timer, ecore_timer_del);
4106 if (dy < 0)
4107 {
4108 if (ady > adx)
4109 evas_object_smart_callback_call
4110 (WIDGET(it), "drag,start,up", eo_it);
4111 else
4112 {
4113 if (dx < 0)
4114 evas_object_smart_callback_call
4115 (WIDGET(it), "drag,start,left", eo_it);
4116 else
4117 evas_object_smart_callback_call
4118 (WIDGET(it), "drag,start,right", eo_it);
4119 }
4120 }
4121 else
4122 {
4123 if (ady > adx)
4124 evas_object_smart_callback_call
4125 (WIDGET(it), "drag,start,down", eo_it);
4126 else
4127 {
4128 if (dx < 0)
4129 evas_object_smart_callback_call
4130 (WIDGET(it), "drag,start,left", eo_it);
4131 else
4132 evas_object_smart_callback_call
4133 (WIDGET(it), "drag,start,right", eo_it);
4134 }
4135 }
4136 }
4137 }
4138
4139 static Eina_Bool
_long_press_cb(void * data)4140 _long_press_cb(void *data)
4141 {
4142 Elm_Gen_Item *it = data;
4143 Elm_Object_Item *eo_it_tmp;
4144 Eina_List *list;
4145 ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
4146
4147 if (_is_no_select(it) ||
4148 elm_wdg_item_disabled_get(EO_OBJ(it)) || (it->dragging))
4149 goto end;
4150
4151 sd->longpressed = EINA_TRUE;
4152 evas_object_smart_callback_call
4153 (WIDGET(it), "longpressed", EO_OBJ(it));
4154 if ((sd->reorder_mode) && !(it->item->type & ELM_GENLIST_ITEM_GROUP))
4155 {
4156 sd->reorder_it = it;
4157 sd->reorder_start_y = 0;
4158 if (it->deco_all_view)
4159 evas_object_stack_below(it->deco_all_view, sd->stack[1]);
4160 else
4161 evas_object_stack_below(VIEW(it), sd->stack[1]);
4162
4163 elm_interface_scrollable_hold_set(sd->obj, EINA_TRUE);
4164 elm_interface_scrollable_bounce_allow_set
4165 (sd->obj, EINA_FALSE, EINA_FALSE);
4166
4167 list = elm_genlist_realized_items_get
4168 ((sd)->obj);
4169 EINA_LIST_FREE(list, eo_it_tmp)
4170 {
4171 ELM_GENLIST_ITEM_DATA_GET(eo_it_tmp, it_tmp);
4172 if (it != it_tmp) _item_unselect(it_tmp);
4173 }
4174
4175 if (elm_genlist_item_expanded_get(EO_OBJ(it)))
4176 {
4177 elm_genlist_item_expanded_set(EO_OBJ(it), EINA_FALSE);
4178 return ECORE_CALLBACK_RENEW;
4179 }
4180
4181 if (!sd->decorate_all_mode)
4182 {
4183 edje_object_signal_emit(VIEW(it), SIGNAL_REORDER_ENABLED, "elm");
4184 if (_elm_config->atspi_mode)
4185 efl_access_state_changed_signal_emit(EO_OBJ(it), EFL_ACCESS_STATE_TYPE_ANIMATED, EINA_TRUE);
4186 }
4187 }
4188
4189 end:
4190 it->long_timer = NULL;
4191 return ECORE_CALLBACK_CANCEL;
4192 }
4193
4194 static void
_swipe_do(Elm_Gen_Item * it)4195 _swipe_do(Elm_Gen_Item *it)
4196 {
4197 int i, sum = 0;
4198 ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
4199
4200 if (_is_no_select(it) ||
4201 elm_wdg_item_disabled_get(EO_OBJ(it))) return;
4202
4203 sd->swipe = EINA_FALSE;
4204 for (i = 0; i < sd->movements; i++)
4205 {
4206 sum += sd->history[i].x;
4207 if (abs(sd->history[0].y - sd->history[i].y) > 10)
4208 return;
4209 }
4210
4211 sum /= sd->movements;
4212 if (abs(sum - sd->history[0].x) <= 10) return;
4213 efl_event_callback_legacy_call
4214 (WIDGET(it), ELM_GENLIST_EVENT_SWIPE, EO_OBJ(it));
4215 }
4216
4217 static Eina_Bool
_swipe_cancel(void * data)4218 _swipe_cancel(void *data)
4219 {
4220 Elm_Gen_Item *it = data;
4221 if (!it) return ECORE_CALLBACK_CANCEL;
4222 ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
4223
4224 sd->swipe = EINA_FALSE;
4225 sd->movements = 0;
4226
4227 return ECORE_CALLBACK_RENEW;
4228 }
4229
4230 static Eina_Bool
_multi_cancel(void * data)4231 _multi_cancel(void *data)
4232 {
4233 ELM_GENLIST_DATA_GET(data, sd);
4234
4235 if (!sd) return ECORE_CALLBACK_CANCEL;
4236 sd->multi_timeout = EINA_TRUE;
4237
4238 return ECORE_CALLBACK_RENEW;
4239 }
4240
4241 static void
_multi_touch_gesture_eval(Elm_Gen_Item * it)4242 _multi_touch_gesture_eval(Elm_Gen_Item *it)
4243 {
4244 Evas_Coord minw = 0, minh = 0;
4245 Evas_Coord off_x, off_y, off_mx, off_my;
4246 ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
4247 Elm_Object_Item *eo_it = EO_OBJ(it);
4248
4249 sd->multi_touched = EINA_FALSE;
4250 ELM_SAFE_FREE(sd->multi_timer, ecore_timer_del);
4251 if (sd->multi_timeout)
4252 {
4253 sd->multi_timeout = EINA_FALSE;
4254 return;
4255 }
4256
4257 elm_coords_finger_size_adjust(1, &minw, 1, &minh);
4258 off_x = abs(sd->cur_x - sd->prev_x);
4259 off_y = abs(sd->cur_y - sd->prev_y);
4260 off_mx = abs(sd->cur_mx - sd->prev_mx);
4261 off_my = abs(sd->cur_my - sd->prev_my);
4262
4263 if (((off_x > minw) || (off_y > minh)) && ((off_mx > minw)
4264 || (off_my > minh)))
4265 {
4266 if ((off_x + off_mx) > (off_y + off_my))
4267 {
4268 if ((sd->cur_x > sd->prev_x) && (sd->cur_mx > sd->prev_mx))
4269 efl_event_callback_legacy_call
4270 (WIDGET(it), ELM_GENLIST_EVENT_MULTI_SWIPE_RIGHT, eo_it);
4271 else if ((sd->cur_x < sd->prev_x) && (sd->cur_mx < sd->prev_mx))
4272 efl_event_callback_legacy_call
4273 (WIDGET(it), ELM_GENLIST_EVENT_MULTI_SWIPE_LEFT, eo_it);
4274 else if (abs(sd->cur_x - sd->cur_mx) >
4275 abs(sd->prev_x - sd->prev_mx))
4276 efl_event_callback_legacy_call
4277 (WIDGET(it), ELM_GENLIST_EVENT_MULTI_PINCH_OUT, eo_it);
4278 else
4279 efl_event_callback_legacy_call
4280 (WIDGET(it), ELM_GENLIST_EVENT_MULTI_PINCH_IN, eo_it);
4281 }
4282 else
4283 {
4284 if ((sd->cur_y > sd->prev_y) && (sd->cur_my > sd->prev_my))
4285 efl_event_callback_legacy_call
4286 (WIDGET(it), ELM_GENLIST_EVENT_MULTI_SWIPE_DOWN, eo_it);
4287 else if ((sd->cur_y < sd->prev_y) && (sd->cur_my < sd->prev_my))
4288 efl_event_callback_legacy_call
4289 (WIDGET(it), ELM_GENLIST_EVENT_MULTI_SWIPE_UP, eo_it);
4290 else if (abs(sd->cur_y - sd->cur_my) >
4291 abs(sd->prev_y - sd->prev_my))
4292 efl_event_callback_legacy_call
4293 (WIDGET(it), ELM_GENLIST_EVENT_MULTI_PINCH_OUT, eo_it);
4294 else
4295 efl_event_callback_legacy_call
4296 (WIDGET(it), ELM_GENLIST_EVENT_MULTI_PINCH_IN, eo_it);
4297 }
4298 }
4299
4300 sd->multi_timeout = EINA_FALSE;
4301 }
4302
4303 static void
_item_multi_down_cb(void * data,Evas * evas EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info)4304 _item_multi_down_cb(void *data,
4305 Evas *evas EINA_UNUSED,
4306 Evas_Object *obj EINA_UNUSED,
4307 void *event_info)
4308 {
4309 Elm_Gen_Item *it = data;
4310 Evas_Event_Multi_Down *ev = event_info;
4311 ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
4312
4313 if ((sd->multi_device != 0) || (sd->multi_touched)
4314 || (sd->multi_timeout))
4315 return;
4316
4317 sd->multi_device = ev->device;
4318 sd->multi_down = EINA_TRUE;
4319 sd->multi_touched = EINA_TRUE;
4320 sd->prev_mx = ev->canvas.x;
4321 sd->prev_my = ev->canvas.y;
4322 if (!sd->wasselected) _item_unselect(it);
4323 sd->wasselected = EINA_FALSE;
4324 sd->longpressed = EINA_FALSE;
4325 ELM_SAFE_FREE(it->long_timer, ecore_timer_del);
4326 if (it->dragging)
4327 {
4328 it->dragging = EINA_FALSE;
4329 evas_object_smart_callback_call
4330 (WIDGET(it), "drag,stop", EO_OBJ(it));
4331 }
4332 ELM_SAFE_FREE(it->item->swipe_timer, ecore_timer_del);
4333 if (sd->on_hold)
4334 {
4335 sd->swipe = EINA_FALSE;
4336 sd->movements = 0;
4337 sd->on_hold = EINA_FALSE;
4338 }
4339 }
4340
4341 static void
_item_multi_up_cb(void * data,Evas * evas EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info)4342 _item_multi_up_cb(void *data,
4343 Evas *evas EINA_UNUSED,
4344 Evas_Object *obj EINA_UNUSED,
4345 void *event_info)
4346 {
4347 Elm_Gen_Item *it = data;
4348 Evas_Event_Multi_Up *ev = event_info;
4349 ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
4350
4351 if (sd->multi_device != ev->device) return;
4352 sd->multi_device = 0;
4353 sd->multi_down = EINA_FALSE;
4354 if (sd->mouse_down) return;
4355 _multi_touch_gesture_eval(data);
4356 }
4357
4358 static void
_item_multi_move_cb(void * data,Evas * evas EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info)4359 _item_multi_move_cb(void *data,
4360 Evas *evas EINA_UNUSED,
4361 Evas_Object *obj EINA_UNUSED,
4362 void *event_info)
4363 {
4364 Elm_Gen_Item *it = data;
4365 Evas_Event_Multi_Move *ev = event_info;
4366 ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
4367
4368 if (sd->multi_device != ev->device) return;
4369 sd->cur_mx = ev->cur.canvas.x;
4370 sd->cur_my = ev->cur.canvas.y;
4371 }
4372
4373 static void
_item_mouse_down_cb(void * data,Evas * evas EINA_UNUSED,Evas_Object * obj,void * event_info)4374 _item_mouse_down_cb(void *data,
4375 Evas *evas EINA_UNUSED,
4376 Evas_Object *obj,
4377 void *event_info)
4378 {
4379 Evas_Event_Mouse_Down *ev = event_info;
4380 Elm_Gen_Item *it = data;
4381 Evas_Coord x, y;
4382 ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
4383 Elm_Object_Item *eo_it = EO_OBJ(it);
4384
4385 if (ev->button == 3)
4386 {
4387 evas_object_geometry_get(obj, &x, &y, NULL, NULL);
4388 it->dx = ev->canvas.x - x;
4389 it->dy = ev->canvas.y - y;
4390 return;
4391 }
4392 if (ev->button != 1) return;
4393 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
4394 {
4395 sd->on_hold = EINA_TRUE;
4396 }
4397
4398 it->down = EINA_TRUE;
4399 it->dragging = EINA_FALSE;
4400 evas_object_geometry_get(obj, &x, &y, NULL, NULL);
4401 it->dx = ev->canvas.x - x;
4402 it->dy = ev->canvas.y - y;
4403 sd->mouse_down = EINA_TRUE;
4404 if (!sd->multi_touched)
4405 {
4406 sd->prev_x = ev->canvas.x;
4407 sd->prev_y = ev->canvas.y;
4408 sd->multi_timeout = EINA_FALSE;
4409 ecore_timer_del(sd->multi_timer);
4410 sd->multi_timer = ecore_timer_add(MULTI_DOWN_TIME, _multi_cancel, sd->obj);
4411 }
4412 sd->longpressed = EINA_FALSE;
4413 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) sd->on_hold = EINA_TRUE;
4414 else sd->on_hold = EINA_FALSE;
4415 if (sd->on_hold) return;
4416 sd->wasselected = it->selected;
4417
4418 ecore_timer_del(it->item->swipe_timer);
4419 it->item->swipe_timer = ecore_timer_add(SWIPE_TIME, _swipe_cancel, it);
4420 ELM_SAFE_FREE(it->long_timer, ecore_timer_del);
4421 if (it->realized)
4422 it->long_timer = ecore_timer_add
4423 (sd->longpress_timeout, _long_press_cb, it);
4424 else
4425 it->long_timer = NULL;
4426 sd->swipe = EINA_FALSE;
4427 sd->movements = 0;
4428 it->base->still_in = EINA_TRUE;
4429
4430 if (_is_no_select(it) ||
4431 elm_wdg_item_disabled_get((Eo *)eo_it))
4432 return;
4433
4434 // and finally call the user callbacks.
4435 // NOTE: keep this code at the bottom, as the user can change the
4436 // list at this point (clear, delete, etc...)
4437 _item_highlight(it);
4438 if (ev->flags & EVAS_BUTTON_DOUBLE_CLICK)
4439 {
4440 evas_object_smart_callback_call
4441 ( WIDGET(it), "clicked,double", eo_it);
4442 efl_event_callback_legacy_call
4443 (WIDGET(it), ELM_GENLIST_EVENT_ACTIVATED, eo_it);
4444 }
4445 evas_object_smart_callback_call
4446 (WIDGET(it), "pressed", eo_it);
4447 }
4448
4449 static Item_Block *
_item_block_new(Elm_Genlist_Data * sd,Eina_Bool prepend)4450 _item_block_new(Elm_Genlist_Data *sd,
4451 Eina_Bool prepend)
4452 {
4453 Item_Block *itb;
4454
4455 itb = calloc(1, sizeof(Item_Block));
4456 if (!itb) return NULL;
4457 itb->sd = sd;
4458 if (prepend)
4459 {
4460 sd->blocks = eina_inlist_prepend(sd->blocks, EINA_INLIST_GET(itb));
4461 _item_block_position_update(sd->blocks, 0);
4462 }
4463 else
4464 {
4465 sd->blocks = eina_inlist_append(sd->blocks, EINA_INLIST_GET(itb));
4466 itb->position_update = EINA_TRUE;
4467 if (sd->blocks != EINA_INLIST_GET(itb))
4468 {
4469 itb->position =
4470 ((Item_Block *)(EINA_INLIST_GET(itb)->prev))->position + 1;
4471 }
4472 else
4473 {
4474 itb->position = 0;
4475 }
4476 }
4477
4478 return itb;
4479 }
4480
4481 static void
_update_block_registration(Item_Block * itb,Elm_Gen_Item * element)4482 _update_block_registration(Item_Block *itb, Elm_Gen_Item *element)
4483 {
4484 Elm_Gen_Item *it = NULL;
4485 Eina_List *order = NULL;
4486 const Eina_List *l;
4487
4488 if (!itb->realized) return;
4489
4490 efl_ui_focus_manager_calc_register_logical(itb->sd->obj, EO_OBJ(element), itb->adapter, NULL);
4491
4492 EINA_LIST_FOREACH(itb->items, l, it)
4493 {
4494 order = eina_list_append(order, EO_OBJ(it));
4495 }
4496
4497 efl_ui_focus_manager_calc_update_order(itb->sd->obj, itb->adapter, order);
4498 }
4499
4500 /**
4501 * @internal
4502 *
4503 * This function adds an item to a block's item list. This may or may not
4504 * rearrange existing blocks and create a new block.
4505 *
4506 */
4507 static Eina_Bool
_item_block_add(Elm_Genlist_Data * sd,Elm_Gen_Item * it)4508 _item_block_add(Elm_Genlist_Data *sd,
4509 Elm_Gen_Item *it)
4510 {
4511 Item_Block *itb = NULL;
4512
4513 // when a new item does not depend on another item
4514 if (!it->item->rel)
4515 {
4516 newblock:
4517 if (it->item->rel)
4518 {
4519 // FIXME: Why is this case here??? This doesn't make sense at all!
4520 // There shouldn't be a goto in the first place!
4521 itb = calloc(1, sizeof(Item_Block));
4522 if (!itb) return EINA_FALSE;
4523 itb->sd = sd;
4524 if (!it->item->rel->item->block)
4525 {
4526 sd->blocks =
4527 eina_inlist_append(sd->blocks, EINA_INLIST_GET(itb));
4528 itb->items = eina_list_append(itb->items, it);
4529 _update_block_registration(itb, it);
4530 itb->position_update = EINA_TRUE;
4531 it->position = eina_list_count(itb->items);
4532 it->position_update = EINA_TRUE;
4533
4534 if (sd->blocks != EINA_INLIST_GET(itb))
4535 {
4536 itb->position =
4537 ((Item_Block *)
4538 (EINA_INLIST_GET(itb)->prev))->position + 1;
4539 }
4540 else
4541 {
4542 itb->position = 0;
4543 }
4544 }
4545 else
4546 {
4547 Eina_List *tmp;
4548
4549 tmp = eina_list_data_find_list(itb->items, it->item->rel);
4550 if (it->item->before)
4551 {
4552 sd->blocks = eina_inlist_prepend_relative
4553 (sd->blocks, EINA_INLIST_GET(itb),
4554 EINA_INLIST_GET(it->item->rel->item->block));
4555 itb->items =
4556 eina_list_prepend_relative_list(itb->items, it, tmp);
4557
4558 /* Update index from where we prepended */
4559 _item_position_update
4560 (eina_list_prev(tmp), it->item->rel->position);
4561 _item_block_position_update
4562 (EINA_INLIST_GET(itb),
4563 it->item->rel->item->block->position);
4564 }
4565 else
4566 {
4567 sd->blocks = eina_inlist_append_relative
4568 (sd->blocks, EINA_INLIST_GET(itb),
4569 EINA_INLIST_GET(it->item->rel->item->block));
4570 itb->items =
4571 eina_list_append_relative_list(itb->items, it, tmp);
4572
4573 /* Update block index from where we appended */
4574 _item_position_update
4575 (eina_list_next(tmp), it->item->rel->position + 1);
4576 _item_block_position_update
4577 (EINA_INLIST_GET(itb),
4578 it->item->rel->item->block->position + 1);
4579 }
4580 }
4581 }
4582 else
4583 {
4584 // item move_before, prepend, insert_before, sorted_insert with before
4585 if (it->item->before)
4586 {
4587 if (sd->blocks)
4588 {
4589 itb = (Item_Block *)(sd->blocks);
4590 if (itb->count >= sd->max_items_per_block)
4591 {
4592 itb = _item_block_new(sd, EINA_TRUE);
4593 if (!itb) return EINA_FALSE;
4594 }
4595 }
4596 else
4597 {
4598 itb = _item_block_new(sd, EINA_TRUE);
4599 if (!itb) return EINA_FALSE;
4600 }
4601 itb->items = eina_list_prepend(itb->items, it);
4602 _update_block_registration(itb, it);
4603 _item_position_update(itb->items, 0);
4604 }
4605 // item move_after, append, insert_after, sorted_insert without before
4606 else
4607 {
4608 if (sd->blocks)
4609 {
4610 itb = (Item_Block *)(sd->blocks->last);
4611 if (itb->count >= sd->max_items_per_block)
4612 {
4613 itb = _item_block_new(sd, EINA_FALSE);
4614 if (!itb) return EINA_FALSE;
4615 }
4616 }
4617 else
4618 {
4619 itb = _item_block_new(sd, EINA_FALSE);
4620 if (!itb) return EINA_FALSE;
4621 }
4622 itb->items = eina_list_append(itb->items, it);
4623 _update_block_registration(itb, it);
4624 it->position = eina_list_count(itb->items);
4625 }
4626 }
4627 }
4628 // when a new item depends on another item
4629 else
4630 {
4631 Eina_List *tmp;
4632
4633 if (it->item->rel->item->queued)
4634 {
4635 /* NOTE: for a strange reason eina_list and eina_inlist
4636 don't have the same property on sorted insertion
4637 order, so the queue is not always ordered like the
4638 item list. This lead to issue where we depend on an
4639 item that is not yet created. As a quick work around,
4640 we reschedule the calc of the item and stop reordering
4641 the list to prevent any nasty issue to show up here.
4642 */
4643 sd->queue = eina_list_append(sd->queue, it);
4644 sd->requeued = EINA_TRUE;
4645 it->item->queued = EINA_TRUE;
4646
4647 return EINA_FALSE;
4648 }
4649 itb = it->item->rel->item->block;
4650 if (!itb) goto newblock;
4651 tmp = eina_list_data_find_list(itb->items, it->item->rel);
4652 if (it->item->before)
4653 {
4654 itb->items = eina_list_prepend_relative_list(itb->items, it, tmp);
4655 _update_block_registration(itb, it);
4656 _item_position_update
4657 (eina_list_prev(tmp), it->item->rel->position);
4658 }
4659 else
4660 {
4661 itb->items = eina_list_append_relative_list(itb->items, it, tmp);
4662 _update_block_registration(itb, it);
4663 _item_position_update
4664 (eina_list_next(tmp), it->item->rel->position + 1);
4665 }
4666 }
4667
4668 itb->count++;
4669 itb->changed = EINA_TRUE;
4670 it->item->block = itb;
4671 efl_canvas_group_change(itb->sd->obj);
4672
4673 if (itb->count > itb->sd->max_items_per_block)
4674 {
4675 int newc;
4676 Item_Block *itb2;
4677 Elm_Gen_Item *it2;
4678 Eina_Bool done = EINA_FALSE;
4679
4680 newc = itb->count / 2;
4681
4682 if (EINA_INLIST_GET(itb)->prev)
4683 {
4684 Item_Block *itbp = (Item_Block *)(EINA_INLIST_GET(itb)->prev);
4685
4686 if (itbp->count + newc < sd->max_items_per_block / 2)
4687 {
4688 /* moving items to previous block */
4689 while ((itb->count > newc) && (itb->items))
4690 {
4691 it2 = eina_list_data_get(itb->items);
4692 itb->items = eina_list_remove_list
4693 (itb->items, itb->items);
4694 itb->count--;
4695 efl_ui_focus_manager_calc_unregister(itb->sd->obj, EO_OBJ(it2));
4696
4697 itbp->items = eina_list_append(itbp->items, it2);
4698 _update_block_registration(itbp, it2);
4699 it2->item->block = itbp;
4700 itbp->count++;
4701 if (!it2->hide)
4702 {
4703 itb->vis_count--;
4704 itbp->num--;
4705 itbp->vis_count++;
4706 }
4707
4708 if (it2->realized)
4709 {
4710 _item_block_realize(itbp);
4711 }
4712 }
4713
4714 done = EINA_TRUE;
4715 }
4716 }
4717
4718 if (!done && EINA_INLIST_GET(itb)->next)
4719 {
4720 Item_Block *itbn = (Item_Block *)(EINA_INLIST_GET(itb)->next);
4721
4722 if (itbn->count + newc < sd->max_items_per_block / 2)
4723 {
4724 /* moving items to next block */
4725 while ((itb->count > newc) && (itb->items))
4726 {
4727 Eina_List *l;
4728
4729 l = eina_list_last(itb->items);
4730 it2 = eina_list_data_get(l);
4731 itb->items = eina_list_remove_list(itb->items, l);
4732 itb->count--;
4733 efl_ui_focus_manager_calc_unregister(itb->sd->obj, EO_OBJ(it2));
4734
4735 itbn->items = eina_list_prepend(itbn->items, it2);
4736 _update_block_registration(itbn, it2);
4737 it2->item->block = itbn;
4738 itbn->count++;
4739 if (!it2->hide)
4740 {
4741 itb->h -= it->item->h;
4742 itb->vis_count--;
4743 itbn->h += it->item->h;
4744 itbn->vis_count++;
4745 }
4746
4747 if (it2->realized)
4748 {
4749 _item_block_realize(itbn);
4750 }
4751 }
4752
4753 done = EINA_TRUE;
4754 }
4755 }
4756
4757 if (!done)
4758 {
4759 /* moving items to new block */
4760 itb2 = calloc(1, sizeof(Item_Block));
4761 if (!itb2) return EINA_FALSE;
4762 itb2->sd = sd;
4763 sd->blocks =
4764 eina_inlist_append_relative(sd->blocks, EINA_INLIST_GET(itb2),
4765 EINA_INLIST_GET(itb));
4766 itb2->changed = EINA_TRUE;
4767 while ((itb->count > newc) && (itb->items))
4768 {
4769 Eina_List *l;
4770
4771 l = eina_list_last(itb->items);
4772 it2 = l->data;
4773 itb->items = eina_list_remove_list(itb->items, l);
4774 itb->count--;
4775 efl_ui_focus_manager_calc_unregister(itb->sd->obj, EO_OBJ(it2));
4776
4777 itb2->items = eina_list_prepend(itb2->items, it2);
4778 _update_block_registration(itb2, it2);
4779 it2->item->block = itb2;
4780 itb2->count++;
4781 if (!it2->hide)
4782 {
4783 itb->vis_count--;
4784 itb->h -= it2->item->h;
4785 itb2->vis_count++;
4786 itb2->h += it2->item->h;
4787 }
4788
4789 if (it2->realized)
4790 {
4791 _item_block_realize(itb2);
4792 }
4793 }
4794
4795 itb2->num = itb->num + itb->vis_count;
4796 itb2->x = itb->x;
4797 itb2->w = itb->w;
4798 itb2->y = itb->y + itb->h;
4799 }
4800 }
4801
4802 return EINA_TRUE;
4803 }
4804
4805 static Eina_Bool
_item_process(Elm_Genlist_Data * sd,Elm_Gen_Item * it)4806 _item_process(Elm_Genlist_Data *sd,
4807 Elm_Gen_Item *it)
4808 {
4809 if (!_item_block_add(sd, it)) return EINA_FALSE;
4810 if (!sd->blocks)
4811 _item_block_realize(it->item->block);
4812
4813 return EINA_TRUE;
4814 }
4815
4816 static void
_item_process_post(Elm_Genlist_Data * sd,Elm_Gen_Item * it)4817 _item_process_post(Elm_Genlist_Data *sd, Elm_Gen_Item *it)
4818 {
4819 Eina_Bool show_me = EINA_FALSE;
4820
4821 EINA_SAFETY_ON_FALSE_RETURN(it && it->item && it->item->block);
4822 if (it->item->block->changed)
4823 {
4824 show_me = _item_block_recalc
4825 (it->item->block, it->item->block->num, EINA_TRUE);
4826 it->item->block->changed = 0;
4827 if (sd->pan_changed)
4828 {
4829 evas_object_smart_changed(sd->pan_obj);
4830 }
4831 }
4832 if (show_me) it->item->block->show_me = EINA_TRUE;
4833
4834 /* when prepending, move the scroller along with the first selected
4835 * item to create the illusion that we're watching the selected
4836 * item this prevents the selected item being scrolled off the
4837 * viewport
4838 */
4839 if (sd->selected && it->item->before && !it->hide)
4840 {
4841 int y = 0, h;
4842 Elm_Object_Item *eo_it2;
4843
4844 eo_it2 = sd->selected->data;
4845 ELM_GENLIST_ITEM_DATA_GET(eo_it2, it2);
4846 if (!it2->item->block) return;
4847 if (it2->item->order_num_in < it->item->order_num_in) return;
4848 elm_interface_scrollable_content_pos_get(sd->obj, NULL, &y);
4849 evas_object_geometry_get(sd->pan_obj, NULL, NULL, NULL, &h);
4850 if ((it->y + it->item->block->y > y + h) ||
4851 (it->y + it->item->block->y + it->item->h < y))
4852 /* offscreen, just update */
4853 elm_interface_scrollable_content_region_show
4854 (sd->obj, it2->x + it2->item->block->x, y, it2->item->block->w, h);
4855 else
4856 elm_interface_scrollable_content_region_show
4857 (sd->obj, it->x + it->item->block->x, y + it->item->h, it->item->block->w, h);
4858 }
4859 }
4860
4861 static int
_queue_process(Elm_Genlist_Data * sd)4862 _queue_process(Elm_Genlist_Data *sd)
4863 {
4864 int n;
4865 double t0, t;
4866 Evas *e = evas_object_evas_get(sd->obj);
4867
4868 t0 = ecore_time_get();
4869 evas_event_freeze(e);
4870 for (n = 0; (sd->queue) && (n < ITEM_QUEUE_MAX); n++)
4871 {
4872 Elm_Gen_Item *it;
4873
4874 it = eina_list_data_get(sd->queue);
4875 sd->queue = eina_list_remove_list(sd->queue, sd->queue);
4876 it->item->queued = EINA_FALSE;
4877 if (!_item_process(sd, it)) continue;
4878 t = ecore_time_get();
4879 _item_process_post(sd, it);
4880 /* same as eina_inlist_count > 1 */
4881 if (sd->blocks && sd->blocks->next)
4882 {
4883 if ((t - t0) > (ecore_animator_frametime_get())) break;
4884 }
4885 }
4886 evas_event_thaw(e);
4887 evas_event_thaw_eval(e);
4888 return n;
4889 }
4890
4891 static Eina_Bool
_idle_process(void * data,Eina_Bool * wakeup)4892 _idle_process(void *data,
4893 Eina_Bool *wakeup)
4894 {
4895 Elm_Genlist_Data *sd = data;
4896
4897 if (_queue_process(sd) > 0) *wakeup = EINA_TRUE;
4898 if (!sd->queue)
4899 {
4900 return ECORE_CALLBACK_CANCEL;
4901 }
4902 return ECORE_CALLBACK_RENEW;
4903 }
4904
4905 static Eina_Bool
_item_idle_enterer(void * data)4906 _item_idle_enterer(void *data)
4907 {
4908 Eina_Bool wakeup = EINA_FALSE;
4909 ELM_GENLIST_DATA_GET(data, sd);
4910 Eina_Bool ok = _idle_process(sd, &wakeup);
4911
4912 if (wakeup)
4913 {
4914 // wake up mainloop
4915 efl_canvas_group_change(sd->obj);
4916 }
4917 if (ok == ECORE_CALLBACK_CANCEL) sd->queue_idle_enterer = NULL;
4918
4919 return ok;
4920 }
4921
4922 static void
_requeue_idle_enterer(Elm_Genlist_Data * sd)4923 _requeue_idle_enterer(Elm_Genlist_Data *sd)
4924 {
4925 ecore_idle_enterer_del(sd->queue_idle_enterer);
4926 sd->queue_idle_enterer = ecore_idle_enterer_add(_item_idle_enterer, sd->obj);
4927 }
4928
4929 static void
_item_queue(Elm_Genlist_Data * sd,Elm_Gen_Item * it,Eina_Compare_Cb cb)4930 _item_queue(Elm_Genlist_Data *sd,
4931 Elm_Gen_Item *it,
4932 Eina_Compare_Cb cb)
4933 {
4934 Evas_Coord w = 0;
4935
4936 if (it->item->queued) return;
4937 it->item->queued = EINA_TRUE;
4938 if (cb && !sd->requeued)
4939 sd->queue = eina_list_sorted_insert(sd->queue, cb, it);
4940 else
4941 sd->queue = eina_list_append(sd->queue, it);
4942 // FIXME: why does a freeze then thaw here cause some genlist
4943 // elm_genlist_item_append() to be much much slower?
4944 // evas_event_freeze(evas_object_evas_get(sd->obj));
4945 while ((sd->queue) && ((!sd->blocks) || (!sd->blocks->next)))
4946 {
4947 ELM_SAFE_FREE(sd->queue_idle_enterer, ecore_idle_enterer_del);
4948 _queue_process(sd);
4949 }
4950 while ((sd->queue) && (sd->blocks) &&
4951 (sd->homogeneous) && (sd->mode == ELM_LIST_COMPRESS))
4952 {
4953 ELM_SAFE_FREE(sd->queue_idle_enterer, ecore_idle_enterer_del);
4954 _queue_process(sd);
4955 }
4956
4957 // evas_event_thaw(evas_object_evas_get(sd->obj));
4958 // evas_event_thaw_eval(evas_object_evas_get(sd->obj));
4959 evas_object_geometry_get(sd->obj, NULL, NULL, &w, NULL);
4960 if (w > 0) _requeue_idle_enterer(sd);
4961
4962 if (_elm_config->atspi_mode)
4963 {
4964 efl_access_added(EO_OBJ(it));
4965 efl_access_children_changed_added_signal_emit(sd->obj, EO_OBJ(it));
4966 }
4967 }
4968
4969 /* If the application wants to know the relative item, use
4970 * elm_genlist_item_prev_get(it)*/
4971 static void
_item_move_after(Elm_Gen_Item * it,Elm_Gen_Item * after)4972 _item_move_after(Elm_Gen_Item *it,
4973 Elm_Gen_Item *after)
4974 {
4975 if (!it) return;
4976 if (!after) return;
4977 if (it == after) return;
4978 ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
4979
4980 sd->items =
4981 eina_inlist_remove(sd->items, EINA_INLIST_GET(it));
4982 if (it->item->block) _item_block_del(it);
4983
4984 sd->items = eina_inlist_append_relative
4985 (sd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(after));
4986 if (it->item->rel)
4987 it->item->rel->item->rel_revs =
4988 eina_list_remove(it->item->rel->item->rel_revs, it);
4989 it->item->rel = after;
4990 after->item->rel_revs = eina_list_append(after->item->rel_revs, it);
4991 it->item->before = EINA_FALSE;
4992 if (after->item->group_item) it->item->group_item = after->item->group_item;
4993 _item_queue(sd, it, NULL);
4994
4995 efl_event_callback_legacy_call(WIDGET(it), ELM_GENLIST_EVENT_MOVED_AFTER, EO_OBJ(it));
4996 }
4997
4998 static void
_access_activate_cb(void * data EINA_UNUSED,Evas_Object * part_obj EINA_UNUSED,Elm_Object_Item * eo_it)4999 _access_activate_cb(void *data EINA_UNUSED,
5000 Evas_Object *part_obj EINA_UNUSED,
5001 Elm_Object_Item *eo_it)
5002 {
5003 ELM_GENLIST_ITEM_DATA_GET(eo_it, it);
5004 if (!it) return;
5005
5006 ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
5007 if (!sd) return;
5008
5009 if (sd->multi)
5010 {
5011 if (!it->selected)
5012 {
5013 _item_highlight(it);
5014 _item_select(it);
5015 }
5016 else
5017 _item_unselect(it);
5018 }
5019 else
5020 {
5021 if (!it->selected)
5022 {
5023 while (sd->selected)
5024 {
5025 Elm_Object_Item *eo_sel = sd->selected->data;
5026 Elm_Gen_Item *sel = efl_data_scope_get(eo_sel, ELM_GENLIST_ITEM_CLASS);
5027 _item_unselect(sel);
5028 }
5029 }
5030 else
5031 {
5032 const Eina_List *l, *l_next;
5033 Elm_Object_Item *eo_it2;
5034
5035 EINA_LIST_FOREACH_SAFE(sd->selected, l, l_next, eo_it2)
5036 {
5037 ELM_GENLIST_ITEM_DATA_GET(eo_it2, it2);
5038 if (it2 != it)
5039 _item_unselect(it2);
5040 }
5041 }
5042 _item_highlight(it);
5043 _item_select(it);
5044 }
5045 }
5046
5047 /* If the application wants to know the relative item, use
5048 * elm_genlist_item_next_get(it)*/
5049 static void
_item_move_before(Elm_Gen_Item * it,Elm_Gen_Item * before)5050 _item_move_before(Elm_Gen_Item *it,
5051 Elm_Gen_Item *before)
5052 {
5053 if (!it) return;
5054 if (!before) return;
5055 if (it == before) return;
5056 ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
5057
5058 sd->items =
5059 eina_inlist_remove(sd->items, EINA_INLIST_GET(it));
5060 if (it->item->block) _item_block_del(it);
5061 sd->items = eina_inlist_prepend_relative
5062 (sd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(before));
5063 if (it->item->rel)
5064 it->item->rel->item->rel_revs =
5065 eina_list_remove(it->item->rel->item->rel_revs, it);
5066 it->item->rel = before;
5067 before->item->rel_revs = eina_list_append(before->item->rel_revs, it);
5068 it->item->before = EINA_TRUE;
5069 if (before->item->group_item)
5070 it->item->group_item = before->item->group_item;
5071 _item_queue(sd, it, NULL);
5072
5073 efl_event_callback_legacy_call(WIDGET(it), ELM_GENLIST_EVENT_MOVED_BEFORE, EO_OBJ(it));
5074 }
5075
5076 static void
_item_mouse_up_cb(void * data,Evas * evas EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info)5077 _item_mouse_up_cb(void *data,
5078 Evas *evas EINA_UNUSED,
5079 Evas_Object *obj EINA_UNUSED,
5080 void *event_info)
5081 {
5082 Evas_Event_Mouse_Up *ev = event_info;
5083 Eina_Bool dragged = EINA_FALSE;
5084 Elm_Gen_Item *it = data;
5085 Evas_Coord x, y, dx, dy;
5086
5087 if ((ev->button == 3) && (!it->dragging))
5088 {
5089 evas_object_geometry_get(obj, &x, &y, NULL, NULL);
5090 dx = it->dx - (ev->canvas.x - x);
5091 dy = it->dy - (ev->canvas.y - y);
5092 if (dx < 0) dx = -dx;
5093 if (dy < 0) dy = -dy;
5094 if ((dx < 5) && (dy < 5))
5095 evas_object_smart_callback_call
5096 ( WIDGET(it), "clicked,right", EO_OBJ(it));
5097 return;
5098 }
5099
5100 if (ev->button != 1) return;
5101 it->down = EINA_FALSE;
5102 ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
5103
5104 evas_object_ref(WIDGET(it));
5105 efl_ref(EO_OBJ(it));
5106 sd->mouse_down = EINA_FALSE;
5107
5108 efl_event_callback_legacy_call(WIDGET(it), ELM_GENLIST_EVENT_RELEASED, EO_OBJ(it));
5109
5110 if (sd->multi_touched)
5111 {
5112 if ((!sd->multi) && (!it->selected) && (it->highlighted))
5113 _item_unhighlight(it);
5114 if (sd->multi_down) goto early;
5115 _multi_touch_gesture_eval(it);
5116 goto early;
5117 }
5118 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
5119 sd->on_hold = EINA_TRUE;
5120 else sd->on_hold = EINA_FALSE;
5121 ELM_SAFE_FREE(it->long_timer, ecore_timer_del);
5122 if (it->dragging)
5123 {
5124 it->dragging = EINA_FALSE;
5125 evas_object_smart_callback_call
5126 (WIDGET(it), "drag,stop", EO_OBJ(it));
5127 dragged = 1;
5128 }
5129 ELM_SAFE_FREE(it->item->swipe_timer, ecore_timer_del);
5130 if (sd->multi_timer)
5131 {
5132 ELM_SAFE_FREE(sd->multi_timer, ecore_timer_del);
5133 sd->multi_timeout = EINA_FALSE;
5134 }
5135 if (sd->swipe)
5136 {
5137 if (!sd->wasselected) _item_unselect(it);
5138 _swipe_do(it);
5139 sd->longpressed = EINA_FALSE;
5140 sd->on_hold = EINA_FALSE;
5141 sd->wasselected = EINA_FALSE;
5142 goto early;
5143 }
5144 if ((sd->reorder_mode) && (sd->reorder_it))
5145 {
5146 Evas_Coord it_scrl_y = ev->canvas.y - sd->reorder_it->dy;
5147 sd->reorder_fast = 0;
5148
5149 if (sd->reorder_rel &&
5150 (sd->reorder_it->parent == sd->reorder_rel->parent))
5151 {
5152 if (it_scrl_y <= sd->reorder_rel->item->scrl_y)
5153 _item_move_before(sd->reorder_it, sd->reorder_rel);
5154 else
5155 _item_move_after(sd->reorder_it, sd->reorder_rel);
5156 efl_event_callback_legacy_call(WIDGET(it), ELM_GENLIST_EVENT_MOVED, EO_OBJ(it));
5157 }
5158 else
5159 {
5160 efl_canvas_group_change(sd->obj);
5161 }
5162 edje_object_signal_emit(VIEW(it), SIGNAL_REORDER_DISABLED, "elm");
5163 if (_elm_config->atspi_mode)
5164 efl_access_state_changed_signal_emit(EO_OBJ(it), EFL_ACCESS_STATE_TYPE_ANIMATED, EINA_FALSE);
5165 sd->reorder_it = sd->reorder_rel = NULL;
5166 elm_interface_scrollable_hold_set(sd->obj, EINA_FALSE);
5167 elm_interface_scrollable_bounce_allow_set
5168 (sd->obj, sd->h_bounce, sd->v_bounce);
5169 }
5170 if (sd->longpressed)
5171 {
5172 if (!sd->wasselected) _item_unselect(it);
5173 sd->longpressed = EINA_FALSE;
5174 sd->wasselected = EINA_FALSE;
5175 goto early;
5176 }
5177 if (dragged)
5178 {
5179 if (it->want_unrealize)
5180 {
5181 _elm_genlist_item_unrealize(it, EINA_FALSE);
5182 if (it->item->block->want_unrealize)
5183 _item_block_unrealize(it->item->block);
5184 }
5185 }
5186
5187 /* this is handled implicitly in _item_unselect() below unless there
5188 * will be no select
5189 */
5190 if (!it->selected && it->highlighted && _is_no_select(it))
5191 _item_unhighlight(it);
5192
5193 if ((ev->flags != EVAS_BUTTON_NONE) ||
5194 (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) ||
5195 !it->base->still_in ||
5196 _is_no_select(it) ||
5197 (elm_wdg_item_disabled_get(EO_OBJ(it))))
5198 goto early;
5199
5200 evas_object_ref(sd->obj);
5201
5202 if (sd->focused_item != EO_OBJ(it))
5203 elm_object_item_focus_set(EO_OBJ(it), EINA_TRUE);
5204
5205 if (efl_invalidated_get(EO_OBJ(it))) goto deleted;
5206
5207 if (sd->multi &&
5208 ((sd->multi_select_mode != ELM_OBJECT_MULTI_SELECT_MODE_WITH_CONTROL) ||
5209 (evas_key_modifier_is_set(ev->modifiers, "Control"))))
5210 {
5211 if (!it->selected)
5212 {
5213 /* this should only be handled on mouse down
5214 _item_highlight(it);
5215 */
5216 if (_item_select(it)) goto deleted;
5217 }
5218 else
5219 _item_unselect(it);
5220 }
5221 else
5222 {
5223 if (!it->selected)
5224 {
5225 while (sd->selected)
5226 {
5227 Elm_Object_Item *eo_sel = sd->selected->data;
5228 Elm_Gen_Item *sel = efl_data_scope_get(eo_sel, ELM_GENLIST_ITEM_CLASS);
5229 _item_unselect(sel);
5230 }
5231 }
5232 else
5233 {
5234 const Eina_List *l, *l_next;
5235 Elm_Object_Item *eo_it2;
5236
5237 EINA_LIST_FOREACH_SAFE(sd->selected, l, l_next, eo_it2)
5238 {
5239 ELM_GENLIST_ITEM_DATA_GET(eo_it2, it2);
5240 if (it2 != it)
5241 _item_unselect(it2);
5242 }
5243 }
5244 /* this should only be handled on mouse down
5245 _item_highlight(it);
5246 */
5247 if (_item_select(it)) goto deleted;
5248 }
5249
5250 deleted:
5251 evas_object_unref(sd->obj);
5252 early:
5253 evas_object_unref(WIDGET(it));
5254 efl_unref(EO_OBJ(it));
5255 }
5256
5257 static void
_item_mouse_callbacks_add(Elm_Gen_Item * it,Evas_Object * view)5258 _item_mouse_callbacks_add(Elm_Gen_Item *it,
5259 Evas_Object *view)
5260 {
5261 if (it->callbacks) return ;
5262 it->callbacks = EINA_TRUE;
5263 evas_object_event_callback_add
5264 (view, EVAS_CALLBACK_MOUSE_DOWN, _item_mouse_down_cb, it);
5265 evas_object_event_callback_add
5266 (view, EVAS_CALLBACK_MOUSE_UP, _item_mouse_up_cb, it);
5267 evas_object_event_callback_add
5268 (view, EVAS_CALLBACK_MOUSE_MOVE, _item_mouse_move_cb, it);
5269 evas_object_event_callback_add
5270 (view, EVAS_CALLBACK_MULTI_DOWN, _item_multi_down_cb, it);
5271 evas_object_event_callback_add
5272 (view, EVAS_CALLBACK_MULTI_UP, _item_multi_up_cb, it);
5273 evas_object_event_callback_add
5274 (view, EVAS_CALLBACK_MULTI_MOVE, _item_multi_move_cb, it);
5275 evas_object_event_callback_add
5276 (view, EVAS_CALLBACK_MOUSE_IN, _item_mouse_in_cb, it);
5277 }
5278
5279 static void
_item_mouse_callbacks_del(Elm_Gen_Item * it,Evas_Object * view)5280 _item_mouse_callbacks_del(Elm_Gen_Item *it,
5281 Evas_Object *view)
5282 {
5283 if (!it->callbacks) return ;
5284 it->callbacks = EINA_FALSE;
5285 evas_object_event_callback_del_full
5286 (view, EVAS_CALLBACK_MOUSE_DOWN, _item_mouse_down_cb, it);
5287 evas_object_event_callback_del_full
5288 (view, EVAS_CALLBACK_MOUSE_UP, _item_mouse_up_cb, it);
5289 evas_object_event_callback_del_full
5290 (view, EVAS_CALLBACK_MOUSE_MOVE, _item_mouse_move_cb, it);
5291 evas_object_event_callback_del_full
5292 (view, EVAS_CALLBACK_MULTI_DOWN, _item_multi_down_cb, it);
5293 evas_object_event_callback_del_full
5294 (view, EVAS_CALLBACK_MULTI_UP, _item_multi_up_cb, it);
5295 evas_object_event_callback_del_full
5296 (view, EVAS_CALLBACK_MULTI_MOVE, _item_multi_move_cb, it);
5297 evas_object_event_callback_del_full
5298 (view, EVAS_CALLBACK_MOUSE_IN, _item_mouse_in_cb, it);
5299 }
5300
5301 static Eina_Bool
_scroll_hold_timer_cb(void * data)5302 _scroll_hold_timer_cb(void *data)
5303 {
5304 ELM_GENLIST_DATA_GET(data, sd);
5305
5306 if (!data) return ECORE_CALLBACK_CANCEL;
5307
5308 elm_interface_scrollable_hold_set(sd->obj, EINA_FALSE);
5309 sd->scr_hold_timer = NULL;
5310
5311 return ECORE_CALLBACK_CANCEL;
5312 }
5313
5314 static void
_decorate_item_unrealize(Elm_Gen_Item * it,Eina_Bool state_update)5315 _decorate_item_unrealize(Elm_Gen_Item *it, Eina_Bool state_update)
5316 {
5317 ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
5318 Evas_Object *obj = sd->obj;
5319 Evas *e;
5320
5321 if (!it->item->deco_it_view) return;
5322
5323 e = evas_object_evas_get(obj);
5324 evas_event_freeze(e);
5325
5326 _view_clear(it->item->deco_it_view, &(it->item->deco_it_texts),
5327 &(it->item->deco_it_contents));
5328
5329 edje_object_part_unswallow(it->item->deco_it_view, VIEW(it));
5330 ELM_SAFE_FREE(it->item->deco_it_view, evas_object_del);
5331 evas_object_smart_member_add(VIEW(it), sd->pan_obj);
5332 evas_object_clip_set(VIEW(it), evas_object_clip_get(sd->pan_obj));
5333 if (state_update)
5334 {
5335 _elm_genlist_item_state_update(it);
5336 _item_order_update(it, it->item->order_num_in, EINA_TRUE);
5337 }
5338
5339 if (sd->mode_item != it)
5340 it->decorate_it_set = EINA_FALSE;
5341
5342 evas_event_thaw(e);
5343 evas_event_thaw_eval(e);
5344 }
5345
5346 static void
_decorate_item_finished_signal_cb(void * data,Evas_Object * obj,const char * emission EINA_UNUSED,const char * source EINA_UNUSED)5347 _decorate_item_finished_signal_cb(void *data,
5348 Evas_Object *obj,
5349 const char *emission EINA_UNUSED,
5350 const char *source EINA_UNUSED)
5351 {
5352 Elm_Gen_Item *it = data;
5353 char buf[1024];
5354 Evas *te;
5355
5356 if (!it || !obj) return;
5357 ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
5358
5359 te = evas_object_evas_get(obj);
5360
5361 if ((!it->realized) || (!it->item->deco_it_view)) return;
5362
5363 evas_event_freeze(te);
5364 snprintf(buf, sizeof(buf), "elm,state,%s,passive,finished",
5365 sd->decorate_it_type);
5366 edje_object_signal_callback_del_full
5367 (it->item->deco_it_view, buf, "elm", _decorate_item_finished_signal_cb, it);
5368 it->item->nocache_once = EINA_FALSE;
5369 _decorate_item_unrealize(it, EINA_TRUE);
5370 if (it->item->group_item)
5371 evas_object_stack_above(it->item->VIEW(group_item), sd->stack[1]);
5372
5373 evas_event_thaw(te);
5374 evas_event_thaw_eval(te);
5375 }
5376
5377 static void
_item_unrealize(Elm_Gen_Item * it)5378 _item_unrealize(Elm_Gen_Item *it)
5379 {
5380 Evas_Object *c;
5381 Eina_List *cache = NULL;
5382
5383 EINA_LIST_FREE(it->item->flip_contents, c)
5384 evas_object_del(c);
5385
5386 /* access */
5387 if (_elm_config->access_mode == ELM_ACCESS_MODE_ON)
5388 _elm_access_widget_item_unregister(it->base);
5389
5390 // unswallow VIEW(it) first then manipulate VIEW(it)
5391 _decorate_item_unrealize(it, EINA_FALSE);
5392 if (it->item->wsd->decorate_all_mode) _decorate_all_item_unrealize(it);
5393
5394 if (!_item_cache_add(it, _content_cache_add(it, &cache)))
5395 {
5396 Evas_Object *view = VIEW(it);
5397 efl_wref_del(VIEW(it), &VIEW(it));
5398 ELM_SAFE_FREE(view, efl_del);
5399 VIEW(it) = NULL;
5400 it->callbacks = EINA_FALSE;
5401 ELM_SAFE_FREE(it->spacer, evas_object_del);
5402 EINA_LIST_FREE(cache, c)
5403 {
5404 evas_object_del(c);
5405 }
5406 }
5407
5408 it->states = NULL;
5409 it->realized = EINA_FALSE;
5410 it->want_unrealize = EINA_FALSE;
5411 }
5412
5413 static void
_item_temp_realize(Elm_Gen_Item * it,const int index)5414 _item_temp_realize(Elm_Gen_Item *it, const int index)
5415 {
5416 it->item->unfocusable = EINA_TRUE;
5417 _item_realize(it, index, EINA_TRUE);
5418 _elm_genlist_item_unrealize(it, EINA_TRUE);
5419 it->item->unfocusable = EINA_FALSE;
5420 }
5421
5422 static Eina_Bool
_item_block_recalc(Item_Block * itb,const int blk_idx,Eina_Bool qadd)5423 _item_block_recalc(Item_Block *itb, const int blk_idx, Eina_Bool qadd)
5424 {
5425 const Eina_List *l;
5426 Elm_Gen_Item *it;
5427 Evas_Coord minw = 0, minh = 0;
5428 Eina_Bool show_me = EINA_FALSE, changed = EINA_FALSE;
5429 Evas_Coord y = 0;
5430 Item_Size *size = NULL;
5431 int vis_count = 0;
5432
5433 itb->num = blk_idx;
5434 EINA_LIST_FOREACH(itb->items, l, it)
5435 {
5436 show_me |= it->item->show_me;
5437
5438 if (!_item_filtered_get(it, itb->sd))
5439 {
5440 if (it->realized) evas_object_hide(VIEW(it));
5441 continue;
5442 }
5443 if (!itb->realized)
5444 {
5445 if (itb->sd->homogeneous &&
5446 ((!size) || it->itc != size->itc))
5447 size = eina_hash_find(itb->sd->size_caches, &(it->itc));
5448 if (qadd || (itb->sd->homogeneous && !size))
5449 {
5450 if (!it->item->mincalcd) changed = EINA_TRUE;
5451 if (changed)
5452 {
5453 if (!size || (it->item->expanded_depth != size->expanded_depth))
5454 {
5455 _item_temp_realize(it, blk_idx + vis_count);
5456 }
5457 else
5458 {
5459 it->item->w = it->item->minw = size->minw;
5460 it->item->h = it->item->minh = size->minh;
5461 it->item->mincalcd = EINA_TRUE;
5462 }
5463 }
5464 }
5465 else
5466 {
5467 if ((itb->sd->homogeneous) && size &&
5468 (it->item->expanded_depth == size->expanded_depth) &&
5469 (itb->sd->mode == ELM_LIST_COMPRESS))
5470 {
5471 it->item->w = it->item->minw = size->minw;
5472 it->item->h = it->item->minh = size->minh;
5473 it->item->mincalcd = EINA_TRUE;
5474 }
5475 else
5476 _item_temp_realize(it, blk_idx + vis_count);
5477 }
5478 }
5479 else
5480 {
5481 if (!it->item->mincalcd) changed = EINA_TRUE;
5482 _item_realize(it, blk_idx + vis_count, EINA_FALSE);
5483 }
5484 minh += it->item->minh;
5485 if (minw < it->item->minw) minw = it->item->minw;
5486 vis_count++;
5487 it->x = 0;
5488 it->y = y;
5489 y += it->item->h;
5490 }
5491 if (changed) itb->sd->pan_changed = changed;
5492 itb->minw = minw;
5493 itb->minh = minh;
5494 itb->changed = EINA_FALSE;
5495 itb->position_update = EINA_FALSE;
5496 itb->vis_count = vis_count;
5497
5498 return show_me;
5499 }
5500
5501 static void
_update_job(void * data)5502 _update_job(void *data)
5503 {
5504 Eina_Bool position = EINA_FALSE, recalc = EINA_FALSE;
5505 ELM_GENLIST_DATA_GET(data, sd);
5506 Item_Block *itb;
5507 Eina_List *l2;
5508 int num, num0;
5509 Evas *e = evas_object_evas_get(sd->obj);;
5510
5511 sd->update_job = NULL;
5512 num = 0;
5513
5514 evas_event_freeze(e);
5515 EINA_INLIST_FOREACH(sd->blocks, itb)
5516 {
5517 Evas_Coord itminw, itminh;
5518 Elm_Gen_Item *it;
5519
5520 if (!itb->updateme)
5521 {
5522 if (position)
5523 _item_block_position(itb, num);
5524 num += itb->vis_count;
5525 continue;
5526 }
5527 num0 = num;
5528 recalc = EINA_FALSE;
5529 EINA_LIST_FOREACH(itb->items, l2, it)
5530 {
5531 if (it->item->updateme)
5532 {
5533 itminw = it->item->minw;
5534 itminh = it->item->minh;
5535
5536 it->item->updateme = EINA_FALSE;
5537 if (it->realized)
5538 {
5539 _elm_genlist_item_unrealize(it, EINA_FALSE);
5540 _item_realize(it, num, EINA_FALSE);
5541 position = EINA_TRUE;
5542 }
5543 else
5544 {
5545 _item_realize(it, num, EINA_TRUE);
5546 _elm_genlist_item_unrealize(it, EINA_TRUE);
5547 }
5548 if ((it->item->minw != itminw) || (it->item->minh != itminh))
5549 recalc = EINA_TRUE;
5550 }
5551 if (!it->hide) num++;
5552 }
5553 itb->updateme = EINA_FALSE;
5554 if (recalc)
5555 {
5556 position = EINA_TRUE;
5557 itb->changed = EINA_TRUE;
5558 _item_block_recalc(itb, num0, EINA_FALSE);
5559 _item_block_position(itb, num0);
5560 }
5561 }
5562 if (position)
5563 {
5564 efl_canvas_group_change(sd->pan_obj);
5565 efl_canvas_group_change(sd->obj);
5566 }
5567 evas_event_thaw(e);
5568 evas_event_thaw_eval(e);
5569 }
5570
5571 static void
_scroll_animate_start_cb(Evas_Object * obj,void * data EINA_UNUSED)5572 _scroll_animate_start_cb(Evas_Object *obj,
5573 void *data EINA_UNUSED)
5574 {
5575 evas_object_smart_callback_call(obj, "scroll,anim,start", NULL);
5576 }
5577
5578 static void
_scroll_animate_stop_cb(Evas_Object * obj,void * data EINA_UNUSED)5579 _scroll_animate_stop_cb(Evas_Object *obj,
5580 void *data EINA_UNUSED)
5581 {
5582 evas_object_smart_callback_call(obj, "scroll,anim,stop", NULL);
5583 }
5584
5585 static void
_scroll_drag_start_cb(Evas_Object * obj,void * data EINA_UNUSED)5586 _scroll_drag_start_cb(Evas_Object *obj,
5587 void *data EINA_UNUSED)
5588 {
5589 evas_object_smart_callback_call(obj, "scroll,drag,start", NULL);
5590 }
5591
5592 static void
_scroll_cb(Evas_Object * obj,void * data EINA_UNUSED)5593 _scroll_cb(Evas_Object *obj,
5594 void *data EINA_UNUSED)
5595 {
5596 evas_object_smart_callback_call(obj, "scroll", NULL);
5597 }
5598
5599 static void
_scroll_drag_stop_cb(Evas_Object * obj,void * data EINA_UNUSED)5600 _scroll_drag_stop_cb(Evas_Object *obj,
5601 void *data EINA_UNUSED)
5602 {
5603 evas_object_smart_callback_call(obj, "scroll,drag,stop", NULL);
5604 }
5605
5606 static void
_edge_left_cb(Evas_Object * obj,void * data EINA_UNUSED)5607 _edge_left_cb(Evas_Object *obj,
5608 void *data EINA_UNUSED)
5609 {
5610 efl_event_callback_legacy_call(obj, ELM_GENLIST_EVENT_EDGE_LEFT, NULL);
5611 }
5612
5613 static void
_edge_right_cb(Evas_Object * obj,void * data EINA_UNUSED)5614 _edge_right_cb(Evas_Object *obj,
5615 void *data EINA_UNUSED)
5616 {
5617 efl_event_callback_legacy_call(obj, ELM_GENLIST_EVENT_EDGE_RIGHT, NULL);
5618 }
5619
5620 static void
_edge_top_cb(Evas_Object * obj,void * data EINA_UNUSED)5621 _edge_top_cb(Evas_Object *obj,
5622 void *data EINA_UNUSED)
5623 {
5624 efl_event_callback_legacy_call(obj, ELM_GENLIST_EVENT_EDGE_TOP, NULL);
5625 }
5626
5627 static void
_edge_bottom_cb(Evas_Object * obj,void * data EINA_UNUSED)5628 _edge_bottom_cb(Evas_Object *obj,
5629 void *data EINA_UNUSED)
5630 {
5631 efl_event_callback_legacy_call(obj, ELM_GENLIST_EVENT_EDGE_BOTTOM, NULL);
5632 }
5633
5634 static void
_vbar_drag_cb(Evas_Object * obj,void * data EINA_UNUSED)5635 _vbar_drag_cb(Evas_Object *obj,
5636 void *data EINA_UNUSED)
5637 {
5638 efl_event_callback_legacy_call(obj, ELM_GENLIST_EVENT_VBAR_DRAG, NULL);
5639 }
5640
5641 static void
_vbar_press_cb(Evas_Object * obj,void * data EINA_UNUSED)5642 _vbar_press_cb(Evas_Object *obj,
5643 void *data EINA_UNUSED)
5644 {
5645 efl_event_callback_legacy_call(obj, ELM_GENLIST_EVENT_VBAR_PRESS, NULL);
5646 }
5647
5648 static void
_vbar_unpress_cb(Evas_Object * obj,void * data EINA_UNUSED)5649 _vbar_unpress_cb(Evas_Object *obj,
5650 void *data EINA_UNUSED)
5651 {
5652 efl_event_callback_legacy_call(obj, ELM_GENLIST_EVENT_VBAR_UNPRESS, NULL);
5653 }
5654
5655 static void
_hbar_drag_cb(Evas_Object * obj,void * data EINA_UNUSED)5656 _hbar_drag_cb(Evas_Object *obj,
5657 void *data EINA_UNUSED)
5658 {
5659 efl_event_callback_legacy_call(obj, ELM_GENLIST_EVENT_HBAR_DRAG, NULL);
5660 }
5661
5662 static void
_hbar_press_cb(Evas_Object * obj,void * data EINA_UNUSED)5663 _hbar_press_cb(Evas_Object *obj,
5664 void *data EINA_UNUSED)
5665 {
5666 efl_event_callback_legacy_call(obj, ELM_GENLIST_EVENT_HBAR_PRESS, NULL);
5667 }
5668
5669 static void
_hbar_unpress_cb(Evas_Object * obj,void * data EINA_UNUSED)5670 _hbar_unpress_cb(Evas_Object *obj,
5671 void *data EINA_UNUSED)
5672 {
5673 efl_event_callback_legacy_call(obj, ELM_GENLIST_EVENT_HBAR_UNPRESS, NULL);
5674 }
5675
5676 static void
_decorate_item_realize(Elm_Gen_Item * it)5677 _decorate_item_realize(Elm_Gen_Item *it)
5678 {
5679 ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
5680 Evas_Object *obj = sd->obj;
5681 char buf[1024];
5682 Evas *e;
5683
5684 if (it->item->deco_it_view) return;
5685
5686 e = evas_object_evas_get(obj);
5687 evas_event_freeze(e);
5688 it->item->deco_it_view = _view_create(it, it->itc->decorate_item_style);
5689
5690 /* signal callback add */
5691 evas_object_event_callback_add
5692 (it->item->deco_it_view, EVAS_CALLBACK_MOUSE_DOWN, _item_mouse_down_cb,
5693 it);
5694 evas_object_event_callback_add
5695 (it->item->deco_it_view, EVAS_CALLBACK_MOUSE_UP, _item_mouse_up_cb, it);
5696 evas_object_event_callback_add
5697 (it->item->deco_it_view, EVAS_CALLBACK_MOUSE_MOVE, _item_mouse_move_cb,
5698 it);
5699
5700 _view_inflate(it->item->deco_it_view, it, &it->item->deco_it_texts,
5701 &it->item->deco_it_contents, EINA_FALSE);
5702 edje_object_part_swallow
5703 (it->item->deco_it_view,
5704 edje_object_data_get(it->item->deco_it_view, "mode_part"), VIEW(it));
5705
5706 snprintf(buf, sizeof(buf), "elm,state,%s,active", sd->decorate_it_type);
5707 edje_object_signal_emit(it->item->deco_it_view, buf, "elm");
5708 edje_object_signal_emit(VIEW(it), buf, "elm");
5709
5710 it->want_unrealize = EINA_FALSE;
5711 evas_event_thaw(e);
5712 evas_event_thaw_eval(e);
5713 }
5714
5715 static void
_decorate_item_set(Elm_Gen_Item * it)5716 _decorate_item_set(Elm_Gen_Item *it)
5717 {
5718 Evas *e;
5719 if (!it) return;
5720
5721 ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
5722
5723 sd->mode_item = it;
5724 it->item->nocache_once = EINA_TRUE;
5725
5726 ELM_SAFE_FREE(sd->scr_hold_timer, ecore_timer_del);
5727 elm_interface_scrollable_hold_set(sd->obj, EINA_TRUE);
5728 sd->scr_hold_timer = ecore_timer_add(SCR_HOLD_TIME, _scroll_hold_timer_cb, sd->obj);
5729
5730 e = evas_object_evas_get(sd->obj);
5731 evas_event_freeze(e);
5732 _decorate_item_realize(it);
5733 if (it->item->group_item)
5734 evas_object_stack_above(it->item->VIEW(group_item), sd->stack[1]);
5735 _item_position
5736 (it, it->item->deco_it_view, it->item->scrl_x, it->item->scrl_y);
5737 evas_event_thaw(e);
5738 evas_event_thaw_eval(e);
5739
5740 }
5741
5742 static void
_decorate_item_unset(Elm_Genlist_Data * sd)5743 _decorate_item_unset(Elm_Genlist_Data *sd)
5744 {
5745 char buf[1024], buf2[1024];
5746 Elm_Gen_Item *it;
5747
5748 if (!sd->mode_item) return;
5749
5750 it = sd->mode_item;
5751 it->item->nocache_once = EINA_TRUE;
5752 it->decorate_it_set = EINA_FALSE;
5753
5754 snprintf(buf, sizeof(buf), "elm,state,%s,passive", sd->decorate_it_type);
5755 snprintf(buf2, sizeof(buf2), "elm,state,%s,passive,finished",
5756 sd->decorate_it_type);
5757 edje_object_signal_emit(it->item->deco_it_view, buf, "elm");
5758 edje_object_signal_callback_add
5759 (it->item->deco_it_view, buf2, "elm", _decorate_item_finished_signal_cb,
5760 it);
5761 sd->mode_item = NULL;
5762 }
5763
5764 static void
_elm_genlist_looping_up_cb(void * data,Evas_Object * obj EINA_UNUSED,const char * emission EINA_UNUSED,const char * source EINA_UNUSED)5765 _elm_genlist_looping_up_cb(void *data,
5766 Evas_Object *obj EINA_UNUSED,
5767 const char *emission EINA_UNUSED,
5768 const char *source EINA_UNUSED)
5769 {
5770 Evas_Object *genlist = data;
5771
5772 ELM_GENLIST_DATA_GET(genlist, sd);
5773
5774 Elm_Object_Item *eo_it = elm_genlist_last_item_get(genlist);
5775
5776 elm_genlist_item_show(eo_it, ELM_GENLIST_ITEM_SCROLLTO_IN);
5777 elm_layout_signal_emit(genlist, "elm,action,looping,up,end", "elm");
5778 sd->item_looping_on = EINA_FALSE;
5779
5780 if (!_elm_config->item_select_on_focus_disable)
5781 elm_genlist_item_selected_set(eo_it, EINA_TRUE);
5782 else
5783 elm_object_item_focus_set(eo_it, EINA_TRUE);
5784 }
5785
5786 static void
_elm_genlist_looping_down_cb(void * data,Evas_Object * obj EINA_UNUSED,const char * emission EINA_UNUSED,const char * source EINA_UNUSED)5787 _elm_genlist_looping_down_cb(void *data,
5788 Evas_Object *obj EINA_UNUSED,
5789 const char *emission EINA_UNUSED,
5790 const char *source EINA_UNUSED)
5791 {
5792 Evas_Object *genlist = data;
5793
5794 ELM_GENLIST_DATA_GET(genlist, sd);
5795
5796 Elm_Object_Item *eo_it = elm_genlist_first_item_get(genlist);
5797
5798 elm_genlist_item_show(eo_it, ELM_GENLIST_ITEM_SCROLLTO_IN);
5799 elm_layout_signal_emit(genlist, "elm,action,looping,down,end", "elm");
5800 sd->item_looping_on = EINA_FALSE;
5801
5802 if (!_elm_config->item_select_on_focus_disable)
5803 elm_genlist_item_selected_set(eo_it, EINA_TRUE);
5804 else
5805 elm_object_item_focus_set(eo_it, EINA_TRUE);
5806 }
5807
5808 static void
_evas_viewport_resize_cb(void * d,Evas * e EINA_UNUSED,void * ei EINA_UNUSED)5809 _evas_viewport_resize_cb(void *d, Evas *e EINA_UNUSED, void *ei EINA_UNUSED)
5810 {
5811 Elm_Genlist_Data *priv = d;
5812 evas_object_smart_changed(priv->pan_obj);
5813 }
5814
5815 EOLIAN static void
_elm_genlist_efl_canvas_group_group_add(Eo * obj,Elm_Genlist_Data * priv)5816 _elm_genlist_efl_canvas_group_group_add(Eo *obj, Elm_Genlist_Data *priv)
5817 {
5818 ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
5819 Elm_Genlist_Pan_Data *pan_data;
5820 Evas_Coord minw, minh;
5821 Evas *e = evas_object_evas_get(obj);
5822 int i;
5823
5824 efl_canvas_group_add(efl_super(obj, MY_CLASS));
5825
5826 priv->size_caches = eina_hash_pointer_new(_size_cache_free);
5827 priv->hit_rect = evas_object_rectangle_add(e);
5828 evas_object_smart_member_add(priv->hit_rect, obj);
5829 elm_widget_sub_object_add(obj, priv->hit_rect);
5830
5831 /* common scroller hit rectangle setup */
5832 evas_object_color_set(priv->hit_rect, 0, 0, 0, 0);
5833 evas_object_show(priv->hit_rect);
5834 evas_object_repeat_events_set(priv->hit_rect, EINA_TRUE);
5835
5836 elm_widget_can_focus_set(obj, EINA_TRUE);
5837 elm_widget_on_show_region_hook_set(obj, NULL, _show_region_hook, NULL);
5838
5839 if (!elm_layout_theme_set
5840 (obj, "genlist", "base", elm_widget_style_get(obj)))
5841 CRI("Failed to set layout!");
5842
5843 elm_interface_scrollable_objects_set(obj, wd->resize_obj, priv->hit_rect);
5844
5845 elm_interface_scrollable_bounce_allow_set
5846 (obj, EINA_FALSE, _elm_config->thumbscroll_bounce_enable);
5847 priv->v_bounce = _elm_config->thumbscroll_bounce_enable;
5848
5849 elm_interface_scrollable_animate_start_cb_set(obj, _scroll_animate_start_cb);
5850 elm_interface_scrollable_animate_stop_cb_set(obj, _scroll_animate_stop_cb);
5851 elm_interface_scrollable_scroll_cb_set(obj, _scroll_cb);
5852 elm_interface_scrollable_drag_start_cb_set(obj, _scroll_drag_start_cb);
5853 elm_interface_scrollable_drag_stop_cb_set(obj, _scroll_drag_stop_cb);
5854 elm_interface_scrollable_edge_left_cb_set(obj, _edge_left_cb);
5855 elm_interface_scrollable_edge_right_cb_set(obj, _edge_right_cb);
5856 elm_interface_scrollable_edge_top_cb_set(obj, _edge_top_cb);
5857 elm_interface_scrollable_edge_bottom_cb_set(obj, _edge_bottom_cb);
5858 elm_interface_scrollable_vbar_drag_cb_set(obj, _vbar_drag_cb);
5859 elm_interface_scrollable_vbar_press_cb_set(obj, _vbar_press_cb);
5860 elm_interface_scrollable_vbar_unpress_cb_set(obj, _vbar_unpress_cb);
5861 elm_interface_scrollable_hbar_drag_cb_set(obj, _hbar_drag_cb);
5862 elm_interface_scrollable_hbar_press_cb_set(obj, _hbar_press_cb);
5863 elm_interface_scrollable_hbar_unpress_cb_set(obj, _hbar_unpress_cb);
5864 elm_interface_scrollable_content_min_limit_cb_set(obj, _content_min_limit_cb);
5865
5866 priv->mode = ELM_LIST_SCROLL;
5867 priv->max_items_per_block = MAX_ITEMS_PER_BLOCK;
5868 priv->item_cache_max = priv->max_items_per_block * 2;
5869 priv->longpress_timeout = _elm_config->longpress_timeout;
5870 priv->highlight = EINA_TRUE;
5871 priv->pin_item = NULL;
5872 priv->pin_item_top = EINA_FALSE;
5873
5874 priv->pan_obj = efl_add(MY_PAN_CLASS, e);
5875 pan_data = efl_data_scope_get(priv->pan_obj, MY_PAN_CLASS);
5876 efl_data_ref(obj, MY_CLASS);
5877 pan_data->wobj = obj;
5878 pan_data->wsd = priv;
5879
5880 for (i = 0; i < 2; i++)
5881 {
5882 priv->stack[i] = evas_object_rectangle_add(e);
5883 evas_object_smart_member_add(priv->stack[i], priv->pan_obj);
5884 }
5885
5886 elm_interface_scrollable_extern_pan_set(obj, priv->pan_obj);
5887
5888 edje_object_size_min_calc(wd->resize_obj, &minw, &minh);
5889 evas_object_size_hint_min_set(obj, minw, minh);
5890
5891 _mirrored_set(obj, efl_ui_mirrored_get(obj));
5892
5893 elm_layout_sizing_eval(obj);
5894
5895 edje_object_signal_callback_add(wd->resize_obj, "elm,looping,up,done", "elm", _elm_genlist_looping_up_cb, obj);
5896 edje_object_signal_callback_add(wd->resize_obj, "elm,looping,down,done", "elm", _elm_genlist_looping_down_cb, obj);
5897 evas_event_callback_add(e,
5898 EVAS_CALLBACK_CANVAS_VIEWPORT_RESIZE,
5899 _evas_viewport_resize_cb, priv);
5900 }
5901
5902 EOLIAN static void
_elm_genlist_efl_canvas_group_group_del(Eo * obj,Elm_Genlist_Data * sd)5903 _elm_genlist_efl_canvas_group_group_del(Eo *obj, Elm_Genlist_Data *sd)
5904 {
5905 int i;
5906
5907 elm_genlist_clear(obj);
5908 _item_cache_zero(sd);
5909
5910 efl_canvas_group_del(efl_super(obj, MY_CLASS));
5911
5912 for (i = 0; i < 2; i++)
5913 ELM_SAFE_FREE(sd->stack[i], evas_object_del);
5914
5915 evas_event_callback_del_full(evas_object_evas_get(obj),
5916 EVAS_CALLBACK_CANVAS_VIEWPORT_RESIZE,
5917 _evas_viewport_resize_cb, sd);
5918
5919 ELM_SAFE_FREE(sd->update_job, ecore_job_del);
5920 ELM_SAFE_FREE(sd->pan_obj, evas_object_del);
5921 ELM_SAFE_FREE(sd->queue_idle_enterer, ecore_idle_enterer_del);
5922 ELM_SAFE_FREE(sd->must_recalc_idler, ecore_idler_del);
5923 ELM_SAFE_FREE(sd->multi_timer, ecore_timer_del);
5924 ELM_SAFE_FREE(sd->size_caches, eina_hash_free);
5925
5926 eina_stringshare_replace(&sd->decorate_it_type, NULL);
5927
5928 eina_hash_free(sd->content_item_map);
5929 _elm_genlist_tree_effect_stop(sd);
5930 }
5931
5932 EOLIAN static void
_elm_genlist_efl_gfx_entity_position_set(Eo * obj,Elm_Genlist_Data * sd,Eina_Position2D pos)5933 _elm_genlist_efl_gfx_entity_position_set(Eo *obj, Elm_Genlist_Data *sd, Eina_Position2D pos)
5934 {
5935 if (_evas_object_intercept_call(obj, EVAS_OBJECT_INTERCEPT_CB_MOVE, 0, pos.x, pos.y))
5936 return;
5937
5938 efl_gfx_entity_position_set(efl_super(obj, MY_CLASS), pos);
5939 efl_gfx_entity_position_set(sd->hit_rect, pos);
5940 }
5941
5942 EOLIAN static void
_elm_genlist_efl_gfx_entity_size_set(Eo * obj,Elm_Genlist_Data * sd,Eina_Size2D sz)5943 _elm_genlist_efl_gfx_entity_size_set(Eo *obj, Elm_Genlist_Data *sd, Eina_Size2D sz)
5944 {
5945 if (_evas_object_intercept_call(obj, EVAS_OBJECT_INTERCEPT_CB_RESIZE, 0, sz.w, sz.h))
5946 return;
5947
5948 efl_gfx_entity_size_set(sd->hit_rect, sz);
5949 if ((sd->queue) && (!sd->queue_idle_enterer) && (sz.w > 0))
5950 _requeue_idle_enterer(sd);
5951
5952 efl_gfx_entity_size_set(efl_super(obj, MY_CLASS), sz);
5953 }
5954
5955 EOLIAN static void
_elm_genlist_efl_canvas_group_group_member_add(Eo * obj,Elm_Genlist_Data * sd,Evas_Object * member)5956 _elm_genlist_efl_canvas_group_group_member_add(Eo *obj, Elm_Genlist_Data *sd, Evas_Object *member)
5957 {
5958 efl_canvas_group_member_add(efl_super(obj, MY_CLASS), member);
5959
5960 if (sd->hit_rect)
5961 evas_object_raise(sd->hit_rect);
5962 }
5963
5964 static void
_access_obj_process(Elm_Genlist_Data * sd,Eina_Bool is_access)5965 _access_obj_process(Elm_Genlist_Data *sd, Eina_Bool is_access)
5966 {
5967 Item_Block *itb;
5968 Eina_Bool done = EINA_FALSE;
5969
5970 EINA_INLIST_FOREACH(sd->blocks, itb)
5971 {
5972 if (itb->realized)
5973 {
5974 Eina_List *l;
5975 Elm_Gen_Item *it;
5976
5977 done = EINA_TRUE;
5978 EINA_LIST_FOREACH(itb->items, l, it)
5979 {
5980 if (!it->realized || it->hide) continue;
5981 if (is_access) _access_widget_item_register(it);
5982 else
5983 _elm_access_widget_item_unregister(it->base);
5984 }
5985 }
5986 else if (done) break;
5987 }
5988 }
5989
5990 EOLIAN static void
_elm_genlist_efl_ui_widget_on_access_update(Eo * obj EINA_UNUSED,Elm_Genlist_Data * sd,Eina_Bool acs)5991 _elm_genlist_efl_ui_widget_on_access_update(Eo *obj EINA_UNUSED, Elm_Genlist_Data *sd, Eina_Bool acs)
5992 {
5993 _elm_genlist_smart_focus_next_enable = acs;
5994 _access_obj_process(sd, _elm_genlist_smart_focus_next_enable);
5995 }
5996
5997 EAPI Evas_Object *
elm_genlist_add(Evas_Object * parent)5998 elm_genlist_add(Evas_Object *parent)
5999 {
6000 EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
6001 return elm_legacy_add(MY_CLASS, parent);
6002 }
6003
6004 static void
_genlist_element_focused(void * data,const Efl_Event * ev)6005 _genlist_element_focused(void *data, const Efl_Event *ev)
6006 {
6007 ELM_GENLIST_DATA_GET(data, pd);
6008 Efl_Ui_Widget *focused = efl_ui_focus_manager_focus_get(ev->object);
6009 Elm_Widget_Item *item;
6010
6011 if (!focused || focused == data) return;
6012
6013 item = efl_ui_focus_parent_provider_gen_item_fetch(pd->provider, focused);
6014
6015 EINA_SAFETY_ON_FALSE_RETURN(efl_isa(item, ELM_GENLIST_ITEM_CLASS));
6016 elm_object_item_focus_set(item, EINA_TRUE);
6017 }
6018
6019 EOLIAN static Eo *
_elm_genlist_efl_object_constructor(Eo * obj,Elm_Genlist_Data * sd)6020 _elm_genlist_efl_object_constructor(Eo *obj, Elm_Genlist_Data *sd)
6021 {
6022 legacy_efl_ui_focus_manager_widget_legacy_signals(obj, obj);
6023 obj = efl_constructor(efl_super(obj, MY_CLASS));
6024
6025 sd->content_item_map = eina_hash_pointer_new(NULL);
6026 sd->provider = efl_add(EFL_UI_FOCUS_PARENT_PROVIDER_GEN_CLASS, obj,
6027 efl_ui_focus_parent_provider_gen_container_set(efl_added, obj),
6028 efl_ui_focus_parent_provider_gen_content_item_map_set(efl_added, sd->content_item_map));
6029
6030 sd->obj = obj;
6031
6032 efl_canvas_object_type_set(obj, MY_CLASS_NAME_LEGACY);
6033 evas_object_smart_callbacks_descriptions_set(obj, _smart_callbacks);
6034 efl_access_object_role_set(obj, EFL_ACCESS_ROLE_LIST);
6035
6036 efl_event_callback_add(obj, EFL_UI_FOCUS_MANAGER_EVENT_MANAGER_FOCUS_CHANGED, _genlist_element_focused, obj);
6037
6038 return obj;
6039 }
6040
6041 static void
_internal_elm_genlist_clear(Evas_Object * obj)6042 _internal_elm_genlist_clear(Evas_Object *obj)
6043 {
6044 ELM_GENLIST_DATA_GET(obj, sd);
6045 Elm_Gen_Item *it;
6046 Evas *e = evas_object_evas_get(sd->obj);
6047
6048 _elm_genlist_item_unfocused(sd->focused_item);
6049 if (sd->mode_item) sd->mode_item = NULL;
6050
6051 ELM_SAFE_FREE(sd->state, eina_inlist_sorted_state_free);
6052
6053 sd->filter_data = NULL;
6054 if (sd->filter_queue)
6055 ELM_SAFE_FREE(sd->queue_filter_enterer, ecore_idle_enterer_del);
6056 ELM_SAFE_FREE(sd->filter_queue, eina_list_free);
6057 ELM_SAFE_FREE(sd->filtered_list, eina_list_free);
6058
6059 evas_event_freeze(e);
6060
6061 // Do not use EINA_INLIST_FOREACH or EINA_INLIST_FOREACH_SAFE
6062 // because sd->items can be modified inside elm_widget_item_del()
6063 while (sd->items)
6064 {
6065 it = EINA_INLIST_CONTAINER_GET(sd->items, Elm_Gen_Item);
6066 efl_del(EO_OBJ(it));
6067 }
6068
6069 sd->pan_changed = EINA_TRUE;
6070 if (!sd->queue)
6071 {
6072 sd->anchor_item = NULL;
6073 ELM_SAFE_FREE(sd->queue_idle_enterer, ecore_idle_enterer_del);
6074 ELM_SAFE_FREE(sd->must_recalc_idler, ecore_idler_del);
6075 ELM_SAFE_FREE(sd->reorder_move_animator, ecore_animator_del);
6076 sd->reorder_old_pan_y = 0;
6077 }
6078
6079 if (sd->selected) ELM_SAFE_FREE(sd->selected, eina_list_free);
6080
6081 sd->show_item = NULL;
6082
6083 sd->pan_x = 0;
6084 sd->pan_y = 0;
6085 sd->minw = 0;
6086 sd->minh = 0;
6087
6088 if (sd->pan_obj)
6089 {
6090 evas_object_size_hint_min_set(sd->pan_obj, sd->minw, sd->minh);
6091 efl_event_callback_legacy_call
6092 (sd->pan_obj, ELM_PAN_EVENT_CHANGED, NULL);
6093 }
6094 elm_layout_sizing_eval(sd->obj);
6095 elm_interface_scrollable_content_region_show(obj, 0, 0, 0, 0);
6096
6097 _elm_genlist_tree_effect_stop(sd);
6098
6099 ELM_SAFE_FREE(sd->multi_timer, ecore_timer_del);
6100 ELM_SAFE_FREE(sd->update_job, ecore_job_del);
6101 ELM_SAFE_FREE(sd->queue_idle_enterer, ecore_idle_enterer_del);
6102 ELM_SAFE_FREE(sd->must_recalc_idler, ecore_idler_del);
6103 ELM_SAFE_FREE(sd->event_block_rect, evas_object_del);
6104 ELM_SAFE_FREE(sd->scr_hold_timer, ecore_timer_del);
6105 ELM_SAFE_FREE(sd->queue, eina_list_free);
6106
6107 evas_event_thaw(e);
6108 evas_event_thaw_eval(e);
6109
6110 _elm_widget_focus_highlight_start(obj);
6111 }
6112
6113 /* Return EINA_TRUE if the item is deleted in this function */
6114 static Eina_Bool
_item_select(Elm_Gen_Item * it)6115 _item_select(Elm_Gen_Item *it)
6116 {
6117 Evas_Object *obj = WIDGET(it);
6118 ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
6119 Elm_Object_Item *eo_it = EO_OBJ(it);
6120 Eina_Bool r = EINA_FALSE;
6121
6122 if (elm_wdg_item_disabled_get(eo_it)) return EINA_FALSE;
6123 if (_is_no_select(it) || (it->decorate_it_set)) return EINA_FALSE;
6124 if ((sd->select_mode != ELM_OBJECT_SELECT_MODE_ALWAYS) &&
6125 (it->select_mode != ELM_OBJECT_SELECT_MODE_ALWAYS) && it->selected)
6126 return EINA_FALSE;
6127
6128 if (!sd->multi)
6129 {
6130 const Eina_List *l, *ll;
6131 Elm_Object_Item *eo_it2;
6132 EINA_LIST_FOREACH_SAFE(sd->selected, l, ll, eo_it2)
6133 {
6134 ELM_GENLIST_ITEM_DATA_GET(eo_it2, it2);
6135 if (it2 != it) _item_unselect(it2);
6136 }
6137 }
6138
6139 if (!it->selected)
6140 {
6141 it->selected = EINA_TRUE;
6142 sd->selected =
6143 eina_list_append(sd->selected, eo_it);
6144 }
6145
6146 efl_ref(eo_it);
6147
6148 elm_object_item_focus_set(eo_it, EINA_TRUE);
6149 if ((it->base)->on_deletion) goto item_deleted;
6150 _elm_genlist_item_content_focus_set(it, ELM_FOCUS_PREVIOUS);
6151 sd->last_selected_item = eo_it;
6152 _item_highlight(it);
6153
6154 if (it->func.func) it->func.func((void *)it->func.data, WIDGET(it), eo_it);
6155 // delete item if it's requested deletion in the above callbacks.
6156 if ((it->base)->on_deletion) goto item_deleted;
6157 evas_object_smart_callback_call(WIDGET(it), "selected", eo_it);
6158 if (_elm_config->atspi_mode)
6159 efl_access_state_changed_signal_emit(eo_it, EFL_ACCESS_STATE_TYPE_SELECTED, EINA_TRUE);
6160 // delete item if it's requested deletion in the above callbacks.
6161 if ((it->base)->on_deletion)
6162 {
6163 r = EINA_TRUE;
6164 goto item_deleted;
6165 }
6166
6167 if (!(sd->focus_on_selection_enabled || _elm_config->item_select_on_focus_disable))
6168 {
6169 efl_ui_focus_manager_focus_set(obj, it->base->eo_obj);
6170 }
6171
6172 item_deleted:
6173 efl_unref(eo_it);
6174
6175 return r;
6176 }
6177
6178 EOLIAN static Evas_Object *
_elm_genlist_item_elm_widget_item_part_content_get(const Eo * eo_it EINA_UNUSED,Elm_Gen_Item * it,const char * part)6179 _elm_genlist_item_elm_widget_item_part_content_get(const Eo *eo_it EINA_UNUSED, Elm_Gen_Item *it, const char * part)
6180 {
6181 Evas_Object *ret = NULL;
6182 if (it->deco_all_view)
6183 ret = edje_object_part_swallow_get(it->deco_all_view, part);
6184 else if (it->decorate_it_set)
6185 ret = edje_object_part_swallow_get(it->item->deco_it_view, part);
6186 if (!ret)
6187 {
6188 if (part)
6189 ret = edje_object_part_swallow_get(VIEW(it), part);
6190 else
6191 ret = edje_object_part_swallow_get(VIEW(it), "elm.swallow.icon");
6192 }
6193 return ret;
6194 }
6195
6196 EOLIAN static const char *
_elm_genlist_item_elm_widget_item_part_text_get(const Eo * eo_it EINA_UNUSED,Elm_Gen_Item * it,const char * part)6197 _elm_genlist_item_elm_widget_item_part_text_get(const Eo *eo_it EINA_UNUSED, Elm_Gen_Item *it, const char * part)
6198 {
6199 if (!it->itc->func.text_get) return NULL;
6200 const char *ret = NULL;
6201 if (it->deco_all_view)
6202 ret = edje_object_part_text_get(it->deco_all_view, part);
6203 else if (it->decorate_it_set)
6204 ret = edje_object_part_text_get(it->item->deco_it_view, part);
6205 if (!ret)
6206 {
6207 if (part)
6208 ret = edje_object_part_text_get(VIEW(it), part);
6209 else
6210 ret = edje_object_part_text_get(VIEW(it), "elm.text");
6211 }
6212 return ret;
6213 }
6214
6215 EOLIAN static void
_elm_genlist_item_elm_widget_item_disable(Eo * eo_it,Elm_Gen_Item * it)6216 _elm_genlist_item_elm_widget_item_disable(Eo *eo_it, Elm_Gen_Item *it)
6217 {
6218 Eina_List *l;
6219 Evas_Object *obj;
6220
6221 _item_unselect(it);
6222 if (eo_it == it->item->wsd->focused_item)
6223 _elm_genlist_item_unfocused(eo_it);
6224 ELM_SAFE_FREE(it->long_timer, ecore_timer_del);
6225
6226 if (it->realized)
6227 {
6228 if (elm_wdg_item_disabled_get(EO_OBJ(it)))
6229 {
6230 edje_object_signal_emit(VIEW(it), SIGNAL_DISABLED, "elm");
6231 if (it->deco_all_view)
6232 edje_object_signal_emit
6233 (it->deco_all_view, SIGNAL_DISABLED, "elm");
6234 }
6235 else
6236 {
6237 edje_object_signal_emit(VIEW(it), SIGNAL_ENABLED, "elm");
6238 if (it->deco_all_view)
6239 edje_object_signal_emit
6240 (it->deco_all_view, SIGNAL_ENABLED, "elm");
6241 }
6242 EINA_LIST_FOREACH(it->contents, l, obj)
6243 elm_widget_disabled_set(obj, elm_wdg_item_disabled_get(EO_OBJ(it)));
6244 }
6245 }
6246
6247 EOLIAN static void
_elm_genlist_item_elm_widget_item_del_pre(Eo * eo_it EINA_UNUSED,Elm_Gen_Item * it)6248 _elm_genlist_item_elm_widget_item_del_pre(Eo *eo_it EINA_UNUSED,
6249 Elm_Gen_Item *it)
6250 {
6251 /* This item is getting removed from a callback that triggered in the
6252 _item_select(). Just pend removing. Because this will be removed right
6253 after in the _item_select(). So pratically, this item won't be
6254 dangled. */
6255 if (_elm_config->atspi_mode)
6256 efl_access_children_changed_del_signal_emit(WIDGET(it),eo_it);
6257
6258 _item_del(it);
6259 }
6260
6261 EOLIAN static void
_elm_genlist_item_elm_widget_item_signal_emit(Eo * eo_it EINA_UNUSED,Elm_Gen_Item * it,const char * emission,const char * source)6262 _elm_genlist_item_elm_widget_item_signal_emit(Eo *eo_it EINA_UNUSED, Elm_Gen_Item *it, const char *emission, const char *source)
6263 {
6264 if (!it->realized)
6265 {
6266 WRN("Item is not realized yet");
6267 return;
6268 }
6269 edje_object_signal_emit(VIEW(it), emission, source);
6270 if (it->deco_all_view)
6271 edje_object_signal_emit(it->deco_all_view, emission, source);
6272 }
6273
6274 EOLIAN static void
_elm_genlist_item_elm_widget_item_style_set(Eo * eo_it,Elm_Gen_Item * it,const char * style)6275 _elm_genlist_item_elm_widget_item_style_set(Eo *eo_it,
6276 Elm_Gen_Item *it,
6277 const char *style)
6278 {
6279 if (it->itc && !strcmp(it->itc->item_style, style)) return;
6280
6281 Elm_Genlist_Item_Class *itc = elm_genlist_item_class_new();
6282
6283 itc->item_style = style;
6284 if (it->itc)
6285 {
6286 itc->func.text_get = it->itc->func.text_get;
6287 itc->func.content_get = it->itc->func.content_get;
6288 itc->func.state_get = it->itc->func.state_get;
6289 itc->func.filter_get = it->itc->func.filter_get;
6290 itc->func.reusable_content_get = it->itc->func.reusable_content_get;
6291 itc->decorate_item_style = it->itc->decorate_item_style;
6292 itc->decorate_all_item_style = it->itc->decorate_all_item_style;
6293 }
6294
6295 elm_genlist_item_item_class_update(eo_it, itc);
6296 elm_genlist_item_class_free(itc);
6297 }
6298
6299 EOLIAN static const char *
_elm_genlist_item_elm_widget_item_style_get(const Eo * eo_it EINA_UNUSED,Elm_Gen_Item * it)6300 _elm_genlist_item_elm_widget_item_style_get(const Eo *eo_it EINA_UNUSED,
6301 Elm_Gen_Item *it)
6302 {
6303 if (it->itc) return it->itc->item_style;
6304 else return NULL;
6305 }
6306
6307 EOLIAN static void
_elm_genlist_item_elm_widget_item_item_focus_set(Eo * eo_it,Elm_Gen_Item * it,Eina_Bool focused)6308 _elm_genlist_item_elm_widget_item_item_focus_set(Eo *eo_it, Elm_Gen_Item *it, Eina_Bool focused)
6309 {
6310 Evas_Object *obj = WIDGET(it);
6311 ELM_GENLIST_DATA_GET(obj, sd);
6312
6313 if (focused)
6314 {
6315 sd->last_focused_item = eo_it;
6316 if (!elm_object_focus_get(obj))
6317 elm_object_focus_set(obj, EINA_TRUE);
6318
6319 if (!elm_object_focus_get(obj))
6320 return;
6321
6322 if (eo_it != sd->focused_item)
6323 {
6324 if (sd->focused_item)
6325 _elm_genlist_item_unfocused(sd->focused_item);
6326 _elm_genlist_item_focused(eo_it);
6327
6328 /* If item is not realized state, widget couldn't get focus_highlight data. */
6329 if (it->realized)
6330 {
6331 _elm_widget_item_highlight_in_theme(obj, EO_OBJ(it));
6332 _elm_widget_highlight_in_theme_update(obj);
6333 _elm_widget_focus_highlight_start(obj);
6334 efl_ui_focus_manager_focus_set(it->base->widget, eo_it);
6335 sd->focus_on_realization = NULL;
6336 }
6337 else
6338 {
6339 sd->focus_on_realization = it;
6340 }
6341 }
6342 }
6343 else
6344 {
6345 if (!efl_ui_focus_object_focus_get(obj))
6346 return;
6347 _elm_genlist_item_unfocused(eo_it);
6348 }
6349 }
6350
6351 EOLIAN static Eina_Bool
_elm_genlist_item_elm_widget_item_item_focus_get(const Eo * eo_it,Elm_Gen_Item * it)6352 _elm_genlist_item_elm_widget_item_item_focus_get(const Eo *eo_it, Elm_Gen_Item *it)
6353 {
6354 Evas_Object *obj = WIDGET(it);
6355 ELM_GENLIST_DATA_GET(obj, sd);
6356
6357 if (eo_it == sd->focused_item)
6358 return EINA_TRUE;
6359
6360 return EINA_FALSE;
6361 }
6362
6363 EOLIAN static Eo *
_elm_genlist_item_efl_object_constructor(Eo * eo_it,Elm_Gen_Item * it)6364 _elm_genlist_item_efl_object_constructor(Eo *eo_it, Elm_Gen_Item *it)
6365 {
6366 eo_it = efl_constructor(efl_super(eo_it, ELM_GENLIST_ITEM_CLASS));
6367
6368 it->base = efl_data_scope_get(eo_it, ELM_WIDGET_ITEM_CLASS);
6369 efl_access_object_role_set(eo_it, EFL_ACCESS_ROLE_LIST_ITEM);
6370
6371 return eo_it;
6372 }
6373
6374 static Elm_Gen_Item *
_elm_genlist_item_new(Elm_Genlist_Data * sd,const Elm_Genlist_Item_Class * itc,const void * data,Elm_Object_Item * eo_parent,Elm_Genlist_Item_Type type,Evas_Smart_Cb func,const void * func_data)6375 _elm_genlist_item_new(Elm_Genlist_Data *sd,
6376 const Elm_Genlist_Item_Class *itc,
6377 const void *data,
6378 Elm_Object_Item *eo_parent,
6379 Elm_Genlist_Item_Type type,
6380 Evas_Smart_Cb func,
6381 const void *func_data)
6382 {
6383 Elm_Gen_Item *it2;
6384 int depth = 0;
6385
6386 if (!itc) return NULL;
6387
6388 Eo *eo_it = efl_add(ELM_GENLIST_ITEM_CLASS, sd->obj);
6389 if (!eo_it) return NULL;
6390 ELM_GENLIST_ITEM_DATA_GET(eo_it, it);
6391
6392 it->itc = itc;
6393 elm_genlist_item_class_ref((Elm_Genlist_Item_Class *)itc);
6394
6395 ELM_GENLIST_ITEM_DATA_GET(eo_parent, parent);
6396 WIDGET_ITEM_DATA_SET(EO_OBJ(it), data);
6397 it->parent = parent;
6398 it->func.func = func;
6399 it->func.data = func_data;
6400
6401 it->item = ELM_NEW(Elm_Gen_Item_Type);
6402 it->item->wsd = sd;
6403 it->item->type = type;
6404 it->item->order_num_in = -1;
6405
6406 if (it->parent)
6407 {
6408 if (it->parent->item->type & ELM_GENLIST_ITEM_GROUP)
6409 it->item->group_item = parent;
6410 else if (it->parent->item->group_item)
6411 it->item->group_item = it->parent->item->group_item;
6412 }
6413 for (it2 = it, depth = 0; it2->parent; it2 = it2->parent)
6414 {
6415 if (!(it2->parent->item->type & ELM_GENLIST_ITEM_GROUP)) depth += 1;
6416 }
6417 it->item->expanded_depth = depth;
6418 sd->item_count++;
6419
6420 return it;
6421 }
6422
6423 static int
_elm_genlist_item_compare(const void * data,const void * data1)6424 _elm_genlist_item_compare(const void *data,
6425 const void *data1)
6426 {
6427 const Elm_Gen_Item *it, *item1;
6428
6429 it = ELM_GEN_ITEM_FROM_INLIST(data);
6430 item1 = ELM_GEN_ITEM_FROM_INLIST(data1);
6431 return it->item->wsd->item_compare_cb(EO_OBJ(it), EO_OBJ(item1));
6432 }
6433
6434 static int
_elm_genlist_item_list_compare(const void * data,const void * data1)6435 _elm_genlist_item_list_compare(const void *data,
6436 const void *data1)
6437 {
6438 const Elm_Gen_Item *it = data;
6439 const Elm_Gen_Item *item1 = data1;
6440
6441 return it->item->wsd->item_compare_cb(EO_OBJ(it), EO_OBJ(item1));
6442 }
6443
6444 static int
_elm_genlist_eo_item_list_compare(const void * data,const void * data1)6445 _elm_genlist_eo_item_list_compare(const void *data,
6446 const void *data1)
6447 {
6448 const Elm_Object_Item *eo_it = data;
6449 const Elm_Object_Item *eo_item1 = data1;
6450 ELM_GENLIST_ITEM_DATA_GET(eo_it, it);
6451
6452 return it->item->wsd->item_compare_cb(eo_it, eo_item1);
6453 }
6454
6455 EOLIAN static unsigned int
_elm_genlist_items_count(const Eo * obj EINA_UNUSED,Elm_Genlist_Data * sd)6456 _elm_genlist_items_count(const Eo *obj EINA_UNUSED, Elm_Genlist_Data *sd)
6457 {
6458 return sd->item_count;
6459 }
6460
6461 static Eina_List *
_list_last_recursive(Eina_List * list)6462 _list_last_recursive(Eina_List *list)
6463 {
6464 Eina_List *ll, *ll2;
6465 Elm_Object_Item *eo_it2;
6466
6467 ll = eina_list_last(list);
6468 if (!ll) return NULL;
6469
6470 eo_it2 = ll->data;
6471 ELM_GENLIST_ITEM_DATA_GET(eo_it2, it2);
6472
6473 if (it2->item->items)
6474 {
6475 ll2 = _list_last_recursive(it2->item->items);
6476 if (ll2)
6477 {
6478 return ll2;
6479 }
6480 }
6481
6482 return ll;
6483 }
6484
6485 EOLIAN static Elm_Object_Item*
_elm_genlist_item_append(Eo * obj EINA_UNUSED,Elm_Genlist_Data * sd,const Elm_Genlist_Item_Class * itc,const void * data,Elm_Object_Item * eo_parent,Elm_Genlist_Item_Type type,Evas_Smart_Cb func,const void * func_data)6486 _elm_genlist_item_append(Eo *obj EINA_UNUSED, Elm_Genlist_Data *sd, const Elm_Genlist_Item_Class *itc, const void *data, Elm_Object_Item *eo_parent, Elm_Genlist_Item_Type type, Evas_Smart_Cb func, const void *func_data)
6487 {
6488 Elm_Gen_Item *it;
6489
6490 if (eo_parent)
6491 {
6492 ELM_GENLIST_ITEM_DATA_GET(eo_parent, parent);
6493 ELM_GENLIST_ITEM_CHECK_OR_RETURN(parent, NULL);
6494 EINA_SAFETY_ON_FALSE_RETURN_VAL((obj == WIDGET(parent)), NULL);
6495 }
6496
6497 it = _elm_genlist_item_new
6498 (sd, itc, data, eo_parent, type, func, func_data);
6499 if (!it) return NULL;
6500
6501 if (!it->parent)
6502 {
6503 if (it->item->type & ELM_GENLIST_ITEM_GROUP)
6504 sd->group_items = eina_list_append(sd->group_items, it);
6505 sd->items = eina_inlist_append(sd->items, EINA_INLIST_GET(it));
6506 it->item->rel = NULL;
6507 }
6508 else
6509 {
6510 Elm_Object_Item *eo_it2 = NULL;
6511 Eina_List *ll = _list_last_recursive(it->parent->item->items);
6512
6513 if (ll) eo_it2 = ll->data;
6514 if (!it->parent->item->items)
6515 sd->top_level_parent_items++;
6516 it->parent->item->items =
6517 eina_list_append(it->parent->item->items, EO_OBJ(it));
6518 if (!eo_it2) eo_it2 = EO_OBJ(it->parent);
6519 ELM_GENLIST_ITEM_DATA_GET(eo_it2, it2);
6520 sd->items = eina_inlist_append_relative
6521 (sd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(it2));
6522 it->item->rel = it2;
6523 it2->item->rel_revs = eina_list_append(it2->item->rel_revs, it);
6524 _item_expanded_set_noevent(it->parent, EINA_TRUE);
6525 }
6526 it->item->before = EINA_FALSE;
6527 _item_queue(sd, it, NULL);
6528
6529 return EO_OBJ(it);
6530 }
6531
6532 EOLIAN static Elm_Object_Item*
_elm_genlist_item_prepend(Eo * obj EINA_UNUSED,Elm_Genlist_Data * sd,const Elm_Genlist_Item_Class * itc,const void * data,Elm_Object_Item * eo_parent,Elm_Genlist_Item_Type type,Evas_Smart_Cb func,const void * func_data)6533 _elm_genlist_item_prepend(Eo *obj EINA_UNUSED, Elm_Genlist_Data *sd, const Elm_Genlist_Item_Class *itc, const void *data, Elm_Object_Item *eo_parent, Elm_Genlist_Item_Type type, Evas_Smart_Cb func, const void *func_data)
6534 {
6535 Elm_Gen_Item *it;
6536
6537 if (eo_parent)
6538 {
6539 ELM_GENLIST_ITEM_DATA_GET(eo_parent, parent);
6540 ELM_GENLIST_ITEM_CHECK_OR_RETURN(parent, NULL);
6541 EINA_SAFETY_ON_FALSE_RETURN_VAL((obj == WIDGET(parent)), NULL);
6542 /* first sub-item should allways be appended */
6543 if (!parent->item->items)
6544 return _elm_genlist_item_append(obj, sd, itc, data, eo_parent, type, func, func_data);
6545 }
6546
6547 it = _elm_genlist_item_new
6548 (sd, itc, data, eo_parent, type, func, func_data);
6549 if (!it) return NULL;
6550
6551 if (!it->parent)
6552 {
6553 if (it->item->type & ELM_GENLIST_ITEM_GROUP)
6554 sd->group_items = eina_list_prepend(sd->group_items, it);
6555 sd->items = eina_inlist_prepend(sd->items, EINA_INLIST_GET(it));
6556 it->item->rel = NULL;
6557 }
6558 else
6559 {
6560 Elm_Object_Item *eo_it2 = NULL;
6561 Eina_List *ll = it->parent->item->items;
6562
6563 if (ll) eo_it2 = ll->data;
6564 if (!it->parent->item->items)
6565 sd->top_level_parent_items++;
6566 it->parent->item->items =
6567 eina_list_prepend(it->parent->item->items, EO_OBJ(it));
6568 if (!eo_it2) eo_it2 = EO_OBJ(it->parent);
6569 ELM_GENLIST_ITEM_DATA_GET(eo_it2, it2);
6570 sd->items = eina_inlist_prepend_relative
6571 (sd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(it2));
6572 it->item->rel = it2;
6573 it2->item->rel_revs = eina_list_append(it2->item->rel_revs, it);
6574 _item_expanded_set_noevent(it->parent, EINA_TRUE);
6575 }
6576 it->item->before = EINA_TRUE;
6577 _item_queue(sd, it, NULL);
6578
6579 return EO_OBJ(it);
6580 }
6581
6582 EOLIAN static Elm_Object_Item*
_elm_genlist_item_insert_after(Eo * obj EINA_UNUSED,Elm_Genlist_Data * sd,const Elm_Genlist_Item_Class * itc,const void * data,Elm_Object_Item * eo_parent,Elm_Object_Item * eo_after,Elm_Genlist_Item_Type type,Evas_Smart_Cb func,const void * func_data)6583 _elm_genlist_item_insert_after(Eo *obj EINA_UNUSED, Elm_Genlist_Data *sd, const Elm_Genlist_Item_Class *itc, const void *data, Elm_Object_Item *eo_parent, Elm_Object_Item *eo_after, Elm_Genlist_Item_Type type, Evas_Smart_Cb func, const void *func_data)
6584 {
6585 EINA_SAFETY_ON_NULL_RETURN_VAL(eo_after, NULL);
6586 ELM_GENLIST_ITEM_DATA_GET(eo_after, after);
6587 Elm_Gen_Item *it;
6588
6589 ELM_GENLIST_ITEM_CHECK_OR_RETURN(after, NULL);
6590 EINA_SAFETY_ON_FALSE_RETURN_VAL((obj == WIDGET(after)), NULL);
6591 if (eo_parent)
6592 {
6593 ELM_GENLIST_ITEM_DATA_GET(eo_parent, parent);
6594 ELM_GENLIST_ITEM_CHECK_OR_RETURN(parent, NULL);
6595 EINA_SAFETY_ON_FALSE_RETURN_VAL((obj == WIDGET(parent)), NULL);
6596 }
6597
6598 /* It makes no sense to insert after in an empty list with after !=
6599 * NULL, something really bad is happening in your app. */
6600 EINA_SAFETY_ON_NULL_RETURN_VAL(sd->items, NULL);
6601
6602 it = _elm_genlist_item_new
6603 (sd, itc, data, eo_parent, type, func, func_data);
6604 if (!it) return NULL;
6605
6606 if (!it->parent)
6607 {
6608 if ((it->item->type & ELM_GENLIST_ITEM_GROUP) &&
6609 (after->item->type & ELM_GENLIST_ITEM_GROUP))
6610 sd->group_items = eina_list_append_relative
6611 (sd->group_items, it, after);
6612 else if (it->item->type & ELM_GENLIST_ITEM_GROUP)
6613 CRI("GROUP ITEM INSERT FAILED: NON-GROUP ITEM PASSED AS 'after'!");
6614 }
6615 else
6616 {
6617 if (!it->parent->item->items)
6618 sd->top_level_parent_items++;
6619 it->parent->item->items =
6620 eina_list_append_relative(it->parent->item->items, EO_OBJ(it), eo_after);
6621 _item_expanded_set_noevent(it->parent, EINA_TRUE);
6622 }
6623
6624 if (after->item->items)
6625 {
6626 Eina_List *ll = _list_last_recursive(after->item->items);
6627 if (ll)
6628 {
6629 eo_after = ll->data;
6630 after = efl_data_scope_get(eo_after, ELM_GENLIST_ITEM_CLASS);
6631 }
6632 }
6633
6634 sd->items = eina_inlist_append_relative
6635 (sd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(after));
6636
6637 it->item->rel = after;
6638 after->item->rel_revs = eina_list_append(after->item->rel_revs, it);
6639 it->item->before = EINA_FALSE;
6640 _item_queue(sd, it, NULL);
6641
6642 return EO_OBJ(it);
6643 }
6644
6645 EOLIAN static Elm_Object_Item*
_elm_genlist_item_insert_before(Eo * obj,Elm_Genlist_Data * sd,const Elm_Genlist_Item_Class * itc,const void * data,Elm_Object_Item * eo_parent,Elm_Object_Item * eo_before,Elm_Genlist_Item_Type type,Evas_Smart_Cb func,const void * func_data)6646 _elm_genlist_item_insert_before(Eo *obj, Elm_Genlist_Data *sd, const Elm_Genlist_Item_Class *itc, const void *data, Elm_Object_Item *eo_parent, Elm_Object_Item *eo_before, Elm_Genlist_Item_Type type, Evas_Smart_Cb func, const void *func_data)
6647 {
6648 EINA_SAFETY_ON_NULL_RETURN_VAL(eo_before, NULL);
6649 ELM_GENLIST_ITEM_DATA_GET(eo_before, before);
6650 Elm_Gen_Item *it;
6651
6652 ELM_GENLIST_ITEM_CHECK_OR_RETURN(before, NULL);
6653 EINA_SAFETY_ON_FALSE_RETURN_VAL((obj == WIDGET(before)), NULL);
6654 if (eo_parent)
6655 {
6656 ELM_GENLIST_ITEM_DATA_GET(eo_parent, parent);
6657 ELM_GENLIST_ITEM_CHECK_OR_RETURN(parent, NULL);
6658 EINA_SAFETY_ON_FALSE_RETURN_VAL((obj == WIDGET(parent)), NULL);
6659 }
6660
6661 /* It makes no sense to insert before in an empty list with before
6662 * != NULL, something really bad is happening in your app. */
6663 EINA_SAFETY_ON_NULL_RETURN_VAL(sd->items, NULL);
6664
6665 it = _elm_genlist_item_new
6666 (sd, itc, data, eo_parent, type, func, func_data);
6667 if (!it) return NULL;
6668
6669 if (!it->parent)
6670 {
6671 if ((it->item->type & ELM_GENLIST_ITEM_GROUP) &&
6672 (before->item->type & ELM_GENLIST_ITEM_GROUP))
6673 sd->group_items =
6674 eina_list_prepend_relative(sd->group_items, it, before);
6675 else if (it->item->type & ELM_GENLIST_ITEM_GROUP)
6676 CRI("GROUP ITEM INSERT FAILED: NON-GROUP ITEM PASSED AS 'after'!");
6677 }
6678 else
6679 {
6680 if (!it->parent->item->items)
6681 sd->top_level_parent_items++;
6682 it->parent->item->items =
6683 eina_list_prepend_relative(it->parent->item->items, EO_OBJ(it), eo_before);
6684 _item_expanded_set_noevent(it->parent, EINA_TRUE);
6685 }
6686 sd->items = eina_inlist_prepend_relative
6687 (sd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(before));
6688
6689 it->item->rel = before;
6690 before->item->rel_revs = eina_list_append(before->item->rel_revs, it);
6691 it->item->before = EINA_TRUE;
6692 _item_queue(sd, it, NULL);
6693
6694 return EO_OBJ(it);
6695 }
6696
6697 EOLIAN static Elm_Object_Item*
_elm_genlist_item_sorted_insert(Eo * obj,Elm_Genlist_Data * sd,const Elm_Genlist_Item_Class * itc,const void * data,Elm_Object_Item * eo_parent,Elm_Genlist_Item_Type type,Eina_Compare_Cb comp,Evas_Smart_Cb func,const void * func_data)6698 _elm_genlist_item_sorted_insert(Eo *obj, Elm_Genlist_Data *sd, const Elm_Genlist_Item_Class *itc, const void *data, Elm_Object_Item *eo_parent, Elm_Genlist_Item_Type type, Eina_Compare_Cb comp, Evas_Smart_Cb func, const void *func_data)
6699 {
6700 Elm_Object_Item *eo_rel = NULL;
6701 Elm_Gen_Item *rel = NULL;
6702 Elm_Gen_Item *it;
6703
6704 EINA_SAFETY_ON_NULL_RETURN_VAL(comp, NULL);
6705 if (eo_parent)
6706 {
6707 ELM_GENLIST_ITEM_DATA_GET(eo_parent, parent);
6708 ELM_GENLIST_ITEM_CHECK_OR_RETURN(parent, NULL);
6709 EINA_SAFETY_ON_FALSE_RETURN_VAL((obj == WIDGET(parent)), NULL);
6710 }
6711
6712 it = _elm_genlist_item_new
6713 (sd, itc, data, eo_parent, type, func, func_data);
6714 if (!it) return NULL;
6715 Elm_Object_Item *eo_it = EO_OBJ(it);
6716
6717 sd->item_compare_cb = comp;
6718
6719 if (it->parent)
6720 {
6721 Eina_List *l;
6722 int cmp_result;
6723
6724 l = eina_list_search_sorted_near_list
6725 (it->parent->item->items, _elm_genlist_eo_item_list_compare, eo_it,
6726 &cmp_result);
6727
6728 if (l)
6729 {
6730 eo_rel = eina_list_data_get(l);
6731 rel = efl_data_scope_get(eo_rel, ELM_GENLIST_ITEM_CLASS);
6732
6733 if (cmp_result >= 0)
6734 {
6735 it->parent->item->items = eina_list_prepend_relative_list
6736 (it->parent->item->items, eo_it, l);
6737 sd->items = eina_inlist_prepend_relative
6738 (sd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(rel));
6739 it->item->before = EINA_TRUE;
6740 }
6741 else // if (cmp_result < 0)
6742 {
6743 it->parent->item->items = eina_list_append_relative_list
6744 (it->parent->item->items, eo_it, l);
6745 if (rel->item->items)
6746 {
6747 Eina_List *ll = _list_last_recursive(rel->item->items);
6748 if (ll)
6749 {
6750 eo_rel = ll->data;
6751 rel = efl_data_scope_get(eo_rel, ELM_GENLIST_ITEM_CLASS);
6752 }
6753 }
6754 sd->items = eina_inlist_append_relative
6755 (sd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(rel));
6756 it->item->before = EINA_FALSE;
6757 }
6758 }
6759 else
6760 {
6761 // parent had no child
6762 rel = it->parent;
6763
6764 it->parent->item->items = eina_list_prepend
6765 (it->parent->item->items, eo_it);
6766 sd->items = eina_inlist_append_relative
6767 (sd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(rel));
6768 it->item->before = EINA_FALSE;
6769 sd->top_level_parent_items++;
6770 }
6771
6772 ELM_SAFE_FREE(sd->state, eina_inlist_sorted_state_free);
6773
6774 // ensure expanded state is on
6775 _item_expanded_set_noevent(it->parent, EINA_TRUE);
6776 }
6777 else
6778 {
6779 if (!sd->state && !sd->top_level_parent_items)
6780 {
6781 sd->state = eina_inlist_sorted_state_new();
6782 eina_inlist_sorted_state_init(sd->state, sd->items);
6783 sd->requeued = EINA_FALSE;
6784 }
6785
6786 if (it->item->type == ELM_GENLIST_ITEM_GROUP)
6787 sd->group_items = eina_list_append(sd->group_items, it);
6788
6789 if (!sd->top_level_parent_items)
6790 {
6791 sd->items = eina_inlist_sorted_state_insert
6792 (sd->items, EINA_INLIST_GET(it), _elm_genlist_item_compare,
6793 sd->state);
6794
6795 if (EINA_INLIST_GET(it)->next)
6796 {
6797 rel = ELM_GEN_ITEM_NEXT(it);
6798 it->item->before = EINA_TRUE;
6799 }
6800 else if (EINA_INLIST_GET(it)->prev)
6801 {
6802 rel = ELM_GEN_ITEM_PREV(it);
6803 it->item->before = EINA_FALSE;
6804 }
6805 }
6806 else
6807 {
6808 // Inlist is not sorted!
6809 Elm_Gen_Item *prev_rel = NULL;
6810 int cmp = 0;
6811
6812 EINA_INLIST_FOREACH(sd->items, rel)
6813 {
6814 cmp = comp(EO_OBJ(it), EO_OBJ(rel));
6815 if (cmp < 0) break;
6816 prev_rel = rel;
6817 if (rel->item->items)
6818 {
6819 Eina_List *ll = _list_last_recursive(rel->item->items);
6820 if (ll)
6821 {
6822 eo_rel = ll->data;
6823 rel = efl_data_scope_get(eo_rel, ELM_GENLIST_ITEM_CLASS);
6824 }
6825 }
6826 if (!EINA_INLIST_GET(rel)->next)
6827 {
6828 cmp = 1;
6829 break;
6830 }
6831 }
6832
6833 if (!rel)
6834 {
6835 sd->items = eina_inlist_prepend_relative(sd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(prev_rel));
6836 it->item->before = EINA_TRUE;
6837 rel = prev_rel;
6838 }
6839 else if (cmp >= 0)
6840 {
6841 sd->items = eina_inlist_append_relative(sd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(rel));
6842 it->item->before = EINA_FALSE;
6843 }
6844 else
6845 {
6846 sd->items = eina_inlist_prepend_relative(sd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(rel));
6847 it->item->before = EINA_TRUE;
6848 }
6849 }
6850 }
6851
6852 if (rel)
6853 {
6854 it->item->rel = rel;
6855 rel->item->rel_revs = eina_list_append(rel->item->rel_revs, it);
6856 }
6857
6858 _item_queue(sd, it, _elm_genlist_item_list_compare);
6859
6860 return eo_it;
6861 }
6862
6863 EOLIAN static void
_elm_genlist_clear(Eo * obj,Elm_Genlist_Data * sd EINA_UNUSED)6864 _elm_genlist_clear(Eo *obj, Elm_Genlist_Data *sd EINA_UNUSED)
6865 {
6866 _internal_elm_genlist_clear(obj);
6867 }
6868
6869 EOLIAN static void
_elm_genlist_multi_select_set(Eo * obj EINA_UNUSED,Elm_Genlist_Data * sd,Eina_Bool multi)6870 _elm_genlist_multi_select_set(Eo *obj EINA_UNUSED, Elm_Genlist_Data *sd, Eina_Bool multi)
6871 {
6872 sd->multi = !!multi;
6873
6874 if (!sd->multi && sd->selected)
6875 {
6876 Eina_List *l, *ll;
6877 Elm_Object_Item *eo_it;
6878 Elm_Object_Item *last = sd->selected->data;
6879 EINA_LIST_FOREACH_SAFE(sd->selected, l, ll, eo_it)
6880 {
6881 if (last != eo_it)
6882 {
6883 ELM_GENLIST_ITEM_DATA_GET(eo_it, it);
6884 _item_unselect(it);
6885 }
6886 }
6887 }
6888 }
6889
6890 EOLIAN static Eina_Bool
_elm_genlist_multi_select_get(const Eo * obj EINA_UNUSED,Elm_Genlist_Data * sd)6891 _elm_genlist_multi_select_get(const Eo *obj EINA_UNUSED, Elm_Genlist_Data *sd)
6892 {
6893 return sd->multi;
6894 }
6895
6896 EOLIAN static void
_elm_genlist_multi_select_mode_set(Eo * obj EINA_UNUSED,Elm_Genlist_Data * sd,Elm_Object_Multi_Select_Mode mode)6897 _elm_genlist_multi_select_mode_set(Eo *obj EINA_UNUSED, Elm_Genlist_Data *sd, Elm_Object_Multi_Select_Mode mode)
6898 {
6899 if (mode >= ELM_OBJECT_MULTI_SELECT_MODE_MAX)
6900 return;
6901
6902 if (sd->multi_select_mode != mode)
6903 sd->multi_select_mode = mode;
6904 }
6905
6906 EOLIAN static Elm_Object_Multi_Select_Mode
_elm_genlist_multi_select_mode_get(const Eo * obj EINA_UNUSED,Elm_Genlist_Data * sd)6907 _elm_genlist_multi_select_mode_get(const Eo *obj EINA_UNUSED, Elm_Genlist_Data *sd)
6908 {
6909 return sd->multi_select_mode;
6910 }
6911
6912 EOLIAN static Elm_Object_Item*
_elm_genlist_selected_item_get(const Eo * obj EINA_UNUSED,Elm_Genlist_Data * sd)6913 _elm_genlist_selected_item_get(const Eo *obj EINA_UNUSED, Elm_Genlist_Data *sd)
6914 {
6915 if (sd->selected)
6916 return sd->selected->data;
6917 else
6918 return NULL;
6919 }
6920
6921 EOLIAN static const Eina_List*
_elm_genlist_selected_items_get(const Eo * obj EINA_UNUSED,Elm_Genlist_Data * sd)6922 _elm_genlist_selected_items_get(const Eo *obj EINA_UNUSED, Elm_Genlist_Data *sd)
6923 {
6924 return sd->selected;
6925 }
6926
6927 EOLIAN static Eina_List*
_elm_genlist_realized_items_get(const Eo * obj EINA_UNUSED,Elm_Genlist_Data * sd)6928 _elm_genlist_realized_items_get(const Eo *obj EINA_UNUSED, Elm_Genlist_Data *sd)
6929 {
6930 Item_Block *itb;
6931 Eina_Bool done = EINA_FALSE;
6932
6933 Eina_List *ret = NULL;
6934
6935 EINA_INLIST_FOREACH(sd->blocks, itb)
6936 {
6937 if (itb->realized)
6938 {
6939 Eina_List *l;
6940 Elm_Gen_Item *it;
6941
6942 done = EINA_TRUE;
6943 EINA_LIST_FOREACH(itb->items, l, it)
6944 {
6945 if (it->realized) ret = eina_list_append(ret, EO_OBJ(it));
6946 }
6947 }
6948 else
6949 {
6950 if (done) break;
6951 }
6952 }
6953
6954 return ret;
6955 }
6956
6957 EOLIAN static Elm_Object_Item*
_elm_genlist_at_xy_item_get(const Eo * obj EINA_UNUSED,Elm_Genlist_Data * sd,Evas_Coord x,Evas_Coord y,int * posret)6958 _elm_genlist_at_xy_item_get(const Eo *obj EINA_UNUSED, Elm_Genlist_Data *sd, Evas_Coord x, Evas_Coord y, int *posret)
6959 {
6960 Evas_Coord ox, oy, ow, oh;
6961 Evas_Coord lasty;
6962 Item_Block *itb;
6963
6964 evas_object_geometry_get(sd->pan_obj, &ox, &oy, &ow, &oh);
6965 lasty = oy;
6966 EINA_INLIST_FOREACH(sd->blocks, itb)
6967 {
6968 Eina_List *l;
6969 Elm_Gen_Item *it;
6970
6971 if (!ELM_RECTS_INTERSECT(ox + itb->x - itb->sd->pan_x,
6972 oy + itb->y - itb->sd->pan_y,
6973 itb->w, itb->h, x, y, 1, 1))
6974 continue;
6975 EINA_LIST_FOREACH(itb->items, l, it)
6976 {
6977 Evas_Coord itx, ity;
6978
6979 itx = ox + itb->x + it->x - itb->sd->pan_x;
6980 ity = oy + itb->y + it->y - itb->sd->pan_y;
6981 if (ELM_RECTS_INTERSECT
6982 (itx, ity, it->item->w, it->item->h, x, y, 1, 1))
6983 {
6984 if (posret)
6985 {
6986 if (y <= (ity + (it->item->h / 4))) *posret = -1;
6987 else if (y >= (ity + it->item->h - (it->item->h / 4)))
6988 *posret = 1;
6989 else *posret = 0;
6990 }
6991
6992 return EO_OBJ(it);
6993 }
6994 lasty = ity + it->item->h;
6995 }
6996 }
6997 if (posret)
6998 {
6999 if (y > lasty) *posret = 1;
7000 else *posret = -1;
7001 }
7002
7003 return NULL;
7004 }
7005
7006 EOLIAN static Elm_Object_Item*
_elm_genlist_first_item_get(const Eo * obj EINA_UNUSED,Elm_Genlist_Data * sd)7007 _elm_genlist_first_item_get(const Eo *obj EINA_UNUSED, Elm_Genlist_Data *sd)
7008 {
7009 Elm_Gen_Item *it = ELM_GEN_ITEM_FROM_INLIST(sd->items);
7010
7011 while (it && sd->filter && !_item_filtered_get(it, sd))
7012 it = ELM_GEN_ITEM_NEXT(it);
7013
7014 return EO_OBJ(it);
7015 }
7016
7017 EOLIAN static Elm_Object_Item*
_elm_genlist_last_item_get(const Eo * obj EINA_UNUSED,Elm_Genlist_Data * sd)7018 _elm_genlist_last_item_get(const Eo *obj EINA_UNUSED, Elm_Genlist_Data *sd)
7019 {
7020 Elm_Gen_Item *it;
7021
7022 if (!sd->items) return NULL;
7023 it = ELM_GEN_ITEM_FROM_INLIST(sd->items->last);
7024
7025 while (it && sd->filter && !_item_filtered_get(it, sd))
7026 it = ELM_GEN_ITEM_PREV(it);
7027
7028 return EO_OBJ(it);
7029 }
7030
7031 EOLIAN static Elm_Object_Item *
_elm_genlist_item_next_get(const Eo * eo_it EINA_UNUSED,Elm_Gen_Item * it)7032 _elm_genlist_item_next_get(const Eo *eo_it EINA_UNUSED, Elm_Gen_Item *it)
7033 {
7034 ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
7035
7036 do it = ELM_GEN_ITEM_NEXT(it);
7037 while (it && sd->filter && !_item_filtered_get(it, sd));
7038
7039 return EO_OBJ(it);
7040 }
7041
7042 EOLIAN static Elm_Object_Item *
_elm_genlist_item_prev_get(const Eo * eo_it EINA_UNUSED,Elm_Gen_Item * it)7043 _elm_genlist_item_prev_get(const Eo *eo_it EINA_UNUSED, Elm_Gen_Item *it)
7044 {
7045 ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
7046
7047 do it = ELM_GEN_ITEM_PREV(it);
7048 while (it && sd->filter && !_item_filtered_get(it, sd));
7049
7050 return EO_OBJ(it);
7051 }
7052
7053 EOLIAN static Elm_Object_Item *
_elm_genlist_item_parent_item_get(const Eo * eo_it EINA_UNUSED,Elm_Gen_Item * it)7054 _elm_genlist_item_parent_item_get(const Eo *eo_it EINA_UNUSED, Elm_Gen_Item *it)
7055 {
7056 ELM_GENLIST_ITEM_CHECK_OR_RETURN(it, NULL);
7057
7058 return EO_OBJ(it->parent);
7059 }
7060
7061 EOLIAN static unsigned int
_elm_genlist_item_subitems_count(Eo * eo_item EINA_UNUSED,Elm_Gen_Item * item)7062 _elm_genlist_item_subitems_count(Eo *eo_item EINA_UNUSED, Elm_Gen_Item *item)
7063 {
7064 ELM_GENLIST_ITEM_CHECK_OR_RETURN(item, 0);
7065
7066 return eina_list_count(item->item->items);
7067 }
7068
7069 EOLIAN static const Eina_List *
_elm_genlist_item_subitems_get(const Eo * eo_item EINA_UNUSED,Elm_Gen_Item * item)7070 _elm_genlist_item_subitems_get(const Eo *eo_item EINA_UNUSED, Elm_Gen_Item *item)
7071 {
7072 ELM_GENLIST_ITEM_CHECK_OR_RETURN(item, NULL);
7073
7074 return item->item->items;
7075 }
7076
7077 EOLIAN static void
_elm_genlist_item_subitems_clear(Eo * eo_item EINA_UNUSED,Elm_Gen_Item * it)7078 _elm_genlist_item_subitems_clear(Eo *eo_item EINA_UNUSED, Elm_Gen_Item *it)
7079 {
7080 ELM_GENLIST_ITEM_CHECK_OR_RETURN(it);
7081 ELM_GENLIST_DATA_GET(WIDGET(it), sd);
7082
7083 if (!sd->tree_effect_enabled || !sd->move_effect_mode)
7084 _item_sub_items_clear(it);
7085 else
7086 {
7087 if (!_elm_genlist_tree_effect_setup(sd))
7088 _item_sub_items_clear(it);
7089 }
7090 }
7091
7092 EOLIAN static void
_elm_genlist_item_selected_set(Eo * eo_item EINA_UNUSED,Elm_Gen_Item * it,Eina_Bool selected)7093 _elm_genlist_item_selected_set(Eo *eo_item EINA_UNUSED, Elm_Gen_Item *it,
7094 Eina_Bool selected)
7095 {
7096 ELM_GENLIST_ITEM_CHECK_OR_RETURN(it);
7097
7098 if (elm_wdg_item_disabled_get(EO_OBJ(it))) return;
7099
7100 selected = !!selected;
7101 if (it->selected == selected) return;
7102
7103 if (selected) _item_select(it);
7104 else _item_unselect(it);
7105 }
7106
7107 EOLIAN static Eina_Bool
_elm_genlist_item_selected_get(const Eo * eo_item EINA_UNUSED,Elm_Gen_Item * it)7108 _elm_genlist_item_selected_get(const Eo *eo_item EINA_UNUSED, Elm_Gen_Item *it)
7109 {
7110 ELM_GENLIST_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
7111
7112 return it->selected;
7113 }
7114
7115 static Elm_Gen_Item *
_elm_genlist_expanded_next_item_get(Elm_Gen_Item * it)7116 _elm_genlist_expanded_next_item_get(Elm_Gen_Item *it)
7117 {
7118 Elm_Object_Item *eo_it = EO_OBJ(it);
7119 Elm_Object_Item *eo_it2;
7120
7121 if (it->item->expanded)
7122 {
7123 eo_it2 = elm_genlist_item_next_get(eo_it);
7124 ELM_GENLIST_ITEM_DATA_GET(eo_it2, it2);
7125 return it2;
7126 }
7127 else
7128 {
7129 eo_it2 = elm_genlist_item_next_get(eo_it);
7130 while (eo_it2)
7131 {
7132 ELM_GENLIST_ITEM_DATA_GET(eo_it2, it2);
7133 if (it->item->expanded_depth >= it2->item->expanded_depth) return it2;
7134 eo_it2 = elm_genlist_item_next_get(eo_it2);
7135 }
7136 }
7137 return efl_data_scope_get(eo_it2, ELM_GENLIST_ITEM_CLASS);
7138 }
7139
7140 static void
_elm_genlist_move_items_set(Elm_Gen_Item * it,Eina_Bool expanded)7141 _elm_genlist_move_items_set(Elm_Gen_Item *it, Eina_Bool expanded)
7142 {
7143 Eina_List *l, *ll;
7144 Elm_Gen_Item *it2 = NULL;
7145 Evas_Coord ox, oy, ow, oh, dh = 0;
7146 ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
7147
7148 sd->expanded_next_item =
7149 _elm_genlist_expanded_next_item_get(it);
7150
7151 if (expanded)
7152 {
7153 Elm_Object_Item *eo_item;
7154 l = elm_genlist_realized_items_get((sd)->obj);
7155 EINA_LIST_FREE(l, eo_item)
7156 {
7157 ELM_GENLIST_ITEM_DATA_GET(eo_item, item);
7158 sd->move_items = eina_list_append(sd->move_items, item);
7159 }
7160
7161 EINA_LIST_FOREACH_SAFE(sd->move_items, l, ll, it2)
7162 {
7163 if (it2 == sd->expanded_next_item) break;
7164 sd->move_items = eina_list_remove(sd->move_items, it2);
7165 }
7166 }
7167 else
7168 {
7169 Elm_Object_Item *eo_it2 = NULL;
7170 evas_object_geometry_get(sd->pan_obj, &ox, &oy, &ow, &oh);
7171 if (sd->expanded_next_item) eo_it2 = EO_OBJ(sd->expanded_next_item);
7172
7173 while (eo_it2 && (dh < oy + oh))
7174 {
7175 it2 = efl_data_scope_get(eo_it2, ELM_GENLIST_ITEM_CLASS);
7176 dh += it2->item->h;
7177 sd->move_items = eina_list_append(sd->move_items, it2);
7178 eo_it2 = elm_genlist_item_next_get(eo_it2);
7179 }
7180 }
7181 }
7182
7183 static void
_event_block_rect_update(const Evas_Object * obj)7184 _event_block_rect_update(const Evas_Object *obj)
7185 {
7186 Evas_Coord ox, oy, ow, oh;
7187
7188 ELM_GENLIST_CHECK(obj);
7189 ELM_GENLIST_DATA_GET(obj, sd);
7190
7191 if (!sd->event_block_rect)
7192 {
7193 sd->event_block_rect = evas_object_rectangle_add(
7194 evas_object_evas_get(sd->obj));
7195 evas_object_smart_member_add(sd->event_block_rect, sd->pan_obj);
7196 evas_object_color_set(sd->event_block_rect, 0, 0, 0, 0);
7197 }
7198
7199 evas_object_geometry_get(sd->pan_obj, &ox, &oy, &ow, &oh);
7200 efl_gfx_entity_geometry_set(sd->pan_obj, EINA_RECT(ox, oy, ow, oh));
7201 }
7202
7203 static void
_item_expanded_set_noevent(Elm_Gen_Item * it,Eina_Bool expanded)7204 _item_expanded_set_noevent(Elm_Gen_Item *it, Eina_Bool expanded)
7205 {
7206 EINA_SAFETY_ON_NULL_RETURN(it);
7207
7208 if (it->item->expanded == expanded) return;
7209 it->item->expanded = expanded;
7210 if (expanded)
7211 {
7212 if (it->realized)
7213 edje_object_signal_emit(VIEW(it), SIGNAL_EXPANDED, "elm");
7214 }
7215 else
7216 {
7217 if (it->realized)
7218 edje_object_signal_emit(VIEW(it), SIGNAL_CONTRACTED, "elm");
7219 }
7220 }
7221
7222 EOLIAN static void
_elm_genlist_item_expanded_set(Eo * eo_item EINA_UNUSED,Elm_Gen_Item * it,Eina_Bool expanded)7223 _elm_genlist_item_expanded_set(Eo *eo_item EINA_UNUSED, Elm_Gen_Item *it, Eina_Bool expanded)
7224 {
7225 ELM_GENLIST_ITEM_CHECK_OR_RETURN(it);
7226 ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
7227
7228 expanded = !!expanded;
7229 if (it->item->expanded == expanded) return;
7230 if (it->item->type != ELM_GENLIST_ITEM_TREE) return;
7231 sd->expanded_item = it;
7232 _elm_genlist_move_items_set(it, expanded);
7233
7234 if (sd->tree_effect_enabled)
7235 _event_block_rect_update(WIDGET(it));
7236
7237 if (expanded)
7238 {
7239 sd->move_effect_mode = ELM_GENLIST_TREE_EFFECT_EXPAND;
7240 _item_expanded_set_noevent(it, EINA_TRUE);
7241 efl_event_callback_legacy_call
7242 (WIDGET(it), ELM_GENLIST_EVENT_EXPANDED, EO_OBJ(it));
7243 sd->auto_scroll_enabled = EINA_TRUE;
7244 if (_elm_config->atspi_mode)
7245 efl_access_state_changed_signal_emit(eo_item, EFL_ACCESS_STATE_TYPE_EXPANDED, EINA_TRUE);
7246 }
7247 else
7248 {
7249 sd->move_effect_mode = ELM_GENLIST_TREE_EFFECT_CONTRACT;
7250 _item_expanded_set_noevent(it, EINA_FALSE);
7251 efl_event_callback_legacy_call
7252 (WIDGET(it), ELM_GENLIST_EVENT_CONTRACTED, EO_OBJ(it));
7253 sd->auto_scroll_enabled = EINA_FALSE;
7254 if (_elm_config->atspi_mode)
7255 efl_access_state_changed_signal_emit(eo_item, EFL_ACCESS_STATE_TYPE_EXPANDED, EINA_FALSE);
7256 }
7257 }
7258
7259 EOLIAN static Eina_Bool
_elm_genlist_item_expanded_get(const Eo * eo_item EINA_UNUSED,Elm_Gen_Item * it)7260 _elm_genlist_item_expanded_get(const Eo *eo_item EINA_UNUSED, Elm_Gen_Item *it)
7261 {
7262 ELM_GENLIST_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
7263
7264 return it->item->expanded;
7265 }
7266
7267 EOLIAN static int
_elm_genlist_item_expanded_depth_get(const Eo * eo_item EINA_UNUSED,Elm_Gen_Item * it)7268 _elm_genlist_item_expanded_depth_get(const Eo *eo_item EINA_UNUSED, Elm_Gen_Item *it)
7269 {
7270 ELM_GENLIST_ITEM_CHECK_OR_RETURN(it, 0);
7271
7272 return it->item->expanded_depth;
7273 }
7274
7275 static Eina_Bool
_elm_genlist_item_coordinates_calc(Elm_Gen_Item * it,Elm_Genlist_Item_Scrollto_Type type,Eina_Bool bring_in,Evas_Coord * x,Evas_Coord * y,Evas_Coord * w,Evas_Coord * h)7276 _elm_genlist_item_coordinates_calc(Elm_Gen_Item *it,
7277 Elm_Genlist_Item_Scrollto_Type type,
7278 Eina_Bool bring_in,
7279 Evas_Coord *x,
7280 Evas_Coord *y,
7281 Evas_Coord *w,
7282 Evas_Coord *h)
7283 {
7284 Evas_Coord gith = 0;
7285 ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
7286
7287 Eina_Bool deferred_show = EINA_FALSE;
7288
7289 switch (type)
7290 {
7291 case ELM_GENLIST_ITEM_SCROLLTO_IN:
7292 case ELM_GENLIST_ITEM_SCROLLTO_TOP:
7293 case ELM_GENLIST_ITEM_SCROLLTO_MIDDLE:
7294 case ELM_GENLIST_ITEM_SCROLLTO_BOTTOM:
7295 break;
7296 default: /* Filters unsupported type */
7297 return EINA_FALSE;
7298 }
7299
7300 //Can't goto the item right now. Reserve it instead.
7301 if (sd->queue || !(sd->homogeneous && (sd->mode == ELM_LIST_COMPRESS)))
7302 {
7303 if ((it->item->queued) || (!it->item->mincalcd) || (sd->queue))
7304 deferred_show = EINA_TRUE;
7305 }
7306 if ((it->item->block) && (it->item->block->w < 1)) deferred_show = EINA_TRUE;
7307
7308 evas_object_geometry_get(sd->pan_obj, NULL, NULL, w, h);
7309 if (*w < 1 || *h < 1) deferred_show = EINA_TRUE;
7310
7311 if (deferred_show)
7312 {
7313 sd->check_scroll = EINA_TRUE;
7314 sd->show_item = it;
7315 sd->bring_in = bring_in;
7316 sd->scroll_to_type = type;
7317 it->item->show_me = EINA_TRUE;
7318
7319 efl_canvas_group_change(sd->obj);
7320
7321 return EINA_FALSE;
7322 }
7323
7324 if (sd->show_item)
7325 {
7326 sd->show_item->item->show_me = EINA_FALSE;
7327 sd->show_item = NULL;
7328 }
7329
7330 switch (type)
7331 {
7332 case ELM_GENLIST_ITEM_SCROLLTO_IN:
7333 if ((it->item->group_item) &&
7334 (sd->pan_y > (it->y + it->item->block->y)))
7335 gith = it->item->group_item->item->h;
7336 *h = it->item->h;
7337 *y = it->y + it->item->block->y - gith;
7338 break;
7339
7340 case ELM_GENLIST_ITEM_SCROLLTO_TOP:
7341 if (it->item->group_item) gith = it->item->group_item->item->h;
7342 *y = it->y + it->item->block->y - gith;
7343 break;
7344
7345 case ELM_GENLIST_ITEM_SCROLLTO_MIDDLE:
7346 *y = it->y + it->item->block->y - (*h / 2) + (it->item->h / 2);
7347 break;
7348
7349 case ELM_GENLIST_ITEM_SCROLLTO_BOTTOM:
7350 *y = it->y + it->item->block->y - *h + it->item->h;
7351 break;
7352
7353 default:
7354 return EINA_FALSE;
7355 }
7356
7357 *x = it->x + it->item->block->x;
7358 *w = it->item->block->w;
7359
7360 return EINA_TRUE;
7361 }
7362
7363 EOLIAN static void
_elm_genlist_item_promote(Eo * eo_it EINA_UNUSED,Elm_Gen_Item * it)7364 _elm_genlist_item_promote(Eo *eo_it EINA_UNUSED, Elm_Gen_Item *it)
7365 {
7366 ELM_GENLIST_ITEM_CHECK_OR_RETURN(it);
7367
7368 Elm_Object_Item *eo_first_item = elm_genlist_first_item_get(WIDGET(it));
7369 ELM_GENLIST_ITEM_DATA_GET(eo_first_item, first_item);
7370 _item_move_before(it, first_item);
7371 }
7372
7373 EOLIAN static void
_elm_genlist_item_demote(Eo * eo_it EINA_UNUSED,Elm_Gen_Item * it)7374 _elm_genlist_item_demote(Eo *eo_it EINA_UNUSED, Elm_Gen_Item *it)
7375 {
7376 ELM_GENLIST_ITEM_CHECK_OR_RETURN(it);
7377 Elm_Object_Item *eo_last_item = elm_genlist_last_item_get(WIDGET(it));
7378 ELM_GENLIST_ITEM_DATA_GET(eo_last_item, last_item);
7379 _item_move_after(it, last_item);
7380 }
7381
7382 EOLIAN static void
_elm_genlist_item_show(Eo * eo_item EINA_UNUSED,Elm_Gen_Item * item,Elm_Genlist_Item_Scrollto_Type type)7383 _elm_genlist_item_show(Eo *eo_item EINA_UNUSED, Elm_Gen_Item *item, Elm_Genlist_Item_Scrollto_Type type)
7384 {
7385 Evas_Coord x, y, w, h;
7386
7387 ELM_GENLIST_ITEM_CHECK_OR_RETURN(item);
7388
7389 if (_elm_genlist_item_coordinates_calc
7390 (item, type, EINA_FALSE, &x, &y, &w, &h))
7391 elm_interface_scrollable_content_region_show
7392 (WIDGET(item), x, y, w, h);
7393 }
7394
7395 EOLIAN static void
_elm_genlist_item_bring_in(Eo * eo_item EINA_UNUSED,Elm_Gen_Item * item,Elm_Genlist_Item_Scrollto_Type type)7396 _elm_genlist_item_bring_in(Eo *eo_item EINA_UNUSED, Elm_Gen_Item *item, Elm_Genlist_Item_Scrollto_Type type)
7397 {
7398 Evas_Coord x, y, w, h;
7399
7400 ELM_GENLIST_ITEM_CHECK_OR_RETURN(item);
7401
7402 if (_elm_genlist_item_coordinates_calc
7403 (item, type, EINA_TRUE, &x, &y, &w, &h))
7404 elm_interface_scrollable_region_bring_in(WIDGET(item), x, y, w, h);
7405 }
7406
7407 EOLIAN static void
_elm_genlist_item_all_contents_unset(Eo * eo_item EINA_UNUSED,Elm_Gen_Item * it,Eina_List ** l)7408 _elm_genlist_item_all_contents_unset(Eo *eo_item EINA_UNUSED, Elm_Gen_Item *it, Eina_List **l)
7409 {
7410 Evas_Object *content;
7411
7412 ELM_GENLIST_ITEM_CHECK_OR_RETURN(it);
7413
7414 EINA_LIST_FREE(it->contents, content)
7415 {
7416 _elm_widget_sub_object_redirect_to_top(WIDGET(it), content);
7417 edje_object_part_unswallow(VIEW(it), content);
7418 evas_object_hide(content);
7419 if (l) *l = eina_list_append(*l, content);
7420 }
7421 }
7422
7423 static void
_mark_item_update(Elm_Gen_Item * it)7424 _mark_item_update(Elm_Gen_Item *it)
7425 {
7426 it->item->mincalcd = EINA_FALSE;
7427 it->item->updateme = EINA_TRUE;
7428 it->item->block->updateme = EINA_TRUE;
7429 }
7430
7431 EOLIAN static void
_elm_genlist_item_update(Eo * eo_item EINA_UNUSED,Elm_Gen_Item * it)7432 _elm_genlist_item_update(Eo *eo_item EINA_UNUSED, Elm_Gen_Item *it)
7433 {
7434 ELM_GENLIST_ITEM_CHECK_OR_RETURN(it);
7435 ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
7436
7437 if (!it->item->block) return;
7438 _mark_item_update(it);
7439 ecore_job_del(sd->update_job);
7440 sd->update_job = ecore_job_add(_update_job, sd->obj);
7441 }
7442
7443 EOLIAN static void
_elm_genlist_item_fields_update(Eo * eo_item EINA_UNUSED,Elm_Gen_Item * it,const char * parts,Elm_Genlist_Item_Field_Type itf)7444 _elm_genlist_item_fields_update(Eo *eo_item EINA_UNUSED, Elm_Gen_Item *it,
7445 const char *parts,
7446 Elm_Genlist_Item_Field_Type itf)
7447 {
7448 ELM_GENLIST_ITEM_CHECK_OR_RETURN(it);
7449
7450 if (!it->item->block) return;
7451
7452 if (!it->realized)
7453 {
7454 if (!itf || (itf & ELM_GENLIST_ITEM_FIELD_CONTENT))
7455 elm_genlist_item_update(eo_item);
7456 return;
7457 }
7458
7459 if ((!itf) || (itf & ELM_GENLIST_ITEM_FIELD_TEXT))
7460 {
7461 _item_text_realize(it, VIEW(it), &it->texts, parts);
7462 }
7463 if ((!itf) || (itf & ELM_GENLIST_ITEM_FIELD_CONTENT))
7464 {
7465 _item_content_realize(it, VIEW(it), &it->contents, "contents", parts, EINA_FALSE);
7466 if (it->flipped)
7467 {
7468 _item_content_realize(it, VIEW(it), &it->item->flip_contents,
7469 "flips", parts, EINA_FALSE);
7470 }
7471 if (it->item->deco_it_view)
7472 {
7473 _item_content_realize(it, it->item->deco_it_view,
7474 &it->item->deco_it_contents,
7475 "contents", parts, EINA_FALSE);
7476 }
7477 if (it->item->wsd->decorate_all_mode)
7478 {
7479 _item_content_realize(it, it->deco_all_view,
7480 &it->item->deco_all_contents,
7481 "contents", parts, EINA_FALSE);
7482 }
7483 if (it->has_contents != (!!it->contents))
7484 it->item->mincalcd = EINA_FALSE;
7485 it->has_contents = !!it->contents;
7486 if (it->item->type == ELM_GENLIST_ITEM_NONE)
7487 {
7488 Evas_Object* eobj;
7489 Eina_List* l;
7490 it->item_focus_chain = eina_list_free(it->item_focus_chain);
7491 EINA_LIST_FOREACH(it->contents, l, eobj)
7492 if (elm_widget_is(eobj) && elm_object_focus_allow_get(eobj))
7493 it->item_focus_chain = eina_list_append(it->item_focus_chain, eobj);
7494 }
7495 }
7496
7497 if ((!itf) || (itf & ELM_GENLIST_ITEM_FIELD_STATE))
7498 _item_state_realize(it, VIEW(it), parts);
7499
7500 if (!it->item->mincalcd)
7501 elm_genlist_item_update(eo_item);
7502 }
7503
7504 EOLIAN static void
_elm_genlist_item_item_class_update(Eo * eo_it,Elm_Gen_Item * it,const Elm_Genlist_Item_Class * itc)7505 _elm_genlist_item_item_class_update(Eo *eo_it, Elm_Gen_Item *it,
7506 const Elm_Genlist_Item_Class *itc)
7507 {
7508 ELM_GENLIST_ITEM_CHECK_OR_RETURN(it);
7509 EINA_SAFETY_ON_NULL_RETURN(itc);
7510
7511 /* Decrease the orignal item class refcount to prevent memory leak */
7512 if (it->itc != itc)
7513 {
7514 elm_genlist_item_class_unref((Elm_Genlist_Item_Class *)it->itc);
7515 it->itc = itc;
7516 elm_genlist_item_class_ref((Elm_Genlist_Item_Class *)it->itc);
7517 }
7518
7519 if (!it->item->block) return;
7520 it->item->nocache_once = EINA_TRUE;
7521
7522 ELM_SAFE_FREE(it->texts, elm_widget_stringlist_free);
7523 ELM_SAFE_FREE(it->item->deco_it_texts, elm_widget_stringlist_free);
7524 ELM_SAFE_FREE(it->item->deco_all_texts, elm_widget_stringlist_free);
7525
7526 elm_genlist_item_update(eo_it);
7527 }
7528
7529 EOLIAN static const Elm_Genlist_Item_Class *
_elm_genlist_item_item_class_get(const Eo * eo_item EINA_UNUSED,Elm_Gen_Item * it)7530 _elm_genlist_item_item_class_get(const Eo *eo_item EINA_UNUSED, Elm_Gen_Item *it)
7531 {
7532 ELM_GENLIST_ITEM_CHECK_OR_RETURN(it, NULL);
7533
7534 return it->itc;
7535 }
7536
7537 static Evas_Object *
_elm_genlist_item_label_create(void * data,Evas_Object * obj EINA_UNUSED,Evas_Object * tooltip,void * it EINA_UNUSED)7538 _elm_genlist_item_label_create(void *data,
7539 Evas_Object *obj EINA_UNUSED,
7540 Evas_Object *tooltip,
7541 void *it EINA_UNUSED)
7542 {
7543 Evas_Object *label = elm_label_add(tooltip);
7544
7545 if (!label)
7546 return NULL;
7547
7548 elm_object_style_set(label, "tooltip");
7549 elm_object_text_set(label, data);
7550
7551 return label;
7552 }
7553
7554 static void
_elm_genlist_item_label_del_cb(void * data,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)7555 _elm_genlist_item_label_del_cb(void *data,
7556 Evas_Object *obj EINA_UNUSED,
7557 void *event_info EINA_UNUSED)
7558 {
7559 eina_stringshare_del(data);
7560 }
7561
7562 EAPI void
elm_genlist_item_tooltip_text_set(Elm_Object_Item * it,const char * text)7563 elm_genlist_item_tooltip_text_set(Elm_Object_Item *it,
7564 const char *text)
7565 {
7566 elm_wdg_item_tooltip_text_set(it, text);
7567 }
7568
7569 EOLIAN static void
_elm_genlist_item_elm_widget_item_tooltip_text_set(Eo * eo_it,Elm_Gen_Item * it,const char * text)7570 _elm_genlist_item_elm_widget_item_tooltip_text_set(Eo *eo_it, Elm_Gen_Item *it, const char *text)
7571 {
7572 ELM_GENLIST_ITEM_CHECK_OR_RETURN(it);
7573
7574 text = eina_stringshare_add(text);
7575 elm_genlist_item_tooltip_content_cb_set
7576 (eo_it, _elm_genlist_item_label_create, text,
7577 _elm_genlist_item_label_del_cb);
7578 }
7579
7580 EAPI void
elm_genlist_item_tooltip_content_cb_set(Elm_Object_Item * item,Elm_Tooltip_Item_Content_Cb func,const void * data,Evas_Smart_Cb del_cb)7581 elm_genlist_item_tooltip_content_cb_set(Elm_Object_Item *item,
7582 Elm_Tooltip_Item_Content_Cb func,
7583 const void *data,
7584 Evas_Smart_Cb del_cb)
7585 {
7586 elm_wdg_item_tooltip_content_cb_set(item, func, data, del_cb);
7587 }
7588
7589 EOLIAN static void
_elm_genlist_item_elm_widget_item_tooltip_content_cb_set(Eo * eo_it,Elm_Gen_Item * it,Elm_Tooltip_Item_Content_Cb func,const void * data,Evas_Smart_Cb del_cb)7590 _elm_genlist_item_elm_widget_item_tooltip_content_cb_set(Eo *eo_it, Elm_Gen_Item *it,
7591 Elm_Tooltip_Item_Content_Cb func,
7592 const void *data,
7593 Evas_Smart_Cb del_cb)
7594 {
7595 ELM_GENLIST_ITEM_CHECK_OR_GOTO(it, error);
7596
7597 if ((it->tooltip.content_cb != func) || (it->tooltip.data != data))
7598 {
7599 if (it->tooltip.del_cb)
7600 it->tooltip.del_cb((void *)it->tooltip.data, WIDGET(it), it);
7601
7602 it->tooltip.content_cb = func;
7603 it->tooltip.data = data;
7604 it->tooltip.del_cb = del_cb;
7605 }
7606
7607 if (VIEW(it))
7608 {
7609 elm_wdg_item_tooltip_content_cb_set
7610 (efl_super(eo_it, ELM_GENLIST_ITEM_CLASS), it->tooltip.content_cb, it->tooltip.data, NULL);
7611 elm_wdg_item_tooltip_style_set(eo_it, it->tooltip.style);
7612 elm_wdg_item_tooltip_window_mode_set(eo_it, it->tooltip.free_size);
7613 }
7614
7615 return;
7616
7617 error:
7618 if (del_cb) del_cb((void *)data, NULL, NULL);
7619 }
7620
7621 EAPI void
elm_genlist_item_tooltip_unset(Elm_Object_Item * item)7622 elm_genlist_item_tooltip_unset(Elm_Object_Item *item)
7623 {
7624 elm_wdg_item_tooltip_unset(item);
7625 }
7626
7627 EOLIAN static void
_elm_genlist_item_elm_widget_item_tooltip_unset(Eo * eo_it,Elm_Gen_Item * it)7628 _elm_genlist_item_elm_widget_item_tooltip_unset(Eo *eo_it, Elm_Gen_Item *it)
7629 {
7630 ELM_GENLIST_ITEM_CHECK_OR_RETURN(it);
7631
7632 if ((VIEW(it)) && (it->tooltip.content_cb))
7633 elm_wdg_item_tooltip_unset(efl_super(eo_it, ELM_GENLIST_ITEM_CLASS));
7634
7635 if (it->tooltip.del_cb)
7636 it->tooltip.del_cb((void *)it->tooltip.data, WIDGET(it), it);
7637 it->tooltip.del_cb = NULL;
7638 it->tooltip.content_cb = NULL;
7639 it->tooltip.data = NULL;
7640 it->tooltip.free_size = EINA_FALSE;
7641 if (it->tooltip.style)
7642 elm_wdg_item_tooltip_style_set(eo_it, NULL);
7643 }
7644
7645 EAPI void
elm_genlist_item_tooltip_style_set(Elm_Object_Item * item,const char * style)7646 elm_genlist_item_tooltip_style_set(Elm_Object_Item *item,
7647 const char *style)
7648 {
7649 elm_wdg_item_tooltip_style_set(item, style);
7650 }
7651
7652 EOLIAN static void
_elm_genlist_item_elm_widget_item_tooltip_style_set(Eo * eo_it,Elm_Gen_Item * it,const char * style)7653 _elm_genlist_item_elm_widget_item_tooltip_style_set(Eo *eo_it, Elm_Gen_Item *it,
7654 const char *style)
7655 {
7656 ELM_GENLIST_ITEM_CHECK_OR_RETURN(it);
7657
7658 eina_stringshare_replace(&it->tooltip.style, style);
7659 if (VIEW(it)) elm_wdg_item_tooltip_style_set(efl_super(eo_it, ELM_GENLIST_ITEM_CLASS), style);
7660 }
7661
7662 EAPI const char *
elm_genlist_item_tooltip_style_get(const Elm_Object_Item * it)7663 elm_genlist_item_tooltip_style_get(const Elm_Object_Item *it)
7664 {
7665 return elm_wdg_item_tooltip_style_get(it);
7666 }
7667
7668 EOLIAN static const char *
_elm_genlist_item_elm_widget_item_tooltip_style_get(const Eo * eo_it EINA_UNUSED,Elm_Gen_Item * it)7669 _elm_genlist_item_elm_widget_item_tooltip_style_get(const Eo *eo_it EINA_UNUSED, Elm_Gen_Item *it)
7670 {
7671 return it->tooltip.style;
7672 }
7673
7674 EAPI Eina_Bool
elm_genlist_item_tooltip_window_mode_set(Elm_Object_Item * item,Eina_Bool disable)7675 elm_genlist_item_tooltip_window_mode_set(Elm_Object_Item *item,
7676 Eina_Bool disable)
7677 {
7678 return elm_wdg_item_tooltip_window_mode_set(item, disable);
7679 }
7680
7681 EOLIAN static Eina_Bool
_elm_genlist_item_elm_widget_item_tooltip_window_mode_set(Eo * eo_it,Elm_Gen_Item * it,Eina_Bool disable)7682 _elm_genlist_item_elm_widget_item_tooltip_window_mode_set(Eo *eo_it, Elm_Gen_Item *it,
7683 Eina_Bool disable)
7684 {
7685 ELM_GENLIST_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
7686
7687 it->tooltip.free_size = disable;
7688 if (VIEW(it))
7689 {
7690 Eina_Bool ret;
7691 ret = elm_wdg_item_tooltip_window_mode_set(efl_super(eo_it, ELM_GENLIST_ITEM_CLASS), disable);
7692 return ret;
7693 }
7694
7695 return disable;
7696 }
7697
7698 EAPI Eina_Bool
elm_genlist_item_tooltip_window_mode_get(const Elm_Object_Item * eo_it)7699 elm_genlist_item_tooltip_window_mode_get(const Elm_Object_Item *eo_it)
7700 {
7701 return elm_wdg_item_tooltip_window_mode_get(eo_it);
7702 }
7703
7704 EOLIAN static Eina_Bool
_elm_genlist_item_elm_widget_item_tooltip_window_mode_get(const Eo * eo_it EINA_UNUSED,Elm_Gen_Item * it)7705 _elm_genlist_item_elm_widget_item_tooltip_window_mode_get(const Eo *eo_it EINA_UNUSED, Elm_Gen_Item *it)
7706 {
7707 return it->tooltip.free_size;
7708 }
7709
7710 EAPI void
elm_genlist_item_cursor_set(Elm_Object_Item * item,const char * cursor)7711 elm_genlist_item_cursor_set(Elm_Object_Item *item,
7712 const char *cursor)
7713 {
7714 elm_wdg_item_cursor_set(item, cursor);
7715 }
7716
7717 EOLIAN static void
_elm_genlist_item_elm_widget_item_cursor_set(Eo * eo_it,Elm_Gen_Item * it,const char * cursor)7718 _elm_genlist_item_elm_widget_item_cursor_set(Eo *eo_it, Elm_Gen_Item *it,
7719 const char *cursor)
7720 {
7721 ELM_GENLIST_ITEM_CHECK_OR_RETURN(it);
7722 eina_stringshare_replace(&it->mouse_cursor, cursor);
7723 if (VIEW(it)) elm_wdg_item_cursor_set(efl_super(eo_it, ELM_GENLIST_ITEM_CLASS), cursor);
7724 }
7725
7726 EAPI const char *
elm_genlist_item_cursor_get(const Elm_Object_Item * eo_it)7727 elm_genlist_item_cursor_get(const Elm_Object_Item *eo_it)
7728 {
7729 return elm_wdg_item_cursor_get(eo_it);
7730 }
7731
7732 EAPI void
elm_genlist_item_cursor_unset(Elm_Object_Item * item)7733 elm_genlist_item_cursor_unset(Elm_Object_Item *item)
7734 {
7735 elm_wdg_item_cursor_unset(item);
7736 }
7737
7738 EOLIAN static void
_elm_genlist_item_elm_widget_item_cursor_unset(Eo * eo_it,Elm_Gen_Item * it)7739 _elm_genlist_item_elm_widget_item_cursor_unset(Eo *eo_it, Elm_Gen_Item *it)
7740 {
7741 ELM_GENLIST_ITEM_CHECK_OR_RETURN(it);
7742
7743 if (!it->mouse_cursor) return;
7744
7745 if (VIEW(it)) elm_wdg_item_cursor_unset(efl_super(eo_it, ELM_GENLIST_ITEM_CLASS));
7746
7747 ELM_SAFE_FREE(it->mouse_cursor, eina_stringshare_del);
7748 }
7749
7750 EAPI void
elm_genlist_item_cursor_style_set(Elm_Object_Item * eo_it,const char * style)7751 elm_genlist_item_cursor_style_set(Elm_Object_Item *eo_it,
7752 const char *style)
7753 {
7754 elm_wdg_item_cursor_style_set(eo_it, style);
7755 }
7756
7757 EAPI const char *
elm_genlist_item_cursor_style_get(const Elm_Object_Item * eo_it)7758 elm_genlist_item_cursor_style_get(const Elm_Object_Item *eo_it)
7759 {
7760 return elm_wdg_item_cursor_style_get(eo_it);
7761 }
7762
7763 EAPI void
elm_genlist_item_cursor_engine_only_set(Elm_Object_Item * eo_it,Eina_Bool engine_only)7764 elm_genlist_item_cursor_engine_only_set(Elm_Object_Item *eo_it,
7765 Eina_Bool engine_only)
7766 {
7767 elm_wdg_item_cursor_engine_only_set(eo_it, engine_only);
7768 }
7769
7770 EAPI Eina_Bool
elm_genlist_item_cursor_engine_only_get(const Elm_Object_Item * eo_it)7771 elm_genlist_item_cursor_engine_only_get(const Elm_Object_Item *eo_it)
7772 {
7773 return elm_wdg_item_cursor_engine_only_get(eo_it);
7774 }
7775
7776 EOLIAN static int
_elm_genlist_item_index_get(const Eo * eo_it EINA_UNUSED,Elm_Gen_Item * it)7777 _elm_genlist_item_index_get(const Eo *eo_it EINA_UNUSED, Elm_Gen_Item *it)
7778 {
7779 int cnt = 1;
7780 Elm_Gen_Item *tmp;
7781 ELM_GENLIST_ITEM_CHECK_OR_RETURN(it, -1);
7782
7783 EINA_INLIST_FOREACH(it->item->wsd->items, tmp)
7784 {
7785 if (tmp == it) break;
7786 cnt++;
7787 }
7788 return cnt;
7789 }
7790
7791 EOLIAN static void
_elm_genlist_mode_set(Eo * obj,Elm_Genlist_Data * sd,Elm_List_Mode mode)7792 _elm_genlist_mode_set(Eo *obj, Elm_Genlist_Data *sd, Elm_List_Mode mode)
7793 {
7794 if (sd->mode == mode) return;
7795 sd->mode = mode;
7796
7797 if (sd->mode == ELM_LIST_LIMIT)
7798 {
7799 sd->scr_minw = EINA_TRUE;
7800 sd->scr_minh = EINA_FALSE;
7801 }
7802 else if (sd->mode == ELM_LIST_EXPAND)
7803 {
7804 sd->scr_minw = EINA_TRUE;
7805 sd->scr_minh = EINA_TRUE;
7806 }
7807 else
7808 {
7809 sd->scr_minw = EINA_FALSE;
7810 sd->scr_minh = EINA_FALSE;
7811 }
7812
7813 elm_layout_sizing_eval(obj);
7814 }
7815
7816 EOLIAN static Elm_List_Mode
_elm_genlist_mode_get(const Eo * obj EINA_UNUSED,Elm_Genlist_Data * sd)7817 _elm_genlist_mode_get(const Eo *obj EINA_UNUSED, Elm_Genlist_Data *sd)
7818 {
7819 return sd->mode;
7820 }
7821
7822 EAPI void
elm_genlist_bounce_set(Evas_Object * obj,Eina_Bool h_bounce,Eina_Bool v_bounce)7823 elm_genlist_bounce_set(Evas_Object *obj,
7824 Eina_Bool h_bounce,
7825 Eina_Bool v_bounce)
7826 {
7827 ELM_GENLIST_CHECK(obj);
7828 elm_interface_scrollable_bounce_allow_set(obj, h_bounce, v_bounce);
7829 }
7830
7831 EOLIAN static void
_elm_genlist_elm_interface_scrollable_bounce_allow_set(Eo * obj,Elm_Genlist_Data * sd,Eina_Bool h_bounce,Eina_Bool v_bounce)7832 _elm_genlist_elm_interface_scrollable_bounce_allow_set(Eo *obj, Elm_Genlist_Data *sd, Eina_Bool h_bounce, Eina_Bool v_bounce)
7833 {
7834 sd->h_bounce = !!h_bounce;
7835 sd->v_bounce = !!v_bounce;
7836 elm_interface_scrollable_bounce_allow_set
7837 (efl_super(obj, MY_CLASS), sd->h_bounce, sd->v_bounce);
7838 }
7839
7840 EAPI void
elm_genlist_bounce_get(const Evas_Object * obj,Eina_Bool * h_bounce,Eina_Bool * v_bounce)7841 elm_genlist_bounce_get(const Evas_Object *obj,
7842 Eina_Bool *h_bounce,
7843 Eina_Bool *v_bounce)
7844 {
7845 ELM_GENLIST_CHECK(obj);
7846 elm_interface_scrollable_bounce_allow_get
7847 (obj, h_bounce, v_bounce);
7848 }
7849
7850 EOLIAN static void
_elm_genlist_elm_interface_scrollable_bounce_allow_get(const Eo * obj EINA_UNUSED,Elm_Genlist_Data * sd,Eina_Bool * h_bounce,Eina_Bool * v_bounce)7851 _elm_genlist_elm_interface_scrollable_bounce_allow_get(const Eo *obj EINA_UNUSED, Elm_Genlist_Data *sd, Eina_Bool *h_bounce, Eina_Bool *v_bounce)
7852 {
7853 if (h_bounce) *h_bounce = sd->h_bounce;
7854 if (v_bounce) *v_bounce = sd->v_bounce;
7855 }
7856
7857 EOLIAN static void
_elm_genlist_homogeneous_set(Eo * obj EINA_UNUSED,Elm_Genlist_Data * sd,Eina_Bool homogeneous)7858 _elm_genlist_homogeneous_set(Eo *obj EINA_UNUSED, Elm_Genlist_Data *sd, Eina_Bool homogeneous)
7859 {
7860 sd->homogeneous = !!homogeneous;
7861 }
7862
7863 EOLIAN static Eina_Bool
_elm_genlist_homogeneous_get(const Eo * obj EINA_UNUSED,Elm_Genlist_Data * sd)7864 _elm_genlist_homogeneous_get(const Eo *obj EINA_UNUSED, Elm_Genlist_Data *sd)
7865 {
7866 return sd->homogeneous;
7867 }
7868
7869 EOLIAN static void
_elm_genlist_block_count_set(Eo * obj EINA_UNUSED,Elm_Genlist_Data * sd,int count)7870 _elm_genlist_block_count_set(Eo *obj EINA_UNUSED, Elm_Genlist_Data *sd, int count)
7871 {
7872 EINA_SAFETY_ON_TRUE_RETURN(count < 1);
7873
7874 sd->max_items_per_block = count;
7875 sd->item_cache_max = sd->max_items_per_block * 2;
7876 _item_cache_clean(sd);
7877 }
7878
7879 EOLIAN static int
_elm_genlist_block_count_get(const Eo * obj EINA_UNUSED,Elm_Genlist_Data * sd)7880 _elm_genlist_block_count_get(const Eo *obj EINA_UNUSED, Elm_Genlist_Data *sd)
7881 {
7882 return sd->max_items_per_block;
7883 }
7884
7885 static void
_filter_item_internal(Elm_Gen_Item * it)7886 _filter_item_internal(Elm_Gen_Item *it)
7887 {
7888 ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
7889 if (sd->filter_data)
7890 {
7891 if ((it->parent && !_item_filtered_get(it->parent, sd)) ||
7892 (it->itc->func.filter_get &&
7893 !it->itc->func.filter_get(
7894 (void *)WIDGET_ITEM_DATA_GET(EO_OBJ(it)),
7895 WIDGET(it), sd->filter_data)))
7896 {
7897 it->hide = EINA_TRUE;
7898 if (it->item->block)
7899 it->item->block->changed = EINA_TRUE;
7900 }
7901 else
7902 sd->filtered_count++;
7903 }
7904 it->filtered = EINA_TRUE;
7905 sd->processed_count++;
7906 }
7907
7908 // Returns true if the item is not filtered out, but remains visible.
7909 static Eina_Bool
_item_filtered_get(Elm_Gen_Item * it,Elm_Genlist_Data * sd)7910 _item_filtered_get(Elm_Gen_Item *it, Elm_Genlist_Data *sd)
7911 {
7912 Eina_List *l;
7913 /* no filter exists: item will always be visible */
7914 if (!sd->filter_data) return EINA_TRUE;
7915 if (!it->filtered)
7916 {
7917 l = eina_list_data_find_list(sd->filter_queue, it);
7918 if (l)
7919 sd->filter_queue = eina_list_remove_list(sd->filter_queue, l);
7920 if (it->item->queued)
7921 l = eina_list_data_find_list(sd->queue, it);
7922 else
7923 l = NULL;
7924 if (l)
7925 {
7926 sd->queue = eina_list_remove_list(sd->queue, l);
7927 it->item->queued = EINA_FALSE;
7928 _item_process(sd, it);
7929 _item_process_post(sd, it);
7930 }
7931
7932 _filter_item_internal(it);
7933 if (it->item->block)
7934 it->item->block->changed = EINA_TRUE;
7935 efl_canvas_group_change(sd->obj);
7936 sd->need_calc = EINA_TRUE;
7937 }
7938 return !it->hide;
7939 }
7940
7941 static int
_filter_queue_process(Elm_Genlist_Data * sd)7942 _filter_queue_process(Elm_Genlist_Data *sd)
7943 {
7944 int n;
7945 Elm_Gen_Item *it;
7946 double t0;
7947
7948 t0 = ecore_time_get();
7949 for (n = 0; ((sd->filter_queue) && (sd->processed_count < ITEM_QUEUE_MAX)); n++)
7950 {
7951 it = eina_list_data_get(sd->filter_queue);
7952 if (!it) break;
7953 //FIXME: This is added as a fail safe code for items not yet processed.
7954 if (it->item->queued)
7955 {
7956 sd->filter_queue = eina_list_remove_list
7957 (sd->filter_queue, sd->filter_queue);
7958 sd->filter_queue = eina_list_append(sd->filter_queue, it);
7959 it = eina_list_data_get(sd->filter_queue);
7960 }
7961 sd->filter_queue = eina_list_remove_list(sd->filter_queue, sd->filter_queue);
7962 _filter_item_internal(it);
7963 it->item->block->changed = EINA_TRUE;
7964 if ((ecore_time_get() - t0) > (ecore_animator_frametime_get()))
7965 {
7966 //At least 1 item is filtered by this time, so return n+1 for first loop
7967 n++;
7968 break;
7969 }
7970 }
7971 return n;
7972 }
7973
7974 static Eina_Bool
_filter_process(void * data,Eina_Bool * wakeup)7975 _filter_process(void *data,
7976 Eina_Bool *wakeup)
7977 {
7978 Elm_Genlist_Data *sd = data;
7979
7980 if (_filter_queue_process(sd) > 0) *wakeup = EINA_TRUE;
7981 if (!sd->filter_queue) return ECORE_CALLBACK_CANCEL;
7982 return ECORE_CALLBACK_RENEW;
7983 }
7984
7985 static Eina_Bool
_item_filter_enterer(void * data)7986 _item_filter_enterer(void *data)
7987 {
7988 Eina_Bool wakeup = EINA_FALSE;
7989 ELM_GENLIST_DATA_GET(data, sd);
7990 Eina_Bool ok = _filter_process(sd, &wakeup);
7991 if (wakeup)
7992 {
7993 // wake up mainloop
7994 efl_canvas_group_change(sd->obj);
7995 }
7996 if (ok == ECORE_CALLBACK_CANCEL)
7997 {
7998 sd->queue_filter_enterer = NULL;
7999 efl_event_callback_legacy_call(sd->obj, ELM_GENLIST_EVENT_FILTER_DONE, NULL);
8000 }
8001
8002 return ok;
8003 }
8004
8005 EOLIAN void
_elm_genlist_filter_set(Eo * obj EINA_UNUSED,Elm_Genlist_Data * sd,void * filter_data)8006 _elm_genlist_filter_set(Eo *obj EINA_UNUSED, Elm_Genlist_Data *sd, void *filter_data)
8007 {
8008 Item_Block *itb;
8009 Eina_List *l;
8010 Elm_Gen_Item *it;
8011
8012 if (sd->filter_queue)
8013 ELM_SAFE_FREE(sd->queue_filter_enterer, ecore_idle_enterer_del);
8014 ELM_SAFE_FREE(sd->filter_queue, eina_list_free);
8015 ELM_SAFE_FREE(sd->filtered_list, eina_list_free);
8016 sd->filtered_count = 0;
8017 sd->processed_count = 0;
8018 sd->filter = EINA_TRUE;
8019 sd->filter_data = filter_data;
8020
8021 EINA_INLIST_FOREACH(sd->blocks, itb)
8022 {
8023 if (itb->realized)
8024 {
8025 EINA_LIST_FOREACH(itb->items, l, it)
8026 {
8027 it->filtered = EINA_FALSE;
8028 it->hide = EINA_FALSE;
8029 if (it->realized)
8030 _filter_item_internal(it);
8031 else
8032 sd->filter_queue = eina_list_append(sd->filter_queue, it);
8033 }
8034 itb->changed = EINA_TRUE;
8035 evas_object_smart_changed(obj);
8036 sd->need_calc = EINA_TRUE;
8037 }
8038 else
8039 {
8040 EINA_LIST_FOREACH(itb->items, l, it)
8041 {
8042 it->filtered = EINA_FALSE;
8043 it->hide = EINA_FALSE;
8044 sd->filter_queue = eina_list_append(sd->filter_queue, it);
8045 }
8046 }
8047 }
8048 if (!sd->filter_queue)
8049 efl_event_callback_legacy_call(sd->obj, ELM_GENLIST_EVENT_FILTER_DONE, NULL);
8050 else
8051 sd->queue_filter_enterer = ecore_idle_enterer_add(_item_filter_enterer,
8052 sd->obj);
8053 }
8054
8055 static Eina_Bool
_filter_iterator_next(Elm_Genlist_Filter * iter,void ** data)8056 _filter_iterator_next(Elm_Genlist_Filter *iter, void **data)
8057 {
8058 if (!iter->current) return EINA_FALSE;
8059 Elm_Gen_Item *item;
8060 while (iter->current)
8061 {
8062 item = ELM_GENLIST_FILTER_ITERATOR_ITEM_GET(iter->current, Elm_Gen_Item);
8063 iter->current = iter->current->next;
8064 if (_item_filtered_get(item, item->item->block->sd))
8065 {
8066 if (data)
8067 *data = EO_OBJ(item);
8068 return EINA_TRUE;
8069 }
8070 }
8071
8072 return EINA_FALSE;
8073 }
8074
8075 static void
_filter_iterator_free(Elm_Genlist_Filter * iter)8076 _filter_iterator_free(Elm_Genlist_Filter *iter)
8077 {
8078 free(iter);
8079 }
8080
8081 static Evas_Object *
_filter_iterator_get_container(Elm_Genlist_Filter * iter)8082 _filter_iterator_get_container(Elm_Genlist_Filter *iter)
8083 {
8084 if (!iter) return NULL;
8085 return iter->obj;
8086 }
8087
8088 EOLIAN Eina_Iterator *
_elm_genlist_filter_iterator_new(Eo * obj EINA_UNUSED,Elm_Genlist_Data * sd)8089 _elm_genlist_filter_iterator_new(Eo *obj EINA_UNUSED, Elm_Genlist_Data *sd)
8090 {
8091 Elm_Genlist_Filter *iter;
8092 iter = calloc(1, sizeof (Elm_Genlist_Filter));
8093 if (!iter) return NULL;
8094
8095 iter->head = sd->items;
8096 iter->current = sd->items;
8097 iter->obj = sd->obj;
8098
8099 iter->iterator.version = EINA_ITERATOR_VERSION;
8100 iter->iterator.next = FUNC_ITERATOR_NEXT(_filter_iterator_next);
8101 iter->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(
8102 _filter_iterator_get_container);
8103 iter->iterator.free = FUNC_ITERATOR_FREE(_filter_iterator_free);
8104
8105 EINA_MAGIC_SET(&iter->iterator, EINA_MAGIC_ITERATOR);
8106
8107 return &iter->iterator;
8108 }
8109
8110 EOLIAN static unsigned int
_elm_genlist_filtered_items_count(const Eo * obj EINA_UNUSED,Elm_Genlist_Data * sd)8111 _elm_genlist_filtered_items_count(const Eo *obj EINA_UNUSED, Elm_Genlist_Data *sd)
8112 {
8113 return sd->filtered_count;
8114 }
8115
8116 EOLIAN static void
_elm_genlist_longpress_timeout_set(Eo * obj EINA_UNUSED,Elm_Genlist_Data * sd,double timeout)8117 _elm_genlist_longpress_timeout_set(Eo *obj EINA_UNUSED, Elm_Genlist_Data *sd, double timeout)
8118 {
8119 sd->longpress_timeout = timeout;
8120 }
8121
8122 EOLIAN static double
_elm_genlist_longpress_timeout_get(const Eo * obj EINA_UNUSED,Elm_Genlist_Data * sd)8123 _elm_genlist_longpress_timeout_get(const Eo *obj EINA_UNUSED, Elm_Genlist_Data *sd)
8124 {
8125 return sd->longpress_timeout;
8126 }
8127
8128 EAPI void
elm_genlist_scroller_policy_set(Evas_Object * obj,Elm_Scroller_Policy policy_h,Elm_Scroller_Policy policy_v)8129 elm_genlist_scroller_policy_set(Evas_Object *obj,
8130 Elm_Scroller_Policy policy_h,
8131 Elm_Scroller_Policy policy_v)
8132 {
8133 ELM_GENLIST_CHECK(obj);
8134 elm_interface_scrollable_policy_set(obj, policy_h, policy_v);
8135 }
8136
8137 EOLIAN static void
_elm_genlist_elm_interface_scrollable_policy_set(Eo * obj,Elm_Genlist_Data * sd EINA_UNUSED,Elm_Scroller_Policy policy_h,Elm_Scroller_Policy policy_v)8138 _elm_genlist_elm_interface_scrollable_policy_set(Eo *obj, Elm_Genlist_Data *sd EINA_UNUSED, Elm_Scroller_Policy policy_h, Elm_Scroller_Policy policy_v)
8139 {
8140 if ((policy_h >= ELM_SCROLLER_POLICY_LAST) ||
8141 (policy_v >= ELM_SCROLLER_POLICY_LAST))
8142 return;
8143
8144 elm_interface_scrollable_policy_set(efl_super(obj, MY_CLASS), policy_h, policy_v);
8145 }
8146
8147 EAPI void
elm_genlist_scroller_policy_get(const Evas_Object * obj,Elm_Scroller_Policy * policy_h,Elm_Scroller_Policy * policy_v)8148 elm_genlist_scroller_policy_get(const Evas_Object *obj,
8149 Elm_Scroller_Policy *policy_h,
8150 Elm_Scroller_Policy *policy_v)
8151 {
8152 ELM_GENLIST_CHECK(obj);
8153 elm_interface_scrollable_policy_get(obj, policy_h, policy_v);
8154 }
8155
8156 EOLIAN static void
_elm_genlist_elm_interface_scrollable_policy_get(const Eo * obj,Elm_Genlist_Data * sd EINA_UNUSED,Elm_Scroller_Policy * policy_h,Elm_Scroller_Policy * policy_v)8157 _elm_genlist_elm_interface_scrollable_policy_get(const Eo *obj, Elm_Genlist_Data *sd EINA_UNUSED, Elm_Scroller_Policy *policy_h, Elm_Scroller_Policy *policy_v)
8158 {
8159 Elm_Scroller_Policy s_policy_h, s_policy_v;
8160
8161 elm_interface_scrollable_policy_get
8162 (efl_super(obj, MY_CLASS), &s_policy_h, &s_policy_v);
8163 if (policy_h) *policy_h = (Elm_Scroller_Policy)s_policy_h;
8164 if (policy_v) *policy_v = (Elm_Scroller_Policy)s_policy_v;
8165 }
8166
8167 EOLIAN static void
_elm_genlist_realized_items_update(Eo * obj,Elm_Genlist_Data * _pd)8168 _elm_genlist_realized_items_update(Eo *obj, Elm_Genlist_Data *_pd)
8169 {
8170 Eina_List *list;
8171 Elm_Object_Item *it;
8172
8173 list = elm_genlist_realized_items_get(obj);
8174 EINA_LIST_FREE(list, it)
8175 {
8176 ELM_GENLIST_ITEM_DATA_GET(it, it2);
8177 if (!it2->item->block) continue;
8178 _mark_item_update(it2);
8179 }
8180 ecore_job_del(_pd->update_job);
8181 _pd->update_job = ecore_job_add(_update_job, obj);
8182 }
8183
8184 EOLIAN static void
_elm_genlist_item_decorate_mode_set(Eo * eo_it EINA_UNUSED,Elm_Gen_Item * it,const char * decorate_it_type,Eina_Bool decorate_it_set)8185 _elm_genlist_item_decorate_mode_set(Eo *eo_it EINA_UNUSED, Elm_Gen_Item *it,
8186 const char *decorate_it_type,
8187 Eina_Bool decorate_it_set)
8188 {
8189 Elm_Genlist_Data *sd;
8190 Eina_List *l;
8191 Elm_Object_Item *eo_it2 = NULL;
8192
8193 ELM_GENLIST_ITEM_CHECK_OR_RETURN(it);
8194 sd = it->item->wsd;
8195
8196 if (!decorate_it_type) return;
8197 if (elm_wdg_item_disabled_get(eo_it)) return;
8198 if (sd->decorate_all_mode) return;
8199
8200 if ((sd->mode_item == it) &&
8201 (!strcmp(decorate_it_type, sd->decorate_it_type)) &&
8202 (decorate_it_set))
8203 return;
8204 if (!it->itc->decorate_item_style) return;
8205 it->decorate_it_set = decorate_it_set;
8206
8207 if (sd->multi)
8208 {
8209 EINA_LIST_FOREACH(sd->selected, l, eo_it2)
8210 {
8211 ELM_GENLIST_ITEM_DATA_GET(eo_it2, it2);
8212 if (it2->realized)
8213 elm_genlist_item_selected_set(eo_it2, EINA_FALSE);
8214 }
8215 }
8216 else
8217 {
8218 Elm_Gen_Item *it2 = NULL;
8219 eo_it2 = elm_genlist_selected_item_get(sd->obj);
8220 if (eo_it2) it2 = efl_data_scope_get(eo_it2, ELM_GENLIST_ITEM_CLASS);
8221 if (it2 && it2->realized)
8222 elm_genlist_item_selected_set(eo_it2, EINA_FALSE);
8223 }
8224
8225 if (!eina_streq(sd->decorate_it_type, decorate_it_type) ||
8226 decorate_it_set || (it == sd->mode_item))
8227 _decorate_item_unset(sd);
8228
8229 eina_stringshare_replace(&sd->decorate_it_type, decorate_it_type);
8230 if (decorate_it_set) _decorate_item_set(it);
8231 }
8232
8233 EOLIAN static const char *
_elm_genlist_item_decorate_mode_get(const Eo * eo_i EINA_UNUSED,Elm_Gen_Item * i)8234 _elm_genlist_item_decorate_mode_get(const Eo *eo_i EINA_UNUSED, Elm_Gen_Item *i)
8235 {
8236 ELM_GENLIST_ITEM_CHECK_OR_RETURN(i, NULL);
8237 return i->item->wsd->decorate_it_type;
8238 }
8239
8240 EOLIAN static Elm_Object_Item *
_elm_genlist_decorated_item_get(const Eo * obj EINA_UNUSED,Elm_Genlist_Data * sd)8241 _elm_genlist_decorated_item_get(const Eo *obj EINA_UNUSED, Elm_Genlist_Data *sd)
8242 {
8243 return EO_OBJ(sd->mode_item);
8244 }
8245
8246 EOLIAN static Eina_Bool
_elm_genlist_decorate_mode_get(const Eo * obj EINA_UNUSED,Elm_Genlist_Data * sd)8247 _elm_genlist_decorate_mode_get(const Eo *obj EINA_UNUSED, Elm_Genlist_Data *sd)
8248 {
8249 return sd->decorate_all_mode;
8250 }
8251
8252 EOLIAN static void
_elm_genlist_decorate_mode_set(Eo * obj,Elm_Genlist_Data * sd,Eina_Bool decorated)8253 _elm_genlist_decorate_mode_set(Eo *obj, Elm_Genlist_Data *sd, Eina_Bool decorated)
8254 {
8255 Elm_Object_Item *eo_it;
8256 Eina_List *list;
8257
8258 decorated = !!decorated;
8259 if (sd->decorate_all_mode == decorated) return;
8260 // decorate_all_mode should be set first
8261 // because content_get func. will be called after this
8262 // and user can check whether decorate_all_mode_ is enabled.
8263 sd->decorate_all_mode = decorated;
8264
8265 _elm_genlist_tree_effect_stop(sd);
8266 sd->move_effect_mode = ELM_GENLIST_TREE_EFFECT_NONE;
8267
8268 list = elm_genlist_realized_items_get(obj);
8269 if (!sd->decorate_all_mode)
8270 {
8271 EINA_LIST_FREE(list, eo_it)
8272 {
8273 ELM_GENLIST_ITEM_DATA_GET(eo_it, it);
8274 if (it->item->type != ELM_GENLIST_ITEM_GROUP)
8275 _decorate_all_item_unrealize(it);
8276 }
8277 _item_cache_zero(sd);
8278 }
8279 else
8280 {
8281 // unset decorated item
8282 Elm_Object_Item *deco_eo_it = elm_genlist_decorated_item_get(obj);
8283 ELM_GENLIST_ITEM_DATA_GET(deco_eo_it, deco_it);
8284 if (deco_it)
8285 {
8286 elm_genlist_item_decorate_mode_set
8287 (deco_eo_it, elm_genlist_item_decorate_mode_get
8288 (deco_eo_it), EINA_FALSE);
8289 _decorate_item_finished_signal_cb(deco_it, obj, NULL, NULL);
8290 }
8291
8292 EINA_LIST_FREE(list, eo_it)
8293 {
8294 ELM_GENLIST_ITEM_DATA_GET(eo_it, it);
8295 if (it->item->type != ELM_GENLIST_ITEM_GROUP)
8296 {
8297 if (it->itc->decorate_all_item_style)
8298 _decorate_all_item_realize(it, EINA_TRUE);
8299 }
8300 }
8301 }
8302
8303 efl_canvas_group_change(sd->obj);
8304 }
8305
8306 EOLIAN static void
_elm_genlist_reorder_mode_set(Eo * obj EINA_UNUSED,Elm_Genlist_Data * sd,Eina_Bool reorder_mode)8307 _elm_genlist_reorder_mode_set(Eo *obj EINA_UNUSED, Elm_Genlist_Data *sd, Eina_Bool reorder_mode)
8308 {
8309 Eina_List *realized;
8310 Elm_Object_Item *eo_it;
8311
8312 if (sd->reorder_mode == !!reorder_mode) return;
8313 if (sd->pin_item) elm_genlist_item_pin_set(EO_OBJ(sd->pin_item), EINA_FALSE);
8314 sd->reorder_mode = !!reorder_mode;
8315 realized = elm_genlist_realized_items_get(obj);
8316 EINA_LIST_FREE(realized, eo_it)
8317 {
8318 ELM_GENLIST_ITEM_DATA_GET(eo_it, it);
8319 if (sd->reorder_mode)
8320 {
8321 edje_object_signal_emit(VIEW(it), SIGNAL_REORDER_MODE_SET, "elm");
8322 if (it->deco_all_view)
8323 {
8324 edje_object_signal_emit(it->deco_all_view,
8325 SIGNAL_REORDER_MODE_SET, "elm");
8326 }
8327 }
8328 else
8329 {
8330 edje_object_signal_emit(VIEW(it), SIGNAL_REORDER_MODE_UNSET, "elm");
8331 if (it->deco_all_view)
8332 {
8333 edje_object_signal_emit(it->deco_all_view,
8334 SIGNAL_REORDER_MODE_UNSET, "elm");
8335 }
8336 }
8337 }
8338 }
8339
8340 EOLIAN static Eina_Bool
_elm_genlist_reorder_mode_get(const Eo * obj EINA_UNUSED,Elm_Genlist_Data * sd)8341 _elm_genlist_reorder_mode_get(const Eo *obj EINA_UNUSED, Elm_Genlist_Data *sd)
8342 {
8343 return sd->reorder_mode;
8344 }
8345
8346 EOLIAN static Elm_Genlist_Item_Type
_elm_genlist_item_type_get(const Eo * eo_it EINA_UNUSED,Elm_Gen_Item * it)8347 _elm_genlist_item_type_get(const Eo *eo_it EINA_UNUSED, Elm_Gen_Item *it)
8348 {
8349 ELM_GENLIST_ITEM_CHECK_OR_RETURN(it, ELM_GENLIST_ITEM_MAX);
8350
8351 return it->item->type;
8352 }
8353
8354 EOLIAN static void
_elm_genlist_item_pin_set(Eo * eo_it EINA_UNUSED,Elm_Gen_Item * it,Eina_Bool pin)8355 _elm_genlist_item_pin_set(Eo *eo_it EINA_UNUSED, Elm_Gen_Item *it, Eina_Bool pin)
8356 {
8357 ELM_GENLIST_ITEM_CHECK_OR_RETURN(it);
8358 ELM_GENLIST_DATA_GET(WIDGET(it), sd);
8359 if (sd->reorder_mode) return;
8360 if (it->item->type & ELM_GENLIST_ITEM_GROUP) return;
8361
8362 if (pin ^ (sd->pin_item == it))
8363 {
8364 if (sd->pin_item)
8365 {
8366 if (sd->pin_item->item->block)
8367 sd->pin_item->item->block->realized = EINA_TRUE;
8368 evas_object_smart_changed(sd->pan_obj);
8369 }
8370 if (pin)
8371 sd->pin_item = it;
8372 else
8373 sd->pin_item = NULL;
8374 }
8375 }
8376
8377 EOLIAN static Eina_Bool
_elm_genlist_item_pin_get(const Eo * eo_it EINA_UNUSED,Elm_Gen_Item * it)8378 _elm_genlist_item_pin_get(const Eo *eo_it EINA_UNUSED, Elm_Gen_Item *it)
8379 {
8380 ELM_GENLIST_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
8381 ELM_GENLIST_DATA_GET(WIDGET(it), sd);
8382
8383 if (sd->pin_item == it)
8384 return EINA_TRUE;
8385 else
8386 return EINA_FALSE;
8387 }
8388
8389 EAPI Elm_Genlist_Item_Class *
elm_genlist_item_class_new(void)8390 elm_genlist_item_class_new(void)
8391 {
8392 Elm_Genlist_Item_Class *itc = ELM_NEW(Elm_Genlist_Item_Class);
8393 EINA_SAFETY_ON_NULL_RETURN_VAL(itc, NULL);
8394
8395 itc->version = CLASS_ALLOCATED;
8396 itc->refcount = 1;
8397 itc->delete_me = EINA_FALSE;
8398
8399 return itc;
8400 }
8401
8402 EAPI void
elm_genlist_item_class_free(Elm_Genlist_Item_Class * itc)8403 elm_genlist_item_class_free(Elm_Genlist_Item_Class *itc)
8404 {
8405 if (itc && (itc->version == CLASS_ALLOCATED))
8406 {
8407 if (!itc->delete_me) itc->delete_me = EINA_TRUE;
8408 if (itc->refcount > 0) elm_genlist_item_class_unref(itc);
8409 else
8410 {
8411 itc->version = 0;
8412 free(itc);
8413 }
8414 }
8415 }
8416
8417 EAPI void
elm_genlist_item_class_ref(Elm_Genlist_Item_Class * itc)8418 elm_genlist_item_class_ref(Elm_Genlist_Item_Class *itc)
8419 {
8420 if (itc && (itc->version == CLASS_ALLOCATED))
8421 {
8422 itc->refcount++;
8423 if (itc->refcount == 0) itc->refcount--;
8424 }
8425 }
8426
8427 EAPI void
elm_genlist_item_class_unref(Elm_Genlist_Item_Class * itc)8428 elm_genlist_item_class_unref(Elm_Genlist_Item_Class *itc)
8429 {
8430 if (itc && (itc->version == CLASS_ALLOCATED))
8431 {
8432 if (itc->refcount > 0) itc->refcount--;
8433 if (itc->delete_me && (!itc->refcount))
8434 elm_genlist_item_class_free(itc);
8435 }
8436 }
8437
8438 static void
_flip_job(void * data)8439 _flip_job(void *data)
8440 {
8441 Elm_Gen_Item *it = (Elm_Gen_Item *)data;
8442 ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
8443
8444 _item_unselect(it);
8445 _elm_genlist_item_unrealize(it, EINA_FALSE);
8446
8447 it->flipped = EINA_TRUE;
8448 it->item->nocache = EINA_TRUE;
8449 efl_canvas_group_change(sd->obj);
8450 }
8451
8452 EOLIAN static void
_elm_genlist_item_flip_set(Eo * eo_it,Elm_Gen_Item * it,Eina_Bool flip)8453 _elm_genlist_item_flip_set(Eo *eo_it, Elm_Gen_Item *it, Eina_Bool flip)
8454 {
8455 ELM_GENLIST_ITEM_CHECK_OR_RETURN(it);
8456
8457 flip = !!flip;
8458 if (it->flipped == flip) return;
8459
8460 if (flip)
8461 {
8462 ecore_job_add(_flip_job, it);
8463 }
8464 else
8465 {
8466 edje_object_signal_emit(VIEW(it), SIGNAL_FLIP_DISABLED, "elm");
8467 if (it->item->wsd->decorate_all_mode)
8468 edje_object_signal_emit(it->deco_all_view, SIGNAL_FLIP_DISABLED,
8469 "elm");
8470
8471 it->flipped = flip;
8472 _item_cache_zero(it->item->wsd);
8473 elm_genlist_item_update(eo_it);
8474 it->item->nocache = EINA_FALSE;
8475 }
8476 }
8477
8478 EOLIAN static Eina_Bool
_elm_genlist_item_flip_get(const Eo * eo_it EINA_UNUSED,Elm_Gen_Item * it)8479 _elm_genlist_item_flip_get(const Eo *eo_it EINA_UNUSED, Elm_Gen_Item *it)
8480 {
8481 ELM_GENLIST_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
8482
8483 return it->flipped;
8484 }
8485
8486 EOLIAN static void
_elm_genlist_select_mode_set(Eo * obj EINA_UNUSED,Elm_Genlist_Data * sd,Elm_Object_Select_Mode mode)8487 _elm_genlist_select_mode_set(Eo *obj EINA_UNUSED, Elm_Genlist_Data *sd, Elm_Object_Select_Mode mode)
8488 {
8489 if ((mode >= ELM_OBJECT_SELECT_MODE_MAX) || (sd->select_mode == mode))
8490 return;
8491
8492 sd->select_mode = mode;
8493
8494 if ((sd->select_mode == ELM_OBJECT_SELECT_MODE_NONE) ||
8495 (sd->select_mode == ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY))
8496 {
8497 Eina_List *l, *ll;
8498 Elm_Object_Item *eo_it;
8499 EINA_LIST_FOREACH_SAFE(sd->selected, l, ll, eo_it)
8500 {
8501 ELM_GENLIST_ITEM_DATA_GET(eo_it, it);
8502 _item_unselect(it);
8503 }
8504 }
8505 }
8506
8507 EOLIAN static Elm_Object_Select_Mode
_elm_genlist_select_mode_get(const Eo * obj EINA_UNUSED,Elm_Genlist_Data * sd)8508 _elm_genlist_select_mode_get(const Eo *obj EINA_UNUSED, Elm_Genlist_Data *sd)
8509 {
8510 return sd->select_mode;
8511 }
8512
8513 EOLIAN static void
_elm_genlist_highlight_mode_set(Eo * obj EINA_UNUSED,Elm_Genlist_Data * sd,Eina_Bool highlight)8514 _elm_genlist_highlight_mode_set(Eo *obj EINA_UNUSED, Elm_Genlist_Data *sd, Eina_Bool highlight)
8515 {
8516 sd->highlight = !!highlight;
8517 }
8518
8519 EOLIAN static Eina_Bool
_elm_genlist_highlight_mode_get(const Eo * obj EINA_UNUSED,Elm_Genlist_Data * sd)8520 _elm_genlist_highlight_mode_get(const Eo *obj EINA_UNUSED, Elm_Genlist_Data *sd)
8521 {
8522 return sd->highlight;
8523 }
8524
8525 EOLIAN static void
_elm_genlist_item_select_mode_set(Eo * eo_it EINA_UNUSED,Elm_Gen_Item * it,Elm_Object_Select_Mode mode)8526 _elm_genlist_item_select_mode_set(Eo *eo_it EINA_UNUSED, Elm_Gen_Item *it,
8527 Elm_Object_Select_Mode mode)
8528 {
8529 ELM_GENLIST_ITEM_CHECK_OR_RETURN(it);
8530 ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
8531
8532 if ((mode >= ELM_OBJECT_SELECT_MODE_MAX) || (it->select_mode == mode))
8533 return;
8534
8535 it->select_mode = mode;
8536
8537 if ((it->select_mode == ELM_OBJECT_SELECT_MODE_NONE) ||
8538 (it->select_mode == ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY))
8539 _item_unselect(it);
8540
8541 if (it->select_mode == ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY)
8542 {
8543 it->item->mincalcd = EINA_FALSE;
8544 it->item->updateme = EINA_TRUE;
8545 if (it->item->block) it->item->block->updateme = EINA_TRUE;
8546 ecore_job_del(sd->update_job);
8547 sd->update_job = ecore_job_add(_update_job, sd->obj);
8548
8549 // reset homogeneous item size
8550 if (sd->homogeneous)
8551 {
8552 Item_Size *size =
8553 eina_hash_find(sd->size_caches, &(it->itc));
8554 if (size)
8555 eina_hash_del_by_key(sd->size_caches, it->itc);
8556 }
8557 }
8558 }
8559
8560 EOLIAN static Elm_Object_Select_Mode
_elm_genlist_item_select_mode_get(const Eo * eo_it EINA_UNUSED,Elm_Gen_Item * it)8561 _elm_genlist_item_select_mode_get(const Eo *eo_it EINA_UNUSED, Elm_Gen_Item *it)
8562 {
8563 ELM_GENLIST_ITEM_CHECK_OR_RETURN(it, ELM_OBJECT_SELECT_MODE_MAX);
8564
8565 return it->select_mode;
8566 }
8567
8568 EOLIAN Efl_Access_State_Set
_elm_genlist_item_efl_access_object_state_set_get(const Eo * eo_it,Elm_Gen_Item * it EINA_UNUSED)8569 _elm_genlist_item_efl_access_object_state_set_get(const Eo *eo_it, Elm_Gen_Item *it EINA_UNUSED)
8570 {
8571 Efl_Access_State_Set ret;
8572 Eina_Bool sel;
8573
8574 ret = efl_access_object_state_set_get(efl_super(eo_it, ELM_GENLIST_ITEM_CLASS));
8575
8576 sel = elm_obj_genlist_item_selected_get(eo_it);
8577
8578 STATE_TYPE_SET(ret, EFL_ACCESS_STATE_TYPE_SELECTABLE);
8579
8580 if (sel)
8581 STATE_TYPE_SET(ret, EFL_ACCESS_STATE_TYPE_SELECTED);
8582
8583 if (elm_genlist_item_type_get(eo_it) == ELM_GENLIST_ITEM_TREE)
8584 {
8585 STATE_TYPE_SET(ret, EFL_ACCESS_STATE_TYPE_EXPANDABLE);
8586 if (elm_genlist_item_expanded_get(eo_it))
8587 STATE_TYPE_SET(ret, EFL_ACCESS_STATE_TYPE_EXPANDED);
8588 }
8589
8590 return ret;
8591 }
8592
8593 EOLIAN const char*
_elm_genlist_item_efl_access_object_i18n_name_get(const Eo * eo_it,Elm_Gen_Item * it)8594 _elm_genlist_item_efl_access_object_i18n_name_get(const Eo *eo_it, Elm_Gen_Item *it)
8595 {
8596 const char *ret;
8597 Eina_Strbuf *buf;
8598 char *accessible_name;
8599
8600 ret = efl_access_object_i18n_name_get(efl_super(eo_it, ELM_GENLIST_ITEM_CLASS));
8601 if (ret) return ret;
8602
8603 buf = eina_strbuf_new();
8604
8605 if (it->itc->func.text_get)
8606 {
8607 Eina_List *texts;
8608 const char *key;
8609
8610 texts =
8611 elm_widget_stringlist_get(edje_object_data_get(VIEW(it), "texts"));
8612
8613 EINA_LIST_FREE(texts, key)
8614 {
8615 char *str_markup = it->itc->func.text_get
8616 ((void *)WIDGET_ITEM_DATA_GET(EO_OBJ(it)), WIDGET(it), key);
8617 char *str_utf8 = _elm_util_mkup_to_text(str_markup);
8618
8619 free(str_markup);
8620
8621 if (str_utf8)
8622 {
8623 if (eina_strbuf_length_get(buf) > 0) eina_strbuf_append(buf, ", ");
8624 eina_strbuf_append(buf, str_utf8);
8625 free(str_utf8);
8626 }
8627 }
8628 }
8629
8630 accessible_name = eina_strbuf_string_steal(buf);
8631 eina_strbuf_free(buf);
8632
8633 eina_stringshare_del(it->base->accessible_name);
8634 it->base->accessible_name = eina_stringshare_add(accessible_name);
8635 free(accessible_name);
8636 return it->base->accessible_name;
8637 }
8638
8639 EOLIAN static void
_elm_genlist_tree_effect_enabled_set(Eo * obj EINA_UNUSED,Elm_Genlist_Data * sd,Eina_Bool enabled)8640 _elm_genlist_tree_effect_enabled_set(Eo *obj EINA_UNUSED, Elm_Genlist_Data *sd, Eina_Bool enabled)
8641 {
8642 sd->tree_effect_enabled = !!enabled;
8643 }
8644
8645 EOLIAN static Eina_Bool
_elm_genlist_tree_effect_enabled_get(const Eo * obj EINA_UNUSED,Elm_Genlist_Data * sd)8646 _elm_genlist_tree_effect_enabled_get(const Eo *obj EINA_UNUSED, Elm_Genlist_Data *sd)
8647 {
8648 return sd->tree_effect_enabled;
8649 }
8650
8651 EOLIAN static void
_elm_genlist_focus_on_selection_set(Eo * obj EINA_UNUSED,Elm_Genlist_Data * sd,Eina_Bool enabled)8652 _elm_genlist_focus_on_selection_set(Eo *obj EINA_UNUSED, Elm_Genlist_Data *sd, Eina_Bool enabled)
8653 {
8654 sd->focus_on_selection_enabled = !!enabled;
8655 }
8656
8657 EOLIAN static Eina_Bool
_elm_genlist_focus_on_selection_get(const Eo * obj EINA_UNUSED,Elm_Genlist_Data * sd)8658 _elm_genlist_focus_on_selection_get(const Eo *obj EINA_UNUSED, Elm_Genlist_Data *sd)
8659 {
8660 return sd->focus_on_selection_enabled;
8661 }
8662
8663 EAPI Elm_Object_Item *
elm_genlist_nth_item_get(const Evas_Object * obj,unsigned int nth)8664 elm_genlist_nth_item_get(const Evas_Object *obj, unsigned int nth)
8665 {
8666 Elm_Gen_Item *it = NULL;
8667 Eina_Accessor *a;
8668 void *data;
8669
8670 ELM_GENLIST_CHECK(obj) NULL;
8671 ELM_GENLIST_DATA_GET(obj, sd);
8672
8673 if (!sd->items) return NULL;
8674
8675 a = eina_inlist_accessor_new(sd->items);
8676 if (!a) return NULL;
8677 if (eina_accessor_data_get(a, nth, &data))
8678 it = ELM_GEN_ITEM_FROM_INLIST(data);
8679 eina_accessor_free(a);
8680 return EO_OBJ(it);
8681 }
8682
8683 EOLIAN static Eina_Rect
_elm_genlist_efl_ui_widget_focus_highlight_geometry_get(const Eo * obj,Elm_Genlist_Data * sd)8684 _elm_genlist_efl_ui_widget_focus_highlight_geometry_get(const Eo *obj, Elm_Genlist_Data *sd)
8685 {
8686 Evas_Coord ox, oy, oh, ow, item_x = 0, item_y = 0, item_w = 0, item_h = 0;
8687 Eina_Rect r = {};
8688
8689 evas_object_geometry_get(sd->pan_obj, &ox, &oy, &ow, &oh);
8690
8691 if (sd->focused_item)
8692 {
8693 ELM_GENLIST_ITEM_DATA_GET(sd->focused_item, focus_it);
8694 evas_object_geometry_get(VIEW(focus_it), &item_x, &item_y, &item_w, &item_h);
8695 elm_widget_focus_highlight_focus_part_geometry_get(VIEW(focus_it), &item_x, &item_y, &item_w, &item_h);
8696 }
8697 else
8698 {
8699 evas_object_geometry_get(obj, &r.x, &r.y, &r.w, &r.h);
8700 return r;
8701 }
8702
8703 r.x = item_x;
8704 r.y = item_y;
8705 r.w = item_w;
8706 r.h = item_h;
8707
8708 if (item_y < oy)
8709 {
8710 r.y = oy;
8711 }
8712 if (item_y > (oy + oh - item_h))
8713 {
8714 r.y = oy + oh - item_h;
8715 }
8716
8717 if ((item_x + item_w) > (ox + ow))
8718 {
8719 r.w = ow;
8720 }
8721 if (item_x < ox)
8722 {
8723 r.x = ox;
8724 }
8725
8726 return r;
8727 }
8728
8729 EOLIAN static Elm_Object_Item *
_elm_genlist_search_by_text_item_get(Eo * obj EINA_UNUSED,Elm_Genlist_Data * sd,Elm_Object_Item * item_to_search_from,const char * part_name,const char * pattern,Elm_Glob_Match_Flags flags)8730 _elm_genlist_search_by_text_item_get(Eo *obj EINA_UNUSED,
8731 Elm_Genlist_Data *sd,
8732 Elm_Object_Item *item_to_search_from,
8733 const char *part_name,
8734 const char *pattern,
8735 Elm_Glob_Match_Flags flags)
8736 {
8737 Elm_Gen_Item *it = NULL;
8738 char *str = NULL;
8739 Eina_Inlist *start = NULL;
8740 int fnflags = 0;
8741
8742 if (!pattern) return NULL;
8743 if (!sd->items) return NULL;
8744
8745 if (flags & ELM_GLOB_MATCH_NO_ESCAPE) fnflags |= FNM_NOESCAPE;
8746 if (flags & ELM_GLOB_MATCH_PATH) fnflags |= FNM_PATHNAME;
8747 if (flags & ELM_GLOB_MATCH_PERIOD) fnflags |= FNM_PERIOD;
8748 #ifdef FNM_CASEFOLD
8749 if (flags & ELM_GLOB_MATCH_NOCASE) fnflags |= FNM_CASEFOLD;
8750 #endif
8751
8752 start = (item_to_search_from) ?
8753 EINA_INLIST_GET((Elm_Gen_Item *)efl_data_scope_get(item_to_search_from, ELM_GENLIST_ITEM_CLASS)) :
8754 sd->items;
8755 EINA_INLIST_FOREACH(start, it)
8756 {
8757 if (!it->itc->func.text_get) continue;
8758 str = it->itc->func.text_get((void *)WIDGET_ITEM_DATA_GET(EO_OBJ(it)), WIDGET(it), part_name);
8759 if (!str) continue;
8760 if (!fnmatch(pattern, str, fnflags))
8761 {
8762 free(str);
8763 return EO_OBJ(it);
8764 }
8765 free(str);
8766 }
8767 return NULL;
8768 }
8769
8770 EOLIAN static Elm_Object_Item*
_elm_genlist_elm_widget_item_container_focused_item_get(const Eo * obj EINA_UNUSED,Elm_Genlist_Data * sd)8771 _elm_genlist_elm_widget_item_container_focused_item_get(const Eo *obj EINA_UNUSED, Elm_Genlist_Data *sd)
8772 {
8773 return sd->focused_item;
8774 }
8775
8776 EOLIAN static void
_elm_genlist_elm_interface_scrollable_item_loop_enabled_set(Eo * obj EINA_UNUSED,Elm_Genlist_Data * sd,Eina_Bool enable)8777 _elm_genlist_elm_interface_scrollable_item_loop_enabled_set(Eo *obj EINA_UNUSED, Elm_Genlist_Data *sd, Eina_Bool enable)
8778 {
8779 sd->item_loop_enable = !!enable;
8780 }
8781
8782 EOLIAN static Eina_Bool
_elm_genlist_elm_interface_scrollable_item_loop_enabled_get(const Eo * obj EINA_UNUSED,Elm_Genlist_Data * sd)8783 _elm_genlist_elm_interface_scrollable_item_loop_enabled_get(const Eo *obj EINA_UNUSED, Elm_Genlist_Data *sd)
8784 {
8785 return sd->item_loop_enable;
8786 }
8787
8788 EOLIAN static void
_elm_genlist_class_constructor(Efl_Class * klass)8789 _elm_genlist_class_constructor(Efl_Class *klass)
8790 {
8791 if (_elm_config->access_mode)
8792 _elm_genlist_smart_focus_next_enable = EINA_TRUE;
8793
8794 evas_smart_legacy_type_register(MY_CLASS_NAME_LEGACY, klass);
8795 }
8796
8797 EOLIAN const Efl_Access_Action_Data *
_elm_genlist_efl_access_widget_action_elm_actions_get(const Eo * obj EINA_UNUSED,Elm_Genlist_Data * pd EINA_UNUSED)8798 _elm_genlist_efl_access_widget_action_elm_actions_get(const Eo *obj EINA_UNUSED, Elm_Genlist_Data *pd EINA_UNUSED)
8799 {
8800 static Efl_Access_Action_Data atspi_actions[] = {
8801 { "move,prior", "move", "prior", _key_action_move},
8802 { "move,next", "move", "next", _key_action_move},
8803 { "move,left", "move", "left", _key_action_move},
8804 { "move,right", "move", "right", _key_action_move},
8805 { "move,up", "move", "up", _key_action_move},
8806 { "move,up,multi", "move", "up_multi", _key_action_move},
8807 { "move,down", "move", "down", _key_action_move},
8808 { "move,down,multi", "move", "down_multi", _key_action_move},
8809 { "move,first", "move", "first", _key_action_move},
8810 { "move,last", "move", "last", _key_action_move},
8811 { "select", "select", NULL, _key_action_select},
8812 { "select,multi", "select", "multi", _key_action_select},
8813 { "escape", "escape", NULL, _key_action_escape},
8814 { NULL, NULL, NULL, NULL }
8815 };
8816 return &atspi_actions[0];
8817 }
8818
8819 EOLIAN Eina_List*
_elm_genlist_efl_access_object_access_children_get(const Eo * obj,Elm_Genlist_Data * sd)8820 _elm_genlist_efl_access_object_access_children_get(const Eo *obj, Elm_Genlist_Data *sd)
8821 {
8822 Eina_List *ret = NULL, *ret2 = NULL;
8823 Elm_Gen_Item *it;
8824
8825 EINA_INLIST_FOREACH(sd->items, it)
8826 ret = eina_list_append(ret, EO_OBJ(it));
8827
8828 ret2 = efl_access_object_access_children_get(efl_super(obj, ELM_GENLIST_CLASS));
8829
8830 return eina_list_merge(ret, ret2);
8831 }
8832
8833 EOLIAN Efl_Access_State_Set
_elm_genlist_efl_access_object_state_set_get(const Eo * obj,Elm_Genlist_Data * sd EINA_UNUSED)8834 _elm_genlist_efl_access_object_state_set_get(const Eo *obj, Elm_Genlist_Data *sd EINA_UNUSED)
8835 {
8836 Efl_Access_State_Set ret;
8837
8838 ret = efl_access_object_state_set_get(efl_super(obj, ELM_GENLIST_CLASS));
8839
8840 STATE_TYPE_SET(ret, EFL_ACCESS_STATE_TYPE_MANAGES_DESCENDANTS);
8841
8842 if (elm_genlist_multi_select_get(obj))
8843 STATE_TYPE_SET(ret, EFL_ACCESS_STATE_TYPE_MULTISELECTABLE);
8844
8845 if (elm_genlist_reorder_mode_get(obj))
8846 STATE_TYPE_SET(ret, EFL_ACCESS_STATE_TYPE_ANIMATED);
8847
8848 return ret;
8849 }
8850
8851 EOLIAN int
_elm_genlist_efl_access_selection_selected_children_count_get(const Eo * objm EINA_UNUSED,Elm_Genlist_Data * pd)8852 _elm_genlist_efl_access_selection_selected_children_count_get(const Eo *objm EINA_UNUSED, Elm_Genlist_Data *pd)
8853 {
8854 return eina_list_count(pd->selected);
8855 }
8856
8857 EOLIAN Eo*
_elm_genlist_efl_access_selection_selected_child_get(const Eo * obj EINA_UNUSED,Elm_Genlist_Data * pd,int child_idx)8858 _elm_genlist_efl_access_selection_selected_child_get(const Eo *obj EINA_UNUSED, Elm_Genlist_Data *pd, int child_idx)
8859 {
8860 return eina_list_nth(pd->selected, child_idx);
8861 }
8862
8863 EOLIAN Eina_Bool
_elm_genlist_efl_access_selection_child_select(Eo * obj EINA_UNUSED,Elm_Genlist_Data * pd,int child_index)8864 _elm_genlist_efl_access_selection_child_select(Eo *obj EINA_UNUSED, Elm_Genlist_Data *pd, int child_index)
8865 {
8866 Elm_Gen_Item *item;
8867 if (pd->select_mode != ELM_OBJECT_SELECT_MODE_NONE)
8868 {
8869 EINA_INLIST_FOREACH(pd->items, item)
8870 {
8871 if (child_index-- == 0)
8872 {
8873 elm_genlist_item_selected_set(EO_OBJ(item), EINA_TRUE);
8874 return EINA_TRUE;
8875 }
8876 }
8877 }
8878 return EINA_FALSE;
8879 }
8880
8881 EOLIAN Eina_Bool
_elm_genlist_efl_access_selection_selected_child_deselect(Eo * obj EINA_UNUSED,Elm_Genlist_Data * pd,int child_index)8882 _elm_genlist_efl_access_selection_selected_child_deselect(Eo *obj EINA_UNUSED, Elm_Genlist_Data *pd, int child_index)
8883 {
8884 Eo *item;
8885 Eina_List *l;
8886
8887 EINA_LIST_FOREACH(pd->selected, l, item)
8888 {
8889 if (child_index-- == 0)
8890 {
8891 elm_genlist_item_selected_set(item, EINA_FALSE);
8892 return EINA_TRUE;
8893 }
8894 }
8895 return EINA_FALSE;
8896 }
8897
8898 EOLIAN Eina_Bool
_elm_genlist_efl_access_selection_is_child_selected(Eo * obj EINA_UNUSED,Elm_Genlist_Data * pd,int child_index)8899 _elm_genlist_efl_access_selection_is_child_selected(Eo *obj EINA_UNUSED, Elm_Genlist_Data *pd, int child_index)
8900 {
8901 Elm_Gen_Item *item;
8902
8903 EINA_INLIST_FOREACH(pd->items, item)
8904 {
8905 if (child_index-- == 0)
8906 {
8907 return elm_genlist_item_selected_get(EO_OBJ(item));
8908 }
8909 }
8910 return EINA_FALSE;
8911 }
8912
8913 EOLIAN Eina_Bool
_elm_genlist_efl_access_selection_all_children_select(Eo * obj,Elm_Genlist_Data * pd)8914 _elm_genlist_efl_access_selection_all_children_select(Eo *obj, Elm_Genlist_Data *pd)
8915 {
8916 Elm_Gen_Item *item;
8917
8918 if (!elm_genlist_multi_select_get(obj))
8919 return EINA_FALSE;
8920
8921 EINA_INLIST_FOREACH(pd->items, item)
8922 elm_genlist_item_selected_set(EO_OBJ(item), EINA_TRUE);
8923
8924 return EINA_TRUE;
8925 }
8926
8927 EOLIAN Eina_Bool
_elm_genlist_efl_access_selection_access_selection_clear(Eo * obj EINA_UNUSED,Elm_Genlist_Data * pd)8928 _elm_genlist_efl_access_selection_access_selection_clear(Eo *obj EINA_UNUSED, Elm_Genlist_Data *pd)
8929 {
8930 return _all_items_deselect(pd);
8931 }
8932
8933 EOLIAN Eina_Bool
_elm_genlist_efl_access_selection_child_deselect(Eo * obj EINA_UNUSED,Elm_Genlist_Data * pd,int child_index)8934 _elm_genlist_efl_access_selection_child_deselect(Eo *obj EINA_UNUSED, Elm_Genlist_Data *pd, int child_index)
8935 {
8936 Elm_Gen_Item *item;
8937 if (pd->select_mode != ELM_OBJECT_SELECT_MODE_NONE)
8938 {
8939 EINA_INLIST_FOREACH(pd->items, item)
8940 {
8941 if (child_index-- == 0)
8942 {
8943 elm_genlist_item_selected_set(EO_OBJ(item), EINA_FALSE);
8944 return EINA_TRUE;
8945 }
8946 }
8947 }
8948 return EINA_FALSE;
8949 }
8950
8951 EOLIAN static Efl_Object*
_elm_genlist_efl_object_provider_find(const Eo * obj,Elm_Genlist_Data * pd,const Efl_Object * klass)8952 _elm_genlist_efl_object_provider_find(const Eo *obj, Elm_Genlist_Data *pd, const Efl_Object *klass)
8953 {
8954 if (klass == EFL_UI_FOCUS_PARENT_PROVIDER_INTERFACE)
8955 return pd->provider;
8956 return efl_provider_find(efl_super(obj, ELM_GENLIST_CLASS), klass);
8957 }
8958
8959 EOLIAN static void
_elm_genlist_item_efl_ui_focus_object_setup_order_non_recursive(Eo * obj,Elm_Gen_Item * pd)8960 _elm_genlist_item_efl_ui_focus_object_setup_order_non_recursive(Eo *obj, Elm_Gen_Item *pd)
8961 {
8962 Eina_List *n;
8963 Efl_Ui_Widget *wid;
8964
8965 EINA_LIST_FOREACH(pd->contents, n, wid)
8966 {
8967 if (efl_isa(wid, EFL_UI_WIDGET_CLASS))
8968 _elm_widget_full_eval(wid);
8969 }
8970
8971 if (pd->realized)
8972 efl_ui_focus_object_setup_order_non_recursive(efl_super(obj, ELM_GENLIST_ITEM_CLASS));
8973 }
8974
8975 EOLIAN static Eina_Bool
_elm_genlist_efl_ui_widget_focus_state_apply(Eo * obj,Elm_Genlist_Data * pd EINA_UNUSED,Efl_Ui_Widget_Focus_State current_state,Efl_Ui_Widget_Focus_State * configured_state,Efl_Ui_Widget * redirect EINA_UNUSED)8976 _elm_genlist_efl_ui_widget_focus_state_apply(Eo *obj, Elm_Genlist_Data *pd EINA_UNUSED, Efl_Ui_Widget_Focus_State current_state, Efl_Ui_Widget_Focus_State *configured_state, Efl_Ui_Widget *redirect EINA_UNUSED)
8977 {
8978 return efl_ui_widget_focus_state_apply(efl_super(obj, MY_CLASS), current_state, configured_state, obj);
8979 }
8980
8981 EOLIAN static Efl_Ui_Focus_Object*
_elm_genlist_item_efl_ui_focus_object_focus_parent_get(const Eo * obj EINA_UNUSED,Elm_Gen_Item * pd)8982 _elm_genlist_item_efl_ui_focus_object_focus_parent_get(const Eo *obj EINA_UNUSED, Elm_Gen_Item *pd)
8983 {
8984 if (!pd->item->block) return NULL;
8985 return pd->item->block->adapter;
8986 }
8987
8988 /* Standard widget overrides */
8989
8990 ELM_WIDGET_KEY_DOWN_DEFAULT_IMPLEMENT(elm_genlist, Elm_Genlist_Data)
8991
8992 /* Internal EO APIs and hidden overrides */
8993
8994 #define ELM_GENLIST_EXTRA_OPS \
8995 EFL_CANVAS_GROUP_CALC_OPS(elm_genlist), \
8996 EFL_CANVAS_GROUP_ADD_DEL_OPS(elm_genlist)
8997
8998 #define ELM_GENLIST_PAN_EXTRA_OPS \
8999 EFL_CANVAS_GROUP_DEL_OPS(elm_genlist_pan)
9000
9001 #include "elm_genlist_eo.c"
9002 #include "elm_genlist_pan_eo.c"
9003 #include "elm_genlist_item_eo.c"
9004