1 #ifdef HAVE_CONFIG_H
2 # include "elementary_config.h"
3 #endif
4
5 #define EFL_ACCESS_OBJECT_PROTECTED
6 #define EFL_ACCESS_COMPONENT_PROTECTED
7 #define ELM_WIDGET_PROTECTED
8 #define ELM_WIDGET_ITEM_PROTECTED
9 #define EFL_INPUT_EVENT_PROTECTED
10 #define EFL_UI_L10N_PROTECTED
11 #define EFL_UI_FOCUS_OBJECT_PROTECTED
12 #define EFL_UI_WIDGET_PART_BG_PROTECTED
13 #define EFL_PART_PROTECTED
14
15 #include <Elementary.h>
16
17 #include "elm_priv.h"
18 #include "elm_widget_container.h"
19 #include "elm_interface_scrollable.h"
20 #include "elm_pan_eo.h"
21 #include "elm_part_helper.h"
22 #include "elm_widget_combobox.h"
23
24 #define MY_CLASS EFL_UI_WIDGET_CLASS
25
26 #define MY_CLASS_NAME "Efl_Ui_Widget"
27 #define MY_CLASS_NAME_LEGACY "elm_widget"
28
29 #define API_ENTRY \
30 Elm_Widget_Smart_Data *sd = NULL; \
31 if (!_elm_widget_is(obj) || \
32 (!(sd = efl_data_scope_get(obj, MY_CLASS))))
33
34 #define INTERNAL_ENTRY \
35 ELM_WIDGET_DATA_GET(obj, sd); \
36 if (!sd) return
37
38 #define ELM_WIDGET_FOCUS_GET(obj) \
39 (efl_isa(obj, EFL_UI_WIDGET_CLASS) && \
40 ((_elm_access_auto_highlight_get()) ? (elm_widget_highlight_get(obj)) : \
41 (efl_ui_focus_object_focus_get(obj))))
42
43 const char SIG_WIDGET_FOCUSED[] = "focused";
44 const char SIG_WIDGET_UNFOCUSED[] = "unfocused";
45 const char SIG_WIDGET_LANG_CHANGED[] = "language,changed";
46 const char SIG_WIDGET_ACCESS_CHANGED[] = "access,changed";
47
48 typedef struct _Elm_Event_Cb_Data Elm_Event_Cb_Data;
49 typedef struct _Elm_Label_Data Elm_Label_Data;
50 typedef struct _Elm_Translate_String_Data Elm_Translate_String_Data;
51
52 static Eina_Error _efl_ui_property_bind(Eo *widget, Eo *target, Efl_Ui_Widget_Data *pd,
53 const char *part,
54 const char *key, const char *property);
55
56 struct _Elm_Event_Cb_Data
57 {
58 Elm_Event_Cb func;
59 const void *data;
60 };
61
62 struct _Elm_Label_Data
63 {
64 const char *part;
65 const char *text;
66 };
67
68 struct _Elm_Translate_String_Data
69 {
70 EINA_INLIST;
71 Eina_Stringshare *id;
72 Eina_Stringshare *domain;
73 Eina_Stringshare *string;
74 Eina_Bool preset : 1;
75 };
76
77 /* For keeping backward compatibility (EFL 1.18 or older versions).
78 * Since EFL 1.19 which starts to use eolian_gen2, it does not convert
79 * "." to "_" among the class name. */
80 static const char *legacy_type_table[][2] =
81 {
82 { "Efl.Ui.Bg_Legacy", "Elm_Bg" },
83 { "Efl.Ui.Button_Legacy", "Elm_Button" },
84 { "Efl.Ui.Check_Legacy", "Elm_Check" },
85 { "Efl.Ui.Clock_Legacy", "Elm_Datetime" },
86 { "Efl.Ui.Flip_Legacy", "Elm_Flip" },
87 { "Efl.Ui.Frame_Legacy", "Elm_Frame" },
88 { "Efl.Ui.Image_Legacy", "Elm_Image" },
89 { "Efl.Ui.Image_Zoomable_Legacy", "Elm_Photocam" },
90 { "Efl.Ui.Layout_Legacy", "Elm_Layout" },
91 { "Efl.Ui.Panes_Legacy", "Elm_Panes" },
92 { "Efl.Ui.Progressbar_Legacy", "Elm_Progressbar" },
93 { "Efl.Ui.Radio_Legacy", "Elm_Radio" },
94 { "Efl.Ui.Video_Legacy", "Elm_Video" },
95 { "Efl.Ui.Win_Legacy", "Elm_Win" },
96 { "Efl.Ui.Win_Socket_Legacy", "Elm_Win" },
97 { "Efl.Ui.Win_Inlined_Legacy", "Elm_Win" },
98 { "Elm.Code_Widget_Legacy", "Elm_Code_Widget" },
99 { "Elm.Ctxpopup", "Elm_Ctxpopup" },
100 { "Elm.Entry", "Elm_Entry" },
101 { "Elm.Colorselector", "Elm_Colorselector" },
102 { "Elm.List", "Elm_List" },
103 { "Elm.Photo", "Elm_Photo" },
104 { "Elm.Actionslider", "Elm_Actionslider" },
105 { "Elm.Box", "Elm_Box" },
106 { "Elm.Table", "Elm_Table" },
107 { "Elm.Thumb", "Elm_Thumb" },
108 { "Elm.Menu", "Elm_Menu" },
109 { "Elm.Icon", "Elm_Icon" },
110 { "Elm.Prefs", "Elm_Prefs" },
111 { "Elm.Map", "Elm_Map" },
112 { "Elm.Glview", "Elm_Glview" },
113 { "Elm.Web", "Elm_Web" },
114 { "Elm.Toolbar", "Elm_Toolbar" },
115 { "Elm.Grid", "Elm_Grid" },
116 { "Elm.Diskselector", "Elm_Diskselector" },
117 { "Elm.Notify", "Elm_Notify" },
118 { "Elm.Mapbuf", "Elm_Mapbuf" },
119 { "Elm.Separator", "Elm_Separator" },
120 { "Elm.Calendar", "Elm_Calendar" },
121 { "Elm.Inwin", "Elm_Inwin" },
122 { "Elm.Gengrid", "Elm_Gengrid" },
123 { "Elm.Scroller", "Elm_Scroller" },
124 { "Elm.Player", "Elm_Player" },
125 { "Elm.Segment_Control", "Elm_Segment_Control" },
126 { "Elm.Fileselector", "Elm_Fileselector" },
127 { "Elm.Fileselector_Button", "Elm_Fileselector_Button" },
128 { "Elm.Fileselector_Entry", "Elm_Fileselector_Entry" },
129 { "Elm.Flipselector", "Elm_Flipselector" },
130 { "Elm.Hoversel", "Elm_Hoversel" },
131 { "Elm.Naviframe", "Elm_Naviframe" },
132 { "Elm.Popup", "Elm_Popup" },
133 { "Elm.Bubble", "Elm_Bubble" },
134 { "Elm.Clock", "Elm_Clock" },
135 { "Elm.Conformant", "Elm_Conformant" },
136 { "Elm.Dayselector", "Elm_Dayselector" },
137 { "Elm.Genlist", "Elm_Genlist" },
138 { "Elm.Hover", "Elm_Hover" },
139 { "Elm.Index", "Elm_Index" },
140 { "Elm.Label", "Elm_Label" },
141 { "Elm.Panel", "Elm_Panel" },
142 { "Elm.Slider", "Elm_Slider" },
143 { "Elm.Slideshow", "Elm_Slideshow" },
144 { "Elm.Spinner", "Elm_Spinner" },
145 { "Elm.Plug", "Elm_Plug" },
146 { "Elm.Web.None", "Elm_Web" },
147 { "Elm.Multibuttonentry", "Elm_Multibuttonentry" },
148 { NULL, NULL }
149 };
150
151 /* local subsystem globals */
152 static inline Eina_Bool
_elm_widget_is(const Evas_Object * obj)153 _elm_widget_is(const Evas_Object *obj)
154 {
155 return efl_isa(obj, MY_CLASS);
156 }
157
158 static inline Eina_Bool
_is_focusable(Evas_Object * obj)159 _is_focusable(Evas_Object *obj)
160 {
161 API_ENTRY return EINA_FALSE;
162 return sd->can_focus || (sd->logical.child_count > 0);
163 }
164
165 static inline Eina_Bool
_is_focused(Evas_Object * obj)166 _is_focused(Evas_Object *obj)
167 {
168 API_ENTRY return EINA_FALSE;
169 return sd->focused;
170 }
171
172 static inline Eina_Bool
_elm_scrollable_is(const Evas_Object * obj)173 _elm_scrollable_is(const Evas_Object *obj)
174 {
175 INTERNAL_ENTRY EINA_FALSE;
176 if (elm_widget_is_legacy(obj))
177 return
178 efl_isa(obj, ELM_INTERFACE_SCROLLABLE_MIXIN);
179 else
180 return
181 efl_isa(obj, EFL_UI_SCROLLABLE_INTERFACE);
182 }
183
184 static void
185 _on_sub_obj_del(void *data, const Efl_Event *event);
186 static void _propagate_event(void *data, const Efl_Event *eo_event);
187 static void _elm_widget_shadow_update(Efl_Ui_Widget *obj);
188
189 EFL_CALLBACKS_ARRAY_DEFINE(efl_subitems_callbacks,
190 { EFL_EVENT_DEL, _on_sub_obj_del });
191 EFL_CALLBACKS_ARRAY_DEFINE(focus_callbacks,
192 { EFL_EVENT_KEY_DOWN, _propagate_event },
193 { EFL_EVENT_KEY_UP, _propagate_event },
194 { EFL_EVENT_POINTER_WHEEL, _propagate_event });
195
196 static inline void
_callbacks_add(Eo * widget,void * data)197 _callbacks_add(Eo *widget, void *data)
198 {
199 efl_event_callback_array_add(widget, efl_subitems_callbacks(), data);
200 }
201
202 static inline void
_callbacks_del(Eo * widget,void * data)203 _callbacks_del(Eo *widget, void *data)
204 {
205 efl_event_callback_array_del(widget, efl_subitems_callbacks(), data);
206 }
207
208 void
_elm_widget_item_highlight_in_theme(Evas_Object * obj,Elm_Object_Item * eo_it)209 _elm_widget_item_highlight_in_theme(Evas_Object *obj, Elm_Object_Item *eo_it)
210 {
211 const char *str;
212
213 if (!eo_it) return;
214 if (efl_isa(eo_it, ELM_WIDGET_ITEM_CLASS))
215 {
216 Elm_Widget_Item_Data *it = efl_data_scope_get(eo_it, ELM_WIDGET_ITEM_CLASS);
217
218 if (efl_isa(it->view, EFL_UI_LAYOUT_BASE_CLASS))
219 str = edje_object_data_get(elm_layout_edje_get(it->view), "focus_highlight");
220 else
221 str = edje_object_data_get(it->view, "focus_highlight");
222 }
223 else
224 str = edje_object_data_get(((Elm_Widget_Item_Data *)eo_it)->view, "focus_highlight");
225 if ((str) && (!strcmp(str, "on")))
226 elm_widget_highlight_in_theme_set(obj, EINA_TRUE);
227 else
228 elm_widget_highlight_in_theme_set(obj, EINA_FALSE);
229 }
230
231 void
_elm_widget_focus_highlight_start(const Evas_Object * obj)232 _elm_widget_focus_highlight_start(const Evas_Object *obj)
233 {
234 Evas_Object *top = efl_provider_find(obj, EFL_UI_WIN_CLASS);
235
236 EINA_SAFETY_ON_FALSE_RETURN(efl_isa(top, EFL_UI_WIN_CLASS));
237
238 _elm_win_focus_highlight_start(top);
239 }
240
241 Evas_Object *
_efl_ui_widget_focus_highlight_object_get(const Evas_Object * obj)242 _efl_ui_widget_focus_highlight_object_get(const Evas_Object *obj)
243 {
244 Evas_Object *top = efl_provider_find(obj, EFL_UI_WIN_CLASS);
245
246 EINA_SAFETY_ON_FALSE_RETURN_VAL(efl_isa(top, EFL_UI_WIN_CLASS), NULL);
247
248 return _elm_win_focus_highlight_object_get(top);
249 }
250
251 static Eina_Bool
_legacy_focus_eval(Eo * obj)252 _legacy_focus_eval(Eo *obj)
253 {
254 Eina_List *lst;
255 Efl_Ui_Widget *wid = obj, *top;
256 Elm_Widget_Smart_Data *wid_pd;
257
258 wid_pd = efl_data_scope_get(wid, MY_CLASS);
259 do {
260
261 top = wid;
262
263 wid = elm_widget_parent_get(wid);
264 if (!wid) break;
265 wid_pd = efl_data_scope_get(wid, MY_CLASS);
266
267 lst = wid_pd->legacy_focus.custom_chain;
268 if (lst)
269 {
270 if (!eina_list_data_find(lst, top))
271 {
272 WRN("Widget %p disabled due to custom chain of %p", top, wid);
273 return EINA_TRUE;
274 }
275 }
276
277 } while (1);
278
279 return !efl_isa(top, EFL_UI_WIN_CLASS);
280 }
281
282 static void _full_eval(Eo *obj, Elm_Widget_Smart_Data *pd);
283
284 static Efl_Ui_Focus_Object*
_focus_manager_eval(Eo * obj,Elm_Widget_Smart_Data * pd)285 _focus_manager_eval(Eo *obj, Elm_Widget_Smart_Data *pd)
286 {
287 Evas_Object *provider = NULL;
288 Evas_Object *parent;
289 Efl_Ui_Focus_Manager *new = NULL, *old = NULL;
290
291 parent = elm_widget_parent_get(obj);
292 if (efl_isa(parent, EFL_UI_FOCUS_MANAGER_INTERFACE))
293 {
294 new = parent;
295 }
296 else if (parent)
297 {
298 new = efl_ui_focus_object_focus_manager_get(parent);
299 provider = parent;
300 }
301
302 if (new != pd->manager.manager)
303 {
304 old = pd->manager.manager;
305
306 pd->manager.manager = new;
307 pd->manager.provider = provider;
308 }
309
310 return old;
311 }
312
313 EOLIAN static Eina_Bool
_efl_ui_widget_focus_state_apply(Eo * obj,Elm_Widget_Smart_Data * pd EINA_UNUSED,Efl_Ui_Widget_Focus_State current_state,Efl_Ui_Widget_Focus_State * configured_state,Efl_Ui_Widget * redirect)314 _efl_ui_widget_focus_state_apply(Eo *obj, Elm_Widget_Smart_Data *pd EINA_UNUSED, Efl_Ui_Widget_Focus_State current_state, Efl_Ui_Widget_Focus_State *configured_state, Efl_Ui_Widget *redirect)
315 {
316 Eina_Bool registered = EINA_TRUE;
317
318 //shortcut for having the same configurations
319 if (current_state.manager == configured_state->manager && !current_state.manager)
320 return !!current_state.manager;
321
322 if (configured_state->logical == current_state.logical &&
323 configured_state->manager == current_state.manager &&
324 configured_state->parent == current_state.parent)
325 return !!current_state.manager;
326
327 //this thing doesnt want to be registered, but it is ...
328 if (!configured_state->manager && current_state.manager)
329 {
330 efl_ui_focus_manager_calc_unregister(current_state.manager, obj);
331 return EINA_FALSE;
332 }
333 //by that point we have always a configured manager
334
335 if (!current_state.manager) registered = EINA_FALSE;
336
337 if ((//check if we have changed the manager
338 (current_state.manager != configured_state->manager) ||
339 //check if we are already registered but in a different state
340 (current_state.logical != configured_state->logical))
341 && registered)
342 {
343 //we need to unregister here
344 efl_ui_focus_manager_calc_unregister(current_state.manager, obj);
345 registered = EINA_FALSE;
346 }
347
348 //the parent may has changed
349 if (current_state.parent != configured_state->parent && registered)
350 {
351 return efl_ui_focus_manager_calc_update_parent(current_state.manager, obj, configured_state->parent);
352 }
353
354 if (!registered)
355 {
356 if (configured_state->logical)
357 return efl_ui_focus_manager_calc_register_logical(configured_state->manager, obj, configured_state->parent, redirect);
358 else
359 return efl_ui_focus_manager_calc_register(configured_state->manager, obj, configured_state->parent, redirect);
360 }
361 ERR("Uncaught focus state consider this as unregistered (%d) \n (%p,%p,%d) \n (%p,%p,%d) ", registered,
362 configured_state->manager, configured_state->parent, configured_state->logical,
363 current_state.manager, current_state.parent, current_state.logical
364 );
365 return EINA_FALSE;
366 }
367 static void
_eval_registration_candidate(Eo * obj,Elm_Widget_Smart_Data * pd,Eina_Bool * should,Eina_Bool * want_full)368 _eval_registration_candidate(Eo *obj, Elm_Widget_Smart_Data *pd, Eina_Bool *should, Eina_Bool *want_full)
369 {
370 *should = *want_full = EINA_FALSE;
371
372 //can focus can be overridden by the following properties
373 if ((!pd->parent_obj) ||
374 (!evas_object_visible_get(obj)) ||
375 pd->disabled > 0 ||
376 pd->tree_unfocusable > 0)
377 return;
378
379 if (!pd->shared_win_data || ((Efl_Ui_Shared_Win_Data*)pd->shared_win_data)->legacy_focus_api_used)
380 {
381 if (_legacy_focus_eval(obj))
382 return;
383 }
384
385 if (pd->can_focus)
386 {
387 *should = *want_full = EINA_TRUE;
388 }
389 else if (pd->logical.child_count > 0)
390 {
391 *should = EINA_TRUE;
392 }
393 }
394
395 static void
_focus_state_eval(Eo * obj,Elm_Widget_Smart_Data * pd,Eina_Bool should,Eina_Bool want_full)396 _focus_state_eval(Eo *obj, Elm_Widget_Smart_Data *pd, Eina_Bool should, Eina_Bool want_full)
397 {
398 Efl_Ui_Widget_Focus_State configuration;
399
400 //this would mean we are registering again the root, we dont want that
401 if (pd->manager.manager == obj) return;
402
403 //there are two reasons to be registered, the child count is bigger than 0, or the widget is flagged to be able to handle focus
404 if (should)
405 {
406 configuration.parent = pd->logical.parent;
407 configuration.manager = pd->manager.manager;
408 configuration.logical = !want_full;
409 }
410 else
411 {
412 configuration.parent = NULL;
413 configuration.manager = NULL;
414 configuration.logical = EINA_FALSE;
415 }
416
417 if (!efl_ui_widget_focus_state_apply(obj, pd->focus, &configuration, NULL))
418 {
419 //things went wrong or this thing is unregistered. Purge the current configuration.
420 pd->focus.manager = NULL;
421 pd->focus.parent = NULL;
422 pd->focus.logical = EINA_FALSE;
423 }
424 else
425 {
426 pd->focus.parent = configuration.parent;
427 pd->focus.manager = configuration.manager;
428 pd->focus.logical = configuration.logical;
429 }
430
431 }
432
433 static Efl_Ui_Focus_Object*
_logical_parent_eval(Eo * obj EINA_UNUSED,Elm_Widget_Smart_Data * pd,Eina_Bool should,Eina_Bool * state_change_to_parent)434 _logical_parent_eval(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *pd, Eina_Bool should, Eina_Bool *state_change_to_parent)
435 {
436 Efl_Ui_Widget *parent;
437 Efl_Ui_Focus_Parent_Provider *provider;
438
439 if (!pd->shared_win_data || ((Efl_Ui_Shared_Win_Data*)pd->shared_win_data)->custom_parent_provider)
440 {
441 if (should)
442 {
443 provider = efl_provider_find(obj, EFL_UI_FOCUS_PARENT_PROVIDER_INTERFACE);
444 EINA_SAFETY_ON_NULL_RETURN_VAL(provider, NULL);
445 parent = efl_ui_focus_parent_provider_find_logical_parent(provider, obj);
446 }
447 else
448 parent = NULL;
449 }
450 else
451 {
452 parent = efl_ui_widget_parent_get(obj);
453 }
454
455
456 if (pd->logical.parent != parent)
457 {
458 Efl_Ui_Focus_Object *old = NULL;
459
460 //update old logical parent;
461 if (pd->logical.parent)
462 {
463 if (efl_isa(pd->logical.parent, EFL_UI_WIDGET_CLASS))
464 {
465 ELM_WIDGET_DATA_GET_OR_RETURN(pd->logical.parent, logical_wd, NULL);
466 logical_wd->logical.child_count --;
467 if (logical_wd->logical.child_count == 0)
468 {
469 *state_change_to_parent = EINA_TRUE;
470 }
471 }
472 old = pd->logical.parent;
473 efl_weak_unref(&pd->logical.parent);
474 pd->logical.parent = NULL;
475 }
476 if (parent)
477 {
478 if (efl_isa(parent, EFL_UI_WIDGET_CLASS))
479 {
480 ELM_WIDGET_DATA_GET_OR_RETURN(parent, parent_wd, NULL);
481 parent_wd->logical.child_count ++;
482 if (parent_wd->logical.child_count == 1)
483 {
484 *state_change_to_parent = EINA_TRUE;
485 }
486 }
487 pd->logical.parent = parent;
488 efl_weak_ref(&pd->logical.parent);
489 }
490 return old;
491 }
492 return NULL;
493 }
494
495 static void
_full_eval(Eo * obj,Elm_Widget_Smart_Data * pd)496 _full_eval(Eo *obj, Elm_Widget_Smart_Data *pd)
497 {
498 Efl_Ui_Focus_Object *old_parent;
499 Efl_Ui_Focus_Object *old_registered_parent, *old_registered_manager;
500 Eina_Bool should, want_full, state_change_to_parent = EINA_FALSE;
501
502 _eval_registration_candidate(obj, pd, &should, &want_full);
503
504 old_parent = _logical_parent_eval(obj, pd, should, &state_change_to_parent);
505
506 if (state_change_to_parent)
507 {
508 if (efl_isa(old_parent, EFL_UI_WIDGET_CLASS))
509 {
510 //emit signal and focus eval old and new
511 ELM_WIDGET_DATA_GET(old_parent, old_pd);
512 if (old_pd) _full_eval(old_parent, old_pd);
513 }
514
515 if (efl_isa(pd->logical.parent, EFL_UI_WIDGET_CLASS))
516 {
517 ELM_WIDGET_DATA_GET(pd->logical.parent, new_pd);
518 if (new_pd) _full_eval(pd->logical.parent, new_pd);
519 }
520 }
521
522
523 _focus_manager_eval(obj, pd);
524
525 old_registered_parent = pd->focus.parent;
526 old_registered_manager = pd->focus.manager;
527
528 _focus_state_eval(obj, pd, should, want_full);
529
530 if (old_registered_parent != pd->focus.parent)
531 {
532 efl_event_callback_call(obj,
533 EFL_UI_FOCUS_OBJECT_EVENT_FOCUS_PARENT_CHANGED, old_registered_parent);
534 }
535
536 if (old_registered_manager != pd->focus.manager)
537 {
538 _elm_widget_full_eval_children(obj, pd);
539 efl_event_callback_call(obj,
540 EFL_UI_FOCUS_OBJECT_EVENT_FOCUS_MANAGER_CHANGED, old_registered_manager);
541 }
542
543 }
544
545 void
_elm_widget_full_eval(Eo * obj)546 _elm_widget_full_eval(Eo *obj)
547 {
548 ELM_WIDGET_DATA_GET(obj, pd);
549 if (pd) _full_eval(obj, pd);
550 }
551
552 /**
553 * @internal
554 *
555 * Resets the mirrored mode from the system mirror mode for widgets that are in
556 * automatic mirroring mode. This function does not call elm_widget_theme.
557 *
558 * @param obj The widget.
559 * @param mirrored EINA_TRUE to set mirrored mode. EINA_FALSE to unset.
560 */
561 static void
_elm_widget_mirrored_reload(Evas_Object * obj)562 _elm_widget_mirrored_reload(Evas_Object *obj)
563 {
564 API_ENTRY return;
565 Eina_Bool mirrored = elm_config_mirrored_get();
566
567 if (efl_ui_mirrored_automatic_get(obj) && (sd->is_mirrored != mirrored))
568 {
569 sd->is_mirrored = mirrored;
570 }
571 }
572
573 static void
_parents_focus(Evas_Object * obj)574 _parents_focus(Evas_Object *obj)
575 {
576 for (; obj; obj = elm_widget_parent_get(obj))
577 {
578 INTERNAL_ENTRY;
579 if (sd->focused) return;
580 sd->focused = 1;
581 }
582 }
583
584 static void
_parents_unfocus(Evas_Object * obj)585 _parents_unfocus(Evas_Object *obj)
586 {
587 for (; obj; obj = elm_widget_parent_get(obj))
588 {
589 INTERNAL_ENTRY;
590 if (!sd->focused) return;
591 sd->focused = 0;
592 }
593 }
594
595 static void
_on_sub_obj_del(void * data,const Efl_Event * event)596 _on_sub_obj_del(void *data, const Efl_Event *event)
597 {
598 ELM_WIDGET_DATA_GET_OR_RETURN(data, sd);
599
600 if (_elm_widget_is(event->object))
601 {
602 if (_is_focused(event->object)) _parents_unfocus(data);
603 }
604 if (event->object == sd->resize_obj)
605 {
606 /* already dels sub object */
607 elm_widget_resize_object_set(data, NULL);
608 }
609 else if (event->object == sd->hover_obj)
610 {
611 sd->hover_obj = NULL;
612 }
613 else
614 {
615 if (!elm_widget_sub_object_del(data, event->object))
616 ERR("failed to remove sub object %p from %p\n", event->object, data);
617 }
618 }
619
620 static const Evas_Smart_Cb_Description _smart_callbacks[] =
621 {
622 {SIG_WIDGET_FOCUSED, ""},
623 {SIG_WIDGET_UNFOCUSED, ""},
624 {SIG_WIDGET_LANG_CHANGED, ""},
625 {SIG_WIDGET_ACCESS_CHANGED, ""},
626 {NULL, NULL}
627 };
628
629 static void
_obj_mouse_down(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info)630 _obj_mouse_down(void *data,
631 Evas *e EINA_UNUSED,
632 Evas_Object *obj EINA_UNUSED,
633 void *event_info)
634 {
635 Evas_Object *top;
636
637 ELM_WIDGET_DATA_GET(data, sd);
638 if (!sd) return;
639 Evas_Event_Mouse_Down *ev = event_info;
640 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return;
641
642 top = elm_widget_top_get(data);
643 if (top && efl_isa(top, EFL_UI_WIN_CLASS)) _elm_win_focus_auto_hide(top);
644 sd->still_in = EINA_TRUE;
645 }
646
647 static void
_obj_mouse_move(void * data,Evas * e EINA_UNUSED,Evas_Object * obj,void * event_info)648 _obj_mouse_move(void *data,
649 Evas *e EINA_UNUSED,
650 Evas_Object *obj,
651 void *event_info)
652 {
653 ELM_WIDGET_DATA_GET(data, sd);
654 if (!sd) return;
655 Evas_Event_Mouse_Move *ev = event_info;
656 if (!sd->still_in) return;
657
658 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
659 sd->still_in = EINA_FALSE;
660 else
661 {
662 Evas_Coord x, y, w, h;
663 evas_object_geometry_get(obj, &x, &y, &w, &h);
664 if (ELM_RECTS_POINT_OUT(x, y, w, h, ev->cur.canvas.x, ev->cur.canvas.y))
665 sd->still_in = EINA_FALSE;
666 }
667 }
668
669 static void
_obj_mouse_up(void * data,Evas * e EINA_UNUSED,Evas_Object * obj,void * event_info)670 _obj_mouse_up(void *data,
671 Evas *e EINA_UNUSED,
672 Evas_Object *obj,
673 void *event_info)
674 {
675 ELM_WIDGET_DATA_GET(data, sd);
676 if (!sd) return;
677 Evas_Event_Mouse_Up *ev = event_info;
678
679 if (sd->still_in && (ev->flags == EVAS_BUTTON_NONE) &&
680 (sd->focus_move_policy == ELM_FOCUS_MOVE_POLICY_CLICK) &&
681 !efl_invalidated_get(data))
682 elm_widget_focus_mouse_up_handle(evas_object_widget_parent_find(obj));
683
684 sd->still_in = EINA_FALSE;
685 }
686
687 static void
_obj_mouse_in(void * data,Evas * e EINA_UNUSED,Evas_Object * obj,void * event_info EINA_UNUSED)688 _obj_mouse_in(void *data,
689 Evas *e EINA_UNUSED,
690 Evas_Object *obj,
691 void *event_info EINA_UNUSED)
692 {
693 ELM_WIDGET_DATA_GET(data, sd);
694 if (!sd) return;
695 if (sd->focus_move_policy == ELM_FOCUS_MOVE_POLICY_IN &&
696 !efl_invalidated_get(data))
697 elm_widget_focus_mouse_up_handle(evas_object_widget_parent_find(obj));
698 }
699
700 EOLIAN static void
_efl_ui_widget_efl_canvas_group_group_add(Eo * obj,Elm_Widget_Smart_Data * priv)701 _efl_ui_widget_efl_canvas_group_group_add(Eo *obj, Elm_Widget_Smart_Data *priv)
702 {
703 priv->mirrored_auto_mode = EINA_TRUE; /* will follow system locale
704 * settings */
705 priv->focus_move_policy_auto_mode = EINA_TRUE;
706 priv->focus_region_show_mode = ELM_FOCUS_REGION_SHOW_WIDGET;
707 elm_widget_can_focus_set(obj, EINA_TRUE);
708 priv->is_mirrored = elm_config_mirrored_get();
709 priv->focus_move_policy = _elm_config->focus_move_policy;
710
711 evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_DOWN,
712 _obj_mouse_down, obj);
713 evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_MOVE,
714 _obj_mouse_move, obj);
715 evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_UP,
716 _obj_mouse_up, obj);
717 evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_IN,
718 _obj_mouse_in, obj);
719 }
720
721 static Eina_Bool
_keep(void * data,void * gdata)722 _keep(void *data, void *gdata)
723 {
724 if (data == gdata)
725 return EINA_FALSE;
726 return EINA_TRUE;
727 }
728
729 EOLIAN static void
_efl_ui_widget_efl_canvas_group_group_del(Eo * obj,Elm_Widget_Smart_Data * sd)730 _efl_ui_widget_efl_canvas_group_group_del(Eo *obj, Elm_Widget_Smart_Data *sd)
731 {
732 Evas_Object *sobj;
733 Elm_Translate_String_Data *ts;
734 Elm_Event_Cb_Data *ecb;
735
736 if (sd->hover_obj)
737 {
738 /* detach it from us */
739 _callbacks_del(sd->hover_obj, obj);
740 sd->hover_obj = NULL;
741 }
742 while(eina_array_count(sd->children))
743 {
744 sobj = eina_array_data_get(sd->children, 0);
745
746 if (!elm_widget_sub_object_del(obj, sobj))
747 {
748 ERR("failed to remove sub object %p from %p\n", sobj, obj);
749 eina_array_remove(sd->children, _keep, sobj);
750 }
751 // FIXME: is that a legacy or a new object ?
752 evas_object_del(sobj);
753 EINA_SAFETY_ON_TRUE_RETURN(eina_array_count(sd->children) && sobj == eina_array_data_get(sd->children, 0));
754 }
755 sd->tooltips = eina_list_free(sd->tooltips); /* should be empty anyway */
756 sd->cursors = eina_list_free(sd->cursors); /* should be empty anyway */
757 while (sd->translate_strings)
758 {
759 ts = EINA_INLIST_CONTAINER_GET(sd->translate_strings,
760 Elm_Translate_String_Data);
761 eina_stringshare_del(ts->id);
762 eina_stringshare_del(ts->domain);
763 eina_stringshare_del(ts->string);
764 sd->translate_strings = eina_inlist_remove(sd->translate_strings,
765 sd->translate_strings);
766 free(ts);
767 }
768
769 EINA_LIST_FREE(sd->event_cb, ecb)
770 free(ecb);
771
772 eina_stringshare_del(sd->klass);
773 eina_stringshare_del(sd->group);
774 eina_stringshare_del(sd->style);
775 if (sd->theme) elm_theme_free(sd->theme);
776 eina_stringshare_del(sd->access_info);
777 eina_stringshare_del(sd->accessible_name);
778 evas_object_smart_data_set(obj, NULL);
779 efl_canvas_group_del(efl_super(obj, MY_CLASS));
780 }
781
782 static void
_smart_reconfigure(Eo * obj,Elm_Widget_Smart_Data * sd)783 _smart_reconfigure(Eo *obj, Elm_Widget_Smart_Data *sd)
784 {
785 Eina_Rect geom = efl_gfx_entity_geometry_get(obj);
786
787 if (sd->resize_obj)
788 {
789 efl_gfx_entity_geometry_set(sd->resize_obj, geom);
790 }
791 if (sd->hover_obj)
792 {
793 efl_gfx_entity_geometry_set(sd->hover_obj, geom);
794 }
795 if (sd->bg)
796 {
797 efl_gfx_entity_geometry_set(sd->bg, geom);
798 }
799 if (sd->has_shadow)
800 _elm_widget_shadow_update(obj);
801 }
802
803 EOLIAN static void
_efl_ui_widget_efl_gfx_entity_position_set(Eo * obj EINA_UNUSED,Elm_Widget_Smart_Data * sd,Eina_Position2D pos)804 _efl_ui_widget_efl_gfx_entity_position_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, Eina_Position2D pos)
805 {
806 if (_evas_object_intercept_call(obj, EVAS_OBJECT_INTERCEPT_CB_MOVE, 0, pos.x, pos.y))
807 return;
808
809 if (sd->resize_obj)
810 efl_gfx_entity_position_set(sd->resize_obj, pos);
811 if (sd->hover_obj)
812 efl_gfx_entity_position_set(sd->hover_obj, pos);
813 if (sd->bg)
814 efl_gfx_entity_position_set(sd->bg, pos);
815
816 if (sd->has_shadow)
817 _elm_widget_shadow_update(obj);
818
819 efl_gfx_entity_position_set(efl_super(obj, MY_CLASS), pos);
820 }
821
822 EOLIAN static void
_efl_ui_widget_efl_gfx_entity_size_set(Eo * obj EINA_UNUSED,Elm_Widget_Smart_Data * sd,Eina_Size2D sz)823 _efl_ui_widget_efl_gfx_entity_size_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, Eina_Size2D sz)
824 {
825 if (_evas_object_intercept_call(obj, EVAS_OBJECT_INTERCEPT_CB_RESIZE, 0, sz.w, sz.h))
826 return;
827
828 if (sd->resize_obj)
829 efl_gfx_entity_size_set(sd->resize_obj, sz);
830 if (sd->hover_obj)
831 efl_gfx_entity_size_set(sd->hover_obj, sz);
832 if (sd->bg)
833 efl_gfx_entity_size_set(sd->bg, sz);
834
835 if (sd->has_shadow)
836 _elm_widget_shadow_update(obj);
837
838 efl_gfx_entity_size_set(efl_super(obj, MY_CLASS), sz);
839 }
840
841 void
_elm_widget_full_eval_children(Eo * obj,Elm_Widget_Smart_Data * sd)842 _elm_widget_full_eval_children(Eo *obj, Elm_Widget_Smart_Data *sd)
843 {
844 Eo *child;
845
846 _full_eval(obj, sd);
847
848 for (unsigned int i = 0; i < eina_array_count(sd->children); ++i)
849 {
850 Elm_Widget_Smart_Data *sd_child;
851 child = eina_array_data_get(sd->children, i);
852
853 if (!efl_isa(child, EFL_UI_WIDGET_CLASS)) continue;
854
855 sd_child = efl_data_scope_get(child, EFL_UI_WIDGET_CLASS);
856 _elm_widget_full_eval_children(child, sd_child);
857 }
858 }
859
860 EOLIAN static void
_efl_ui_widget_efl_gfx_entity_visible_set(Eo * obj,Elm_Widget_Smart_Data * pd,Eina_Bool vis)861 _efl_ui_widget_efl_gfx_entity_visible_set(Eo *obj, Elm_Widget_Smart_Data *pd, Eina_Bool vis)
862 {
863 Eina_Iterator *it;
864 Evas_Object *o;
865
866 if (_evas_object_intercept_call(obj, EVAS_OBJECT_INTERCEPT_CB_VISIBLE, 0, vis))
867 {
868 _elm_widget_full_eval_children(obj, pd);
869 return;
870 }
871
872 efl_gfx_entity_visible_set(efl_super(obj, MY_CLASS), vis);
873
874 _elm_widget_full_eval_children(obj, pd);
875
876
877 it = evas_object_smart_iterator_new(obj);
878 EINA_ITERATOR_FOREACH(it, o)
879 {
880 if (evas_object_data_get(o, "_elm_leaveme")) continue;
881 efl_gfx_entity_visible_set(o, vis);
882 }
883 eina_iterator_free(it);
884
885 if (!_elm_config->atspi_mode || pd->on_destroy)
886 return;
887
888 if (vis)
889 {
890 efl_access_added(obj);
891 if (_elm_widget_onscreen_is(obj))
892 efl_access_state_changed_signal_emit(obj, EFL_ACCESS_STATE_TYPE_SHOWING, EINA_TRUE);
893 }
894 else
895 {
896 efl_access_state_changed_signal_emit(obj, EFL_ACCESS_STATE_TYPE_SHOWING, EINA_FALSE);
897 }
898 }
899
900 EOLIAN static void
_efl_ui_widget_efl_gfx_color_color_set(Eo * obj,Elm_Widget_Smart_Data * pd,int r,int g,int b,int a)901 _efl_ui_widget_efl_gfx_color_color_set(Eo *obj, Elm_Widget_Smart_Data *pd, int r, int g, int b, int a)
902 {
903 Eina_Iterator *it;
904 Evas_Object *o;
905
906 if (_evas_object_intercept_call(obj, EVAS_OBJECT_INTERCEPT_CB_COLOR_SET, 0, r, g, b, a))
907 return;
908
909 efl_gfx_color_set(efl_super(obj, MY_CLASS), r, g, b, a);
910
911 it = evas_object_smart_iterator_new(obj);
912 EINA_ITERATOR_FOREACH(it, o)
913 {
914 if (pd->bg == o) continue;
915 if (evas_object_data_get(o, "_elm_leaveme")) continue;
916 evas_object_color_set(o, r, g, b, a);
917 }
918 eina_iterator_free(it);
919 }
920
921 EOLIAN static void
_efl_ui_widget_efl_canvas_object_no_render_set(Eo * obj,Elm_Widget_Smart_Data * _pd EINA_UNUSED,Eina_Bool hide)922 _efl_ui_widget_efl_canvas_object_no_render_set(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED, Eina_Bool hide)
923 {
924 Eina_Iterator *it;
925 Evas_Object *o;
926
927 hide = !!hide;
928 if (efl_canvas_object_no_render_get(obj) == hide)
929 return;
930
931 it = evas_object_smart_iterator_new(obj);
932 EINA_ITERATOR_FOREACH(it, o)
933 {
934 if (evas_object_data_get(o, "_elm_leaveme")) continue;
935 efl_canvas_object_no_render_set(o, hide);
936 }
937 eina_iterator_free(it);
938
939 // bypass implementation in Efl.Canvas.Group
940 efl_canvas_object_no_render_set(efl_super(obj, EFL_CANVAS_GROUP_CLASS), hide);
941 }
942
943 EOLIAN static void
_efl_ui_widget_efl_canvas_object_is_frame_object_set(Eo * obj,Elm_Widget_Smart_Data * pd,Eina_Bool frame)944 _efl_ui_widget_efl_canvas_object_is_frame_object_set(Eo *obj, Elm_Widget_Smart_Data *pd, Eina_Bool frame)
945 {
946 Evas_Object *o;
947
948 frame = !!frame;
949 efl_canvas_object_is_frame_object_set(efl_super(obj, MY_CLASS), frame);
950 for (unsigned int i = 0; i < eina_array_count(pd->children); ++i)
951 {
952 o = eina_array_data_get(pd->children, i);
953
954 if (evas_object_data_get(o, "_elm_leaveme")) continue;
955 efl_canvas_object_is_frame_object_set(o, frame);
956 }
957 }
958
959 EOLIAN static void
_efl_ui_widget_efl_canvas_object_clipper_set(Eo * obj,Elm_Widget_Smart_Data * _pd EINA_UNUSED,Evas_Object * clip)960 _efl_ui_widget_efl_canvas_object_clipper_set(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED, Evas_Object *clip)
961 {
962 Eina_Iterator *it;
963 Evas_Object *o;
964
965 if (_evas_object_intercept_call(obj, EVAS_OBJECT_INTERCEPT_CB_CLIP_SET, 0, clip))
966 return;
967
968 efl_canvas_object_clipper_set(efl_super(obj, MY_CLASS), clip);
969
970 it = evas_object_smart_iterator_new(obj);
971 EINA_ITERATOR_FOREACH(it, o)
972 {
973 if (evas_object_data_get(o, "_elm_leaveme")) continue;
974 evas_object_clip_set(o, clip);
975 }
976 eina_iterator_free(it);
977 }
978
979 EOLIAN static void
_efl_ui_widget_efl_canvas_group_group_calculate(Eo * obj EINA_UNUSED,Elm_Widget_Smart_Data * _pd EINA_UNUSED)980 _efl_ui_widget_efl_canvas_group_group_calculate(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd EINA_UNUSED)
981 {
982 /* a NO-OP, on the base */
983 efl_canvas_group_need_recalculate_set(obj, EINA_FALSE);
984 }
985
986 EOLIAN static void
_efl_ui_widget_efl_canvas_group_group_member_add(Eo * obj,Elm_Widget_Smart_Data * pd,Evas_Object * child)987 _efl_ui_widget_efl_canvas_group_group_member_add(Eo *obj, Elm_Widget_Smart_Data *pd, Evas_Object *child)
988 {
989 int r, g, b, a;
990 efl_canvas_group_member_add(efl_super(obj, MY_CLASS), child);
991
992 if (evas_object_data_get(child, "_elm_leaveme")) return;
993
994 if (pd->bg != child)
995 {
996 evas_object_color_get(obj, &r, &g, &b, &a);
997 evas_object_color_set(child, r, g, b, a);
998 }
999
1000 efl_canvas_object_no_render_set(child, efl_canvas_object_no_render_get(obj));
1001 evas_object_clip_set(child, evas_object_clip_get(obj));
1002
1003 if (evas_object_visible_get(obj))
1004 evas_object_show(child);
1005 else
1006 evas_object_hide(child);
1007 }
1008
1009 EOLIAN static void
_efl_ui_widget_efl_canvas_group_group_member_remove(Eo * obj EINA_UNUSED,Elm_Widget_Smart_Data * _pd EINA_UNUSED,Evas_Object * child)1010 _efl_ui_widget_efl_canvas_group_group_member_remove(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd EINA_UNUSED, Evas_Object *child)
1011 {
1012 if (!evas_object_data_get(child, "_elm_leaveme"))
1013 evas_object_clip_unset(child);
1014 efl_canvas_group_member_remove(efl_super(obj, MY_CLASS), child);
1015 }
1016
1017 // internal funcs
1018 static void
_propagate_x_drag_lock(Evas_Object * obj,int dir)1019 _propagate_x_drag_lock(Evas_Object *obj,
1020 int dir)
1021 {
1022 INTERNAL_ENTRY;
1023 if (sd->parent_obj)
1024 {
1025 ELM_WIDGET_DATA_GET(sd->parent_obj, sd2);
1026 if (sd2)
1027 {
1028 sd2->child_drag_x_locked += dir;
1029 _propagate_x_drag_lock(sd->parent_obj, dir);
1030 }
1031 }
1032 }
1033
1034 static void
_propagate_y_drag_lock(Evas_Object * obj,int dir)1035 _propagate_y_drag_lock(Evas_Object *obj,
1036 int dir)
1037 {
1038 INTERNAL_ENTRY;
1039 if (sd->parent_obj)
1040 {
1041 ELM_WIDGET_DATA_GET(sd->parent_obj, sd2);
1042 if (sd2)
1043 {
1044 sd2->child_drag_y_locked += dir;
1045 _propagate_y_drag_lock(sd->parent_obj, dir);
1046 }
1047 }
1048 }
1049
1050 static Eina_Bool
_propagate_event_legacy(Eo * parent,const Efl_Event * event,Eo * obj,Elm_Event_Cb_Data * ecd)1051 _propagate_event_legacy(Eo *parent, const Efl_Event *event, Eo *obj, Elm_Event_Cb_Data *ecd)
1052 {
1053 Evas_Callback_Type type;
1054 Evas_Event_Flags *event_flags, prev_flags;
1055 union {
1056 Evas_Event_Key_Down *down;
1057 Evas_Event_Key_Up *up;
1058 Evas_Event_Mouse_Wheel *wheel;
1059 void *any;
1060 } event_info;
1061
1062 if (event->desc == EFL_EVENT_KEY_DOWN)
1063 {
1064 event_info.down = efl_input_legacy_info_get(event->info);
1065 EINA_SAFETY_ON_NULL_RETURN_VAL(event_info.down, EINA_FALSE);
1066 type = EVAS_CALLBACK_KEY_DOWN;
1067 event_flags = &event_info.down->event_flags;
1068 }
1069 else if (event->desc == EFL_EVENT_KEY_UP)
1070 {
1071 event_info.up = efl_input_legacy_info_get(event->info);
1072 EINA_SAFETY_ON_NULL_RETURN_VAL(event_info.up, EINA_FALSE);
1073 type = EVAS_CALLBACK_KEY_UP;
1074 event_flags = &event_info.up->event_flags;
1075 }
1076 else if (event->desc == EFL_EVENT_POINTER_WHEEL)
1077 {
1078 event_info.wheel = efl_input_legacy_info_get(event->info);
1079 EINA_SAFETY_ON_NULL_RETURN_VAL(event_info.wheel, EINA_FALSE);
1080 type = EVAS_CALLBACK_MOUSE_WHEEL;
1081 event_flags = &event_info.wheel->event_flags;
1082 }
1083 else
1084 return EINA_FALSE;
1085
1086 prev_flags = *event_flags;
1087 if (ecd->func((void *)ecd->data, parent, obj, type, event_info.any) ||
1088 ((*event_flags) & EVAS_EVENT_FLAG_ON_HOLD))
1089 {
1090 if (prev_flags != *event_flags)
1091 efl_input_event_flags_set(event->info, (Efl_Input_Flags)*event_flags);
1092 return EINA_TRUE;
1093 }
1094
1095 return EINA_FALSE;
1096 }
1097
1098 /**
1099 * @internal
1100 *
1101 * If elm_widget_focus_region_get() returns an empty rect (w or h <= 0),
1102 * this function will ignore region show action.
1103 */
1104 EAPI void
elm_widget_focus_region_show(Eo * obj)1105 elm_widget_focus_region_show(Eo *obj)
1106 {
1107 Evas_Coord ox, oy;
1108 Eina_Rect r;
1109 Evas_Object *o;
1110
1111 o = elm_widget_parent_get(obj);
1112 if (!o) return;
1113
1114 r = elm_widget_focus_region_get(obj);
1115 if (eina_rectangle_is_empty(&r.rect)) return;
1116
1117 evas_object_geometry_get(obj, &ox, &oy, NULL, NULL);
1118
1119 while (o)
1120 {
1121 Evas_Coord px, py;
1122 evas_object_geometry_get(o, &px, &py, NULL, NULL);
1123
1124 if (_elm_scrollable_is(o) && !elm_widget_disabled_get(o))
1125 {
1126 Evas_Coord sx, sy;
1127 Evas_Coord vx, vy;
1128
1129 elm_interface_scrollable_content_region_get(o, &sx, &sy, NULL, NULL);
1130 elm_interface_scrollable_content_viewport_geometry_get(o, &vx, &vy, NULL, NULL);
1131
1132 // Get the object's on_focus_region position relative to the pan in the scroller.
1133 Evas_Coord rx, ry;
1134 rx = ox + r.x - vx + sx;
1135 ry = oy + r.y - vy + sy;
1136
1137 switch (_elm_config->focus_autoscroll_mode)
1138 {
1139 case ELM_FOCUS_AUTOSCROLL_MODE_SHOW:
1140 elm_interface_scrollable_content_region_show(o, rx, ry, r.w, r.h);
1141 break;
1142 case ELM_FOCUS_AUTOSCROLL_MODE_BRING_IN:
1143 elm_interface_scrollable_region_bring_in(o, rx, ry, r.w, r.h);
1144 break;
1145 default:
1146 break;
1147 }
1148
1149 r = elm_widget_focus_region_get(o);
1150 evas_object_geometry_get(o, &ox, &oy, NULL, NULL);
1151 }
1152 else
1153 {
1154 r.x += ox - px;
1155 r.y += oy - py;
1156 ox = px;
1157 oy = py;
1158 }
1159 o = elm_widget_parent_get(o);
1160 }
1161 }
1162
1163
1164 EAPI Eina_Bool
elm_widget_api_check(int ver)1165 elm_widget_api_check(int ver)
1166 {
1167 if (ver != ELM_INTERNAL_API_VERSION)
1168 {
1169 CRI("Elementary widget api versions do not match");
1170 return EINA_FALSE;
1171 }
1172 return EINA_TRUE;
1173 }
1174
1175 EAPI Eina_Bool
elm_widget_access(Evas_Object * obj,Eina_Bool is_access)1176 elm_widget_access(Evas_Object *obj,
1177 Eina_Bool is_access)
1178 {
1179 Evas_Object *child;
1180 Eina_Bool ret = EINA_TRUE;
1181
1182 API_ENTRY return EINA_FALSE;
1183 for (unsigned int i = 0; i < eina_array_count(sd->children); ++i)
1184 {
1185 child = eina_array_data_get(sd->children, i);
1186
1187 if (elm_widget_is(child))
1188 ret &= elm_widget_access(child, is_access);
1189 }
1190
1191 efl_ui_widget_on_access_update(obj, is_access);
1192 efl_event_callback_legacy_call(obj, EFL_UI_WIDGET_EVENT_ACCESS_CHANGED, NULL);
1193
1194 return ret;
1195 }
1196
1197 EOLIAN static void
_efl_ui_widget_on_access_update(Eo * obj EINA_UNUSED,Elm_Widget_Smart_Data * _pd EINA_UNUSED,Eina_Bool is_access EINA_UNUSED)1198 _efl_ui_widget_on_access_update(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd EINA_UNUSED, Eina_Bool is_access EINA_UNUSED)
1199 {
1200 }
1201
1202 static void
_elm_widget_theme_helper(Eina_Error err,Eina_Bool * err_default,Eina_Bool * err_generic)1203 _elm_widget_theme_helper(Eina_Error err, Eina_Bool *err_default, Eina_Bool *err_generic)
1204 {
1205 if (err == EFL_UI_THEME_APPLY_ERROR_DEFAULT)
1206 *err_default = EINA_TRUE;
1207 else if (err == EFL_UI_THEME_APPLY_ERROR_GENERIC)
1208 *err_generic = EINA_TRUE;
1209 }
1210
1211 EAPI Eina_Error
elm_widget_theme(Evas_Object * obj)1212 elm_widget_theme(Evas_Object *obj)
1213 {
1214 const Eina_List *l;
1215 Evas_Object *child;
1216 Elm_Tooltip *tt;
1217 Elm_Cursor *cur;
1218 Eina_Bool err_default = EINA_FALSE;
1219 Eina_Bool err_generic = EINA_FALSE;
1220
1221 API_ENTRY return EFL_UI_THEME_APPLY_ERROR_GENERIC;
1222 for (unsigned int i = 0; i < eina_array_count(sd->children); ++i)
1223 {
1224 child = eina_array_data_get(sd->children, i);
1225 if (_elm_widget_is(child))
1226 _elm_widget_theme_helper(elm_widget_theme(child), &err_default, &err_generic);
1227 }
1228
1229 if (sd->hover_obj)
1230 _elm_widget_theme_helper(elm_widget_theme(sd->hover_obj), &err_default, &err_generic);
1231
1232 EINA_LIST_FOREACH(sd->tooltips, l, tt)
1233 elm_tooltip_theme(tt);
1234 EINA_LIST_FOREACH(sd->cursors, l, cur)
1235 elm_cursor_theme(cur);
1236
1237 _elm_widget_theme_helper(efl_ui_widget_theme_apply(obj), &err_default, &err_generic);
1238 if (err_generic) return EFL_UI_THEME_APPLY_ERROR_GENERIC;
1239 if (err_default) return EFL_UI_THEME_APPLY_ERROR_DEFAULT;
1240 return EFL_UI_THEME_APPLY_ERROR_NONE;
1241 }
1242
1243 EAPI void
elm_widget_theme_specific(Evas_Object * obj,Elm_Theme * th,Eina_Bool force)1244 elm_widget_theme_specific(Evas_Object *obj,
1245 Elm_Theme *th,
1246 Eina_Bool force)
1247 {
1248 const Eina_List *l;
1249 Evas_Object *child;
1250 Elm_Tooltip *tt;
1251 Elm_Cursor *cur;
1252 Elm_Theme *th2, *thdef;
1253
1254 API_ENTRY return;
1255
1256 thdef = elm_theme_default_get();
1257 if (!th) th = thdef;
1258 if (!force)
1259 {
1260 th2 = sd->theme;
1261 if (!th2) th2 = thdef;
1262 while (th2)
1263 {
1264 if (th2 == th)
1265 {
1266 force = EINA_TRUE;
1267 break;
1268 }
1269 if (th2 == thdef) break;
1270 th2 = th2->ref_theme;
1271 if (!th2) th2 = thdef;
1272 }
1273 }
1274 if (!force) return;
1275 for (unsigned int i = 0; i < eina_array_count(sd->children); ++i)
1276 {
1277 child = eina_array_data_get(sd->children, i);
1278 if (elm_widget_is(child))
1279 elm_widget_theme_specific(child, th, force);
1280 }
1281 if (sd->hover_obj) elm_widget_theme(sd->hover_obj);
1282 EINA_LIST_FOREACH(sd->tooltips, l, tt)
1283 elm_tooltip_theme(tt);
1284 EINA_LIST_FOREACH(sd->cursors, l, cur)
1285 elm_cursor_theme(cur);
1286 efl_ui_widget_theme_apply(obj);
1287 }
1288
1289 EOLIAN static Eina_Error
_efl_ui_widget_theme_apply(Eo * obj,Elm_Widget_Smart_Data * _pd EINA_UNUSED)1290 _efl_ui_widget_theme_apply(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED)
1291 {
1292 _elm_widget_mirrored_reload(obj);
1293
1294 return EFL_UI_THEME_APPLY_ERROR_NONE;
1295 }
1296
1297 /**
1298 * @internal
1299 *
1300 * Returns the widget's mirrored mode.
1301 *
1302 * @param obj The widget.
1303 * @return mirrored mode of the object.
1304 *
1305 **/
1306 EOLIAN static Eina_Bool
_efl_ui_widget_efl_ui_i18n_mirrored_get(const Eo * obj EINA_UNUSED,Elm_Widget_Smart_Data * sd)1307 _efl_ui_widget_efl_ui_i18n_mirrored_get(const Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
1308 {
1309 return sd->is_mirrored;
1310 }
1311
1312 /**
1313 * @internal
1314 *
1315 * Sets the widget's mirrored mode.
1316 *
1317 * @param obj The widget.
1318 * @param mirrored EINA_TRUE to set mirrored mode. EINA_FALSE to unset.
1319 */
1320 EOLIAN static void
_efl_ui_widget_efl_ui_i18n_mirrored_set(Eo * obj,Elm_Widget_Smart_Data * sd,Eina_Bool mirrored)1321 _efl_ui_widget_efl_ui_i18n_mirrored_set(Eo *obj, Elm_Widget_Smart_Data *sd, Eina_Bool mirrored)
1322 {
1323 mirrored = !!mirrored;
1324
1325 if (sd->is_mirrored == mirrored) return;
1326
1327 sd->is_mirrored = mirrored;
1328 elm_widget_theme(obj);
1329 }
1330
1331 /**
1332 * Returns the widget's mirrored mode setting.
1333 *
1334 * @param obj The widget.
1335 * @return mirrored mode setting of the object.
1336 *
1337 **/
1338 EOLIAN static Eina_Bool
_efl_ui_widget_efl_ui_i18n_mirrored_automatic_get(const Eo * obj EINA_UNUSED,Elm_Widget_Smart_Data * sd)1339 _efl_ui_widget_efl_ui_i18n_mirrored_automatic_get(const Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
1340 {
1341 return sd->mirrored_auto_mode;
1342 }
1343
1344 /**
1345 * @internal
1346 *
1347 * Sets the widget's mirrored mode setting.
1348 * When widget in automatic mode, it follows the system mirrored mode set by
1349 * elm_mirrored_set().
1350 * @param obj The widget.
1351 * @param automatic EINA_TRUE for auto mirrored mode. EINA_FALSE for manual.
1352 */
1353 EOLIAN static void
_efl_ui_widget_efl_ui_i18n_mirrored_automatic_set(Eo * obj,Elm_Widget_Smart_Data * sd,Eina_Bool automatic)1354 _efl_ui_widget_efl_ui_i18n_mirrored_automatic_set(Eo *obj, Elm_Widget_Smart_Data *sd, Eina_Bool automatic)
1355 {
1356 if (sd->mirrored_auto_mode != automatic)
1357 {
1358 sd->mirrored_auto_mode = automatic;
1359
1360 if (automatic)
1361 {
1362 efl_ui_mirrored_set(obj, elm_config_mirrored_get());
1363 }
1364 }
1365 }
1366
1367 /*
1368 * @internal
1369 *
1370 * Add myself as a sub object of parent object
1371 *
1372 * @see elm_widget_sub_object_add()
1373 */
1374 EAPI Eina_Bool
elm_widget_sub_object_parent_add(Evas_Object * sobj)1375 elm_widget_sub_object_parent_add(Evas_Object *sobj)
1376 {
1377 Eo *parent = NULL;
1378
1379 parent = efl_parent_get(sobj);
1380 if (!efl_isa(parent, EFL_UI_WIDGET_CLASS))
1381 {
1382 ERR("You passed a wrong parent parameter (%p %s). "
1383 "Elementary widget's parent should be an elementary widget.", parent, evas_object_type_get(parent));
1384 return EINA_FALSE;
1385 }
1386
1387 return elm_widget_sub_object_add(parent, sobj);
1388 }
1389
1390 static int
_disabled_counter_get(Eo * widget)1391 _disabled_counter_get(Eo *widget)
1392 {
1393 ELM_WIDGET_DATA_GET_OR_RETURN(widget, pd, -1);
1394
1395 return pd->disabled;
1396 }
1397
1398 static void
_mirror_disabled_state(Eo * obj,Elm_Widget_Smart_Data * pd,int disabled_delta)1399 _mirror_disabled_state(Eo *obj, Elm_Widget_Smart_Data *pd, int disabled_delta)
1400 {
1401 int prev_disabled = pd->disabled;
1402
1403 pd->disabled = (pd->parent_obj ? _disabled_counter_get(pd->parent_obj) : 0) + disabled_delta;
1404
1405 //The current disabled state is the same as the parent
1406 //when the parent is assigned or changed, no further action is required.
1407 if (((prev_disabled > 0 && pd->disabled > 0)) ||
1408 ((prev_disabled <= 0 && pd->disabled <= 0)))
1409 return;
1410
1411 //we should not call disabled_set when things are invalidated
1412 //otherwise we will unleashe an amount of errors in efl_ui_layout
1413 if (efl_invalidated_get(obj)) return;
1414
1415 if (pd->disabled > 0)
1416 {
1417 pd->disabled --;
1418 efl_ui_widget_disabled_set(obj, EINA_TRUE);
1419 }
1420 else
1421 {
1422 pd->disabled ++;
1423 efl_ui_widget_disabled_set(obj, EINA_FALSE);
1424 }
1425 }
1426
1427 EOLIAN static void
_efl_ui_widget_widget_parent_set(Eo * obj,Elm_Widget_Smart_Data * pd,Efl_Ui_Widget * parent)1428 _efl_ui_widget_widget_parent_set(Eo *obj, Elm_Widget_Smart_Data *pd, Efl_Ui_Widget *parent)
1429 {
1430 Efl_Ui_Widget *old_parent;
1431 //check if we are in the subobject list of parents
1432 if (parent)
1433 {
1434 ELM_WIDGET_DATA_GET_OR_RETURN(parent, ppd);
1435 EINA_SAFETY_ON_FALSE_RETURN(eina_array_find(ppd->children, obj, NULL));
1436 if (ppd->parent_obj == parent)
1437 {
1438 CRI("ATTEMPTING TO SET CHILD OF PARENT AS PARENT OF ITS OWN PARENT. THIS IS A BUG.");
1439 return;
1440 }
1441 }
1442
1443 /* NOTE: In the following two lines, 'obj' is correct. Do not change it.
1444 * Due to elementary's scale policy, scale and prev_scale can be different in
1445 * some cases. This happens when obj's previous parent and new parent have
1446 * different scale value.
1447 * For example, if obj's previous parent's scale is 5 and new parent's scale
1448 * is 2 while obj's scale is 0. Then 'prev_pscale' is 5 and 'scale' is 2. So
1449 * we need to reset obj's scale to 5.
1450 * Note that each widget's scale is 1.0 by default.
1451 */
1452 double scale, prev_scale = efl_gfx_entity_scale_get(obj);
1453 Elm_Theme *th, *prev_th = elm_widget_theme_get(obj);
1454 int disabled_delta = pd->disabled - (pd->parent_obj ? _disabled_counter_get(pd->parent_obj) : 0);
1455
1456 old_parent = pd->parent_obj;
1457 pd->parent_obj = parent;
1458
1459 // now lets sync up all states
1460 if (pd->parent_obj)
1461 {
1462 Eina_Bool mirrored, pmirrored = efl_ui_mirrored_get(pd->parent_obj);
1463 scale = efl_gfx_entity_scale_get(obj);
1464 th = elm_widget_theme_get(obj);
1465 mirrored = efl_ui_mirrored_get(obj);
1466
1467 if (!pd->on_create)
1468 {
1469 if (!EINA_DBL_EQ(scale, prev_scale) || (th != prev_th) ||
1470 (pmirrored != mirrored))
1471 elm_widget_theme(obj);
1472 }
1473 if (_is_focused(obj)) _parents_focus(parent);
1474 elm_widget_display_mode_set(obj, evas_object_size_hint_display_mode_get(parent));
1475 _elm_widget_top_win_focused_set(obj, _elm_widget_top_win_focused_get(parent));
1476 }
1477 _mirror_disabled_state(obj, pd, disabled_delta);
1478 _full_eval(obj, pd);
1479
1480 if (!efl_alive_get(obj)) return;
1481 if (old_parent && _elm_config->atspi_mode)
1482 {
1483 Efl_Access_Object *aparent;
1484 aparent = efl_provider_find(efl_parent_get(obj), EFL_ACCESS_OBJECT_MIXIN);
1485 if (aparent)
1486 efl_access_children_changed_del_signal_emit(aparent, obj);
1487 }
1488
1489 if (pd->parent_obj && _elm_config->atspi_mode && efl_finalized_get(parent))
1490 {
1491 Efl_Access_Object *aparent;
1492 aparent = efl_provider_find(efl_parent_get(obj), EFL_ACCESS_OBJECT_MIXIN);
1493 if (aparent)
1494 efl_access_children_changed_added_signal_emit(aparent, obj);
1495 }
1496 }
1497
1498 static void
_widget_add_sub(Eo * obj,Elm_Widget_Smart_Data * sd,Evas_Object * sobj)1499 _widget_add_sub(Eo *obj, Elm_Widget_Smart_Data *sd, Evas_Object *sobj)
1500 {
1501 if (!sd->children) sd->children = eina_array_new(1);
1502 eina_array_push(sd->children, sobj);
1503 evas_object_data_set(sobj, "elm-parent", obj);
1504 _callbacks_add(sobj, obj);
1505 }
1506
1507 static void
_widget_del_sub(Eo * obj,Elm_Widget_Smart_Data * sd,Evas_Object * sobj)1508 _widget_del_sub(Eo *obj, Elm_Widget_Smart_Data *sd, Evas_Object *sobj)
1509 {
1510 eina_array_remove(sd->children, _keep, sobj);
1511 evas_object_data_del(sobj, "elm-parent");
1512 _callbacks_del(sobj, obj);
1513 }
1514
1515 EOLIAN static Eina_Bool
_efl_ui_widget_widget_sub_object_add(Eo * obj,Elm_Widget_Smart_Data * sd,Evas_Object * sobj)1516 _efl_ui_widget_widget_sub_object_add(Eo *obj, Elm_Widget_Smart_Data *sd, Evas_Object *sobj)
1517 {
1518 Efl_Ui_Widget *parent;
1519 Eina_Bool is_widget;
1520
1521 EINA_SAFETY_ON_FALSE_RETURN_VAL(efl_isa(sobj, EFL_GFX_ENTITY_INTERFACE), EINA_FALSE);
1522 EINA_SAFETY_ON_TRUE_RETURN_VAL(obj == sobj, EINA_FALSE);
1523
1524 is_widget = elm_widget_is(sobj);
1525 //first make sure that we unregister the sobj from the parent
1526 if (is_widget)
1527 parent = efl_ui_widget_parent_get(sobj);
1528 else
1529 parent = evas_object_data_get(sobj, "elm-parent");
1530 if (parent == obj) return EINA_TRUE;
1531 if (parent)
1532 {
1533 if (sd->parent_obj == sobj)
1534 {
1535 CRI("ATTEMPTING TO SET CHILD OF PARENT AS PARENT OF ITS OWN PARENT. THIS IS A BUG.");
1536 return EINA_FALSE;
1537 }
1538
1539 if (!efl_ui_widget_sub_object_del(parent, sobj))
1540 return EINA_FALSE;
1541 }
1542
1543 //sobj does not have a parent here
1544 //first add it to our own children list
1545 _widget_add_sub(obj, sd, sobj);
1546
1547 //and if it is a widget, please set the correct parent on the widget itself
1548 //the parent set method will take care of the property syncing etc.
1549 if (is_widget)
1550 efl_ui_widget_parent_set(sobj, obj);
1551
1552 return EINA_TRUE;
1553 }
1554
1555 EOLIAN static Eina_Bool
_efl_ui_widget_widget_sub_object_del(Eo * obj,Elm_Widget_Smart_Data * sd,Evas_Object * sobj)1556 _efl_ui_widget_widget_sub_object_del(Eo *obj, Elm_Widget_Smart_Data *sd, Evas_Object *sobj)
1557 {
1558 Evas_Object *sobj_parent = NULL;
1559 Eina_Bool is_widget;
1560
1561 if (!sobj) return EINA_FALSE;
1562
1563 EINA_SAFETY_ON_TRUE_RETURN_VAL(obj == sobj, EINA_FALSE);
1564
1565 is_widget = _elm_widget_is(sobj);
1566
1567 if (!is_widget) sobj_parent = evas_object_data_del(sobj, "elm-parent");
1568
1569 if (sobj_parent && sobj_parent != obj)
1570 {
1571 static int abort_on_warn = -1;
1572
1573 ERR("removing sub object %p (%s) from parent %p (%s), "
1574 "but elm-parent is different %p (%s)!",
1575 sobj, elm_widget_type_get(sobj), obj, elm_widget_type_get(obj),
1576 sobj_parent, elm_widget_type_get(sobj_parent));
1577
1578 if (EINA_UNLIKELY(abort_on_warn == -1))
1579 {
1580 if (getenv("ELM_ERROR_ABORT")) abort_on_warn = 1;
1581 else abort_on_warn = 0;
1582 }
1583 if (abort_on_warn == 1) abort();
1584
1585 return EINA_FALSE;
1586 }
1587
1588 if (is_widget)
1589 {
1590 if (efl_ui_widget_parent_get(sobj) != obj)
1591 return EINA_FALSE;
1592 if (_is_focused(sobj))
1593 {
1594 elm_widget_tree_unfocusable_set(sobj, EINA_TRUE);
1595 elm_widget_tree_unfocusable_set(sobj, EINA_FALSE);
1596 }
1597
1598 efl_ui_widget_parent_set(sobj, NULL);
1599 }
1600
1601 if (sd->resize_obj == sobj) sd->resize_obj = NULL;
1602
1603 _widget_del_sub(obj, sd, sobj);
1604
1605 return EINA_TRUE;
1606 }
1607
1608 /* protected function - for widget developers only */
1609 EOLIAN static void
_efl_ui_widget_resize_object_set(Eo * obj,Elm_Widget_Smart_Data * sd,Eo * sobj)1610 _efl_ui_widget_resize_object_set(Eo *obj, Elm_Widget_Smart_Data *sd, Eo *sobj)
1611 {
1612 Evas_Object *parent;
1613
1614 if (sd->resize_obj == sobj) return;
1615 EINA_SAFETY_ON_TRUE_RETURN(sobj && !efl_isa(sobj, EFL_CANVAS_OBJECT_CLASS));
1616
1617 // orphan previous resize obj
1618 if (sd->resize_obj)
1619 {
1620 evas_object_clip_unset(sd->resize_obj);
1621 evas_object_smart_member_del(sd->resize_obj);
1622
1623 if (_elm_widget_is(sd->resize_obj))
1624 {
1625 if (_is_focused(sd->resize_obj)) _parents_unfocus(obj);
1626 }
1627 elm_widget_sub_object_del(obj, sd->resize_obj);
1628 }
1629
1630 sd->resize_obj = sobj;
1631 if (!sobj) return;
1632
1633 // orphan new resize obj
1634 parent = evas_object_data_get(sobj, "elm-parent");
1635 if (parent && parent != obj)
1636 {
1637 ELM_WIDGET_DATA_GET(parent, sdp);
1638
1639 /* should be there, just being paranoid */
1640 if (sdp)
1641 {
1642 if (sdp->resize_obj == sobj)
1643 elm_widget_resize_object_set(parent, NULL);
1644 else
1645 elm_widget_sub_object_del(parent, sobj);
1646 }
1647 }
1648
1649 elm_widget_sub_object_add(obj, sobj);
1650 evas_object_smart_member_add(sobj, obj);
1651 _smart_reconfigure(obj, sd);
1652 }
1653
1654 /*
1655 * @internal
1656 *
1657 * WARNING: the programmer is responsible, in the scenario of
1658 * exchanging a hover object, of cleaning the old hover "target"
1659 * before
1660 */
1661 EAPI void
elm_widget_hover_object_set(Eo * obj,Evas_Object * sobj)1662 elm_widget_hover_object_set(Eo *obj, Evas_Object *sobj)
1663 {
1664 Elm_Widget_Smart_Data *sd = efl_data_scope_safe_get(obj, MY_CLASS);
1665 if (!sd) return;
1666
1667 if (sd->hover_obj)
1668 {
1669 _callbacks_del(sd->hover_obj, obj);
1670 }
1671 sd->hover_obj = sobj;
1672 if (sd->hover_obj)
1673 {
1674 _callbacks_add(sobj, obj);
1675 _smart_reconfigure(obj, sd);
1676 }
1677 }
1678
1679 EOLIAN static void
_efl_ui_widget_focus_allow_set(Eo * obj,Elm_Widget_Smart_Data * sd,Eina_Bool can_focus)1680 _efl_ui_widget_focus_allow_set(Eo *obj, Elm_Widget_Smart_Data *sd, Eina_Bool can_focus)
1681 {
1682 can_focus = !!can_focus;
1683
1684 if (sd->can_focus == can_focus) return;
1685 sd->can_focus = can_focus;
1686 if (sd->can_focus)
1687 {
1688 efl_event_callback_array_add(obj, focus_callbacks(), NULL);
1689 }
1690 else
1691 {
1692 efl_event_callback_array_del(obj, focus_callbacks(), NULL);
1693 }
1694 if (efl_finalized_get(obj))
1695 _full_eval(obj, sd);
1696 }
1697
1698 EOLIAN static Eina_Bool
_efl_ui_widget_focus_allow_get(const Eo * obj EINA_UNUSED,Elm_Widget_Smart_Data * sd)1699 _efl_ui_widget_focus_allow_get(const Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
1700 {
1701 return sd->can_focus;
1702 }
1703
1704 EAPI Eina_Bool
elm_widget_child_can_focus_get(const Eo * obj)1705 elm_widget_child_can_focus_get(const Eo *obj)
1706 {
1707 Elm_Widget_Smart_Data *sd = efl_data_scope_safe_get(obj, MY_CLASS);
1708 if (!sd) return EINA_FALSE;
1709
1710 return sd->logical.child_count > 0;
1711 }
1712
1713
1714 static int
_tree_unfocusable_counter_get(Eo * widget)1715 _tree_unfocusable_counter_get(Eo *widget)
1716 {
1717 ELM_WIDGET_DATA_GET_OR_RETURN(widget, pd, -1);
1718
1719 return pd->tree_unfocusable;
1720 }
1721
1722 /**
1723 * Evalulate tree number.
1724 *
1725 * This is here to support properties which are propagating through the widget tree. If this property is set to true,
1726 * every widget in the subtree, will also be automatically true.
1727 * When one of the widgets in the subtree then seperatly will be set to true, the unsetting on the original widget will not unset the flag automatically in this tree.
1728 *
1729 * The basic idea here is:
1730 * - The numeric number beeing bigger than 0, means that the property is true
1731 * - The difference between the number of the parent, and the number of the object, represents the boolean flag
1732 * (0 means that the flag is equal to the one of the parent, 1 means that if the parent is false, this child is true).
1733 */
1734 static int
_calculate_tree_number(int self_counter,int parent_counter,Eina_Bool flag)1735 _calculate_tree_number(int self_counter, int parent_counter, Eina_Bool flag)
1736 {
1737 int distance = self_counter - parent_counter;
1738
1739 if (flag)
1740 self_counter ++;
1741 else
1742 self_counter --;
1743
1744 distance = self_counter - parent_counter;
1745
1746 if ((distance < 0) || (distance > 1))
1747 {
1748 distance = MAX(MIN(flag, 1), 0);
1749 self_counter = parent_counter + distance;
1750 }
1751
1752 return self_counter;
1753 }
1754
1755 static void
_propagate_bool_property(Elm_Widget_Smart_Data * pd,Eina_Bool flag,void (* property_setting)(Eo * obj,Eina_Bool flag))1756 _propagate_bool_property(Elm_Widget_Smart_Data *pd, Eina_Bool flag, void (*property_setting)(Eo *obj, Eina_Bool flag))
1757 {
1758 Efl_Ui_Widget *subs;
1759 for (unsigned int i = 0; i < eina_array_count(pd->children); ++i)
1760 {
1761 subs = eina_array_data_get(pd->children, i);
1762 if (efl_isa(subs, EFL_UI_WIDGET_CLASS))
1763 property_setting(subs, flag);
1764 }
1765 }
1766
1767 /**
1768 * @internal
1769 *
1770 * This API makes the widget object and its children to be unfocusable.
1771 *
1772 * This API can be helpful for an object to be deleted.
1773 * When an object will be deleted soon, it and its children may not
1774 * want to get focus (by focus reverting or by other focus controls).
1775 * Then, just use this API before deleting.
1776 *
1777 * @param obj The widget root of sub-tree
1778 * @param tree_unfocusable If true, set the object sub-tree as unfocusable
1779 *
1780 * @ingroup Widget
1781 */
1782 EAPI void
elm_widget_tree_unfocusable_set(Eo * obj,Eina_Bool tree_unfocusable)1783 elm_widget_tree_unfocusable_set(Eo *obj, Eina_Bool tree_unfocusable)
1784 {
1785 Elm_Widget_Smart_Data *pd = efl_data_scope_safe_get(obj, MY_CLASS);
1786 EINA_SAFETY_ON_NULL_RETURN(pd);
1787 int old_tree_unfocusable;
1788
1789 old_tree_unfocusable = pd->tree_unfocusable;
1790
1791 pd->tree_unfocusable = _calculate_tree_number(pd->tree_unfocusable,
1792 (pd->parent_obj ? _tree_unfocusable_counter_get(pd->parent_obj) : 0),
1793 tree_unfocusable);
1794
1795 if (old_tree_unfocusable != pd->tree_unfocusable)
1796 {
1797 _full_eval(obj, pd);
1798 _propagate_bool_property(pd, tree_unfocusable, elm_widget_tree_unfocusable_set);
1799 }
1800 }
1801
1802 /**
1803 * @internal
1804 *
1805 * This returns true, if the object sub-tree is unfocusable.
1806 *
1807 * @param obj The widget root of sub-tree
1808 * @return EINA_TRUE if the object sub-tree is unfocusable
1809 *
1810 * @ingroup Widget
1811 */
1812 EAPI Eina_Bool
elm_widget_tree_unfocusable_get(const Eo * obj)1813 elm_widget_tree_unfocusable_get(const Eo *obj)
1814 {
1815 Elm_Widget_Smart_Data *sd = efl_data_scope_safe_get(obj, MY_CLASS);
1816 EINA_SAFETY_ON_NULL_RETURN_VAL(sd, EINA_FALSE);
1817
1818 return !!sd->tree_unfocusable;
1819 }
1820
1821 /**
1822 * @internal
1823 *
1824 * Get the list of focusable child objects.
1825 *
1826 * This function returns list of child objects which can get focus.
1827 *
1828 * @param obj The parent widget
1829 * @return list of focusable child objects.
1830 *
1831 * @ingroup Widget
1832 */
1833 EAPI Eina_List*
elm_widget_can_focus_child_list_get(const Eo * obj)1834 elm_widget_can_focus_child_list_get(const Eo *obj)
1835 {
1836 Elm_Widget_Smart_Data *sd = efl_data_scope_safe_get(obj, MY_CLASS);
1837 Eina_List *child_list = NULL;
1838 Evas_Object *child;
1839
1840 if (!sd) return NULL;
1841 for (unsigned int i = 0; i < eina_array_count(sd->children); ++i)
1842 {
1843 child = eina_array_data_get(sd->children, i);
1844 if (!_elm_widget_is(child)) continue;
1845 if ((elm_widget_can_focus_get(child)) &&
1846 (evas_object_visible_get(child)) &&
1847 (!elm_widget_disabled_get(child)))
1848 child_list = eina_list_append(child_list, child);
1849 else
1850 {
1851 Eina_List *can_focus_list;
1852 can_focus_list = elm_widget_can_focus_child_list_get(child);
1853 if (can_focus_list)
1854 child_list = eina_list_merge(child_list, can_focus_list);
1855 }
1856 }
1857
1858 return child_list;
1859 }
1860
1861 /** @internal */
1862 EAPI void
elm_widget_highlight_ignore_set(Eo * obj,Eina_Bool ignore)1863 elm_widget_highlight_ignore_set(Eo *obj, Eina_Bool ignore)
1864 {
1865 Elm_Widget_Smart_Data *sd = efl_data_scope_safe_get(obj, MY_CLASS);
1866 if (!sd) return;
1867
1868 sd->highlight_ignore = !!ignore;
1869 }
1870
1871 /** @internal */
1872 EAPI Eina_Bool
elm_widget_highlight_ignore_get(const Eo * obj)1873 elm_widget_highlight_ignore_get(const Eo *obj)
1874 {
1875 Elm_Widget_Smart_Data *sd = efl_data_scope_safe_get(obj, MY_CLASS);
1876 if (!sd) return EINA_FALSE;
1877
1878 return sd->highlight_ignore;
1879 }
1880
1881 /** @internal */
1882 EAPI void
elm_widget_highlight_in_theme_set(Eo * obj,Eina_Bool highlight)1883 elm_widget_highlight_in_theme_set(Eo *obj, Eina_Bool highlight)
1884 {
1885 Elm_Widget_Smart_Data *sd = efl_data_scope_safe_get(obj, MY_CLASS);
1886 if (!sd) return;
1887
1888 sd->highlight_in_theme = !!highlight;
1889 /* FIXME: if focused, it should switch from one mode to the other */
1890 }
1891
1892 void
_elm_widget_highlight_in_theme_update(Eo * obj)1893 _elm_widget_highlight_in_theme_update(Eo *obj)
1894 {
1895 Evas_Object *top = elm_widget_top_get(obj);
1896
1897 if (top && efl_isa(top, EFL_UI_WIN_CLASS))
1898 {
1899 _elm_win_focus_highlight_in_theme_update(
1900 top, elm_widget_highlight_in_theme_get(obj));
1901 }
1902 }
1903
1904 /** @internal */
1905 EAPI Eina_Bool
elm_widget_highlight_in_theme_get(const Eo * obj)1906 elm_widget_highlight_in_theme_get(const Eo *obj)
1907 {
1908 Elm_Widget_Smart_Data *sd = efl_data_scope_safe_get(obj, MY_CLASS);
1909 if (!sd) return EINA_FALSE;
1910
1911 return sd->highlight_in_theme;
1912 }
1913
1914 /** @internal */
1915 EAPI void
elm_widget_access_highlight_in_theme_set(Eo * obj,Eina_Bool highlight)1916 elm_widget_access_highlight_in_theme_set(Eo *obj, Eina_Bool highlight)
1917 {
1918 Elm_Widget_Smart_Data *sd = efl_data_scope_safe_get(obj, MY_CLASS);
1919 if (!sd) return;
1920
1921 sd->access_highlight_in_theme = !!highlight;
1922 }
1923
1924 /** @internal */
1925 EAPI Eina_Bool
elm_widget_access_highlight_in_theme_get(const Eo * obj)1926 elm_widget_access_highlight_in_theme_get(const Eo *obj)
1927 {
1928 Elm_Widget_Smart_Data *sd = efl_data_scope_safe_get(obj, MY_CLASS);
1929 if (!sd) return EINA_FALSE;
1930
1931 return sd->access_highlight_in_theme;
1932 }
1933
1934 /** @internal */
1935 EAPI Eina_Bool
elm_widget_highlight_get(const Eo * obj)1936 elm_widget_highlight_get(const Eo *obj)
1937 {
1938 Elm_Widget_Smart_Data *sd = efl_data_scope_safe_get(obj, MY_CLASS);
1939 if (!sd) return EINA_FALSE;
1940
1941 return sd->highlighted;
1942 }
1943
1944 EAPI Eina_Bool
elm_widget_is(const Evas_Object * obj)1945 elm_widget_is(const Evas_Object *obj)
1946 {
1947 return _elm_widget_is(obj);
1948 }
1949
1950 EAPI void
elm_widget_access_info_set(Efl_Ui_Widget * obj,const char * txt)1951 elm_widget_access_info_set(Efl_Ui_Widget *obj, const char *txt)
1952 {
1953 efl_ui_widget_access_info_set(obj, txt);
1954 }
1955
1956 EAPI const char *
elm_widget_access_info_get(const Efl_Ui_Widget * obj)1957 elm_widget_access_info_get(const Efl_Ui_Widget *obj)
1958 {
1959 return efl_ui_widget_access_info_get(obj);
1960 }
1961
1962 EAPI Eo *
elm_widget_top_get(const Eo * obj)1963 elm_widget_top_get(const Eo *obj)
1964 {
1965 Efl_Ui_Widget *parent = elm_widget_parent_get(obj);
1966 if (parent)
1967 {
1968 if (!efl_isa(parent, EFL_UI_WIDGET_CLASS)) return NULL;
1969 return elm_widget_top_get(parent);
1970 }
1971 /* XXX const */
1972 return (Evas_Object *)obj;
1973 }
1974
1975 EAPI Evas_Object *
elm_widget_parent_widget_get(const Evas_Object * obj)1976 elm_widget_parent_widget_get(const Evas_Object *obj)
1977 {
1978 Evas_Object *parent;
1979
1980 if (_elm_widget_is(obj))
1981 {
1982 ELM_WIDGET_DATA_GET(obj, sd);
1983 if (!sd) return NULL;
1984 parent = sd->parent_obj;
1985 }
1986 else
1987 {
1988 parent = evas_object_data_get(obj, "elm-parent");
1989 if (!parent) parent = evas_object_smart_parent_get(obj);
1990 }
1991
1992 while (parent)
1993 {
1994 Evas_Object *elm_parent;
1995 if (_elm_widget_is(parent)) break;
1996 elm_parent = evas_object_data_get(parent, "elm-parent");
1997 if (elm_parent) parent = elm_parent;
1998 else parent = evas_object_smart_parent_get(parent);
1999 }
2000 return parent;
2001 }
2002
2003 EAPI void
elm_widget_event_callback_add(Eo * obj,Elm_Event_Cb func,const void * data)2004 elm_widget_event_callback_add(Eo *obj, Elm_Event_Cb func, const void *data)
2005 {
2006 API_ENTRY return;
2007 EINA_SAFETY_ON_NULL_RETURN(func);
2008
2009 Elm_Event_Cb_Data *ecb = ELM_NEW(Elm_Event_Cb_Data);
2010 if (!ecb)
2011 {
2012 ERR("Failed to allocate memory");
2013 return;
2014 }
2015 ecb->func = func;
2016 ecb->data = data;
2017 sd->event_cb = eina_list_append(sd->event_cb, ecb);
2018 }
2019
2020 EAPI void *
elm_widget_event_callback_del(Eo * obj,Elm_Event_Cb func,const void * data)2021 elm_widget_event_callback_del(Eo *obj, Elm_Event_Cb func, const void *data)
2022 {
2023 API_ENTRY return NULL;
2024 EINA_SAFETY_ON_NULL_RETURN_VAL(func, NULL);
2025 Eina_List *l;
2026 Elm_Event_Cb_Data *ecd;
2027
2028 EINA_LIST_FOREACH(sd->event_cb, l, ecd)
2029 if ((ecd->func == func) && (ecd->data == data))
2030 {
2031 free(ecd);
2032 sd->event_cb = eina_list_remove_list(sd->event_cb, l);
2033 return (void *)data;
2034 }
2035
2036 return NULL;
2037 }
2038
2039 static void
_propagate_event(void * data EINA_UNUSED,const Efl_Event * eo_event)2040 _propagate_event(void *data EINA_UNUSED, const Efl_Event *eo_event)
2041 {
2042 Evas_Object *obj = eo_event->object;
2043 Evas_Object *parent = obj;
2044 Elm_Event_Cb_Data *ecd;
2045 Eina_List *l, *l_prev;
2046
2047 if ((evas_focus_get(evas_object_evas_get(obj)) != elm_widget_top_get(obj)) &&
2048 efl_isa(obj, EFL_UI_WIN_CLASS))
2049 return;
2050
2051 while (parent && !efl_input_processed_get(eo_event->info))
2052 {
2053 Elm_Widget_Smart_Data *sd = efl_data_scope_safe_get(parent, MY_CLASS);
2054 if (!sd) return;
2055
2056 if (elm_widget_disabled_get(obj))
2057 {
2058 parent = sd->parent_obj;
2059 continue;
2060 }
2061
2062 if (efl_ui_widget_input_event_handler(parent, eo_event, obj))
2063 return;
2064
2065 EINA_LIST_FOREACH_SAFE(sd->event_cb, l, l_prev, ecd)
2066 {
2067 if (_propagate_event_legacy(parent, eo_event, obj, ecd))
2068 return;
2069 }
2070
2071 parent = sd->parent_obj;
2072 }
2073 }
2074
2075 /** @internal */
2076 EAPI void
elm_widget_parent_highlight_set(Eo * obj,Eina_Bool highlighted)2077 elm_widget_parent_highlight_set(Eo *obj, Eina_Bool highlighted)
2078 {
2079 Elm_Widget_Smart_Data *sd =efl_data_scope_safe_get(obj, MY_CLASS);
2080 if (!sd) return;
2081
2082 highlighted = !!highlighted;
2083
2084 Evas_Object *o = elm_widget_parent_get(obj);
2085
2086 if (o) elm_widget_parent_highlight_set(o, highlighted);
2087
2088 sd->highlighted = highlighted;
2089 }
2090
2091 EOLIAN static Evas_Object*
_efl_ui_widget_widget_parent_get(const Eo * obj EINA_UNUSED,Elm_Widget_Smart_Data * sd)2092 _efl_ui_widget_widget_parent_get(const Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
2093 {
2094 return sd->parent_obj;
2095 }
2096
2097 void
_elm_widget_focus_auto_show(Evas_Object * obj)2098 _elm_widget_focus_auto_show(Evas_Object *obj)
2099 {
2100 Evas_Object *top = elm_widget_top_get(obj);
2101 if (top && efl_isa(top, EFL_UI_WIN_CLASS)) _elm_win_focus_auto_show(top);
2102 }
2103
2104 void
_elm_widget_top_win_focused_set(Evas_Object * obj,Eina_Bool top_win_focused)2105 _elm_widget_top_win_focused_set(Evas_Object *obj,
2106 Eina_Bool top_win_focused)
2107 {
2108 Evas_Object *child;
2109 API_ENTRY return;
2110
2111 if (sd->top_win_focused == top_win_focused) return;
2112 for (unsigned int i = 0; i < eina_array_count(sd->children); ++i)
2113 {
2114 child = eina_array_data_get(sd->children, i);
2115 if (elm_widget_is(child))
2116 _elm_widget_top_win_focused_set(child, top_win_focused);
2117 }
2118 sd->top_win_focused = top_win_focused;
2119
2120 if (sd->focused && !sd->top_win_focused)
2121 efl_ui_focus_object_on_focus_update(obj);
2122 }
2123
2124 Eina_Bool
_elm_widget_top_win_focused_get(const Evas_Object * obj)2125 _elm_widget_top_win_focused_get(const Evas_Object *obj)
2126 {
2127 API_ENTRY return EINA_FALSE;
2128 return sd->top_win_focused;
2129 }
2130
2131 EOLIAN static void
_efl_ui_widget_disabled_set(Eo * obj EINA_UNUSED,Elm_Widget_Smart_Data * pd,Eina_Bool disabled)2132 _efl_ui_widget_disabled_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *pd, Eina_Bool disabled)
2133 {
2134 int old_state;
2135
2136 old_state = pd->disabled;
2137
2138 pd->disabled = _calculate_tree_number(pd->disabled, (pd->parent_obj ? _disabled_counter_get(pd->parent_obj) : 0), disabled);
2139 if (old_state != pd->disabled)
2140 {
2141 if (efl_finalized_get(obj))
2142 _full_eval(obj, pd);
2143 _propagate_bool_property(pd, disabled, efl_ui_widget_disabled_set);
2144 }
2145 }
2146
2147 EOLIAN static Eina_Bool
_efl_ui_widget_disabled_get(const Eo * obj EINA_UNUSED,Elm_Widget_Smart_Data * pd)2148 _efl_ui_widget_disabled_get(const Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *pd)
2149 {
2150 return pd->disabled > 0;
2151 }
2152
2153 /**
2154 * @internal
2155 *
2156 * Get the focus region of the given widget.
2157 *
2158 * @return The region to show. If it's not a valid rectangle it will not show.
2159 *
2160 * The focus region is the area of a widget that should brought into the
2161 * visible area when the widget is focused. Mostly used to show the part of
2162 * an entry where the cursor is, for example. The area returned is relative
2163 * to the object @p obj.
2164 *
2165 * @param obj The widget object
2166 * @return The region to show, in relative coordinates. If it's not a valid
2167 * rectangle (i.e. w or h <= 0) it will be ignored.
2168 *
2169 * @ingroup Widget
2170 */
2171 EOLIAN static Eina_Rect
_efl_ui_widget_interest_region_get(const Eo * obj,Elm_Widget_Smart_Data * _pd EINA_UNUSED)2172 _efl_ui_widget_interest_region_get(const Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED)
2173 {
2174 Eina_Rect r = {};
2175 r.size = efl_gfx_entity_size_get(obj);
2176 return r;
2177 }
2178
2179 EOLIAN static void
_efl_ui_widget_scroll_hold_push(Eo * obj,Elm_Widget_Smart_Data * sd)2180 _efl_ui_widget_scroll_hold_push(Eo *obj, Elm_Widget_Smart_Data *sd)
2181 {
2182 sd->scroll_hold++;
2183 if (sd->scroll_hold == 1)
2184 {
2185 if (_elm_scrollable_is(obj))
2186 {
2187 if (elm_widget_is_legacy(obj))
2188 elm_interface_scrollable_hold_set(obj, EINA_TRUE);
2189 else
2190 efl_ui_scrollable_scroll_hold_set(obj, EINA_TRUE);
2191 }
2192 else
2193 {
2194 Evas_Object *child;
2195
2196 for (unsigned int i = 0; i < eina_array_count(sd->children); ++i)
2197 {
2198 child = eina_array_data_get(sd->children, i);
2199 if (elm_widget_is(child) && _elm_scrollable_is(child))
2200 {
2201 if (elm_widget_is_legacy(child))
2202 elm_interface_scrollable_hold_set(child, EINA_TRUE);
2203 else
2204 efl_ui_scrollable_scroll_hold_set(child, EINA_TRUE);
2205 }
2206 }
2207 }
2208 }
2209 if (sd->parent_obj) efl_ui_widget_scroll_hold_push(sd->parent_obj);
2210 // FIXME: on delete/reparent hold pop
2211 }
2212
2213 EOLIAN static void
_efl_ui_widget_scroll_hold_pop(Eo * obj,Elm_Widget_Smart_Data * sd)2214 _efl_ui_widget_scroll_hold_pop(Eo *obj, Elm_Widget_Smart_Data *sd)
2215 {
2216 sd->scroll_hold--;
2217 if (!sd->scroll_hold)
2218 {
2219 if (_elm_scrollable_is(obj))
2220 {
2221 if (elm_widget_is_legacy(obj))
2222 elm_interface_scrollable_hold_set(obj, EINA_FALSE);
2223 else
2224 efl_ui_scrollable_scroll_hold_set(obj, EINA_FALSE);
2225 }
2226 else
2227 {
2228 Evas_Object *child;
2229
2230 for (unsigned int i = 0; i < eina_array_count(sd->children); ++i)
2231 {
2232 child = eina_array_data_get(sd->children, i);
2233 if (elm_widget_is(child) && _elm_scrollable_is(child))
2234 {
2235 if (elm_widget_is_legacy(child))
2236 elm_interface_scrollable_hold_set(child, EINA_FALSE);
2237 else
2238 efl_ui_scrollable_scroll_hold_set(child, EINA_FALSE);
2239 }
2240 }
2241 }
2242 }
2243 if (sd->parent_obj) efl_ui_widget_scroll_hold_pop(sd->parent_obj);
2244 if (sd->scroll_hold < 0) sd->scroll_hold = 0;
2245 }
2246
2247 EAPI int
elm_widget_scroll_hold_get(const Eo * obj)2248 elm_widget_scroll_hold_get(const Eo *obj)
2249 {
2250 Elm_Widget_Smart_Data *sd = efl_data_scope_safe_get(obj, MY_CLASS);
2251
2252 if (!sd) return 0;
2253 return sd->scroll_hold;
2254 }
2255
2256 EOLIAN static void
_efl_ui_widget_scroll_freeze_push(Eo * obj,Elm_Widget_Smart_Data * sd)2257 _efl_ui_widget_scroll_freeze_push(Eo *obj, Elm_Widget_Smart_Data *sd)
2258 {
2259 sd->scroll_freeze++;
2260 if (sd->scroll_freeze == 1)
2261 {
2262 if (_elm_scrollable_is(obj))
2263 {
2264 if (elm_widget_is_legacy(obj))
2265 elm_interface_scrollable_freeze_set(obj, EINA_TRUE);
2266 else
2267 efl_ui_scrollable_scroll_freeze_set(obj, EINA_TRUE);
2268 }
2269 else
2270 {
2271 Evas_Object *child;
2272
2273 for (unsigned int i = 0; i < eina_array_count(sd->children); ++i)
2274 {
2275 child = eina_array_data_get(sd->children, i);
2276 if (elm_widget_is(child) && _elm_scrollable_is(child))
2277 {
2278 if (elm_widget_is_legacy(child))
2279 elm_interface_scrollable_freeze_set(child, EINA_TRUE);
2280 else
2281 efl_ui_scrollable_scroll_freeze_set(child, EINA_TRUE);
2282 }
2283 }
2284 }
2285 }
2286 if (sd->parent_obj) efl_ui_widget_scroll_freeze_push(sd->parent_obj);
2287 // FIXME: on delete/reparent freeze pop
2288 }
2289
2290 EOLIAN static void
_efl_ui_widget_scroll_freeze_pop(Eo * obj,Elm_Widget_Smart_Data * sd)2291 _efl_ui_widget_scroll_freeze_pop(Eo *obj, Elm_Widget_Smart_Data *sd)
2292 {
2293 sd->scroll_freeze--;
2294 if (!sd->scroll_freeze)
2295 {
2296 if (_elm_scrollable_is(obj))
2297 {
2298 if (elm_widget_is_legacy(obj))
2299 elm_interface_scrollable_freeze_set(obj, EINA_FALSE);
2300 else
2301 efl_ui_scrollable_scroll_freeze_set(obj, EINA_FALSE);
2302 }
2303 else
2304 {
2305 Evas_Object *child;
2306
2307 for (unsigned int i = 0; i < eina_array_count(sd->children); ++i)
2308 {
2309 child = eina_array_data_get(sd->children, i);
2310
2311 if (elm_widget_is(child) && _elm_scrollable_is(child))
2312 {
2313 if (elm_widget_is_legacy(child))
2314 elm_interface_scrollable_freeze_set(child, EINA_FALSE);
2315 else
2316 efl_ui_scrollable_scroll_freeze_set(child, EINA_FALSE);
2317 }
2318 }
2319 }
2320 }
2321 if (sd->parent_obj) efl_ui_widget_scroll_freeze_pop(sd->parent_obj);
2322 if (sd->scroll_freeze < 0) sd->scroll_freeze = 0;
2323 }
2324
2325 EAPI int
elm_widget_scroll_freeze_get(const Eo * obj)2326 elm_widget_scroll_freeze_get(const Eo *obj)
2327 {
2328 Elm_Widget_Smart_Data *sd = efl_data_scope_safe_get(obj, MY_CLASS);
2329
2330 if (!sd) return 0;
2331 return sd->scroll_freeze;
2332 }
2333
2334 EOLIAN static void
_efl_ui_widget_efl_gfx_entity_scale_set(Eo * obj,Elm_Widget_Smart_Data * sd,double scale)2335 _efl_ui_widget_efl_gfx_entity_scale_set(Eo *obj, Elm_Widget_Smart_Data *sd, double scale)
2336 {
2337 if (scale < 0.0) scale = 0.0;
2338 if (!EINA_DBL_EQ(sd->scale, scale))
2339 {
2340 sd->scale = scale;
2341 elm_widget_theme(obj);
2342 }
2343 }
2344
2345 EOLIAN static double
_efl_ui_widget_efl_gfx_entity_scale_get(const Eo * obj EINA_UNUSED,Elm_Widget_Smart_Data * sd)2346 _efl_ui_widget_efl_gfx_entity_scale_get(const Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
2347 {
2348 // FIXME: save walking up the tree by storing/caching parent scale
2349 if (EINA_DBL_EQ(sd->scale, 0.0))
2350 {
2351 if (sd->parent_obj)
2352 {
2353 return efl_gfx_entity_scale_get(sd->parent_obj);
2354 }
2355 else
2356 {
2357 return 1.0;
2358 }
2359 }
2360 return sd->scale;
2361 }
2362
2363 EAPI void
elm_widget_theme_set(Evas_Object * obj,Elm_Theme * th)2364 elm_widget_theme_set(Evas_Object *obj, Elm_Theme *th)
2365 {
2366 Elm_Widget_Smart_Data *sd = efl_data_scope_safe_get(obj, MY_CLASS);
2367 if (!sd) return;
2368
2369 Eina_Bool apply = EINA_FALSE;
2370 if (sd->theme != th)
2371 {
2372 if (elm_widget_theme_get(obj) != th) apply = EINA_TRUE;
2373 if (sd->theme) elm_theme_free(sd->theme);
2374 sd->theme = th;
2375 if (th) efl_ref(th->eo_theme);
2376 if (apply) elm_widget_theme(obj);
2377 }
2378 }
2379
2380 EAPI void
elm_widget_part_text_set(Eo * obj,const char * part,const char * label)2381 elm_widget_part_text_set(Eo *obj, const char *part, const char *label)
2382 {
2383 /* legacy support: combobox was special (internal entry is text object). */
2384 if (efl_isa(obj, ELM_COMBOBOX_CLASS))
2385 _elm_combobox_part_text_set(obj, part, label);
2386 else if (efl_isa(obj, EFL_UI_LAYOUT_BASE_CLASS))
2387 elm_layout_text_set(obj, part, label);
2388 }
2389
2390 EAPI const char*
elm_widget_part_text_get(const Eo * obj,const char * part)2391 elm_widget_part_text_get(const Eo *obj, const char *part)
2392 {
2393 /* legacy support: combobox was special (internal entry is text object). */
2394 if (efl_isa(obj, ELM_COMBOBOX_CLASS))
2395 return _elm_combobox_part_text_get(obj, part);
2396 else if (efl_isa(obj, EFL_UI_LAYOUT_BASE_CLASS))
2397 return elm_layout_text_get(obj, part);
2398
2399 return NULL;
2400 }
2401
2402 static Elm_Translate_String_Data *
_translate_string_data_get(Eina_Inlist * translate_strings,const char * part)2403 _translate_string_data_get(Eina_Inlist *translate_strings, const char *part)
2404 {
2405 Elm_Translate_String_Data *ts;
2406 Eina_Stringshare *str;
2407
2408 if (!translate_strings) return NULL;
2409
2410 str = eina_stringshare_add(part);
2411 EINA_INLIST_FOREACH(translate_strings, ts)
2412 {
2413 if (ts->id == str) break;
2414 }
2415
2416 eina_stringshare_del(str);
2417
2418 return ts;
2419 }
2420
2421 static Elm_Translate_String_Data *
_part_text_translatable_set(Eina_Inlist ** translate_strings,const char * part,Eina_Bool translatable,Eina_Bool preset)2422 _part_text_translatable_set(Eina_Inlist **translate_strings, const char *part, Eina_Bool translatable, Eina_Bool preset)
2423 {
2424 Eina_Inlist *t;
2425 Elm_Translate_String_Data *ts;
2426 t = *translate_strings;
2427 ts = _translate_string_data_get(t, part);
2428
2429 if (translatable)
2430 {
2431 if (!ts)
2432 {
2433 ts = ELM_NEW(Elm_Translate_String_Data);
2434 if (!ts) return NULL;
2435
2436 ts->id = eina_stringshare_add(part);
2437 t = eina_inlist_append(t, (Eina_Inlist*) ts);
2438 }
2439 if (preset) ts->preset = EINA_TRUE;
2440 }
2441 //Delete this exist one if this part has been not preset.
2442 //see elm_widget_part_text_translatable_set()
2443 else if (ts && ((preset) || (!ts->preset)))
2444 {
2445 t = eina_inlist_remove(t, EINA_INLIST_GET(ts));
2446 eina_stringshare_del(ts->id);
2447 eina_stringshare_del(ts->domain);
2448 eina_stringshare_del(ts->string);
2449 ELM_SAFE_FREE(ts, free);
2450 }
2451
2452 *translate_strings = t;
2453
2454 return ts;
2455 }
2456
2457 /* internal */
2458 void
elm_widget_part_translatable_text_set(Eo * obj,const char * part,const char * label,const char * domain)2459 elm_widget_part_translatable_text_set(Eo *obj, const char *part, const char *label, const char *domain)
2460 {
2461 Elm_Translate_String_Data *ts;
2462 Elm_Widget_Smart_Data *sd;
2463
2464 sd = efl_data_scope_safe_get(obj, MY_CLASS);
2465 if (!sd) return;
2466
2467 if (!label)
2468 {
2469 _part_text_translatable_set(&sd->translate_strings, part, EINA_FALSE,
2470 EINA_FALSE);
2471 }
2472 else
2473 {
2474 ts = _part_text_translatable_set(&sd->translate_strings, part,
2475 EINA_TRUE, EINA_FALSE);
2476 if (!ts) return;
2477 if (!ts->string) ts->string = eina_stringshare_add(label);
2478 else eina_stringshare_replace(&ts->string, label);
2479 if (!ts->domain) ts->domain = eina_stringshare_add(domain);
2480 else eina_stringshare_replace(&ts->domain, domain);
2481 #ifdef HAVE_GETTEXT
2482 if (label[0]) label = dgettext(domain, label);
2483 #endif
2484 }
2485
2486 sd->on_translate = EINA_TRUE;
2487 elm_widget_part_text_set(obj, part, label);
2488 sd->on_translate = EINA_FALSE;
2489 }
2490
2491 /* legacy only */
2492 EAPI void
elm_widget_domain_part_text_translatable_set(Eo * obj,const char * part,const char * domain,Eina_Bool translatable)2493 elm_widget_domain_part_text_translatable_set(Eo *obj, const char *part, const char *domain, Eina_Bool translatable)
2494 {
2495 Elm_Translate_String_Data *ts;
2496 Elm_Widget_Smart_Data *sd;
2497 const char *text = NULL;
2498
2499 sd = efl_data_scope_safe_get(obj, MY_CLASS);
2500 if (!sd) return;
2501
2502 ts = _part_text_translatable_set(&sd->translate_strings, part,
2503 translatable, EINA_TRUE);
2504 if (!ts) return;
2505 if (!ts->domain) ts->domain = eina_stringshare_add(domain);
2506 else eina_stringshare_replace(&ts->domain, domain);
2507
2508 text = elm_widget_part_text_get(obj, part);
2509 if (!text || !text[0]) return;
2510
2511 if (!ts->string) ts->string = eina_stringshare_add(text);
2512
2513 //Try to translate text since we don't know the text is already translated.
2514 #ifdef HAVE_GETTEXT
2515 text = dgettext(domain, text);
2516 #endif
2517 sd->on_translate = EINA_TRUE;
2518 elm_widget_part_text_set(obj, part, text);
2519 sd->on_translate = EINA_FALSE;
2520 }
2521
2522 /* internal */
2523 const char *
elm_widget_part_translatable_text_get(const Eo * obj,const char * part,const char ** domain)2524 elm_widget_part_translatable_text_get(const Eo *obj, const char *part, const char **domain)
2525 {
2526 Elm_Widget_Smart_Data *sd;
2527 Elm_Translate_String_Data *ts;
2528
2529 if (domain) *domain = NULL;
2530
2531 sd = efl_data_scope_safe_get(obj, MY_CLASS);
2532 if (!sd) return NULL;
2533
2534 ts = _translate_string_data_get(sd->translate_strings, part);
2535 if (!ts) return NULL;
2536
2537 if (domain) *domain = ts->domain;
2538 return ts->string;
2539 }
2540
2541 EOLIAN static void
_efl_ui_widget_efl_ui_l10n_translation_update(Eo * obj EINA_UNUSED,Elm_Widget_Smart_Data * sd)2542 _efl_ui_widget_efl_ui_l10n_translation_update(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
2543 {
2544 Evas_Object *child;
2545
2546 for (unsigned int i = 0; i < eina_array_count(sd->children); ++i)
2547 {
2548 child = eina_array_data_get(sd->children, i);
2549 if (elm_widget_is(child))
2550 efl_ui_l10n_translation_update(child);
2551
2552 }
2553
2554 if (sd->hover_obj) efl_ui_l10n_translation_update(sd->hover_obj);
2555
2556 #ifdef HAVE_GETTEXT
2557 Elm_Translate_String_Data *ts;
2558 EINA_INLIST_FOREACH(sd->translate_strings, ts)
2559 {
2560 if (!ts->string) continue;
2561 const char *s = dgettext(ts->domain, ts->string);
2562 sd->on_translate = EINA_TRUE;
2563 elm_widget_part_text_set(obj, ts->id, s);
2564 sd->on_translate = EINA_FALSE;
2565 }
2566 #endif
2567 efl_event_callback_legacy_call(obj, EFL_UI_WIDGET_EVENT_LANGUAGE_CHANGED, NULL);
2568 }
2569
2570 EOLIAN static void
_efl_ui_widget_access_info_set(Eo * obj EINA_UNUSED,Elm_Widget_Smart_Data * sd,const char * txt)2571 _efl_ui_widget_access_info_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, const char *txt)
2572 {
2573 eina_stringshare_replace(&sd->access_info, txt);
2574 }
2575
2576 EOLIAN static const char*
_efl_ui_widget_access_info_get(const Eo * obj EINA_UNUSED,Elm_Widget_Smart_Data * sd)2577 _efl_ui_widget_access_info_get(const Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
2578 {
2579 return sd->access_info;
2580 }
2581
2582
2583 EAPI void
elm_widget_scroll_hold_push(Efl_Ui_Widget * obj)2584 elm_widget_scroll_hold_push(Efl_Ui_Widget *obj)
2585 {
2586 efl_ui_widget_scroll_hold_push(obj);
2587 }
2588
2589 EAPI void
elm_widget_scroll_hold_pop(Efl_Ui_Widget * obj)2590 elm_widget_scroll_hold_pop(Efl_Ui_Widget *obj)
2591 {
2592 efl_ui_widget_scroll_hold_pop(obj);
2593 }
2594
2595 EAPI void
elm_widget_scroll_freeze_push(Efl_Ui_Widget * obj)2596 elm_widget_scroll_freeze_push(Efl_Ui_Widget *obj)
2597 {
2598 efl_ui_widget_scroll_freeze_push(obj);
2599 }
2600
2601 EAPI void
elm_widget_scroll_freeze_pop(Efl_Ui_Widget * obj)2602 elm_widget_scroll_freeze_pop(Efl_Ui_Widget *obj)
2603 {
2604 efl_ui_widget_scroll_freeze_pop(obj);
2605 }
2606
2607
2608 EAPI Elm_Theme *
elm_widget_theme_get(const Evas_Object * obj)2609 elm_widget_theme_get(const Evas_Object *obj)
2610 {
2611 Elm_Widget_Smart_Data *sd = efl_data_scope_safe_get(obj, MY_CLASS);
2612 if (!sd) return NULL;
2613
2614 if (!sd->theme)
2615 {
2616 if (sd->parent_obj)
2617 return elm_widget_theme_get(sd->parent_obj);
2618 else return NULL;
2619 }
2620 return sd->theme;
2621 }
2622
2623 EOLIAN static Eina_Error
_efl_ui_widget_style_set(Eo * obj,Elm_Widget_Smart_Data * sd,const char * style)2624 _efl_ui_widget_style_set(Eo *obj, Elm_Widget_Smart_Data *sd, const char *style)
2625 {
2626 if (!elm_widget_is_legacy(obj) && efl_finalized_get(obj))
2627 {
2628 ERR("Efl.Ui.Widget.style can only be set before finalize!");
2629 return EFL_UI_THEME_APPLY_ERROR_GENERIC;
2630 }
2631
2632 if (eina_stringshare_replace(&sd->style, style))
2633 return elm_widget_theme(obj);
2634
2635 return EFL_UI_THEME_APPLY_ERROR_NONE;
2636 }
2637
2638 EOLIAN static const char*
_efl_ui_widget_style_get(const Eo * obj EINA_UNUSED,Elm_Widget_Smart_Data * sd)2639 _efl_ui_widget_style_get(const Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
2640 {
2641 const char *ret;
2642 ret = "default";
2643 if (sd->style) ret = sd->style;
2644
2645 return ret;
2646 }
2647
2648 EAPI void
elm_widget_tooltip_add(Eo * obj,Elm_Tooltip * tt)2649 elm_widget_tooltip_add(Eo *obj, Elm_Tooltip *tt)
2650 {
2651 Elm_Widget_Smart_Data *sd = efl_data_scope_safe_get(obj, MY_CLASS);
2652 if (!sd) return;
2653
2654 sd->tooltips = eina_list_append(sd->tooltips, tt);
2655 }
2656
2657 EAPI void
elm_widget_tooltip_del(Eo * obj,Elm_Tooltip * tt)2658 elm_widget_tooltip_del(Eo *obj, Elm_Tooltip *tt)
2659 {
2660 Elm_Widget_Smart_Data *sd = efl_data_scope_safe_get(obj, MY_CLASS);
2661 if (!sd) return;
2662
2663 sd->tooltips = eina_list_remove(sd->tooltips, tt);
2664 }
2665
2666 EAPI void
elm_widget_cursor_add(Eo * obj,Elm_Cursor * cur)2667 elm_widget_cursor_add(Eo *obj, Elm_Cursor *cur)
2668 {
2669 Elm_Widget_Smart_Data *sd = efl_data_scope_safe_get(obj, MY_CLASS);
2670 if (!sd) return;
2671
2672 sd->cursors = eina_list_append(sd->cursors, cur);
2673 }
2674
2675 EAPI void
elm_widget_cursor_del(Eo * obj,Elm_Cursor * cur)2676 elm_widget_cursor_del(Eo *obj, Elm_Cursor *cur)
2677 {
2678 Elm_Widget_Smart_Data *sd = efl_data_scope_safe_get(obj, MY_CLASS);
2679 if (!sd) return;
2680
2681 sd->cursors = eina_list_remove(sd->cursors, cur);
2682 }
2683
2684 EAPI void
elm_widget_scroll_lock_set(Eo * obj,Efl_Ui_Layout_Orientation block)2685 elm_widget_scroll_lock_set(Eo *obj, Efl_Ui_Layout_Orientation block)
2686 {
2687 Elm_Widget_Smart_Data *sd = efl_data_scope_safe_get(obj, MY_CLASS);
2688 Eina_Bool lx, ly;
2689
2690 if (!sd) return;
2691 lx = !!(block & EFL_UI_LAYOUT_ORIENTATION_HORIZONTAL);
2692 ly = !!(block & EFL_UI_LAYOUT_ORIENTATION_VERTICAL);
2693 if (sd->scroll_x_locked != lx)
2694 {
2695 sd->scroll_x_locked = lx;
2696 _propagate_x_drag_lock(obj, lx ? 1 : -1);
2697 }
2698 if (sd->scroll_y_locked != ly)
2699 {
2700 sd->scroll_y_locked = ly;
2701 _propagate_y_drag_lock(obj, ly ? 1 : -1);
2702 }
2703 }
2704
2705 EAPI Efl_Ui_Layout_Orientation
elm_widget_scroll_lock_get(const Eo * obj)2706 elm_widget_scroll_lock_get(const Eo *obj)
2707 {
2708 Elm_Widget_Smart_Data *sd = efl_data_scope_safe_get(obj, MY_CLASS);
2709 Efl_Ui_Layout_Orientation block = EFL_UI_LAYOUT_ORIENTATION_DEFAULT;
2710
2711 if (!sd) return block;
2712 if (sd->scroll_x_locked) block |= EFL_UI_LAYOUT_ORIENTATION_HORIZONTAL;
2713 if (sd->scroll_y_locked) block |= EFL_UI_LAYOUT_ORIENTATION_VERTICAL;
2714
2715 return block;
2716 }
2717
2718 EAPI int
elm_widget_scroll_child_locked_x_get(const Eo * obj)2719 elm_widget_scroll_child_locked_x_get(const Eo *obj)
2720 {
2721 Elm_Widget_Smart_Data *sd = efl_data_scope_safe_get(obj, MY_CLASS);
2722 if (!sd) return EINA_FALSE;
2723 return sd->child_drag_x_locked;
2724 }
2725
2726 EAPI int
elm_widget_scroll_child_locked_y_get(const Eo * obj)2727 elm_widget_scroll_child_locked_y_get(const Eo *obj)
2728 {
2729 Elm_Widget_Smart_Data *sd = efl_data_scope_safe_get(obj, MY_CLASS);
2730 if (!sd) return EINA_FALSE;
2731 return sd->child_drag_y_locked;
2732 }
2733
2734 EAPI Eina_Error
elm_widget_theme_object_set(Evas_Object * obj,Evas_Object * edj,const char * wname,const char * welement,const char * wstyle)2735 elm_widget_theme_object_set(Evas_Object *obj, Evas_Object *edj, const char *wname, const char *welement, const char *wstyle)
2736 {
2737 Elm_Widget_Smart_Data *sd = efl_data_scope_safe_get(obj, MY_CLASS);
2738 if (!sd) return EFL_UI_THEME_APPLY_ERROR_GENERIC;
2739
2740 if (eina_streq(welement, "base"))
2741 welement = NULL;
2742 if (eina_streq(wstyle, "default"))
2743 wstyle = NULL;
2744 return _elm_theme_object_set(obj, edj, wname, welement, wstyle);
2745 }
2746
2747 static void
_convert(Efl_Dbg_Info * info,Eina_Iterator * ptr_list)2748 _convert(Efl_Dbg_Info *info, Eina_Iterator *ptr_list)
2749 {
2750 void *p;
2751 int i = 0;
2752
2753 EINA_ITERATOR_FOREACH(ptr_list, p)
2754 {
2755 char name[100];
2756
2757 snprintf(name, sizeof(name), "Candidate %d", i);
2758
2759 EFL_DBG_INFO_APPEND(info, name, EINA_VALUE_TYPE_UINT64, p);
2760 i++;
2761 }
2762
2763 eina_iterator_free(ptr_list);
2764 }
2765
2766 EOLIAN static void
_efl_ui_widget_efl_object_dbg_info_get(Eo * eo_obj,Elm_Widget_Smart_Data * _pd EINA_UNUSED,Efl_Dbg_Info * root)2767 _efl_ui_widget_efl_object_dbg_info_get(Eo *eo_obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED, Efl_Dbg_Info *root)
2768 {
2769 efl_dbg_info_get(efl_super(eo_obj, MY_CLASS), root);
2770 Efl_Ui_Focus_Relations *rel = NULL;
2771 Efl_Dbg_Info *focus, *group = EFL_DBG_INFO_LIST_APPEND(root, MY_CLASS_NAME);
2772
2773 EFL_DBG_INFO_APPEND(group, "Wid-Type", EINA_VALUE_TYPE_STRING, elm_widget_type_get(eo_obj));
2774 EFL_DBG_INFO_APPEND(group, "Style", EINA_VALUE_TYPE_STRING, elm_widget_style_get(eo_obj));
2775 EFL_DBG_INFO_APPEND(group, "Layer", EINA_VALUE_TYPE_INT,
2776 (int) evas_object_layer_get(eo_obj));
2777 EFL_DBG_INFO_APPEND(group, "Scale", EINA_VALUE_TYPE_DOUBLE,
2778 evas_object_scale_get(eo_obj));
2779 EFL_DBG_INFO_APPEND(group, "Has focus", EINA_VALUE_TYPE_CHAR,
2780 elm_object_focus_get(eo_obj));
2781 EFL_DBG_INFO_APPEND(group, "Can focus", EINA_VALUE_TYPE_CHAR,
2782 elm_widget_can_focus_get(eo_obj));
2783 EFL_DBG_INFO_APPEND(group, "Disabled", EINA_VALUE_TYPE_CHAR,
2784 elm_widget_disabled_get(eo_obj));
2785 EFL_DBG_INFO_APPEND(group, "Mirrored", EINA_VALUE_TYPE_CHAR,
2786 efl_ui_mirrored_get(eo_obj));
2787 EFL_DBG_INFO_APPEND(group, "Tree Unfocusable", EINA_VALUE_TYPE_CHAR,
2788 elm_widget_tree_unfocusable_get(eo_obj));
2789 EFL_DBG_INFO_APPEND(group, "Automatic mirroring", EINA_VALUE_TYPE_CHAR,
2790 efl_ui_mirrored_automatic_get(eo_obj));
2791
2792 rel = efl_ui_focus_manager_fetch(_pd->focus.manager, eo_obj);
2793 if (rel)
2794 {
2795 focus = EFL_DBG_INFO_LIST_APPEND(group, "Focus");
2796
2797 EFL_DBG_INFO_APPEND(focus, "logical", EINA_VALUE_TYPE_CHAR, rel->logical );
2798 EFL_DBG_INFO_APPEND(focus, "manager", EINA_VALUE_TYPE_UINT64, _pd->focus.manager);
2799 EFL_DBG_INFO_APPEND(focus, "parent", EINA_VALUE_TYPE_UINT64, rel->parent);
2800 EFL_DBG_INFO_APPEND(focus, "next", EINA_VALUE_TYPE_UINT64 , rel->next);
2801 EFL_DBG_INFO_APPEND(focus, "prev", EINA_VALUE_TYPE_UINT64 , rel->prev);
2802
2803 EFL_DBG_INFO_APPEND(focus, "redirect", EINA_VALUE_TYPE_UINT64 , rel->redirect);
2804
2805 #define ADD_PTR_LIST(name) \
2806 Efl_Dbg_Info* name = EFL_DBG_INFO_LIST_APPEND(focus, ""#name""); \
2807 _convert(name, rel->name);
2808
2809 ADD_PTR_LIST(top)
2810 ADD_PTR_LIST(down)
2811 ADD_PTR_LIST(right)
2812 ADD_PTR_LIST(left)
2813
2814 #undef ADD_PTR_LIST
2815
2816 }
2817
2818 //if that's a focus manager, give useful information like the border elements
2819 if (efl_isa(eo_obj, EFL_UI_FOCUS_MANAGER_INTERFACE))
2820 {
2821 Efl_Dbg_Info *border;
2822
2823 focus = EFL_DBG_INFO_LIST_APPEND(group, "Focus Manager");
2824 border = EFL_DBG_INFO_LIST_APPEND(focus, "Border Elements");
2825
2826 _convert(border,
2827 efl_ui_focus_manager_border_elements_get(eo_obj)
2828 );
2829
2830 EFL_DBG_INFO_APPEND(focus, "redirect", EINA_VALUE_TYPE_UINT64,
2831 efl_ui_focus_manager_redirect_get(eo_obj));
2832 }
2833 }
2834
2835 EAPI Eina_Bool
elm_widget_is_check(const Evas_Object * obj)2836 elm_widget_is_check(const Evas_Object *obj)
2837 {
2838 static int abort_on_warn = -1;
2839 if (elm_widget_is(obj))
2840 return EINA_TRUE;
2841
2842 ERR("Passing Object: %p.", obj);
2843 if (abort_on_warn == -1)
2844 {
2845 if (getenv("ELM_ERROR_ABORT")) abort_on_warn = 1;
2846 else abort_on_warn = 0;
2847 }
2848 if (abort_on_warn == 1) abort();
2849 return EINA_FALSE;
2850 }
2851
2852 /* If you changed a legacy widget's class name,
2853 * please update the "legacy_type_table". */
2854 EAPI const char *
elm_widget_type_get(const Evas_Object * obj)2855 elm_widget_type_get(const Evas_Object *obj)
2856 {
2857 const char *ret;
2858 int i;
2859
2860 API_ENTRY return NULL;
2861
2862 ret = efl_class_name_get(efl_class_get(obj));
2863
2864 /* If the given widget is created for legacy,
2865 * convert type name to legacy. */
2866 if (elm_widget_is_legacy(obj))
2867 {
2868 for (i = 0; legacy_type_table[i][0] ; i++)
2869 {
2870 if (eina_streq(ret, legacy_type_table[i][0]))
2871 return legacy_type_table[i][1];
2872 }
2873 }
2874
2875 return ret;
2876 }
2877
2878 EAPI Eina_Bool
elm_widget_type_check(const Evas_Object * obj,const char * type,const char * func)2879 elm_widget_type_check(const Evas_Object *obj,
2880 const char *type,
2881 const char *func)
2882 {
2883 const char *provided, *expected = "(unknown)";
2884 static int abort_on_warn = -1;
2885
2886 provided = elm_widget_type_get(obj);
2887 /* TODO: eventually migrate to check_ptr version */
2888 if (evas_object_smart_type_check(obj, type)) return EINA_TRUE;
2889 if (type) expected = type;
2890 if ((!provided) || (!provided[0]))
2891 {
2892 provided = evas_object_type_get(obj);
2893 if ((!provided) || (!provided[0]))
2894 provided = "(unknown)";
2895 }
2896 ERR("Passing Object: %p in function: %s, of type: '%s' when expecting"
2897 " type: '%s'", obj, func, provided, expected);
2898 if (abort_on_warn == -1)
2899 {
2900 if (getenv("ELM_ERROR_ABORT")) abort_on_warn = 1;
2901 else abort_on_warn = 0;
2902 }
2903 if (abort_on_warn == 1) abort();
2904 return EINA_FALSE;
2905 }
2906
2907 /** @internal */
2908 EAPI Evas_Object *
elm_widget_name_find(const Eo * obj,const char * name,int recurse)2909 elm_widget_name_find(const Eo *obj, const char *name, int recurse)
2910 {
2911 Evas_Object *child;
2912 const char *s;
2913 INTERNAL_ENTRY NULL;
2914
2915 if (!name) return NULL;
2916 if (!_elm_widget_is(obj)) return NULL;
2917
2918 for (unsigned int i = 0; i < eina_array_count(sd->children); ++i)
2919 {
2920 child = eina_array_data_get(sd->children, i);
2921 s = evas_object_name_get(child);
2922 if ((s) && (!strcmp(s, name))) return child;
2923 if ((recurse != 0) &&
2924 ((child = elm_widget_name_find(child, name, recurse - 1))))
2925 return child;
2926 }
2927 if (sd->hover_obj)
2928 {
2929 s = evas_object_name_get(sd->hover_obj);
2930 if ((s) && (!strcmp(s, name))) return sd->hover_obj;
2931 if ((recurse != 0) &&
2932 ((child = elm_widget_name_find(sd->hover_obj, name, recurse - 1))))
2933 return child;
2934 }
2935 return NULL;
2936 }
2937
2938 /**
2939 * @internal
2940 *
2941 * Split string in words
2942 *
2943 * @param str Source string
2944 * @return List of const words
2945 *
2946 * @see elm_widget_stringlist_free()
2947 * @ingroup Widget
2948 */
2949 EAPI Eina_List *
elm_widget_stringlist_get(const char * str)2950 elm_widget_stringlist_get(const char *str)
2951 {
2952 Eina_List *list = NULL;
2953 const char *s, *b;
2954 if (!str) return NULL;
2955 for (b = s = str; 1; s++)
2956 {
2957 if ((*s == ' ') || (!*s))
2958 {
2959 char *t = malloc(s - b + 1);
2960 if (t)
2961 {
2962 strncpy(t, b, s - b);
2963 t[s - b] = 0;
2964 list = eina_list_append(list, eina_stringshare_add(t));
2965 free(t);
2966 }
2967 b = s + 1;
2968 }
2969 if (!*s) break;
2970 }
2971 return list;
2972 }
2973
2974 EAPI void
elm_widget_stringlist_free(Eina_List * list)2975 elm_widget_stringlist_free(Eina_List *list)
2976 {
2977 const char *s;
2978 EINA_LIST_FREE(list, s)
2979 eina_stringshare_del(s);
2980 }
2981
2982 /* internal */
2983 EAPI void
elm_widget_focus_mouse_up_handle(Eo * obj)2984 elm_widget_focus_mouse_up_handle(Eo *obj)
2985 {
2986 Elm_Widget_Smart_Data *pd = efl_data_scope_get(obj, MY_CLASS);
2987
2988 if (!_is_focusable(obj)) return;
2989
2990 if (pd->focus.manager && !pd->focus.logical)
2991 {
2992 efl_ui_focus_util_focus(obj);
2993 }
2994 }
2995
2996 /*
2997 * @internal
2998 *
2999 * Get the focus highlight geometry of a widget.
3000 *
3001 * @param obj Widget object for the focus highlight
3002 * @param x Focus highlight x coordinate
3003 * @param y Focus highlight y coordinate
3004 * @param w Focus highlight object width
3005 * @param h Focus highlight object height
3006 * @param is_next @c EINA_TRUE if this request is for the new focused object,
3007 * @c EINA_FALSE if this request is for the previously focused object. This
3008 * information becomes important when the focus highlight is changed inside one
3009 * widget.
3010 *
3011 * @ingroup Widget
3012 */
3013 /*
3014 * @internal
3015 *
3016 * Get the 'focus_part' geometry if there is any
3017 *
3018 * This queries if there is a 'focus_part' request from the edc style. If edc
3019 * style offers 'focus_part' edje data item, this function requests for the
3020 * geometry of a specific part which is described in 'focus_part' edje data.
3021 *
3022 * @param obj Widget object for the focus highlight
3023 * @param x Focus highlight x coordinate
3024 * @param y Focus highlight y coordinate
3025 * @param w Focus highlight object width
3026 * @param h Focus highlight object height
3027 *
3028 * x, y, w, h already contain the object's geometry. If there is a 'focus_part'
3029 * support, these values will be updated accordingly or the values will be
3030 * remained as they were.
3031 *
3032 * @ingroup Widget
3033 */
3034 EAPI void
elm_widget_focus_highlight_focus_part_geometry_get(const Evas_Object * obj,Evas_Coord * x,Evas_Coord * y,Evas_Coord * w,Evas_Coord * h)3035 elm_widget_focus_highlight_focus_part_geometry_get(const Evas_Object *obj,
3036 Evas_Coord *x,
3037 Evas_Coord *y,
3038 Evas_Coord *w,
3039 Evas_Coord *h)
3040 {
3041 Evas_Coord tx = 0, ty = 0, tw = 0, th = 0;
3042 const char *target_hl_part = NULL;
3043 const Evas_Object *edje_obj = NULL;
3044
3045 if (obj && efl_isa(obj, EFL_CANVAS_LAYOUT_CLASS))
3046 {
3047 edje_obj = obj;
3048 if (!(target_hl_part = edje_object_data_get(edje_obj, "focus_part")))
3049 return;
3050 }
3051 else if (obj && efl_isa(obj, EFL_UI_LAYOUT_BASE_CLASS))
3052 {
3053 edje_obj = elm_layout_edje_get(obj);
3054 if (!(target_hl_part = elm_layout_data_get(obj, "focus_part")))
3055 return;
3056 }
3057 else
3058 return;
3059
3060 edje_object_part_geometry_get(edje_obj, target_hl_part,
3061 &tx, &ty, &tw, &th);
3062 *x += tx;
3063 *y += ty;
3064 if (tw != *w) *w = tw;
3065 if (th != *h) *h = th;
3066 }
3067
3068 EOLIAN static Eina_Rect
_efl_ui_widget_focus_highlight_geometry_get(const Eo * obj,Elm_Widget_Smart_Data * sd)3069 _efl_ui_widget_focus_highlight_geometry_get(const Eo *obj, Elm_Widget_Smart_Data *sd)
3070 {
3071 Evas_Coord ox = 0, oy = 0, ow = 0, oh = 0;
3072 Evas_Object *scroller = (Evas_Object *)obj;
3073 Eina_Rect r = {};
3074
3075 evas_object_geometry_get(obj, &r.x, &r.y, &r.w, &r.h);
3076 elm_widget_focus_highlight_focus_part_geometry_get(sd->resize_obj, &r.x, &r.y, &r.w, &r.h);
3077
3078 if (_elm_config->focus_autoscroll_mode != ELM_FOCUS_AUTOSCROLL_MODE_BRING_IN)
3079 return r;
3080
3081 while (scroller)
3082 {
3083 if (_elm_scrollable_is(scroller))
3084 {
3085 elm_interface_scrollable_content_viewport_geometry_get(scroller, &ox, &oy, &ow, &oh);
3086
3087 if (r.y < oy)
3088 r.y = oy;
3089 else if ((oy + oh) < (r.y + r.h))
3090 r.y = (oy + oh - r.h);
3091 else if (r.x < ox)
3092 r.x = ox;
3093 else if ((ox + ow) < (r.x + r.w))
3094 r.x = (ox + ow - r.w);
3095
3096 break;
3097 }
3098 scroller = elm_widget_parent_get(scroller);
3099 }
3100
3101 return r;
3102 }
3103
3104 EAPI void
elm_widget_activate(Evas_Object * obj,Efl_Ui_Activate act)3105 elm_widget_activate(Evas_Object *obj, Efl_Ui_Activate act)
3106 {
3107 Evas_Object *parent;
3108 Eina_Bool ret;
3109
3110 ELM_WIDGET_CHECK(obj);
3111
3112 ret = EINA_FALSE;
3113
3114 ret = efl_ui_widget_on_access_activate(obj, act);
3115
3116 if (ret) return;
3117
3118 parent = elm_widget_parent_get(obj);
3119 if (parent)
3120 elm_widget_activate(parent, act);
3121
3122 return;
3123 }
3124
3125 /**
3126 * @internal
3127 *
3128 * Sets the widget and child widget's Evas_Display_Mode.
3129 *
3130 * @param obj The widget.
3131 * @param dispmode Evas_Display_Mode to set widget's mode.
3132 *
3133 * Widgets are resized by several reasons.
3134 * Evas_Display_Mode can help for widgets to get one more reason of resize.
3135 * For example, elm conform widget resizes it's contents when keypad state changed.
3136 * After keypad showing, conform widget can change child's Evas_Display_Mode.
3137 * @ingroup Widget
3138 */
3139 /* Legacy only */
3140 EAPI void
elm_widget_display_mode_set(Evas_Object * obj,Evas_Display_Mode dispmode)3141 elm_widget_display_mode_set(Evas_Object *obj, Evas_Display_Mode dispmode)
3142 {
3143 Evas_Display_Mode prev_dispmode;
3144 Evas_Object *child;
3145
3146 API_ENTRY return;
3147 prev_dispmode = evas_object_size_hint_display_mode_get(obj);
3148
3149 if ((prev_dispmode == dispmode) ||
3150 (prev_dispmode == EVAS_DISPLAY_MODE_DONT_CHANGE)) return;
3151
3152 evas_object_size_hint_display_mode_set(obj, dispmode);
3153
3154 for (unsigned int i = 0; i < eina_array_count(sd->children); ++i)
3155 {
3156 child = eina_array_data_get(sd->children, i);
3157 if (elm_widget_is(child))
3158 elm_widget_display_mode_set(child, dispmode);
3159 }
3160 }
3161
3162 /**
3163 * @internal
3164 *
3165 * Returns the widget's focus move policy.
3166 *
3167 * @param obj The widget.
3168 * @return focus move policy of the object.
3169 *
3170 **/
3171 EOLIAN static Efl_Ui_Focus_Move_Policy
_efl_ui_widget_focus_move_policy_get(const Eo * obj EINA_UNUSED,Elm_Widget_Smart_Data * sd)3172 _efl_ui_widget_focus_move_policy_get(const Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
3173 {
3174 return (Efl_Ui_Focus_Move_Policy)sd->focus_move_policy;
3175 }
3176
3177 /**
3178 * @internal
3179 *
3180 * Sets the widget's focus move policy.
3181 *
3182 * @param obj The widget.
3183 * @param policy Elm_Focus_Move_Policy to set object's focus move policy.
3184 */
3185
3186 EOLIAN static void
_efl_ui_widget_focus_move_policy_set(Eo * obj EINA_UNUSED,Elm_Widget_Smart_Data * sd,Efl_Ui_Focus_Move_Policy policy)3187 _efl_ui_widget_focus_move_policy_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, Efl_Ui_Focus_Move_Policy policy)
3188 {
3189 if (sd->focus_move_policy == (Elm_Focus_Move_Policy)policy) return;
3190 sd->focus_move_policy = (Elm_Focus_Move_Policy)policy;
3191 }
3192
3193 /**
3194 * Returns the widget's focus_move_policy mode setting.
3195 *
3196 * @param obj The widget.
3197 * @return focus_move_policy mode setting of the object.
3198 *
3199 **/
3200 EOLIAN static Eina_Bool
_efl_ui_widget_focus_move_policy_automatic_get(const Eo * obj EINA_UNUSED,Elm_Widget_Smart_Data * sd)3201 _efl_ui_widget_focus_move_policy_automatic_get(const Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
3202 {
3203 return sd->focus_move_policy_auto_mode;
3204 }
3205
3206 /**
3207 * @internal
3208 *
3209 * Sets the widget's focus_move_policy mode setting.
3210 * When widget in automatic mode, it follows the system focus_move_policy mode set by
3211 * elm_config_focus_move_policy_set().
3212 * @param obj The widget.
3213 * @param automatic EINA_TRUE for auto focus_move_policy mode. EINA_FALSE for manual.
3214 */
3215 EOLIAN static void
_efl_ui_widget_focus_move_policy_automatic_set(Eo * obj,Elm_Widget_Smart_Data * sd,Eina_Bool automatic)3216 _efl_ui_widget_focus_move_policy_automatic_set(Eo *obj, Elm_Widget_Smart_Data *sd, Eina_Bool automatic)
3217 {
3218 if (sd->focus_move_policy_auto_mode != automatic)
3219 {
3220 sd->focus_move_policy_auto_mode = automatic;
3221
3222 if (automatic)
3223 {
3224 efl_ui_widget_focus_move_policy_set
3225 (obj, (Efl_Ui_Focus_Move_Policy)elm_config_focus_move_policy_get());
3226 }
3227 }
3228 }
3229
3230 /**
3231 * @internal
3232 *
3233 * Sets the klass name of a widget.
3234 * @param obj The widget.
3235 * @param name Name of the klass to use.
3236 * @return Whether the name was different and thus replaced.
3237 */
3238 EAPI Eina_Bool
elm_widget_theme_klass_set(Evas_Object * obj,const char * name)3239 elm_widget_theme_klass_set(Evas_Object *obj, const char *name)
3240 {
3241 Elm_Widget_Smart_Data *pd = efl_data_scope_safe_get(obj, MY_CLASS);
3242 if (!pd) return EINA_FALSE;
3243
3244 return eina_stringshare_replace(&(pd->klass), name);
3245 }
3246
3247 /**
3248 * @internal
3249 *
3250 * Gets the klass name of a widget.
3251 * @param obj The widget.
3252 * @return The current klass name of internal canvas object.
3253 */
3254 EAPI const char *
elm_widget_theme_klass_get(const Evas_Object * obj)3255 elm_widget_theme_klass_get(const Evas_Object *obj)
3256 {
3257 Elm_Widget_Smart_Data *pd = efl_data_scope_safe_get(obj, MY_CLASS);
3258 if (!pd) return NULL;
3259
3260 return (const char *)pd->klass;
3261 }
3262
3263 /**
3264 * @internal
3265 *
3266 * Sets the element name of a widget.
3267 *
3268 * @param obj The widget.
3269 * @param name Name of the element to use.
3270 * @return Whether the name was different and thus replaced.
3271 */
3272 EAPI Eina_Bool
elm_widget_theme_element_set(Evas_Object * obj,const char * name)3273 elm_widget_theme_element_set(Evas_Object *obj, const char *name)
3274 {
3275 Elm_Widget_Smart_Data *pd = efl_data_scope_safe_get(obj, MY_CLASS);
3276 if (!pd) return EINA_FALSE;
3277
3278 if (eina_streq(name, "base"))
3279 name = NULL;
3280
3281 return eina_stringshare_replace(&(pd->group), name);
3282 }
3283
3284 /**
3285 * @internal
3286 *
3287 * Gets the element name of a widget.
3288 * @param obj The widget.
3289 * @return The current element name of internal canvas object.
3290 */
3291 EAPI const char *
elm_widget_theme_element_get(const Evas_Object * obj)3292 elm_widget_theme_element_get(const Evas_Object *obj)
3293 {
3294 Elm_Widget_Smart_Data *pd = efl_data_scope_safe_get(obj, MY_CLASS);
3295 if (!pd) return NULL;
3296
3297 return (const char *)pd->group;
3298 }
3299
3300 /**
3301 * @internal
3302 *
3303 * Sets the style name of a widget.
3304 *
3305 * @param obj The widget.
3306 * @param name Name of the style to use.
3307 * @return Whether the name was different and thus replaced.
3308 */
3309 EAPI Eina_Bool
elm_widget_theme_style_set(Evas_Object * obj,const char * name)3310 elm_widget_theme_style_set(Evas_Object *obj, const char *name)
3311 {
3312 Elm_Widget_Smart_Data *pd = efl_data_scope_safe_get(obj, MY_CLASS);
3313 if (!pd) return EINA_FALSE;
3314
3315 if (eina_streq(name, "default"))
3316 name = NULL;
3317
3318 return eina_stringshare_replace(&(pd->style), name);
3319 }
3320
3321 /**
3322 * @internal
3323 *
3324 * Gets the style name of a widget.
3325 * @param obj The widget.
3326 * @return The current style name of internal canvas object.
3327 */
3328 EAPI const char *
elm_widget_theme_style_get(const Evas_Object * obj)3329 elm_widget_theme_style_get(const Evas_Object *obj)
3330 {
3331 Elm_Widget_Smart_Data *pd = efl_data_scope_safe_get(obj, MY_CLASS);
3332 if (!pd) return NULL;
3333
3334 return (const char *)pd->style;
3335 }
3336
3337 /**
3338 * @internal
3339 *
3340 * Register sub object as a group of a widget and re-apply its theme.
3341 * @param obj The widget.
3342 * @param component A sub object to be added as an element of the widget.
3343 * @param name An element name of sub object.
3344 * @return Whether the style was successfully applied or not.
3345 */
3346 EAPI Eina_Error
elm_widget_element_update(Evas_Object * obj,Evas_Object * component,const char * name)3347 elm_widget_element_update(Evas_Object *obj, Evas_Object *component, const char *name)
3348 {
3349 Eina_Error ret = EFL_UI_THEME_APPLY_ERROR_NONE;
3350 Eina_Bool changed = EINA_FALSE;
3351 const char *obj_group;
3352 Eina_Stringshare *group;
3353
3354 obj_group = elm_widget_theme_element_get(obj);
3355 if (!obj_group)
3356 group = eina_stringshare_add(name);
3357 else
3358 group = eina_stringshare_printf("%s/%s", elm_widget_theme_element_get(obj), name);
3359 if (efl_isa(component, EFL_UI_WIDGET_CLASS))
3360 {
3361 changed |= elm_widget_theme_klass_set(component, elm_widget_theme_klass_get(obj));
3362 changed |= elm_widget_theme_element_set(component, (const char *)group);
3363 changed |= elm_widget_theme_style_set(component, elm_widget_theme_style_get(obj));
3364 if (changed)
3365 ret = efl_ui_widget_theme_apply(component);
3366 }
3367 else
3368 {
3369 ret = elm_widget_theme_object_set(obj, component,
3370 elm_widget_theme_klass_get(obj),
3371 (const char *)group,
3372 elm_widget_theme_style_get(obj));
3373 }
3374 eina_stringshare_del(group);
3375
3376 return ret;
3377 }
3378
3379 static void
3380 _track_obj_del(void *data, Evas *e, Evas_Object *obj, void *event_info);
3381
3382 static void
_track_obj_update(Evas_Object * track,Evas_Object * obj)3383 _track_obj_update(Evas_Object *track, Evas_Object *obj)
3384 {
3385 //Geometry
3386 Evas_Coord x, y, w, h;
3387 evas_object_geometry_get(obj, &x, &y, &w, &h);
3388 evas_object_geometry_set(track, x, y, w, h);
3389
3390 //Visibility
3391 if (evas_object_visible_get(obj)) evas_object_show(track);
3392 else evas_object_hide(track);
3393 }
3394
3395 static void
_track_obj_view_update(void * data,const Efl_Event * event)3396 _track_obj_view_update(void *data, const Efl_Event *event)
3397 {
3398 Elm_Widget_Item_Data *item = data;
3399 _track_obj_update(item->track_obj, event->object);
3400 }
3401
3402 static void
3403 _track_obj_view_del(void *data, const Efl_Event *event);
3404
3405 EFL_CALLBACKS_ARRAY_DEFINE(tracker_callbacks,
3406 { EFL_GFX_ENTITY_EVENT_SIZE_CHANGED, _track_obj_view_update },
3407 { EFL_GFX_ENTITY_EVENT_POSITION_CHANGED, _track_obj_view_update },
3408 { EFL_GFX_ENTITY_EVENT_VISIBILITY_CHANGED, _track_obj_view_update },
3409 { EFL_EVENT_DEL, _track_obj_view_del });
3410
3411 static void
_track_obj_view_del(void * data,const Efl_Event * event EINA_UNUSED)3412 _track_obj_view_del(void *data, const Efl_Event *event EINA_UNUSED)
3413 {
3414 Elm_Widget_Item_Data *item = data;
3415
3416 while (evas_object_ref_get(item->track_obj) > 0)
3417 evas_object_unref(item->track_obj);
3418
3419 evas_object_event_callback_del(item->track_obj, EVAS_CALLBACK_DEL,
3420 _track_obj_del);
3421 evas_object_del(item->track_obj);
3422 item->track_obj = NULL;
3423 }
3424
3425 static void
_track_obj_del(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)3426 _track_obj_del(void *data, Evas *e EINA_UNUSED,
3427 Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
3428 {
3429 Elm_Widget_Item_Data *item = data;
3430 item->track_obj = NULL;
3431
3432 if (!item->view) return;
3433
3434 efl_event_callback_array_del(item->view, tracker_callbacks(), item);
3435 }
3436
3437 static void
_elm_widget_item_signal_cb(void * data,Evas_Object * obj EINA_UNUSED,const char * emission,const char * source)3438 _elm_widget_item_signal_cb(void *data, Evas_Object *obj EINA_UNUSED, const char *emission,
3439 const char *source)
3440 {
3441 Elm_Widget_Item_Signal_Data *wisd = data;
3442 wisd->func(wisd->data, wisd->item, emission, source);
3443 }
3444
3445 static void *
_elm_widget_item_signal_callback_list_get(Elm_Widget_Item_Data * item,Eina_List * position)3446 _elm_widget_item_signal_callback_list_get(Elm_Widget_Item_Data *item, Eina_List *position)
3447 {
3448 Elm_Widget_Item_Signal_Data *wisd = eina_list_data_get(position);
3449 void *data;
3450
3451 item->signals = eina_list_remove_list(item->signals, position);
3452 data = wisd->data;
3453
3454 if (_elm_widget_is(item->view))
3455 elm_object_signal_callback_del(item->view,
3456 wisd->emission, wisd->source,
3457 _elm_widget_item_signal_cb);
3458 else if (efl_isa(item->view, EFL_CANVAS_LAYOUT_CLASS))
3459 edje_object_signal_callback_del_full(item->view,
3460 wisd->emission, wisd->source,
3461 _elm_widget_item_signal_cb, wisd);
3462
3463 eina_stringshare_del(wisd->emission);
3464 eina_stringshare_del(wisd->source);
3465 free(wisd);
3466
3467 return data;
3468 }
3469
3470 #define ERR_NOT_SUPPORTED(item, method) ERR("%s does not support %s API.", elm_widget_type_get(item->widget), method);
3471
3472 static void
_efl_del_cb(void * data EINA_UNUSED,const Efl_Event * event)3473 _efl_del_cb(void *data EINA_UNUSED, const Efl_Event *event)
3474 {
3475 Elm_Widget_Item_Data *item = efl_data_scope_get(event->object, ELM_WIDGET_ITEM_CLASS);
3476 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3477 if (item->del_func)
3478 item->del_func((void *) WIDGET_ITEM_DATA_GET(event->object), item->widget, item->eo_obj);
3479 }
3480
3481 /**
3482 * @internal
3483 *
3484 * Allocate a new Elm_Widget_Item-derived structure.
3485 *
3486 * The goal of this structure is to provide common ground for actions
3487 * that a widget item have, such as the owner widget, callback to
3488 * notify deletion, data pointer and maybe more.
3489 *
3490 * @param widget the owner widget that holds this item, must be an elm_widget!
3491 * @param alloc_size any number greater than sizeof(Elm_Widget_Item) that will
3492 * be used to allocate memory.
3493 *
3494 * @return allocated memory that is already zeroed out, or NULL on errors.
3495 *
3496 * @see elm_widget_item_new() convenience macro.
3497 * @see elm_widget_item_del() to release memory.
3498 * @ingroup Widget
3499 */
3500 EOLIAN static Eo *
_elm_widget_item_efl_object_constructor(Eo * eo_item,Elm_Widget_Item_Data * item)3501 _elm_widget_item_efl_object_constructor(Eo *eo_item, Elm_Widget_Item_Data *item)
3502 {
3503 Evas_Object *widget;
3504 widget = efl_parent_get(eo_item);
3505
3506 if (!_elm_widget_is(widget))
3507 {
3508 ERR("Failed");
3509 return NULL;
3510 }
3511
3512 eo_item = efl_constructor(efl_super(eo_item, ELM_WIDGET_ITEM_CLASS));
3513
3514 EINA_MAGIC_SET(item, ELM_WIDGET_ITEM_MAGIC);
3515
3516 item->widget = widget;
3517 item->eo_obj = eo_item;
3518 efl_event_callback_add(eo_item, EFL_EVENT_DEL, _efl_del_cb, NULL);
3519
3520 return eo_item;
3521 }
3522
3523 EOLIAN static void
_elm_widget_item_efl_object_destructor(Eo * eo_item,Elm_Widget_Item_Data * item)3524 _elm_widget_item_efl_object_destructor(Eo *eo_item, Elm_Widget_Item_Data *item)
3525 {
3526 Elm_Translate_String_Data *ts;
3527
3528 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3529
3530 eina_stringshare_del(item->style);
3531 eina_stringshare_del(item->access_info);
3532 eina_stringshare_del(item->accessible_name);
3533
3534 while (item->signals)
3535 _elm_widget_item_signal_callback_list_get(item, item->signals);
3536
3537 while (item->translate_strings)
3538 {
3539 ts = EINA_INLIST_CONTAINER_GET(item->translate_strings,
3540 Elm_Translate_String_Data);
3541 eina_stringshare_del(ts->id);
3542 eina_stringshare_del(ts->domain);
3543 eina_stringshare_del(ts->string);
3544 item->translate_strings = eina_inlist_remove(item->translate_strings,
3545 item->translate_strings);
3546 free(ts);
3547 }
3548 eina_hash_free(item->labels);
3549
3550 efl_access_object_attributes_clear(eo_item);
3551 efl_access_removed(eo_item);
3552
3553 EINA_MAGIC_SET(item, EINA_MAGIC_NONE);
3554
3555 efl_destructor(efl_super(eo_item, ELM_WIDGET_ITEM_CLASS));
3556 }
3557
3558 /**
3559 * @internal
3560 *
3561 * Releases widget item memory, calling back item_del_pre_hook() and
3562 * item_del_cb() if they exist.
3563 *
3564 * @param item a valid #Elm_Widget_Item to be deleted.
3565 *
3566 * If there is an Elm_Widget_Item::del_cb, then it will be called prior
3567 * to memory release. Note that elm_widget_item_pre_notify_del() calls
3568 * this function and then unset it, thus being useful for 2 step
3569 * cleanup whenever the del_cb may use any of the data that must be
3570 * deleted from item.
3571 *
3572 * The Elm_Widget_Item::view will be deleted (evas_object_del()) if it
3573 * is presented!
3574 *
3575 * Note that if item_del_pre_hook() returns @c EINA_TRUE, item free will be
3576 * deferred, or item will be freed here if it returns @c EINA_FALSE.
3577 *
3578 * @see elm_widget_item_del() convenience macro.
3579 * @ingroup Widget
3580 */
3581 EOLIAN static void
_elm_widget_item_efl_object_invalidate(Eo * eo_item,Elm_Widget_Item_Data * item)3582 _elm_widget_item_efl_object_invalidate(Eo *eo_item, Elm_Widget_Item_Data *item)
3583 {
3584 Evas_Object *view;
3585
3586 //Widget item delete callback
3587 elm_wdg_item_del_pre(item->eo_obj);
3588
3589 view = item->view;
3590 if (item->view) efl_wref_del(item->view, &item->view);
3591 // FIXME: Is view an Efl.Ui or a legacy object ?
3592 evas_object_del(view);
3593 item->view = NULL;
3594
3595 efl_invalidate(efl_super(eo_item, ELM_WIDGET_ITEM_CLASS));
3596 }
3597
3598 EOLIAN static void
_elm_widget_item_del_pre(Eo * eo_item EINA_UNUSED,Elm_Widget_Item_Data * item EINA_UNUSED)3599 _elm_widget_item_del_pre(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item EINA_UNUSED)
3600 {
3601 }
3602
3603 /**
3604 * @internal
3605 *
3606 * Notify object will be deleted without actually deleting it.
3607 *
3608 * This function will callback Elm_Widget_Item::del_cb if it is set
3609 * and then unset it so it is not called twice (ie: from
3610 * elm_widget_item_del()).
3611 *
3612 * @param item a valid #Elm_Widget_Item to be notified
3613 * @see elm_widget_item_pre_notify_del() convenience macro.
3614 * @ingroup Widget
3615 */
3616 EOLIAN static void
_elm_widget_item_pre_notify_del(Eo * eo_item,Elm_Widget_Item_Data * item)3617 _elm_widget_item_pre_notify_del(Eo *eo_item, Elm_Widget_Item_Data *item)
3618 {
3619 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3620 if (!item->del_func) return;
3621 item->del_func((void *)WIDGET_ITEM_DATA_GET(eo_item), item->widget, item->eo_obj);
3622 item->del_func = NULL;
3623 }
3624
3625 /**
3626 * @internal
3627 *
3628 * Set the function to notify when item is being deleted.
3629 *
3630 * This function will complain if there was a callback set already,
3631 * however it will set the new one.
3632 *
3633 * The callback will be called from elm_widget_item_pre_notify_del()
3634 * or elm_widget_item_del() will be called with:
3635 * - data: the Elm_Widget_Item::data value.
3636 * - obj: the Elm_Widget_Item::widget evas object.
3637 * - event_info: the item being deleted.
3638 *
3639 * @param item a valid #Elm_Widget_Item to be notified
3640 * @see elm_widget_item_del_cb_set() convenience macro.
3641 * @ingroup Widget
3642 */
3643 EOLIAN static void
_elm_widget_item_del_cb_set(Eo * eo_item EINA_UNUSED,Elm_Widget_Item_Data * item,Evas_Smart_Cb func)3644 _elm_widget_item_del_cb_set(Eo *eo_item EINA_UNUSED,
3645 Elm_Widget_Item_Data *item,
3646 Evas_Smart_Cb func)
3647 {
3648 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3649 ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
3650
3651 if ((item->del_func) && (item->del_func != func))
3652 WRN("You're replacing a previously set del_cb %p of item %p with %p",
3653 item->del_func, item->eo_obj, func);
3654
3655 item->del_func = func;
3656 }
3657
3658 /**
3659 * @internal
3660 *
3661 * Get owner widget of this item.
3662 *
3663 * @param item a valid #Elm_Widget_Item to get data from.
3664 * @return owner widget of this item.
3665 * @ingroup Widget
3666 */
3667 EOLIAN static Evas_Object *
_elm_widget_item_widget_get(const Eo * eo_item EINA_UNUSED,Elm_Widget_Item_Data * item)3668 _elm_widget_item_widget_get(const Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
3669 {
3670 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
3671 ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item, NULL);
3672
3673 return item->widget;
3674 }
3675
3676 EAPI Eina_Bool
_elm_widget_onscreen_is(const Evas_Object * widget)3677 _elm_widget_onscreen_is(const Evas_Object *widget)
3678 {
3679 Evas_Object *parent = (Evas_Object *)widget;
3680 Eina_Rectangle r1, r2;
3681
3682 Evas *evas = evas_object_evas_get(widget);
3683 if (!evas) return EINA_FALSE;
3684
3685 evas_object_geometry_get(widget, &r1.x, &r1.y, &r1.w, &r1.h);
3686 if (eina_rectangle_is_empty(&r1))
3687 return EINA_FALSE;
3688
3689 // window does not have to check viewport and geometry
3690 if (efl_isa(widget, EFL_UI_WIN_CLASS))
3691 return EINA_TRUE;
3692
3693 // check if on canvas
3694 evas_output_viewport_get(evas, &r2.x, &r2.y, &r2.w, &r2.h);
3695 if (!eina_rectangles_intersect(&r1, &r2))
3696 return EINA_FALSE;
3697
3698 // check if inside scrollable parent viewport
3699 do {
3700 parent = elm_widget_parent_get(parent);
3701 if (parent && !evas_object_visible_get(parent))
3702 return EINA_FALSE;
3703 if (parent && efl_isa(parent, ELM_INTERFACE_SCROLLABLE_MIXIN))
3704 {
3705 evas_object_geometry_get(parent, &r2.x, &r2.y, &r2.w, &r2.h);
3706 if (!eina_rectangles_intersect(&r1, &r2))
3707 return EINA_FALSE;
3708 }
3709 } while (parent && (parent != elm_widget_top_get(widget)));
3710
3711 return EINA_TRUE;
3712 }
3713
3714 EAPI Eina_Bool
_elm_widget_item_onscreen_is(const Elm_Object_Item * item)3715 _elm_widget_item_onscreen_is(const Elm_Object_Item *item)
3716 {
3717 Eina_Rectangle r1, r2;
3718 Elm_Widget_Item_Data *id = efl_data_scope_get(item, ELM_WIDGET_ITEM_CLASS);
3719 if (!id || !id->view) return EINA_FALSE;
3720
3721 if (!evas_object_visible_get(id->view))
3722 return EINA_FALSE;
3723
3724 if (!_elm_widget_onscreen_is(id->widget))
3725 return EINA_FALSE;
3726
3727 evas_object_geometry_get(id->view, &r1.x, &r1.y, &r1.w, &r1.h);
3728 if (eina_rectangle_is_empty(&r1))
3729 return EINA_FALSE;
3730
3731 evas_object_geometry_get(id->widget, &r2.x, &r2.y, &r2.w, &r2.h);
3732 if (!eina_rectangles_intersect(&r1, &r2))
3733 return EINA_FALSE;
3734
3735 return EINA_TRUE;
3736 }
3737
3738 const char*
_elm_widget_accessible_plain_name_get(const Evas_Object * obj,const char * name)3739 _elm_widget_accessible_plain_name_get(const Evas_Object *obj, const char* name)
3740 {
3741 char *accessible_plain_name;
3742
3743 API_ENTRY return NULL;
3744
3745 accessible_plain_name = _elm_util_mkup_to_text(name);
3746 eina_stringshare_del(sd->accessible_name);
3747 sd->accessible_name = eina_stringshare_add(accessible_plain_name);
3748 free(accessible_plain_name);
3749 return sd->accessible_name;
3750 }
3751
3752 const char*
_elm_widget_item_accessible_plain_name_get(const Elm_Object_Item * item,const char * name)3753 _elm_widget_item_accessible_plain_name_get(const Elm_Object_Item *item, const char* name)
3754 {
3755 char *accessible_plain_name;
3756
3757 Elm_Widget_Item_Data *id = efl_data_scope_get(item, ELM_WIDGET_ITEM_CLASS);
3758 if (!id) return NULL;
3759
3760 accessible_plain_name = _elm_util_mkup_to_text(name);
3761 eina_stringshare_del(id->accessible_name);
3762 id->accessible_name = eina_stringshare_add(accessible_plain_name);
3763 free(accessible_plain_name);
3764 return id->accessible_name;
3765 }
3766
3767 EOLIAN static Efl_Access_State_Set
_elm_widget_item_efl_access_object_state_set_get(const Eo * eo_item,Elm_Widget_Item_Data * item EINA_UNUSED)3768 _elm_widget_item_efl_access_object_state_set_get(const Eo *eo_item,
3769 Elm_Widget_Item_Data *item EINA_UNUSED)
3770 {
3771 Efl_Access_State_Set states = 0;
3772
3773 STATE_TYPE_SET(states, EFL_ACCESS_STATE_TYPE_FOCUSABLE);
3774
3775 if (elm_object_item_focus_get(eo_item))
3776 STATE_TYPE_SET(states, EFL_ACCESS_STATE_TYPE_FOCUSED);
3777 if (!elm_object_item_disabled_get(eo_item))
3778 {
3779 STATE_TYPE_SET(states, EFL_ACCESS_STATE_TYPE_ENABLED);
3780 STATE_TYPE_SET(states, EFL_ACCESS_STATE_TYPE_SENSITIVE);
3781 STATE_TYPE_SET(states, EFL_ACCESS_STATE_TYPE_VISIBLE);
3782 }
3783 if (_elm_widget_item_onscreen_is(eo_item))
3784 STATE_TYPE_SET(states, EFL_ACCESS_STATE_TYPE_SHOWING);
3785
3786 return states;
3787 }
3788
3789 EAPI void
elm_object_item_data_set(Elm_Object_Item * it,void * data)3790 elm_object_item_data_set(Elm_Object_Item *it, void *data)
3791 {
3792 WIDGET_ITEM_DATA_SET(it, data);
3793 }
3794
3795 EAPI void *
elm_object_item_data_get(const Elm_Object_Item * it)3796 elm_object_item_data_get(const Elm_Object_Item *it)
3797 {
3798 return (void *) WIDGET_ITEM_DATA_GET(it);
3799 }
3800
3801 EOLIAN static void
_elm_widget_item_disabled_set(Eo * eo_item EINA_UNUSED,Elm_Widget_Item_Data * item,Eina_Bool disabled)3802 _elm_widget_item_disabled_set(Eo *eo_item EINA_UNUSED,
3803 Elm_Widget_Item_Data *item,
3804 Eina_Bool disabled)
3805 {
3806 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3807 ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
3808
3809 if (item->disabled == disabled) return;
3810 item->disabled = !!disabled;
3811 elm_wdg_item_disable(item->eo_obj);
3812 }
3813
3814 EOLIAN static Eina_Bool
_elm_widget_item_disabled_get(const Eo * eo_item EINA_UNUSED,Elm_Widget_Item_Data * item)3815 _elm_widget_item_disabled_get(const Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
3816 {
3817 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, EINA_FALSE);
3818 return item->disabled;
3819 }
3820
3821 EOLIAN static void
_elm_widget_item_style_set(Eo * eo_item EINA_UNUSED,Elm_Widget_Item_Data * item,const char * style)3822 _elm_widget_item_style_set(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item, const char *style)
3823 {
3824 eina_stringshare_replace(&item->style, style);
3825 }
3826
3827 EOLIAN static const char *
_elm_widget_item_style_get(const Eo * eo_item EINA_UNUSED,Elm_Widget_Item_Data * item)3828 _elm_widget_item_style_get(const Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
3829 {
3830 return item->style;
3831 }
3832
3833 EOLIAN static void
_elm_widget_item_disable(Eo * eo_item EINA_UNUSED,Elm_Widget_Item_Data * item EINA_UNUSED)3834 _elm_widget_item_disable(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item EINA_UNUSED)
3835 {
3836 }
3837
3838 EOLIAN static void
_elm_widget_item_item_focus_set(Eo * eo_item EINA_UNUSED,Elm_Widget_Item_Data * item,Eina_Bool focused EINA_UNUSED)3839 _elm_widget_item_item_focus_set(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item, Eina_Bool focused EINA_UNUSED)
3840 {
3841 ERR_NOT_SUPPORTED(item, "elm_object_item_focus_set");
3842 }
3843
3844 EOLIAN static Eina_Bool
_elm_widget_item_item_focus_get(const Eo * eo_item EINA_UNUSED,Elm_Widget_Item_Data * item)3845 _elm_widget_item_item_focus_get(const Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
3846 {
3847 ERR_NOT_SUPPORTED(item, "elm_object_item_focus_get");
3848 return EINA_FALSE;
3849 }
3850
3851 EOLIAN static void
_elm_widget_item_domain_translatable_part_text_set(Eo * eo_item EINA_UNUSED,Elm_Widget_Item_Data * item,const char * part,const char * domain,const char * label)3852 _elm_widget_item_domain_translatable_part_text_set(Eo *eo_item EINA_UNUSED,
3853 Elm_Widget_Item_Data *item,
3854 const char *part,
3855 const char *domain,
3856 const char *label)
3857 {
3858 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3859 ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
3860 Elm_Translate_String_Data *ts;
3861
3862 if (!label)
3863 {
3864 _part_text_translatable_set(&item->translate_strings, part, EINA_FALSE,
3865 EINA_FALSE);
3866 }
3867 else
3868 {
3869 ts = _part_text_translatable_set(&item->translate_strings, part,
3870 EINA_TRUE, EINA_FALSE);
3871 if (!ts) return;
3872 if (!ts->string) ts->string = eina_stringshare_add(label);
3873 else eina_stringshare_replace(&ts->string, label);
3874 if (!ts->domain) ts->domain = eina_stringshare_add(domain);
3875 else eina_stringshare_replace(&ts->domain, domain);
3876 #ifdef HAVE_GETTEXT
3877 if (label[0]) label = dgettext(domain, label);
3878 #endif
3879 }
3880 item->on_translate = EINA_TRUE;
3881 elm_wdg_item_part_text_set(item->eo_obj, part, label);
3882 item->on_translate = EINA_FALSE;
3883 }
3884
3885 EOLIAN static const char *
_elm_widget_item_translatable_part_text_get(const Eo * eo_item EINA_UNUSED,Elm_Widget_Item_Data * item,const char * part)3886 _elm_widget_item_translatable_part_text_get(const Eo *eo_item EINA_UNUSED,
3887 Elm_Widget_Item_Data *item,
3888 const char *part)
3889 {
3890 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
3891 ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item, NULL);
3892
3893 Elm_Translate_String_Data *ts;
3894 ts = _translate_string_data_get(item->translate_strings, part);
3895 if (ts) return ts->string;
3896 return NULL;
3897 }
3898
3899 EOLIAN static void
_elm_widget_item_domain_part_text_translatable_set(Eo * eo_item EINA_UNUSED,Elm_Widget_Item_Data * item,const char * part,const char * domain,Eina_Bool translatable)3900 _elm_widget_item_domain_part_text_translatable_set(Eo *eo_item EINA_UNUSED,
3901 Elm_Widget_Item_Data *item,
3902 const char *part,
3903 const char *domain,
3904 Eina_Bool translatable)
3905 {
3906 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3907 ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
3908 Elm_Translate_String_Data *ts;
3909 const char *text;
3910
3911 ts = _part_text_translatable_set(&item->translate_strings, part,
3912 translatable, EINA_TRUE);
3913 if (!ts) return;
3914 if (!ts->domain) ts->domain = eina_stringshare_add(domain);
3915 else eina_stringshare_replace(&ts->domain, domain);
3916
3917 text = elm_wdg_item_part_text_get(item->eo_obj, part);
3918
3919 if (!text || !text[0]) return;
3920
3921 if (!ts->string) ts->string = eina_stringshare_add(text);
3922
3923 //Try to translate text since we don't know the text is already translated.
3924 #ifdef HAVE_GETTEXT
3925 text = dgettext(domain, text);
3926 #endif
3927 item->on_translate = EINA_TRUE;
3928 elm_wdg_item_part_text_set(item->eo_obj, part, text);
3929 item->on_translate = EINA_FALSE;
3930 }
3931
3932 EOLIAN static void
_elm_widget_item_track_cancel(Eo * eo_item EINA_UNUSED,Elm_Widget_Item_Data * item)3933 _elm_widget_item_track_cancel(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
3934 {
3935 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3936 ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
3937
3938 if (!item->track_obj) return;
3939
3940 while (evas_object_ref_get(item->track_obj) > 0)
3941 evas_object_unref(item->track_obj);
3942
3943 evas_object_del(item->track_obj);
3944 }
3945
3946 EOLIAN static Evas_Object *
_elm_widget_item_track(Eo * eo_item EINA_UNUSED,Elm_Widget_Item_Data * item)3947 _elm_widget_item_track(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
3948 {
3949 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
3950 ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item, NULL);
3951
3952 if (item->track_obj)
3953 {
3954 evas_object_ref(item->track_obj);
3955 return item->track_obj;
3956 }
3957
3958 if (!item->view)
3959 {
3960 WRN("view obj of the item(%p) is invalid. Please make sure the view obj is created!", item);
3961 return NULL;
3962 }
3963
3964 Evas_Object *track =
3965 evas_object_rectangle_add(evas_object_evas_get(item->widget));
3966 evas_object_color_set(track, 0, 0, 0, 0);
3967 evas_object_pass_events_set(track, EINA_TRUE);
3968 _track_obj_update(track, item->view);
3969 evas_object_event_callback_add(track, EVAS_CALLBACK_DEL, _track_obj_del,
3970 item);
3971
3972 efl_event_callback_array_add(item->view, tracker_callbacks(), item);
3973
3974 evas_object_ref(track);
3975
3976 item->track_obj = track;
3977
3978 return track;
3979 }
3980
3981 EOLIAN static void
_elm_widget_item_untrack(Eo * eo_item EINA_UNUSED,Elm_Widget_Item_Data * item)3982 _elm_widget_item_untrack(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
3983 {
3984 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3985 ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
3986
3987 if (!item->track_obj) return;
3988 evas_object_unref(item->track_obj);
3989
3990 if (evas_object_ref_get(item->track_obj) == 0)
3991 evas_object_del(item->track_obj);
3992 }
3993
3994 EOLIAN static int
_elm_widget_item_track_get(const Eo * eo_item EINA_UNUSED,Elm_Widget_Item_Data * item)3995 _elm_widget_item_track_get(const Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
3996 {
3997 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, 0);
3998 ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item, 0);
3999
4000 if (!item->track_obj) return 0;
4001 return evas_object_ref_get(item->track_obj);
4002 }
4003
4004 typedef struct _Elm_Widget_Item_Tooltip Elm_Widget_Item_Tooltip;
4005
4006 struct _Elm_Widget_Item_Tooltip
4007 {
4008 Elm_Widget_Item_Data *item;
4009 Elm_Tooltip_Item_Content_Cb func;
4010 Evas_Smart_Cb del_cb;
4011 const void *data;
4012 };
4013
4014 static Evas_Object *
_elm_widget_item_tooltip_label_create(void * data,Evas_Object * obj EINA_UNUSED,Evas_Object * tooltip,void * item EINA_UNUSED)4015 _elm_widget_item_tooltip_label_create(void *data,
4016 Evas_Object *obj EINA_UNUSED,
4017 Evas_Object *tooltip,
4018 void *item EINA_UNUSED)
4019 {
4020 Evas_Object *label = elm_label_add(tooltip);
4021 if (!label)
4022 return NULL;
4023 elm_object_style_set(label, "tooltip");
4024 elm_object_text_set(label, data);
4025 return label;
4026 }
4027
4028 static Evas_Object *
_elm_widget_item_tooltip_trans_label_create(void * data,Evas_Object * obj EINA_UNUSED,Evas_Object * tooltip,void * item EINA_UNUSED)4029 _elm_widget_item_tooltip_trans_label_create(void *data,
4030 Evas_Object *obj EINA_UNUSED,
4031 Evas_Object *tooltip,
4032 void *item EINA_UNUSED)
4033 {
4034 Evas_Object *label = elm_label_add(tooltip);
4035 if (!label)
4036 return NULL;
4037 elm_object_style_set(label, "tooltip");
4038 elm_object_translatable_text_set(label, data);
4039 return label;
4040 }
4041
4042 static void
_elm_widget_item_tooltip_label_del_cb(void * data,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)4043 _elm_widget_item_tooltip_label_del_cb(void *data,
4044 Evas_Object *obj EINA_UNUSED,
4045 void *event_info EINA_UNUSED)
4046 {
4047 eina_stringshare_del(data);
4048 }
4049
4050 /**
4051 * @internal
4052 *
4053 * Set the text to be shown in the widget item.
4054 *
4055 * @param item Target item
4056 * @param text The text to set in the content
4057 *
4058 * Setup the text as tooltip to object. The item can have only one tooltip,
4059 * so any previous tooltip data is removed.
4060 *
4061 * @ingroup Widget
4062 */
4063 EOLIAN static void
_elm_widget_item_tooltip_text_set(Eo * eo_item EINA_UNUSED,Elm_Widget_Item_Data * item EINA_UNUSED,const char * text)4064 _elm_widget_item_tooltip_text_set(Eo *eo_item EINA_UNUSED,
4065 Elm_Widget_Item_Data *item EINA_UNUSED,
4066 const char *text)
4067 {
4068 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4069 ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4070 EINA_SAFETY_ON_NULL_RETURN(text);
4071
4072 text = eina_stringshare_add(text);
4073 elm_wdg_item_tooltip_content_cb_set(item->eo_obj, _elm_widget_item_tooltip_label_create, text, _elm_widget_item_tooltip_label_del_cb);
4074 }
4075
4076 EOLIAN static void
_elm_widget_item_tooltip_translatable_text_set(Eo * eo_item EINA_UNUSED,Elm_Widget_Item_Data * item EINA_UNUSED,const char * text)4077 _elm_widget_item_tooltip_translatable_text_set(Eo *eo_item EINA_UNUSED,
4078 Elm_Widget_Item_Data *item EINA_UNUSED,
4079 const char *text)
4080 {
4081 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4082 ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4083 EINA_SAFETY_ON_NULL_RETURN(text);
4084
4085 text = eina_stringshare_add(text);
4086 elm_wdg_item_tooltip_content_cb_set(item->eo_obj, _elm_widget_item_tooltip_trans_label_create, text, _elm_widget_item_tooltip_label_del_cb);
4087 }
4088
4089 static Evas_Object *
_elm_widget_item_tooltip_create(void * data,Evas_Object * obj,Evas_Object * tooltip)4090 _elm_widget_item_tooltip_create(void *data,
4091 Evas_Object *obj,
4092 Evas_Object *tooltip)
4093 {
4094 Elm_Widget_Item_Tooltip *wit = data;
4095 return wit->func((void *)wit->data, obj, tooltip, wit->item->eo_obj);
4096 }
4097
4098 static void
_elm_widget_item_tooltip_del_cb(void * data,Evas_Object * obj,void * event_info EINA_UNUSED)4099 _elm_widget_item_tooltip_del_cb(void *data,
4100 Evas_Object *obj,
4101 void *event_info EINA_UNUSED)
4102 {
4103 Elm_Widget_Item_Tooltip *wit = data;
4104 if (wit->del_cb) wit->del_cb((void *)wit->data, obj, wit->item->eo_obj);
4105 free(wit);
4106 }
4107
4108 /**
4109 * @internal
4110 *
4111 * Set the content to be shown in the tooltip item
4112 *
4113 * Setup the tooltip to item. The item can have only one tooltip,
4114 * so any previous tooltip data is removed. @p func(with @p data) will
4115 * be called every time that need show the tooltip and it should
4116 * return a valid Evas_Object. This object is then managed fully by
4117 * tooltip system and is deleted when the tooltip is gone.
4118 *
4119 * @param item the widget item being attached a tooltip.
4120 * @param func the function used to create the tooltip contents.
4121 * @param data what to provide to @a func as callback data/context.
4122 * @param del_cb called when data is not needed anymore, either when
4123 * another callback replaces @func, the tooltip is unset with
4124 * elm_widget_item_tooltip_unset() or the owner @a item
4125 * dies. This callback receives as the first parameter the
4126 * given @a data, and @c event_info is the item.
4127 *
4128 * @ingroup Widget
4129 */
4130 EOLIAN static void
_elm_widget_item_tooltip_content_cb_set(Eo * eo_item EINA_UNUSED,Elm_Widget_Item_Data * item,Elm_Tooltip_Item_Content_Cb func,const void * data,Evas_Smart_Cb del_cb)4131 _elm_widget_item_tooltip_content_cb_set(Eo *eo_item EINA_UNUSED,
4132 Elm_Widget_Item_Data *item,
4133 Elm_Tooltip_Item_Content_Cb func,
4134 const void *data,
4135 Evas_Smart_Cb del_cb)
4136 {
4137 Elm_Widget_Item_Tooltip *wit;
4138
4139 ELM_WIDGET_ITEM_CHECK_OR_GOTO(item, error_noitem);
4140 //ELM_WIDGET_ITEM_RETURN_IF_GOTO(item, error_noitem);
4141
4142 if (!func)
4143 {
4144 elm_wdg_item_tooltip_unset(item->eo_obj);
4145 return;
4146 }
4147
4148 wit = ELM_NEW(Elm_Widget_Item_Tooltip);
4149 if (!wit) goto error;
4150 wit->item = item;
4151 wit->func = func;
4152 wit->data = data;
4153 wit->del_cb = del_cb;
4154
4155 elm_object_sub_tooltip_content_cb_set
4156 (item->view, item->widget, _elm_widget_item_tooltip_create, wit,
4157 _elm_widget_item_tooltip_del_cb);
4158
4159 return;
4160
4161 error_noitem:
4162 if (del_cb) del_cb((void *)data, NULL, item);
4163 return;
4164 error:
4165 if (del_cb) del_cb((void *)data, item->widget, item);
4166 }
4167
4168 /**
4169 * @internal
4170 *
4171 * Unset tooltip from item
4172 *
4173 * @param item widget item to remove previously set tooltip.
4174 *
4175 * Remove tooltip from item. The callback provided as del_cb to
4176 * elm_widget_item_tooltip_content_cb_set() will be called to notify
4177 * it is not used anymore.
4178 *
4179 * @see elm_widget_item_tooltip_content_cb_set()
4180 *
4181 * @ingroup Widget
4182 */
4183 EOLIAN static void
_elm_widget_item_tooltip_unset(Eo * eo_item EINA_UNUSED,Elm_Widget_Item_Data * item)4184 _elm_widget_item_tooltip_unset(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
4185 {
4186 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4187 ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4188
4189 elm_object_tooltip_unset(item->view);
4190 }
4191
4192 /**
4193 * @internal
4194 *
4195 * Sets a different style for this item tooltip.
4196 *
4197 * @note before you set a style you should define a tooltip with
4198 * elm_widget_item_tooltip_content_cb_set() or
4199 * elm_widget_item_tooltip_text_set()
4200 *
4201 * @param item widget item with tooltip already set.
4202 * @param style the theme style to use (default, transparent, ...)
4203 *
4204 * @ingroup Widget
4205 */
4206 EOLIAN static void
_elm_widget_item_tooltip_style_set(Eo * eo_item EINA_UNUSED,Elm_Widget_Item_Data * item,const char * style)4207 _elm_widget_item_tooltip_style_set(Eo *eo_item EINA_UNUSED,
4208 Elm_Widget_Item_Data *item,
4209 const char *style)
4210 {
4211 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4212 ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4213
4214 elm_object_tooltip_style_set(item->view, style);
4215 }
4216
4217 EOLIAN static Eina_Bool
_elm_widget_item_tooltip_window_mode_set(Eo * eo_item EINA_UNUSED,Elm_Widget_Item_Data * item,Eina_Bool disable)4218 _elm_widget_item_tooltip_window_mode_set(Eo *eo_item EINA_UNUSED,
4219 Elm_Widget_Item_Data *item,
4220 Eina_Bool disable)
4221 {
4222 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, EINA_FALSE);
4223 ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item, EINA_FALSE);
4224
4225 return elm_object_tooltip_window_mode_set(item->view, disable);
4226 }
4227
4228 EOLIAN static Eina_Bool
_elm_widget_item_tooltip_window_mode_get(const Eo * eo_item EINA_UNUSED,Elm_Widget_Item_Data * item)4229 _elm_widget_item_tooltip_window_mode_get(const Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
4230 {
4231 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, EINA_FALSE);
4232 ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item, EINA_FALSE);
4233
4234 return elm_object_tooltip_window_mode_get(item->view);
4235 }
4236
4237 /**
4238 * @internal
4239 *
4240 * Get the style for this item tooltip.
4241 *
4242 * @param item widget item with tooltip already set.
4243 * @return style the theme style in use, defaults to "default". If the
4244 * object does not have a tooltip set, then NULL is returned.
4245 *
4246 * @ingroup Widget
4247 */
4248 EOLIAN static const char *
_elm_widget_item_tooltip_style_get(const Eo * eo_item EINA_UNUSED,Elm_Widget_Item_Data * item)4249 _elm_widget_item_tooltip_style_get(const Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
4250 {
4251 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
4252
4253 return elm_object_tooltip_style_get(item->view);
4254 }
4255
4256 EOLIAN static void
_elm_widget_item_cursor_set(Eo * eo_item EINA_UNUSED,Elm_Widget_Item_Data * item,const char * cursor)4257 _elm_widget_item_cursor_set(Eo *eo_item EINA_UNUSED,
4258 Elm_Widget_Item_Data *item,
4259 const char *cursor)
4260 {
4261 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4262 ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4263
4264 elm_object_sub_cursor_set(item->view, item->widget, cursor);
4265 }
4266
4267 EOLIAN static const char *
_elm_widget_item_cursor_get(const Eo * eo_item EINA_UNUSED,Elm_Widget_Item_Data * item)4268 _elm_widget_item_cursor_get(const Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
4269 {
4270 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
4271 return elm_object_sub_cursor_get(item->view);
4272 }
4273
4274 EOLIAN static void
_elm_widget_item_cursor_unset(Eo * eo_item EINA_UNUSED,Elm_Widget_Item_Data * item)4275 _elm_widget_item_cursor_unset(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
4276 {
4277 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4278 ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4279
4280 elm_object_cursor_unset(item->view);
4281 }
4282
4283 /**
4284 * @internal
4285 *
4286 * Sets a different style for this item cursor.
4287 *
4288 * @note before you set a style you should define a cursor with
4289 * elm_widget_item_cursor_set()
4290 *
4291 * @param item widget item with cursor already set.
4292 * @param style the theme style to use (default, transparent, ...)
4293 *
4294 * @ingroup Widget
4295 */
4296 EOLIAN static void
_elm_widget_item_cursor_style_set(Eo * eo_item EINA_UNUSED,Elm_Widget_Item_Data * item,const char * style)4297 _elm_widget_item_cursor_style_set(Eo *eo_item EINA_UNUSED,
4298 Elm_Widget_Item_Data *item,
4299 const char *style)
4300 {
4301 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4302 ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4303
4304 elm_object_sub_cursor_style_set(item->view, style);
4305 }
4306
4307 /**
4308 * @internal
4309 *
4310 * Get the style for this item cursor.
4311 *
4312 * @param item widget item with cursor already set.
4313 * @return style the theme style in use, defaults to "default". If the
4314 * object does not have a cursor set, then NULL is returned.
4315 *
4316 * @ingroup Widget
4317 */
4318 EOLIAN static const char *
_elm_widget_item_cursor_style_get(const Eo * eo_item EINA_UNUSED,Elm_Widget_Item_Data * item)4319 _elm_widget_item_cursor_style_get(const Eo *eo_item EINA_UNUSED,
4320 Elm_Widget_Item_Data *item)
4321 {
4322 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
4323 return elm_object_sub_cursor_style_get(item->view);
4324 }
4325
4326 /**
4327 * @internal
4328 *
4329 * Set if the cursor set should be searched on the theme or should use
4330 * the provided by the engine, only.
4331 *
4332 * @note before you set if should look on theme you should define a cursor
4333 * with elm_object_cursor_set(). By default it will only look for cursors
4334 * provided by the engine.
4335 *
4336 * @param item widget item with cursor already set.
4337 * @param engine_only boolean to define it cursors should be looked only
4338 * between the provided by the engine or searched on widget's theme as well.
4339 *
4340 * @ingroup Widget
4341 */
4342 EOLIAN static void
_elm_widget_item_cursor_engine_only_set(Eo * eo_item EINA_UNUSED,Elm_Widget_Item_Data * item,Eina_Bool engine_only)4343 _elm_widget_item_cursor_engine_only_set(Eo *eo_item EINA_UNUSED,
4344 Elm_Widget_Item_Data *item,
4345 Eina_Bool engine_only)
4346 {
4347 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4348 ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4349
4350 elm_object_sub_cursor_theme_search_enabled_set(item->view, !engine_only);
4351 }
4352
4353 /**
4354 * @internal
4355 *
4356 * Get the cursor engine only usage for this item cursor.
4357 *
4358 * @param item widget item with cursor already set.
4359 * @return engine_only boolean to define it cursors should be looked only
4360 * between the provided by the engine or searched on widget's theme as well. If
4361 * the object does not have a cursor set, then EINA_FALSE is returned.
4362 *
4363 * @ingroup Widget
4364 */
4365 EOLIAN static Eina_Bool
_elm_widget_item_cursor_engine_only_get(const Eo * eo_item EINA_UNUSED,Elm_Widget_Item_Data * item)4366 _elm_widget_item_cursor_engine_only_get(const Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
4367 {
4368 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, EINA_FALSE);
4369 return !elm_object_sub_cursor_theme_search_enabled_get(item->view);
4370 }
4371
4372 EOLIAN static void
_elm_widget_item_part_content_set(Eo * eo_item EINA_UNUSED,Elm_Widget_Item_Data * item,const char * part EINA_UNUSED,Evas_Object * content EINA_UNUSED)4373 _elm_widget_item_part_content_set(Eo *eo_item EINA_UNUSED,
4374 Elm_Widget_Item_Data *item,
4375 const char *part EINA_UNUSED,
4376 Evas_Object *content EINA_UNUSED)
4377 {
4378 ERR_NOT_SUPPORTED(item, "elm_object_part_content_set()");
4379 }
4380
4381 EOLIAN static Evas_Object *
_elm_widget_item_part_content_get(const Eo * eo_item EINA_UNUSED,Elm_Widget_Item_Data * item,const char * part EINA_UNUSED)4382 _elm_widget_item_part_content_get(const Eo *eo_item EINA_UNUSED,
4383 Elm_Widget_Item_Data *item,
4384 const char *part EINA_UNUSED)
4385 {
4386 ERR_NOT_SUPPORTED(item, "elm_object_part_content_get()");
4387 return NULL;
4388 }
4389
4390 EOLIAN static Evas_Object *
_elm_widget_item_part_content_unset(Eo * eo_item EINA_UNUSED,Elm_Widget_Item_Data * item,const char * part EINA_UNUSED)4391 _elm_widget_item_part_content_unset(Eo *eo_item EINA_UNUSED,
4392 Elm_Widget_Item_Data *item,
4393 const char *part EINA_UNUSED)
4394 {
4395 ERR_NOT_SUPPORTED(item, "elm_object_part_content_unset()");
4396 return NULL;
4397 }
4398
4399 EOLIAN static void
_elm_widget_item_part_text_set(Eo * eo_item EINA_UNUSED,Elm_Widget_Item_Data * item,const char * part EINA_UNUSED,const char * label EINA_UNUSED)4400 _elm_widget_item_part_text_set(Eo *eo_item EINA_UNUSED,
4401 Elm_Widget_Item_Data *item,
4402 const char *part EINA_UNUSED,
4403 const char *label EINA_UNUSED)
4404 {
4405 ERR_NOT_SUPPORTED(item, "elm_object_part_text_set()");
4406 }
4407
4408 EOLIAN static const char *
_elm_widget_item_part_text_get(const Eo * eo_item EINA_UNUSED,Elm_Widget_Item_Data * item,const char * part EINA_UNUSED)4409 _elm_widget_item_part_text_get(const Eo *eo_item EINA_UNUSED,
4410 Elm_Widget_Item_Data *item,
4411 const char *part EINA_UNUSED)
4412 {
4413 ERR_NOT_SUPPORTED(item, "elm_object_part_text_get()");
4414 return NULL;
4415 }
4416
4417 static void
_elm_widget_item_part_text_custom_free(void * data)4418 _elm_widget_item_part_text_custom_free(void *data)
4419 {
4420 Elm_Label_Data *label;
4421 label = data;
4422 eina_stringshare_del(label->part);
4423 eina_stringshare_del(label->text);
4424 free(label);
4425 }
4426
4427 EOLIAN static void
_elm_widget_item_part_text_custom_set(Eo * eo_item EINA_UNUSED,Elm_Widget_Item_Data * item,const char * part,const char * text)4428 _elm_widget_item_part_text_custom_set(Eo *eo_item EINA_UNUSED,
4429 Elm_Widget_Item_Data *item,
4430 const char *part,
4431 const char *text)
4432 {
4433 Elm_Label_Data *label;
4434 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4435 ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4436
4437 if (!item->labels)
4438 item->labels =
4439 eina_hash_stringshared_new(_elm_widget_item_part_text_custom_free);
4440 label = eina_hash_find(item->labels, part);
4441 if (!label)
4442 {
4443 label = malloc(sizeof(Elm_Label_Data));
4444 if (!label)
4445 {
4446 ERR("Failed to allocate memory");
4447 return;
4448 }
4449 label->part = eina_stringshare_add(part);
4450 label->text = eina_stringshare_add(text);
4451 eina_hash_add(item->labels, part, label);
4452 }
4453 else
4454 eina_stringshare_replace(&label->text, text);
4455 }
4456
4457 EOLIAN static const char *
_elm_widget_item_part_text_custom_get(const Eo * eo_item EINA_UNUSED,Elm_Widget_Item_Data * item,const char * part)4458 _elm_widget_item_part_text_custom_get(const Eo *eo_item EINA_UNUSED,
4459 Elm_Widget_Item_Data *item,
4460 const char *part)
4461 {
4462 Elm_Label_Data *label;
4463 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
4464 label = eina_hash_find(item->labels, part);
4465 return label ? label->text : NULL;
4466 }
4467
4468 static Eina_Bool
_elm_widget_item_part_text_custom_foreach(const Eina_Hash * labels EINA_UNUSED,const void * key EINA_UNUSED,void * data,void * func_data)4469 _elm_widget_item_part_text_custom_foreach(const Eina_Hash *labels EINA_UNUSED,
4470 const void *key EINA_UNUSED,
4471 void *data,
4472 void *func_data)
4473 {
4474 Elm_Label_Data *label;
4475 Elm_Widget_Item_Data *item;
4476 label = data;
4477 item = func_data;
4478
4479 elm_wdg_item_part_text_set(item->eo_obj, label->part, label->text);
4480
4481 return EINA_TRUE;
4482 }
4483
4484 EOLIAN static void
_elm_widget_item_part_text_custom_update(Eo * eo_item EINA_UNUSED,Elm_Widget_Item_Data * item)4485 _elm_widget_item_part_text_custom_update(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
4486 {
4487 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4488 ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4489 if (item->labels)
4490 eina_hash_foreach(item->labels,
4491 _elm_widget_item_part_text_custom_foreach, item);
4492 }
4493
4494 EOLIAN static void
_elm_widget_item_signal_emit(Eo * eo_item EINA_UNUSED,Elm_Widget_Item_Data * item EINA_UNUSED,const char * emission EINA_UNUSED,const char * source EINA_UNUSED)4495 _elm_widget_item_signal_emit(Eo *eo_item EINA_UNUSED,
4496 Elm_Widget_Item_Data *item EINA_UNUSED,
4497 const char *emission EINA_UNUSED,
4498 const char *source EINA_UNUSED)
4499 {
4500
4501 }
4502
4503 EOLIAN static void
_elm_widget_item_signal_callback_add(Eo * eo_item,Elm_Widget_Item_Data * item,const char * emission,const char * source,Elm_Object_Item_Signal_Cb func,void * data)4504 _elm_widget_item_signal_callback_add(Eo *eo_item,
4505 Elm_Widget_Item_Data *item,
4506 const char *emission,
4507 const char *source,
4508 Elm_Object_Item_Signal_Cb func,
4509 void *data)
4510 {
4511 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4512 ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4513 EINA_SAFETY_ON_NULL_RETURN(func);
4514
4515 Elm_Widget_Item_Signal_Data *wisd;
4516
4517 wisd = malloc(sizeof(Elm_Widget_Item_Signal_Data));
4518 if (!wisd) return;
4519
4520 wisd->item = eo_item;
4521 wisd->func = (Elm_Widget_Item_Signal_Cb)func;
4522 wisd->data = data;
4523 wisd->emission = eina_stringshare_add(emission);
4524 wisd->source = eina_stringshare_add(source);
4525
4526 if (_elm_widget_is(item->view))
4527 elm_object_signal_callback_add(item->view, emission, source, _elm_widget_item_signal_cb, wisd);
4528 else if (efl_isa(item->view, EFL_CANVAS_LAYOUT_CLASS))
4529 edje_object_signal_callback_add(item->view, emission, source, _elm_widget_item_signal_cb, wisd);
4530 else
4531 {
4532 WRN("The %s widget item doesn't support signal callback add!",
4533 efl_class_name_get(efl_class_get(item->widget)));
4534 free(wisd);
4535 return;
4536 }
4537
4538 item->signals = eina_list_append(item->signals, wisd);
4539 }
4540
4541 EOLIAN static void *
_elm_widget_item_signal_callback_del(Eo * eo_item EINA_UNUSED,Elm_Widget_Item_Data * item,const char * emission,const char * source,Elm_Object_Item_Signal_Cb func)4542 _elm_widget_item_signal_callback_del(Eo *eo_item EINA_UNUSED,
4543 Elm_Widget_Item_Data *item,
4544 const char *emission,
4545 const char *source,
4546 Elm_Object_Item_Signal_Cb func)
4547 {
4548 Elm_Widget_Item_Signal_Data *wisd;
4549 Eina_List *l;
4550
4551 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
4552 ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item, NULL);
4553 EINA_SAFETY_ON_NULL_RETURN_VAL(func, NULL);
4554
4555 EINA_LIST_FOREACH(item->signals, l, wisd)
4556 {
4557 if ((wisd->func == (Elm_Widget_Item_Signal_Cb)func) &&
4558 !strcmp(wisd->emission, emission) &&
4559 !strcmp(wisd->source, source))
4560 return _elm_widget_item_signal_callback_list_get(item, l);
4561 }
4562
4563 return NULL;
4564 }
4565
4566 EOLIAN static void
_elm_widget_item_access_info_set(Eo * eo_item EINA_UNUSED,Elm_Widget_Item_Data * item,const char * txt)4567 _elm_widget_item_access_info_set(Eo *eo_item EINA_UNUSED,
4568 Elm_Widget_Item_Data *item,
4569 const char *txt)
4570 {
4571 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4572 ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4573
4574 eina_stringshare_del(item->access_info);
4575 if (!txt) item->access_info = NULL;
4576 else item->access_info = eina_stringshare_add(txt);
4577 }
4578
4579 EOLIAN static void
_elm_widget_item_translate(Eo * eo_item EINA_UNUSED,Elm_Widget_Item_Data * item)4580 _elm_widget_item_translate(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
4581 {
4582 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4583 ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4584
4585 #ifdef HAVE_GETTEXT
4586 Elm_Translate_String_Data *ts;
4587 EINA_INLIST_FOREACH(item->translate_strings, ts)
4588 {
4589 if (!ts->string) continue;
4590 const char *s = dgettext(ts->domain, ts->string);
4591 item->on_translate = EINA_TRUE;
4592 elm_wdg_item_part_text_set(item->eo_obj, ts->id, s);
4593 item->on_translate = EINA_FALSE;
4594 }
4595 #endif
4596 }
4597
4598 EOLIAN static void
_elm_widget_item_access_order_set(Eo * eo_item EINA_UNUSED,Elm_Widget_Item_Data * item,Eina_List * objs)4599 _elm_widget_item_access_order_set(Eo *eo_item EINA_UNUSED,
4600 Elm_Widget_Item_Data *item,
4601 Eina_List *objs)
4602 {
4603 _elm_access_widget_item_access_order_set(item, objs);
4604 }
4605
4606 EOLIAN static const Eina_List *
_elm_widget_item_access_order_get(Eo * eo_item EINA_UNUSED,Elm_Widget_Item_Data * item)4607 _elm_widget_item_access_order_get(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
4608 {
4609 return _elm_access_widget_item_access_order_get(item);
4610 }
4611
4612 EOLIAN static void
_elm_widget_item_access_order_unset(Eo * eo_item EINA_UNUSED,Elm_Widget_Item_Data * item)4613 _elm_widget_item_access_order_unset(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
4614 {
4615 _elm_access_widget_item_access_order_unset(item);
4616 }
4617
4618 EOLIAN static Evas_Object*
_elm_widget_item_access_register(Eo * eo_item EINA_UNUSED,Elm_Widget_Item_Data * item)4619 _elm_widget_item_access_register(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
4620 {
4621 _elm_access_widget_item_register(item);
4622 return item->access_obj;
4623 }
4624
4625 EOLIAN static void
_elm_widget_item_access_unregister(Eo * eo_item EINA_UNUSED,Elm_Widget_Item_Data * item)4626 _elm_widget_item_access_unregister(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
4627 {
4628 _elm_access_widget_item_unregister(item);
4629 }
4630
4631 EOLIAN static Evas_Object*
_elm_widget_item_access_object_get(const Eo * eo_item EINA_UNUSED,Elm_Widget_Item_Data * item)4632 _elm_widget_item_access_object_get(const Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
4633 {
4634 return item->access_obj;
4635 }
4636
4637 EOLIAN static Evas_Object *
_elm_widget_item_focus_next_object_get(const Eo * eo_item EINA_UNUSED,Elm_Widget_Item_Data * item,Elm_Focus_Direction dir)4638 _elm_widget_item_focus_next_object_get(const Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item, Elm_Focus_Direction dir)
4639 {
4640 Evas_Object *ret = NULL;
4641
4642 if (dir == ELM_FOCUS_PREVIOUS)
4643 ret = item->focus_previous;
4644 else if (dir == ELM_FOCUS_NEXT)
4645 ret = item->focus_next;
4646 else if (dir == ELM_FOCUS_UP)
4647 ret = item->focus_up;
4648 else if (dir == ELM_FOCUS_DOWN)
4649 ret = item->focus_down;
4650 else if (dir == ELM_FOCUS_RIGHT)
4651 ret = item->focus_right;
4652 else if (dir == ELM_FOCUS_LEFT)
4653 ret = item->focus_left;
4654
4655 return ret;
4656 }
4657
4658 EOLIAN static void
_elm_widget_item_focus_next_object_set(Eo * eo_item EINA_UNUSED,Elm_Widget_Item_Data * item,Evas_Object * next,Elm_Focus_Direction dir)4659 _elm_widget_item_focus_next_object_set(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item, Evas_Object *next, Elm_Focus_Direction dir)
4660 {
4661 if (dir == ELM_FOCUS_PREVIOUS)
4662 item->focus_previous = next;
4663 else if (dir == ELM_FOCUS_NEXT)
4664 item->focus_next = next;
4665 else if (dir == ELM_FOCUS_UP)
4666 item->focus_up = next;
4667 else if (dir == ELM_FOCUS_DOWN)
4668 item->focus_down = next;
4669 else if (dir == ELM_FOCUS_RIGHT)
4670 item->focus_right = next;
4671 else if (dir == ELM_FOCUS_LEFT)
4672 item->focus_left = next;
4673 }
4674
4675 EOLIAN static Elm_Object_Item*
_elm_widget_item_focus_next_item_get(const Eo * eo_item EINA_UNUSED,Elm_Widget_Item_Data * item,Elm_Focus_Direction dir)4676 _elm_widget_item_focus_next_item_get(const Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item, Elm_Focus_Direction dir)
4677 {
4678 Elm_Object_Item *ret = NULL;
4679
4680 if (dir == ELM_FOCUS_PREVIOUS)
4681 ret = item->item_focus_previous;
4682 else if (dir == ELM_FOCUS_NEXT)
4683 ret = item->item_focus_next;
4684 else if (dir == ELM_FOCUS_UP)
4685 ret = item->item_focus_up;
4686 else if (dir == ELM_FOCUS_DOWN)
4687 ret = item->item_focus_down;
4688 else if (dir == ELM_FOCUS_RIGHT)
4689 ret = item->item_focus_right;
4690 else if (dir == ELM_FOCUS_LEFT)
4691 ret = item->item_focus_left;
4692
4693 return ret;
4694 }
4695
4696 EOLIAN static void
_elm_widget_item_focus_next_item_set(Eo * eo_item EINA_UNUSED,Elm_Widget_Item_Data * item,Elm_Object_Item * next_item,Elm_Focus_Direction dir)4697 _elm_widget_item_focus_next_item_set(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item, Elm_Object_Item *next_item, Elm_Focus_Direction dir)
4698 {
4699 if (dir == ELM_FOCUS_PREVIOUS)
4700 item->item_focus_previous = next_item;
4701 else if (dir == ELM_FOCUS_NEXT)
4702 item->item_focus_next = next_item;
4703 else if (dir == ELM_FOCUS_UP)
4704 item->item_focus_up = next_item;
4705 else if (dir == ELM_FOCUS_DOWN)
4706 item->item_focus_down = next_item;
4707 else if (dir == ELM_FOCUS_RIGHT)
4708 item->item_focus_right = next_item;
4709 else if (dir == ELM_FOCUS_LEFT)
4710 item->item_focus_left = next_item;
4711 }
4712
4713 /* happy debug functions */
4714 #ifdef ELM_DEBUG
4715 static void
_sub_obj_tree_dump(const Evas_Object * obj,int lvl)4716 _sub_obj_tree_dump(const Evas_Object *obj,
4717 int lvl)
4718 {
4719 int i;
4720
4721 for (i = 0; i < lvl * 3; i++)
4722 putchar(' ');
4723
4724 if (_elm_widget_is(obj))
4725 {
4726 Eina_List *l;
4727 INTERNAL_ENTRY;
4728 DBG("+ %s(%p)\n",
4729 elm_widget_type_get(obj),
4730 obj);
4731 for (unsigned int i = 0; i < eina_array_count(sd->children); ++i)
4732 {
4733 obj = eina_array_data_get(sd->children, i);
4734 _sub_obj_tree_dump(obj, lvl + 1);
4735 }
4736 }
4737 else
4738 DBG("+ %s(%p)\n", evas_object_type_get(obj), obj);
4739 }
4740
4741 static void
_sub_obj_tree_dot_dump(const Evas_Object * obj,FILE * output)4742 _sub_obj_tree_dot_dump(const Evas_Object *obj,
4743 FILE *output)
4744 {
4745 if (!_elm_widget_is(obj))
4746 return;
4747 INTERNAL_ENTRY;
4748
4749 Eina_Bool visible = evas_object_visible_get(obj);
4750 Eina_Bool disabled = elm_widget_disabled_get(obj);
4751 Eina_Bool focused = efl_ui_focus_object_focus_get(obj);
4752 Eina_Bool can_focus = elm_widget_can_focus_get(obj);
4753
4754 if (sd->parent_obj)
4755 {
4756 fprintf(output, "\"%p\" -- \"%p\" [ color=black", sd->parent_obj, obj);
4757
4758 if (focused)
4759 fprintf(output, ", style=bold");
4760
4761 if (!visible)
4762 fprintf(output, ", color=gray28");
4763
4764 fprintf(output, " ];\n");
4765 }
4766
4767 fprintf(output, "\"%p\" [ label = \"{%p|%s|%s|visible: %d|"
4768 "disabled: %d|focused: %d/%d|focus order:%d}\"",
4769 obj, obj, elm_widget_type_get(obj),
4770 evas_object_name_get(obj), visible, disabled, focused, can_focus,
4771 sd->focus_order);
4772
4773 if (focused)
4774 fprintf(output, ", style=bold");
4775
4776 if (!visible)
4777 fprintf(output, ", fontcolor=gray28");
4778
4779 if ((disabled) || (!visible))
4780 fprintf(output, ", color=gray");
4781
4782 fprintf(output, " ];\n");
4783
4784 Eina_List *l;
4785 Evas_Object *o;
4786
4787 for (unsigned int i = 0; i < eina_array_count(sd->children); ++i)
4788 {
4789 o = eina_array_data_get(sd->children, i);
4790 _sub_obj_tree_dot_dump(o, output);
4791 }
4792 }
4793
4794 #endif
4795
4796 EAPI void
elm_widget_tree_dump(const Evas_Object * top)4797 elm_widget_tree_dump(const Evas_Object *top)
4798 {
4799 #ifdef ELM_DEBUG
4800 if (!_elm_widget_is(top))
4801 return;
4802 _sub_obj_tree_dump(top, 0);
4803 #else
4804 (void)top;
4805 return;
4806 #endif
4807 }
4808
4809 EAPI void
elm_widget_tree_dot_dump(const Evas_Object * top,FILE * output)4810 elm_widget_tree_dot_dump(const Evas_Object *top,
4811 FILE *output)
4812 {
4813 #ifdef ELM_DEBUG
4814 if (!_elm_widget_is(top))
4815 return;
4816 fprintf(output, "graph " " { node [shape=record];\n");
4817 _sub_obj_tree_dot_dump(top, output);
4818 fprintf(output, "}\n");
4819 #else
4820 (void)top;
4821 (void)output;
4822 return;
4823 #endif
4824 }
4825
4826 EOLIAN static Eo *
_efl_ui_widget_efl_object_constructor(Eo * obj,Elm_Widget_Smart_Data * sd EINA_UNUSED)4827 _efl_ui_widget_efl_object_constructor(Eo *obj, Elm_Widget_Smart_Data *sd EINA_UNUSED)
4828 {
4829 Eo *parent = efl_parent_get(obj);
4830 sd->on_create = EINA_TRUE;
4831
4832 sd->window = efl_provider_find(efl_parent_get(obj), EFL_UI_WIN_CLASS);
4833 if (!efl_isa(obj, EFL_UI_WIN_CLASS))
4834 {
4835 if (!efl_isa(parent, EFL_UI_WIDGET_CLASS))
4836 {
4837 ERR("You passed a wrong parent parameter (%p %s). "
4838 "Elementary widget's parent should be an elementary widget.",
4839 parent, evas_object_type_get(parent));
4840 }
4841 else
4842 {
4843 ELM_WIDGET_DATA_GET(parent, parent_sd);
4844 if (parent_sd)
4845 sd->shared_win_data = parent_sd->shared_win_data;
4846 }
4847 }
4848 else
4849 {
4850 sd->shared_win_data = efl_ui_win_shared_data_get(obj);
4851 }
4852
4853 _efl_ui_focus_event_redirector(obj, obj);
4854 efl_canvas_group_clipped_set(obj, EINA_FALSE);
4855 obj = efl_constructor(efl_super(obj, MY_CLASS));
4856 efl_canvas_object_type_set(obj, MY_CLASS_NAME_LEGACY);
4857 evas_object_smart_callbacks_descriptions_set(obj, _smart_callbacks);
4858
4859 if (!efl_isa(obj, EFL_UI_WIN_CLASS) && efl_isa(parent, EFL_UI_WIDGET_CLASS))
4860 efl_ui_widget_sub_object_add(parent, obj);
4861
4862 sd->on_create = EINA_FALSE;
4863
4864 efl_access_object_role_set(obj, EFL_ACCESS_ROLE_UNKNOWN);
4865
4866 if (!elm_widget_is_legacy(obj))
4867 EINA_SAFETY_ON_NULL_RETURN_VAL(sd->shared_win_data, NULL);
4868
4869 return obj;
4870 }
4871
4872 EOLIAN static Efl_Object*
_efl_ui_widget_efl_object_finalize(Eo * obj,Elm_Widget_Smart_Data * pd)4873 _efl_ui_widget_efl_object_finalize(Eo *obj, Elm_Widget_Smart_Data *pd)
4874 {
4875 Eo *eo;
4876
4877 eo = efl_finalize(efl_super(obj, MY_CLASS));
4878
4879 _full_eval(obj, pd);
4880
4881 return eo;
4882 }
4883
4884
4885 EOLIAN static void
_efl_ui_widget_efl_object_destructor(Eo * obj,Elm_Widget_Smart_Data * sd)4886 _efl_ui_widget_efl_object_destructor(Eo *obj, Elm_Widget_Smart_Data *sd)
4887 {
4888 if (sd->manager.provider)
4889 {
4890 sd->manager.provider = NULL;
4891 }
4892 efl_access_object_attributes_clear(obj);
4893 efl_access_removed(obj);
4894 if (sd->logical.parent)
4895 {
4896 efl_weak_unref(&sd->logical.parent);
4897 sd->logical.parent = NULL;
4898 }
4899 if (sd->children)
4900 {
4901 eina_array_free(sd->children);
4902 sd->children = NULL;
4903 }
4904
4905 sd->on_destroy = EINA_TRUE;
4906 efl_destructor(efl_super(obj, EFL_UI_WIDGET_CLASS));
4907 sd->on_destroy = EINA_FALSE;
4908 }
4909
4910 /* internal eo */
4911
4912 EOLIAN static void
_efl_ui_widget_efl_object_debug_name_override(Eo * obj,Elm_Widget_Smart_Data * sd EINA_UNUSED,Eina_Strbuf * sb)4913 _efl_ui_widget_efl_object_debug_name_override(Eo *obj, Elm_Widget_Smart_Data *sd EINA_UNUSED, Eina_Strbuf *sb)
4914 {
4915 const char *focus = "";
4916
4917 if (efl_ui_focus_object_focus_get(obj)) focus = ":focused";
4918 efl_debug_name_override(efl_super(obj, MY_CLASS), sb);
4919 eina_strbuf_append_printf(sb, "%s", focus);
4920 }
4921
4922 EOLIAN static Eina_Bool
_efl_ui_widget_efl_ui_focus_object_on_focus_update(Eo * obj,Elm_Widget_Smart_Data * sd)4923 _efl_ui_widget_efl_ui_focus_object_on_focus_update(Eo *obj, Elm_Widget_Smart_Data *sd)
4924 {
4925 Eina_Bool focused;
4926
4927 if (!elm_widget_can_focus_get(obj))
4928 return EINA_FALSE;
4929
4930 focused = efl_ui_focus_object_focus_get(obj);
4931
4932 if (!sd->resize_obj)
4933 evas_object_focus_set(obj, focused);
4934
4935 if (_elm_config->atspi_mode && !elm_widget_child_can_focus_get(obj))
4936 efl_access_state_changed_signal_emit(obj, EFL_ACCESS_STATE_TYPE_FOCUSED, focused);
4937
4938 return EINA_TRUE;
4939 }
4940
4941 EOLIAN static Eina_Bool
_efl_ui_widget_widget_input_event_handler(Eo * obj EINA_UNUSED,Elm_Widget_Smart_Data * _pd EINA_UNUSED,const Efl_Event * eo_event EINA_UNUSED,Evas_Object * source EINA_UNUSED)4942 _efl_ui_widget_widget_input_event_handler(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd EINA_UNUSED, const Efl_Event *eo_event EINA_UNUSED, Evas_Object *source EINA_UNUSED)
4943 {
4944 return EINA_FALSE;
4945 }
4946
4947 EOLIAN static Eina_Bool
_efl_ui_widget_on_access_activate(Eo * obj EINA_UNUSED,Elm_Widget_Smart_Data * _pd EINA_UNUSED,Efl_Ui_Activate act EINA_UNUSED)4948 _efl_ui_widget_on_access_activate(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd EINA_UNUSED, Efl_Ui_Activate act EINA_UNUSED)
4949 {
4950 WRN("The %s widget does not implement the \"activate\" functions.",
4951 efl_class_name_get(efl_class_get(obj)));
4952 return EINA_TRUE;
4953 }
4954
4955 EOLIAN static void
_efl_ui_widget_class_constructor(Efl_Class * klass)4956 _efl_ui_widget_class_constructor(Efl_Class *klass)
4957 {
4958 evas_smart_legacy_type_register(MY_CLASS_NAME_LEGACY, klass);
4959 }
4960
4961 EOLIAN static Eina_Bool
_efl_ui_widget_efl_access_component_focus_grab(Eo * obj,Elm_Widget_Smart_Data * pd EINA_UNUSED)4962 _efl_ui_widget_efl_access_component_focus_grab(Eo *obj, Elm_Widget_Smart_Data *pd EINA_UNUSED)
4963 {
4964 if (elm_object_focus_allow_get(obj))
4965 {
4966 Ecore_Evas *ee = ecore_evas_ecore_evas_get(evas_object_evas_get(obj));
4967 if (!ee) return EINA_FALSE;
4968 ecore_evas_activate(ee);
4969 elm_object_focus_set(obj, EINA_TRUE);
4970 return EINA_TRUE;
4971 }
4972 return EINA_FALSE;
4973 }
4974
4975 EOLIAN static const char*
_efl_ui_widget_efl_access_object_i18n_name_get(const Eo * obj,Elm_Widget_Smart_Data * _pd EINA_UNUSED)4976 _efl_ui_widget_efl_access_object_i18n_name_get(const Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED)
4977 {
4978 const char *ret, *name;
4979 name = efl_access_object_i18n_name_get(efl_super(obj, EFL_UI_WIDGET_CLASS));
4980
4981 if (name) return name;
4982
4983 ret = elm_object_text_get(obj);
4984 if (!ret) return NULL;
4985
4986 return _elm_widget_accessible_plain_name_get(obj, ret);
4987 }
4988
4989 EOLIAN static Eina_List*
_efl_ui_widget_efl_access_object_access_children_get(const Eo * obj EINA_UNUSED,Elm_Widget_Smart_Data * pd)4990 _efl_ui_widget_efl_access_object_access_children_get(const Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *pd)
4991 {
4992 Eina_List *accs = NULL;
4993 Evas_Object *widget;
4994 Efl_Access_Type type;
4995
4996 for (unsigned int i = 0; i < eina_array_count(pd->children); ++i)
4997 {
4998 widget = eina_array_data_get(pd->children, i);
4999
5000 if (!elm_object_widget_check(widget)) continue;
5001 if (!efl_isa(widget, EFL_ACCESS_OBJECT_MIXIN)) continue;
5002 type = efl_access_object_access_type_get(widget);
5003 if (type == EFL_ACCESS_TYPE_DISABLED) continue;
5004 if (type == EFL_ACCESS_TYPE_SKIPPED)
5005 {
5006 Eina_List *children;
5007 children = efl_access_object_access_children_get(widget);
5008 accs = eina_list_merge(accs, children);
5009 continue;
5010 }
5011 accs = eina_list_append(accs, widget);
5012 }
5013 return accs;
5014 }
5015
5016 EOLIAN static Efl_Access_State_Set
_efl_ui_widget_efl_access_object_state_set_get(const Eo * obj,Elm_Widget_Smart_Data * pd EINA_UNUSED)5017 _efl_ui_widget_efl_access_object_state_set_get(const Eo *obj, Elm_Widget_Smart_Data *pd EINA_UNUSED)
5018 {
5019 Efl_Access_State_Set states = 0;
5020
5021 states = efl_access_object_state_set_get(efl_super(obj, EFL_UI_WIDGET_CLASS));
5022
5023 if (evas_object_visible_get(obj))
5024 {
5025 STATE_TYPE_SET(states, EFL_ACCESS_STATE_TYPE_VISIBLE);
5026 if (_elm_widget_onscreen_is(obj))
5027 STATE_TYPE_SET(states, EFL_ACCESS_STATE_TYPE_SHOWING);
5028 }
5029 if (!elm_widget_child_can_focus_get(obj))
5030 {
5031 if (elm_object_focus_allow_get(obj))
5032 STATE_TYPE_SET(states, EFL_ACCESS_STATE_TYPE_FOCUSABLE);
5033 if (elm_object_focus_get(obj))
5034 STATE_TYPE_SET(states, EFL_ACCESS_STATE_TYPE_FOCUSED);
5035 }
5036 if (!elm_object_disabled_get(obj))
5037 {
5038 STATE_TYPE_SET(states, EFL_ACCESS_STATE_TYPE_ENABLED);
5039 STATE_TYPE_SET(states, EFL_ACCESS_STATE_TYPE_SENSITIVE);
5040 }
5041
5042 return states;
5043 }
5044
5045 EOLIAN static Eina_List*
_efl_ui_widget_efl_access_object_attributes_get(const Eo * obj,Elm_Widget_Smart_Data * pd EINA_UNUSED)5046 _efl_ui_widget_efl_access_object_attributes_get(const Eo *obj, Elm_Widget_Smart_Data *pd EINA_UNUSED)
5047 {
5048 const char *type = NULL;
5049 const char *style = NULL;
5050 Eina_List *attr_list = NULL;
5051 Efl_Access_Attribute *attr = NULL;
5052
5053 attr_list = efl_access_object_attributes_get(efl_super(obj, EFL_UI_WIDGET_CLASS));
5054
5055 //Add type and style information in addition.
5056 type = elm_widget_type_get(obj);
5057 if (type)
5058 {
5059 attr = calloc(1, sizeof(Efl_Access_Attribute));
5060 if (attr)
5061 {
5062 attr->key = eina_stringshare_add("type");
5063 attr->value = eina_stringshare_add(type);
5064 attr_list = eina_list_append(attr_list, attr);
5065 }
5066 }
5067
5068 style = elm_widget_style_get(obj);
5069 if (style)
5070 {
5071 attr = calloc(1, sizeof(Efl_Access_Attribute));
5072 if (attr)
5073 {
5074 attr->key = eina_stringshare_add("style");
5075 attr->value = eina_stringshare_add(style);
5076 attr_list = eina_list_append(attr_list, attr);
5077 }
5078 }
5079
5080 return attr_list;
5081 }
5082
5083 EOLIAN static Eina_List *
_elm_widget_item_efl_access_object_attributes_get(const Eo * eo_item,Elm_Widget_Item_Data * pd EINA_UNUSED)5084 _elm_widget_item_efl_access_object_attributes_get(const Eo *eo_item, Elm_Widget_Item_Data *pd EINA_UNUSED)
5085 {
5086 const char *style = NULL;
5087 Eina_List *attr_list = NULL;
5088 Efl_Access_Attribute *attr = NULL;
5089
5090 attr_list = efl_access_object_attributes_get(efl_super(eo_item, ELM_WIDGET_ITEM_CLASS));
5091
5092 style = elm_object_item_style_get(eo_item);
5093 if (style)
5094 {
5095 attr = calloc(1, sizeof(Efl_Access_Attribute));
5096 if (attr)
5097 {
5098 attr->key = eina_stringshare_add("style");
5099 attr->value = eina_stringshare_add(style);
5100 attr_list = eina_list_append(attr_list, attr);
5101 }
5102 }
5103 return attr_list;
5104 }
5105
5106 EOLIAN static Eina_Rect
_elm_widget_item_efl_access_component_extents_get(const Eo * obj EINA_UNUSED,Elm_Widget_Item_Data * sd EINA_UNUSED,Eina_Bool screen_coords)5107 _elm_widget_item_efl_access_component_extents_get(const Eo *obj EINA_UNUSED, Elm_Widget_Item_Data *sd EINA_UNUSED, Eina_Bool screen_coords)
5108 {
5109 Eina_Rect r = EINA_RECT(-1, -1, -1, -1);
5110 int ee_x, ee_y;
5111
5112 if (!sd->view) return r;
5113
5114 r = efl_gfx_entity_geometry_get(sd->view);
5115 if (screen_coords)
5116 {
5117 Ecore_Evas *ee = ecore_evas_ecore_evas_get(evas_object_evas_get(sd->view));
5118 if (ee)
5119 {
5120 ecore_evas_geometry_get(ee, &ee_x, &ee_y, NULL, NULL);
5121 r.x += ee_x;
5122 r.y += ee_y;
5123 }
5124 }
5125 return r;
5126 }
5127
5128 EOLIAN static Eina_Bool
_elm_widget_item_efl_access_component_extents_set(Eo * obj EINA_UNUSED,Elm_Widget_Item_Data * sd EINA_UNUSED,Eina_Bool screen_coords EINA_UNUSED,Eina_Rect r EINA_UNUSED)5129 _elm_widget_item_efl_access_component_extents_set(Eo *obj EINA_UNUSED, Elm_Widget_Item_Data *sd EINA_UNUSED, Eina_Bool screen_coords EINA_UNUSED, Eina_Rect r EINA_UNUSED)
5130 {
5131 return EINA_FALSE;
5132 }
5133
5134 EOLIAN static Eina_Bool
_elm_widget_item_efl_access_component_focus_grab(Eo * obj EINA_UNUSED,Elm_Widget_Item_Data * _pd EINA_UNUSED)5135 _elm_widget_item_efl_access_component_focus_grab(Eo *obj EINA_UNUSED, Elm_Widget_Item_Data *_pd EINA_UNUSED)
5136 {
5137 elm_object_item_focus_set(obj, EINA_TRUE);
5138 return elm_object_item_focus_get(obj);
5139 }
5140
5141 EOLIAN static Efl_Object *
_efl_ui_widget_efl_object_provider_find(const Eo * obj,Elm_Widget_Smart_Data * pd,const Efl_Object * klass)5142 _efl_ui_widget_efl_object_provider_find(const Eo *obj, Elm_Widget_Smart_Data *pd, const Efl_Object *klass)
5143 {
5144 Efl_Object *lookup = NULL;
5145
5146 if ((klass == EFL_CONFIG_INTERFACE) || (klass == EFL_CONFIG_GLOBAL_CLASS))
5147 return _efl_config_obj;
5148
5149 if (klass == EFL_UI_WIN_CLASS)
5150 {
5151 if (pd->window)
5152 return pd->window;
5153 //let the parent_obj lookup handle this
5154 }
5155
5156 if (klass == EFL_ACCESS_OBJECT_MIXIN)
5157 {
5158 Efl_Access_Type type = efl_access_object_access_type_get(obj);
5159 if (type != EFL_ACCESS_TYPE_SKIPPED)
5160 return (Eo*)obj;
5161 }
5162
5163 if (pd->provider_lookup) return NULL;
5164 pd->provider_lookup = EINA_TRUE;
5165
5166 lookup = efl_provider_find(efl_super(obj, MY_CLASS), klass);
5167 if (!lookup && pd->parent_obj) lookup = efl_provider_find(pd->parent_obj, klass);
5168
5169 pd->provider_lookup = EINA_FALSE;
5170
5171 return lookup;
5172 }
5173
5174 EOLIAN static Efl_Ui_Focus_Manager*
_efl_ui_widget_efl_ui_focus_object_focus_parent_get(const Eo * obj EINA_UNUSED,Elm_Widget_Smart_Data * pd EINA_UNUSED)5175 _efl_ui_widget_efl_ui_focus_object_focus_parent_get(const Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *pd EINA_UNUSED)
5176 {
5177 return pd->focus.parent;
5178 }
5179
5180 EOLIAN static Efl_Ui_Focus_Manager*
_efl_ui_widget_efl_ui_focus_object_focus_manager_get(const Eo * obj EINA_UNUSED,Elm_Widget_Smart_Data * pd EINA_UNUSED)5181 _efl_ui_widget_efl_ui_focus_object_focus_manager_get(const Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *pd EINA_UNUSED)
5182 {
5183 return pd->focus.manager;
5184 }
5185
5186 EOLIAN static Eina_Rect
_efl_ui_widget_efl_ui_focus_object_focus_geometry_get(const Eo * obj,Elm_Widget_Smart_Data * pd EINA_UNUSED)5187 _efl_ui_widget_efl_ui_focus_object_focus_geometry_get(const Eo *obj, Elm_Widget_Smart_Data *pd EINA_UNUSED)
5188 {
5189 return efl_gfx_entity_geometry_get(obj);
5190 }
5191
5192 EOLIAN static void
_efl_ui_widget_efl_ui_focus_object_focus_set(Eo * obj,Elm_Widget_Smart_Data * pd,Eina_Bool focus)5193 _efl_ui_widget_efl_ui_focus_object_focus_set(Eo *obj, Elm_Widget_Smart_Data *pd, Eina_Bool focus)
5194 {
5195 pd->focused = focus;
5196
5197 efl_ui_focus_object_focus_set(efl_super(obj, MY_CLASS), focus);
5198
5199 efl_ui_focus_object_on_focus_update(obj);
5200 }
5201
5202 /* Legacy APIs */
5203
5204 EAPI void
elm_widget_on_show_region_hook_set(Eo * obj,void * data,Elm_Widget_On_Show_Region_Cb func,Eina_Free_Cb func_free_cb)5205 elm_widget_on_show_region_hook_set(Eo *obj, void *data, Elm_Widget_On_Show_Region_Cb func, Eina_Free_Cb func_free_cb)
5206 {
5207 ELM_WIDGET_DATA_GET(obj, sd);
5208
5209 if (!sd) return;
5210 if ((sd->on_show_region_data == data) && (sd->on_show_region == func))
5211 return;
5212
5213 if (sd->on_show_region_data && sd->on_show_region_data_free)
5214 sd->on_show_region_data_free(sd->on_show_region_data);
5215
5216 sd->on_show_region = func;
5217 sd->on_show_region_data = data;
5218 sd->on_show_region_data_free = func_free_cb;
5219 }
5220
5221 EAPI void
elm_widget_show_region_set(Eo * obj,Eina_Rect sr,Eina_Bool forceshow)5222 elm_widget_show_region_set(Eo *obj, Eina_Rect sr, Eina_Bool forceshow)
5223 {
5224 Evas_Object *parent_obj, *child_obj;
5225 Evas_Coord px, py, cx, cy, nx = 0, ny = 0;
5226
5227 ELM_WIDGET_DATA_GET_OR_RETURN(obj, sd);
5228
5229 evas_smart_objects_calculate(evas_object_evas_get(obj));
5230
5231 if (!forceshow && eina_rectangle_equal(&sr.rect, &sd->show_region.rect)) return;
5232
5233 sd->show_region = sr;
5234 if (sd->on_show_region)
5235 {
5236 sd->on_show_region(sd->on_show_region_data, obj, sr);
5237
5238 if (_elm_scrollable_is(obj))
5239 {
5240 if (elm_widget_is_legacy(obj))
5241 {
5242 elm_interface_scrollable_content_pos_get(obj, &nx, &ny);
5243 sr.x -= nx;
5244 sr.y -= ny;
5245 }
5246 else
5247 {
5248 Eina_Position2D pos;
5249 pos = efl_ui_scrollable_content_pos_get(obj);
5250 sr.x -= pos.x;
5251 sr.y -= pos.y;
5252 }
5253 }
5254 }
5255 child_obj = obj;
5256 do
5257 {
5258 parent_obj = sd->parent_obj;
5259 if ((!parent_obj)) break;
5260 sd = efl_data_scope_get(parent_obj, MY_CLASS);
5261 if (!sd) break;
5262
5263 evas_object_geometry_get(parent_obj, &px, &py, NULL, NULL);
5264 evas_object_geometry_get(child_obj, &cx, &cy, NULL, NULL);
5265
5266 sr.x += (cx - px);
5267 sr.y += (cy - py);
5268 sd->show_region = sr;
5269
5270 if (sd->on_show_region)
5271 sd->on_show_region(sd->on_show_region_data, parent_obj, sr);
5272 child_obj = parent_obj;
5273 }
5274 while (parent_obj);
5275 }
5276
5277 EAPI Eina_Rect
elm_widget_show_region_get(const Eo * obj)5278 elm_widget_show_region_get(const Eo *obj)
5279 {
5280 ELM_WIDGET_DATA_GET_OR_RETURN(obj, sd, EINA_RECT_EMPTY());
5281 return (Eina_Rect) sd->show_region;
5282 }
5283 /* elm_object_content_xxx APIs are supposed to work on all objects for which
5284 * elm_object_widget_check() returns true. The below checks avoid printing out
5285 * undesired ERR messages. */
5286 EAPI void
elm_widget_content_part_set(Evas_Object * obj,const char * part,Evas_Object * content)5287 elm_widget_content_part_set(Evas_Object *obj, const char *part, Evas_Object *content)
5288 {
5289 ELM_WIDGET_CHECK(obj);
5290 if (efl_isa(obj, EFL_UI_LAYOUT_BASE_CLASS))
5291 {
5292 elm_layout_content_set(obj, part, content);
5293 return;
5294 }
5295 if (!efl_isa(obj, EFL_PART_INTERFACE)) return;
5296 if (!part)
5297 {
5298 part = efl_ui_widget_default_content_part_get(obj);
5299 if (!part) return;
5300 }
5301 efl_content_set(efl_part(obj, part), content);
5302 }
5303
5304 EAPI Evas_Object *
elm_widget_content_part_get(const Evas_Object * obj,const char * part)5305 elm_widget_content_part_get(const Evas_Object *obj, const char *part)
5306 {
5307 ELM_WIDGET_CHECK(obj) NULL;
5308 if (efl_isa(obj, EFL_UI_LAYOUT_BASE_CLASS))
5309 return elm_layout_content_get(obj, part);
5310 if (!efl_isa(obj, EFL_PART_INTERFACE)) return NULL;
5311 if (!part)
5312 {
5313 part = efl_ui_widget_default_content_part_get(obj);
5314 if (!part) return NULL;
5315 }
5316 return efl_content_get(efl_part(obj, part));
5317 }
5318
5319 EAPI Evas_Object *
elm_widget_content_part_unset(Evas_Object * obj,const char * part)5320 elm_widget_content_part_unset(Evas_Object *obj, const char *part)
5321 {
5322 ELM_WIDGET_CHECK(obj) NULL;
5323 if (efl_isa(obj, EFL_UI_LAYOUT_BASE_CLASS))
5324 return elm_layout_content_unset(obj, part);
5325 if (!efl_isa(obj, EFL_PART_INTERFACE)) return NULL;
5326 if (!part)
5327 {
5328 part = efl_ui_widget_default_content_part_get(obj);
5329 if (!part) return NULL;
5330 }
5331 return efl_content_unset(efl_part(obj, part));
5332 }
5333
5334 EAPI void
elm_widget_signal_emit(Eo * obj,const char * emission,const char * source)5335 elm_widget_signal_emit(Eo *obj, const char *emission, const char *source)
5336 {
5337 ELM_WIDGET_CHECK(obj);
5338
5339 if (efl_isa(obj, EFL_UI_LAYOUT_BASE_CLASS))
5340 elm_layout_signal_emit(obj, emission, source);
5341 else if (evas_object_smart_type_check(obj, "elm_icon"))
5342 {
5343 WRN("Deprecated function. This functionality on icon objects"
5344 " will be dropped on a next release.");
5345 _elm_icon_signal_emit(obj, emission, source);
5346 }
5347 }
5348
5349 EAPI void
elm_widget_signal_callback_add(Eo * obj,const char * emission,const char * source,Edje_Signal_Cb func,void * data)5350 elm_widget_signal_callback_add(Eo *obj, const char *emission, const char *source, Edje_Signal_Cb func, void *data)
5351 {
5352 ELM_WIDGET_CHECK(obj);
5353 EINA_SAFETY_ON_NULL_RETURN(func);
5354 if (evas_object_smart_type_check(obj, "elm_layout"))
5355 elm_layout_signal_callback_add(obj, emission, source, func, data);
5356 else if (evas_object_smart_type_check(obj, "elm_icon"))
5357 {
5358 WRN("Deprecated function. This functionality on icon objects"
5359 " will be dropped on a next release.");
5360
5361 _elm_icon_signal_callback_add(obj, emission, source, func, data);
5362 }
5363 }
5364
5365 EAPI void *
elm_widget_signal_callback_del(Eo * obj,const char * emission,const char * source,Edje_Signal_Cb func)5366 elm_widget_signal_callback_del(Eo *obj, const char *emission, const char *source, Edje_Signal_Cb func)
5367 {
5368 void *data = NULL;
5369
5370 ELM_WIDGET_CHECK(obj) NULL;
5371 EINA_SAFETY_ON_NULL_RETURN_VAL(func, NULL);
5372 if (evas_object_smart_type_check(obj, "elm_layout"))
5373 data = elm_layout_signal_callback_del(obj, emission, source, func);
5374 else if (evas_object_smart_type_check(obj, "elm_icon"))
5375 {
5376 WRN("Deprecated function. This functionality on icon objects"
5377 " will be dropped on a next release.");
5378
5379 data = _elm_icon_signal_callback_del(obj, emission, source, func);
5380 }
5381
5382 return data;
5383 }
5384
5385
5386 /* Widget Shadow Begin */
5387
5388 typedef struct _Widget_Shadow
5389 {
5390 Eo *widget;
5391 Eo *surface;
5392 struct {
5393 double rx, ry, ox, oy, grow;
5394 int r, g, b, a;
5395 } props;
5396 Eina_Stringshare *code, *name;
5397 } Widget_Shadow;
5398
5399 static void _widget_shadow_update(Widget_Shadow *shadow);
5400
5401 static void
_widget_shadow_del_cb(void * data,const Efl_Event * ev EINA_UNUSED)5402 _widget_shadow_del_cb(void *data, const Efl_Event *ev EINA_UNUSED)
5403 {
5404 Widget_Shadow *shadow = data;
5405
5406 efl_del(shadow->surface);
5407 free(shadow);
5408 }
5409
5410 static void
_widget_shadow_event_cb(void * data,const Efl_Event * ev EINA_UNUSED)5411 _widget_shadow_event_cb(void *data, const Efl_Event *ev EINA_UNUSED)
5412 {
5413 Widget_Shadow *shadow = data;
5414 _widget_shadow_update(shadow);
5415 }
5416
5417 EFL_CALLBACKS_ARRAY_DEFINE(widget_shadow_cb,
5418 { EFL_EVENT_DEL, _widget_shadow_del_cb },
5419 { EFL_GFX_ENTITY_EVENT_POSITION_CHANGED, _widget_shadow_event_cb },
5420 { EFL_GFX_ENTITY_EVENT_SIZE_CHANGED, _widget_shadow_event_cb },
5421 { EFL_GFX_ENTITY_EVENT_STACKING_CHANGED, _widget_shadow_event_cb },
5422 { EFL_GFX_ENTITY_EVENT_VISIBILITY_CHANGED, _widget_shadow_event_cb });
5423
5424 static Widget_Shadow *
_widget_shadow_part_get(const Eo * part_obj)5425 _widget_shadow_part_get(const Eo *part_obj)
5426 {
5427 Elm_Part_Data *pd = efl_data_scope_get(part_obj, EFL_UI_WIDGET_PART_CLASS);
5428 Widget_Shadow *shadow;
5429 Eo *widget = pd->obj;
5430
5431 shadow = efl_key_data_get(widget, "__elm_shadow");
5432 if (!shadow)
5433 {
5434 shadow = calloc(1, sizeof(*shadow));
5435 if (!shadow) return NULL;
5436 shadow->widget = pd->obj;
5437 efl_key_data_set(widget, "__elm_shadow", shadow);
5438 efl_event_callback_array_add(widget, widget_shadow_cb(), shadow);
5439 }
5440 return shadow;
5441 }
5442
5443 static void
_widget_shadow_update(Widget_Shadow * ws)5444 _widget_shadow_update(Widget_Shadow *ws)
5445 {
5446 int l = 0, r = 0, t = 0, b = 0;
5447 Eina_Rect srect, wrect;
5448 char filter[1024];
5449
5450 #define FILTER_FMT \
5451 "a = buffer { 'alpha' }" \
5452 "grow { %f, dst = a, alphaonly = true }" \
5453 "blur { src = a, rx = %f, ry = %f, color = color(%d,%d,%d,%d) }"
5454
5455 if (!ws->surface)
5456 {
5457 ws->surface = efl_add(EFL_CANVAS_PROXY_CLASS, ws->widget);
5458 efl_gfx_fill_auto_set(ws->surface, 1);
5459 efl_canvas_proxy_source_clip_set(ws->surface, EINA_FALSE);
5460 efl_canvas_proxy_source_events_set(ws->surface, EINA_FALSE);
5461 efl_canvas_proxy_source_set(ws->surface, ws->widget);
5462 }
5463
5464 if (!ws->code)
5465 {
5466 snprintf(filter, sizeof(filter), FILTER_FMT,
5467 ws->props.grow, ws->props.rx, ws->props.ry,
5468 ws->props.r, ws->props.g, ws->props.b, ws->props.a);
5469 }
5470
5471 efl_gfx_filter_program_set(ws->surface,
5472 ws->code ? ws->code : filter,
5473 ws->name ? ws->name : "shadow");
5474 efl_gfx_filter_padding_get(ws->surface, &l, &r, &t, &b);
5475
5476 wrect = efl_gfx_entity_geometry_get(ws->widget);
5477 srect.x = wrect.x + (int) (-l + ws->props.ox);
5478 srect.y = wrect.y + (int) (-t + ws->props.oy);
5479 srect.w = wrect.w + (int) (l + r);
5480 srect.h = wrect.h + (int) (t + b);
5481
5482 if ((!ws->props.a && !ws->code) ||
5483 !efl_gfx_entity_visible_get(ws->widget))
5484 {
5485 efl_gfx_entity_visible_set(ws->surface, EINA_FALSE);
5486 return;
5487 }
5488
5489 efl_canvas_object_clipper_set(ws->surface, efl_canvas_object_clipper_get(ws->widget));
5490 efl_canvas_group_member_add(efl_canvas_object_render_parent_get(ws->widget), ws->surface);
5491 efl_gfx_entity_geometry_set(ws->surface, srect);
5492 efl_gfx_stack_below(ws->surface, ws->widget);
5493 efl_gfx_entity_visible_set(ws->surface, EINA_TRUE);
5494 }
5495
5496 static void
_elm_widget_shadow_update(Efl_Ui_Widget * obj)5497 _elm_widget_shadow_update(Efl_Ui_Widget *obj)
5498 {
5499 Widget_Shadow *shadow = _widget_shadow_part_get(obj);
5500 _widget_shadow_update(shadow);
5501 }
5502
5503 EOLIAN static void
_efl_ui_widget_part_shadow_efl_gfx_blur_offset_set(Eo * obj,void * _pd EINA_UNUSED,double ox,double oy)5504 _efl_ui_widget_part_shadow_efl_gfx_blur_offset_set(Eo *obj, void *_pd EINA_UNUSED, double ox, double oy)
5505 {
5506 Widget_Shadow *shadow = _widget_shadow_part_get(obj);
5507 shadow->props.ox = ox;
5508 shadow->props.oy = oy;
5509 _widget_shadow_update(shadow);
5510 }
5511
5512 EOLIAN static void
_efl_ui_widget_part_shadow_efl_gfx_blur_offset_get(const Eo * obj,void * _pd EINA_UNUSED,double * ox,double * oy)5513 _efl_ui_widget_part_shadow_efl_gfx_blur_offset_get(const Eo *obj, void *_pd EINA_UNUSED, double *ox, double *oy)
5514 {
5515 Widget_Shadow *shadow = _widget_shadow_part_get(obj);
5516 if (ox) *ox = shadow->props.ox;
5517 if (oy) *oy = shadow->props.oy;
5518 }
5519
5520 EOLIAN static void
_efl_ui_widget_part_shadow_efl_gfx_blur_radius_set(Eo * obj,void * _pd EINA_UNUSED,double rx,double ry)5521 _efl_ui_widget_part_shadow_efl_gfx_blur_radius_set(Eo *obj, void *_pd EINA_UNUSED, double rx, double ry)
5522 {
5523 Widget_Shadow *shadow = _widget_shadow_part_get(obj);
5524 shadow->props.rx = rx;
5525 shadow->props.ry = ry;
5526 _widget_shadow_update(shadow);
5527 }
5528
5529 EOLIAN static void
_efl_ui_widget_part_shadow_efl_gfx_blur_radius_get(const Eo * obj,void * _pd EINA_UNUSED,double * rx,double * ry)5530 _efl_ui_widget_part_shadow_efl_gfx_blur_radius_get(const Eo *obj, void *_pd EINA_UNUSED, double *rx, double *ry)
5531 {
5532 Widget_Shadow *shadow = _widget_shadow_part_get(obj);
5533 if (rx) *rx = shadow->props.rx;
5534 if (ry) *ry = shadow->props.ry;
5535 }
5536
5537 EOLIAN static void
_efl_ui_widget_part_shadow_efl_gfx_color_color_set(Eo * obj,void * _pd EINA_UNUSED,int r,int g,int b,int a)5538 _efl_ui_widget_part_shadow_efl_gfx_color_color_set(Eo *obj, void *_pd EINA_UNUSED, int r, int g, int b, int a)
5539 {
5540 Widget_Shadow *shadow = _widget_shadow_part_get(obj);
5541 shadow->props.r = r;
5542 shadow->props.g = g;
5543 shadow->props.b = b;
5544 shadow->props.a = a;
5545 _widget_shadow_update(shadow);
5546 }
5547
5548 EOLIAN static void
_efl_ui_widget_part_shadow_efl_gfx_color_color_get(const Eo * obj,void * _pd EINA_UNUSED,int * r,int * g,int * b,int * a)5549 _efl_ui_widget_part_shadow_efl_gfx_color_color_get(const Eo *obj, void *_pd EINA_UNUSED, int *r, int *g, int *b, int *a)
5550 {
5551 Widget_Shadow *shadow = _widget_shadow_part_get(obj);
5552 if (r) *r = shadow->props.r;
5553 if (g) *g = shadow->props.g;
5554 if (b) *b = shadow->props.b;
5555 if (a) *a = shadow->props.a;
5556 }
5557
5558 EOLIAN static void
_efl_ui_widget_part_shadow_efl_gfx_blur_grow_set(Eo * obj,void * _pd EINA_UNUSED,double radius)5559 _efl_ui_widget_part_shadow_efl_gfx_blur_grow_set(Eo *obj, void *_pd EINA_UNUSED, double radius)
5560 {
5561 Widget_Shadow *shadow = _widget_shadow_part_get(obj);
5562 shadow->props.grow = radius;
5563 _widget_shadow_update(shadow);
5564 }
5565
5566 EOLIAN static double
_efl_ui_widget_part_shadow_efl_gfx_blur_grow_get(const Eo * obj,void * _pd EINA_UNUSED)5567 _efl_ui_widget_part_shadow_efl_gfx_blur_grow_get(const Eo *obj, void *_pd EINA_UNUSED)
5568 {
5569 Widget_Shadow *shadow = _widget_shadow_part_get(obj);
5570 return shadow->props.grow;
5571 }
5572
5573 EOLIAN static void
_efl_ui_widget_part_shadow_efl_gfx_filter_filter_program_set(Eo * obj,void * _pd EINA_UNUSED,const char * code,const char * name)5574 _efl_ui_widget_part_shadow_efl_gfx_filter_filter_program_set(Eo *obj, void *_pd EINA_UNUSED, const char *code, const char *name)
5575 {
5576 Widget_Shadow *ws = _widget_shadow_part_get(obj);
5577 eina_stringshare_replace(&ws->code, code);
5578 eina_stringshare_replace(&ws->name, name);
5579 _widget_shadow_update(ws);
5580 }
5581
5582 EOLIAN static void
_efl_ui_widget_part_shadow_efl_gfx_filter_filter_program_get(const Eo * obj,void * _pd EINA_UNUSED,const char ** code,const char ** name)5583 _efl_ui_widget_part_shadow_efl_gfx_filter_filter_program_get(const Eo *obj, void *_pd EINA_UNUSED, const char **code, const char **name)
5584 {
5585 Widget_Shadow *ws = _widget_shadow_part_get(obj);
5586 efl_gfx_filter_program_get(ws->surface, code, name);
5587 }
5588
5589 EOLIAN static void
_efl_ui_widget_part_shadow_efl_gfx_filter_filter_source_set(Eo * obj,void * _pd EINA_UNUSED,const char * name,Efl_Gfx_Entity * source)5590 _efl_ui_widget_part_shadow_efl_gfx_filter_filter_source_set(Eo *obj, void *_pd EINA_UNUSED, const char *name, Efl_Gfx_Entity *source)
5591 {
5592 Widget_Shadow *ws = _widget_shadow_part_get(obj);
5593 _widget_shadow_update(ws);
5594 efl_gfx_filter_source_set(ws->surface, name, source);
5595 }
5596
5597 EOLIAN static Efl_Gfx_Entity *
_efl_ui_widget_part_shadow_efl_gfx_filter_filter_source_get(const Eo * obj,void * _pd EINA_UNUSED,const char * name)5598 _efl_ui_widget_part_shadow_efl_gfx_filter_filter_source_get(const Eo *obj, void *_pd EINA_UNUSED, const char *name)
5599 {
5600 Widget_Shadow *ws = _widget_shadow_part_get(obj);
5601 return efl_gfx_filter_source_get(ws->surface, name);
5602 }
5603
5604 EOLIAN static void
_efl_ui_widget_part_shadow_efl_gfx_filter_filter_data_set(Eo * obj,void * _pd EINA_UNUSED,const char * name,const char * value,Eina_Bool execute)5605 _efl_ui_widget_part_shadow_efl_gfx_filter_filter_data_set(Eo *obj, void *_pd EINA_UNUSED, const char *name, const char *value, Eina_Bool execute)
5606 {
5607 Widget_Shadow *ws = _widget_shadow_part_get(obj);
5608 _widget_shadow_update(ws);
5609 efl_gfx_filter_data_set(ws->surface, name, value, execute);
5610 }
5611
5612 EOLIAN static void
_efl_ui_widget_part_shadow_efl_gfx_filter_filter_data_get(const Eo * obj,void * _pd EINA_UNUSED,const char * name,const char ** value,Eina_Bool * execute)5613 _efl_ui_widget_part_shadow_efl_gfx_filter_filter_data_get(const Eo *obj, void *_pd EINA_UNUSED, const char *name, const char **value, Eina_Bool *execute)
5614 {
5615 Widget_Shadow *ws = _widget_shadow_part_get(obj);
5616 efl_gfx_filter_data_get(ws->surface, name, value, execute);
5617 }
5618
5619 EOLIAN static void
_efl_ui_widget_part_shadow_efl_gfx_filter_filter_padding_get(const Eo * obj,void * _pd EINA_UNUSED,int * l,int * r,int * t,int * b)5620 _efl_ui_widget_part_shadow_efl_gfx_filter_filter_padding_get(const Eo *obj, void *_pd EINA_UNUSED, int *l, int *r, int *t, int *b)
5621 {
5622 Widget_Shadow *ws = _widget_shadow_part_get(obj);
5623 efl_gfx_filter_padding_get(ws->surface, l, r, t, b);
5624 }
5625
5626 EOLIAN static void
_efl_ui_widget_part_shadow_efl_gfx_filter_filter_state_set(Eo * obj,void * _pd EINA_UNUSED,const char * cur_state,double cur_val,const char * next_state,double next_val,double pos)5627 _efl_ui_widget_part_shadow_efl_gfx_filter_filter_state_set(Eo *obj, void *_pd EINA_UNUSED, const char *cur_state, double cur_val, const char *next_state, double next_val, double pos)
5628 {
5629 Widget_Shadow *ws = _widget_shadow_part_get(obj);
5630 efl_gfx_filter_state_set(ws->surface, cur_state, cur_val, next_state, next_val, pos);
5631 }
5632
5633 EOLIAN static void
_efl_ui_widget_part_shadow_efl_gfx_filter_filter_state_get(const Eo * obj,void * _pd EINA_UNUSED,const char ** cur_state,double * cur_val,const char ** next_state,double * next_val,double * pos)5634 _efl_ui_widget_part_shadow_efl_gfx_filter_filter_state_get(const Eo *obj, void *_pd EINA_UNUSED, const char **cur_state, double *cur_val, const char **next_state, double *next_val, double *pos)
5635 {
5636 Widget_Shadow *ws = _widget_shadow_part_get(obj);
5637 efl_gfx_filter_state_get(ws->surface, cur_state, cur_val, next_state, next_val, pos);
5638 }
5639
5640 #include "efl_ui_widget_part_shadow.eo.c"
5641
5642 /* Widget Shadow End */
5643
5644
5645 /* Efl.Part implementation */
5646
5647 EOLIAN static Efl_Object *
_efl_ui_widget_efl_part_part_get(const Eo * obj,Elm_Widget_Smart_Data * wd EINA_UNUSED,const char * part)5648 _efl_ui_widget_efl_part_part_get(const Eo *obj, Elm_Widget_Smart_Data *wd EINA_UNUSED, const char *part)
5649 {
5650 if (eina_streq(part, "background"))
5651 return ELM_PART_IMPLEMENT(EFL_UI_WIDGET_PART_BG_CLASS, obj, part);
5652 else if (eina_streq(part, "shadow"))
5653 return ELM_PART_IMPLEMENT(EFL_UI_WIDGET_PART_SHADOW_CLASS, obj, part);
5654 return ELM_PART_IMPLEMENT(EFL_UI_WIDGET_PART_CLASS, obj, part);
5655 }
5656
5657 EOLIAN static void \
_efl_ui_widget_part_efl_object_destructor(Eo * obj,Elm_Part_Data * pd)5658 _efl_ui_widget_part_efl_object_destructor(Eo *obj, Elm_Part_Data *pd)
5659 {
5660 ELM_PART_HOOK;
5661 eina_tmpstr_del(pd->part);
5662 efl_destructor(efl_super(obj, EFL_UI_WIDGET_PART_CLASS));
5663 }
5664
5665 static Efl_Canvas_Layout_Part_Type
_efl_ui_widget_part_efl_canvas_layout_part_type_provider_part_type_get(const Eo * obj EINA_UNUSED,Elm_Part_Data * pd)5666 _efl_ui_widget_part_efl_canvas_layout_part_type_provider_part_type_get(const Eo *obj EINA_UNUSED, Elm_Part_Data *pd)
5667 {
5668 Elm_Widget_Smart_Data *sd = efl_data_scope_safe_get(pd->obj, MY_CLASS);
5669 EINA_SAFETY_ON_NULL_RETURN_VAL(sd, EFL_CANVAS_LAYOUT_PART_TYPE_NONE);
5670 return efl_canvas_layout_part_type_get(efl_part(sd->resize_obj, pd->part));
5671 }
5672
5673 static Eina_Rect
_efl_ui_widget_part_efl_gfx_entity_geometry_get(const Eo * obj EINA_UNUSED,Elm_Part_Data * pd)5674 _efl_ui_widget_part_efl_gfx_entity_geometry_get(const Eo *obj EINA_UNUSED, Elm_Part_Data *pd)
5675 {
5676 Elm_Widget_Smart_Data *sd = efl_data_scope_safe_get(pd->obj, MY_CLASS);
5677 EINA_SAFETY_ON_NULL_RETURN_VAL(sd, EINA_RECT_EMPTY());
5678 return efl_gfx_entity_geometry_get(efl_part(sd->resize_obj, pd->part));
5679 }
5680
5681 static Eina_Error
_efl_ui_widget_part_efl_ui_property_bind_property_bind(Eo * obj,Elm_Part_Data * ppd,const char * key,const char * property)5682 _efl_ui_widget_part_efl_ui_property_bind_property_bind(Eo *obj, Elm_Part_Data *ppd,
5683 const char *key, const char *property)
5684 {
5685 Efl_Ui_Widget_Data *pd;
5686 Eo *widget;
5687
5688 widget = efl_parent_get(obj);
5689 pd = efl_data_scope_get(widget, EFL_UI_WIDGET_CLASS);
5690
5691 return _efl_ui_property_bind(widget, obj, pd, ppd->part, key, property);
5692 }
5693
5694 #include "efl_ui_widget_part.eo.c"
5695
5696 /* Efl.Part end */
5697
5698 /* Efl.Part Bg implementation */
5699
5700 Efl_Canvas_Object *
_efl_ui_widget_bg_get(const Efl_Ui_Widget * obj)5701 _efl_ui_widget_bg_get(const Efl_Ui_Widget *obj)
5702 {
5703 Elm_Widget_Smart_Data *sd = efl_data_scope_get(obj, MY_CLASS);
5704 Evas_Object *bg_obj = sd->bg;
5705
5706 if (!bg_obj)
5707 {
5708 /* XXX const */
5709 bg_obj = efl_add(EFL_UI_BG_CLASS, (Eo *)obj);
5710 EINA_SAFETY_ON_NULL_RETURN_VAL(bg_obj, NULL);
5711 sd->bg = bg_obj;
5712 efl_canvas_group_member_add((Eo *)obj, sd->bg);
5713 evas_object_stack_below(sd->bg, sd->resize_obj);
5714 _smart_reconfigure((Eo*)obj, sd);
5715 }
5716
5717 return bg_obj;
5718 }
5719
5720 static inline Efl_Canvas_Object *
efl_ui_widget_part_bg_get(const Eo * part_obj)5721 efl_ui_widget_part_bg_get(const Eo *part_obj)
5722 {
5723 Elm_Part_Data *pd = efl_data_scope_get(part_obj, EFL_UI_WIDGET_PART_CLASS);
5724 return _efl_ui_widget_bg_get(pd->obj);
5725 }
5726
5727 EOLIAN static Eina_Error
_efl_ui_widget_part_bg_efl_file_load(Eo * obj,void * pd EINA_UNUSED)5728 _efl_ui_widget_part_bg_efl_file_load(Eo *obj, void *pd EINA_UNUSED)
5729 {
5730 Evas_Object *bg_obj = efl_ui_widget_part_bg_get(obj);
5731
5732 return efl_file_load(bg_obj);
5733 }
5734
5735 EOLIAN static void
_efl_ui_widget_part_bg_efl_file_unload(Eo * obj,void * pd EINA_UNUSED)5736 _efl_ui_widget_part_bg_efl_file_unload(Eo *obj, void *pd EINA_UNUSED)
5737 {
5738 Evas_Object *bg_obj = efl_ui_widget_part_bg_get(obj);
5739
5740 efl_file_unload(bg_obj);
5741 }
5742
5743 EOLIAN static const char *
_efl_ui_widget_part_bg_efl_file_file_get(const Eo * obj,void * pd EINA_UNUSED)5744 _efl_ui_widget_part_bg_efl_file_file_get(const Eo *obj, void *pd EINA_UNUSED)
5745 {
5746 Evas_Object *bg_obj = efl_ui_widget_part_bg_get(obj);
5747
5748 return efl_file_get(bg_obj);
5749 }
5750
5751 EOLIAN static Eina_Error
_efl_ui_widget_part_bg_efl_file_file_set(Eo * obj,void * pd EINA_UNUSED,const char * file)5752 _efl_ui_widget_part_bg_efl_file_file_set(Eo *obj, void *pd EINA_UNUSED, const char *file)
5753 {
5754 Evas_Object *bg_obj = efl_ui_widget_part_bg_get(obj);
5755
5756 return efl_file_set(bg_obj, file);
5757 }
5758
5759 EOLIAN static const char *
_efl_ui_widget_part_bg_efl_file_key_get(const Eo * obj,void * pd EINA_UNUSED)5760 _efl_ui_widget_part_bg_efl_file_key_get(const Eo *obj, void *pd EINA_UNUSED)
5761 {
5762 Evas_Object *bg_obj = efl_ui_widget_part_bg_get(obj);
5763
5764 return efl_file_key_get(bg_obj);
5765 }
5766
5767 EOLIAN static void
_efl_ui_widget_part_bg_efl_file_key_set(Eo * obj,void * pd EINA_UNUSED,const char * key)5768 _efl_ui_widget_part_bg_efl_file_key_set(Eo *obj, void *pd EINA_UNUSED, const char *key)
5769 {
5770 Evas_Object *bg_obj = efl_ui_widget_part_bg_get(obj);
5771
5772 efl_file_key_set(bg_obj, key);
5773 }
5774
5775 EOLIAN static const Eina_File *
_efl_ui_widget_part_bg_efl_file_mmap_get(const Eo * obj,void * pd EINA_UNUSED)5776 _efl_ui_widget_part_bg_efl_file_mmap_get(const Eo *obj, void *pd EINA_UNUSED)
5777 {
5778 Evas_Object *bg_obj = efl_ui_widget_part_bg_get(obj);
5779
5780 return efl_file_mmap_get(bg_obj);
5781 }
5782
5783 EOLIAN static Eina_Error
_efl_ui_widget_part_bg_efl_file_mmap_set(Eo * obj,void * pd EINA_UNUSED,const Eina_File * file)5784 _efl_ui_widget_part_bg_efl_file_mmap_set(Eo *obj, void *pd EINA_UNUSED, const Eina_File *file)
5785 {
5786 Evas_Object *bg_obj = efl_ui_widget_part_bg_get(obj);
5787
5788 return efl_file_mmap_set(bg_obj, file);
5789 }
5790
5791 EOLIAN static void
_efl_ui_widget_part_bg_efl_gfx_color_color_set(Eo * obj,void * pd EINA_UNUSED,int r,int g,int b,int a)5792 _efl_ui_widget_part_bg_efl_gfx_color_color_set(Eo *obj, void *pd EINA_UNUSED, int r, int g, int b, int a)
5793 {
5794 Evas_Object *bg_obj = efl_ui_widget_part_bg_get(obj);
5795
5796 efl_gfx_color_set(bg_obj, r, g, b, a);
5797 }
5798
5799 EOLIAN static void
_efl_ui_widget_part_bg_efl_gfx_color_color_get(const Eo * obj,void * pd EINA_UNUSED,int * r,int * g,int * b,int * a)5800 _efl_ui_widget_part_bg_efl_gfx_color_color_get(const Eo *obj, void *pd EINA_UNUSED, int *r, int *g, int *b, int *a)
5801 {
5802 Evas_Object *bg_obj = efl_ui_widget_part_bg_get(obj);
5803
5804 efl_gfx_color_get(bg_obj, r, g, b, a);
5805 }
5806
5807 EOLIAN static Efl_Object*
_efl_ui_widget_part_bg_efl_object_finalize(Eo * obj,void * pd EINA_UNUSED)5808 _efl_ui_widget_part_bg_efl_object_finalize(Eo *obj, void *pd EINA_UNUSED)
5809 {
5810 Evas_Object *bg_obj = efl_ui_widget_part_bg_get(obj);
5811
5812 efl_composite_attach(obj, bg_obj);
5813
5814 return efl_finalize(efl_super(obj, EFL_UI_WIDGET_PART_BG_CLASS));
5815 }
5816
5817
5818 typedef struct _Efl_Ui_Property_Bound Efl_Ui_Property_Bound;
5819 struct _Efl_Ui_Property_Bound
5820 {
5821 Eina_Stringshare *part; // Optional part to apply the property on
5822 Eina_Stringshare *key; // Local object property
5823 Eina_Stringshare *property; // Model property
5824 Eina_Future *f;
5825 };
5826
5827 static void
_efl_ui_property_bind_free(void * data)5828 _efl_ui_property_bind_free(void *data)
5829 {
5830 Efl_Ui_Property_Bound *prop = data;
5831
5832 eina_stringshare_del(prop->part);
5833 eina_stringshare_del(prop->key);
5834 eina_stringshare_del(prop->property);
5835 free(prop);
5836 }
5837
5838 static void
_efl_ui_property_bind_clean(Eo * obj EINA_UNUSED,void * data,const Eina_Future * f EINA_UNUSED)5839 _efl_ui_property_bind_clean(Eo *obj EINA_UNUSED,
5840 void *data,
5841 const Eina_Future *f EINA_UNUSED)
5842 {
5843 Efl_Ui_Property_Bound *prop = data;
5844
5845 prop->f = NULL;
5846 }
5847
5848 static void
_efl_ui_property_bind_get(Eo * obj,Efl_Ui_Widget_Data * pd,Efl_Ui_Property_Bound * prop)5849 _efl_ui_property_bind_get(Eo *obj, Efl_Ui_Widget_Data *pd, Efl_Ui_Property_Bound *prop)
5850 {
5851 Eina_Value *value;
5852 Eina_Future *f;
5853 Eina_Error err;
5854 Eo *target;
5855
5856 // If there is no model set yet, no need to try anything
5857 if (!pd->properties.model) return ;
5858
5859 value = efl_model_property_get(pd->properties.model, prop->property);
5860 target = prop->part ? efl_part(obj, prop->part) : obj;
5861
5862 err = efl_property_reflection_set(target, prop->key, eina_value_reference_copy(value));
5863 eina_value_free(value);
5864
5865 if (!err) return ;
5866
5867 // Report back the error to the model
5868 if (prop->f) eina_future_cancel(prop->f);
5869 f = efl_model_property_set(pd->properties.model, prop->property,
5870 eina_value_error_new(err));
5871 prop->f = efl_future_then(obj, f, .free = _efl_ui_property_bind_clean, .data = prop);
5872 }
5873
5874 static void
_efl_ui_property_bind_set(Eo * obj,Efl_Ui_Widget_Data * pd,Efl_Ui_Property_Bound * prop)5875 _efl_ui_property_bind_set(Eo *obj, Efl_Ui_Widget_Data *pd, Efl_Ui_Property_Bound *prop)
5876 {
5877 Eina_Value value;
5878 Eina_Future *f;
5879 Eo *target;
5880
5881 target = prop->part ? efl_part(obj, prop->part) : obj;
5882 value = efl_property_reflection_get(target, prop->key);
5883
5884 if (prop->f) eina_future_cancel(prop->f);
5885 f = efl_model_property_set(pd->properties.model, prop->property, eina_value_dup(&value));
5886 prop->f = efl_future_then(obj, f, .free = _efl_ui_property_bind_clean, .data = prop);
5887 eina_value_flush(&value);
5888 }
5889
5890 static void
_efl_ui_model_property_bind_changed(void * data,const Efl_Event * event)5891 _efl_ui_model_property_bind_changed(void *data, const Efl_Event *event)
5892 {
5893 Efl_Model_Property_Event *evt = event->info;
5894 ELM_WIDGET_DATA_GET(data, pd);
5895 Eina_Array_Iterator it;
5896 const char *prop;
5897 unsigned int i;
5898
5899 if (!pd) return;
5900 EINA_ARRAY_ITER_NEXT(evt->changed_properties, i, prop, it)
5901 {
5902 Efl_Ui_Property_Bound *lookup;
5903
5904 lookup = eina_hash_find(pd->properties.model_lookup, prop);
5905 if (lookup) _efl_ui_property_bind_get(data, pd, lookup);
5906 }
5907 }
5908
5909 static void
_efl_ui_view_property_bind_changed(void * data,const Efl_Event * event)5910 _efl_ui_view_property_bind_changed(void *data, const Efl_Event *event)
5911 {
5912 Efl_Ui_Property_Event *evt = event->info;
5913 ELM_WIDGET_DATA_GET(data, pd);
5914 Eina_Array_Iterator it;
5915 Eina_Stringshare *prop;
5916 unsigned int i;
5917
5918 if (!pd) return;
5919 EINA_ARRAY_ITER_NEXT(evt->changed_properties, i, prop, it)
5920 {
5921 Efl_Ui_Property_Bound *lookup;
5922
5923 lookup = eina_hash_find(pd->properties.view_lookup, prop);
5924 if (lookup) _efl_ui_property_bind_set(data, pd, lookup);
5925 }
5926 }
5927
5928 static void
_efl_ui_widget_model_update(Eo * obj,Efl_Ui_Widget_Data * pd)5929 _efl_ui_widget_model_update(Eo *obj, Efl_Ui_Widget_Data *pd)
5930 {
5931 Efl_Ui_Property_Bound *property;
5932 Eina_Iterator *it;
5933
5934 it = eina_hash_iterator_data_new(pd->properties.model_lookup);
5935 EINA_ITERATOR_FOREACH(it, property)
5936 _efl_ui_property_bind_get(obj, pd, property);
5937 eina_iterator_free(it);
5938 }
5939
5940 static void _efl_ui_widget_model_provider_model_change(void *data, const Efl_Event *event EINA_UNUSED);
5941 static void _efl_ui_widget_model_provider_invalidate(void *data, const Efl_Event *event EINA_UNUSED);
5942
5943 EFL_CALLBACKS_ARRAY_DEFINE(efl_ui_widget_model_provider_callbacks,
5944 { EFL_EVENT_INVALIDATE, _efl_ui_widget_model_provider_invalidate },
5945 { EFL_UI_VIEW_EVENT_MODEL_CHANGED, _efl_ui_widget_model_provider_model_change });
5946
5947 static void
_efl_ui_widget_model_provider_model_change(void * data,const Efl_Event * event)5948 _efl_ui_widget_model_provider_model_change(void *data, const Efl_Event *event)
5949 {
5950 ELM_WIDGET_DATA_GET(data, pd);
5951
5952 if (!pd) return;
5953 efl_replace(&pd->properties.model,
5954 efl_ui_view_model_get(pd->properties.provider));
5955 _efl_ui_widget_model_update(data, pd);
5956
5957 efl_event_callback_call(data, EFL_UI_VIEW_EVENT_MODEL_CHANGED, event->info);
5958 }
5959
5960 static void
_efl_ui_widget_model_provider_invalidate(void * data,const Efl_Event * event EINA_UNUSED)5961 _efl_ui_widget_model_provider_invalidate(void *data, const Efl_Event *event EINA_UNUSED)
5962 {
5963 ELM_WIDGET_DATA_GET(data, pd);
5964
5965 if (!pd) return;
5966 efl_event_callback_array_del(pd->properties.provider,
5967 efl_ui_widget_model_provider_callbacks(),
5968 data);
5969 efl_replace(&pd->properties.provider, NULL);
5970 efl_replace(&pd->properties.model, NULL);
5971 pd->properties.callback_to_provider = EINA_FALSE;
5972 }
5973
5974 static void
_efl_ui_widget_model_register(Eo * obj,Efl_Ui_Widget_Data * pd)5975 _efl_ui_widget_model_register(Eo *obj, Efl_Ui_Widget_Data *pd)
5976 {
5977 if (pd->properties.registered) return ;
5978
5979 if (!pd->properties.model)
5980 {
5981 Efl_Model_Changed_Event ev;
5982
5983 efl_replace(&pd->properties.provider,
5984 efl_provider_find(obj, EFL_MODEL_PROVIDER_CLASS));
5985 if (!pd->properties.provider) return ;
5986 if (!pd->properties.callback_to_provider)
5987 efl_event_callback_array_add(pd->properties.provider,
5988 efl_ui_widget_model_provider_callbacks(),
5989 obj);
5990 pd->properties.callback_to_provider = EINA_TRUE;
5991 efl_replace(&pd->properties.model,
5992 efl_ui_view_model_get(pd->properties.provider));
5993
5994 if (!pd->properties.model) return ;
5995
5996 ev.current = pd->properties.model;
5997 ev.previous = NULL;
5998 efl_event_callback_call(obj, EFL_UI_VIEW_EVENT_MODEL_CHANGED, &ev);
5999 }
6000
6001 if (!pd->properties.model) return ;
6002 if (!pd->properties.model_lookup) return ;
6003
6004 efl_event_callback_add(pd->properties.model, EFL_MODEL_EVENT_PROPERTIES_CHANGED,
6005 _efl_ui_model_property_bind_changed, obj);
6006 efl_event_callback_add(obj, EFL_UI_PROPERTY_BIND_EVENT_PROPERTIES_CHANGED,
6007 _efl_ui_view_property_bind_changed, obj);
6008 pd->properties.registered = EINA_TRUE;
6009 }
6010
6011 static void
_efl_ui_widget_model_unregister(Eo * obj,Efl_Ui_Widget_Data * pd)6012 _efl_ui_widget_model_unregister(Eo *obj, Efl_Ui_Widget_Data *pd)
6013 {
6014 if (pd->properties.registered)
6015 {
6016 // Remove any existing handler that might exist for any reason
6017 efl_event_callback_del(pd->properties.model, EFL_MODEL_EVENT_PROPERTIES_CHANGED,
6018 _efl_ui_model_property_bind_changed, obj);
6019 efl_event_callback_del(obj, EFL_UI_PROPERTY_BIND_EVENT_PROPERTIES_CHANGED,
6020 _efl_ui_view_property_bind_changed, obj);
6021
6022 pd->properties.registered = EINA_FALSE;
6023 }
6024 // Invalidate must be called before setting a new model and even if no model is registered
6025 if (pd->properties.provider)
6026 _efl_ui_widget_model_provider_invalidate(obj, NULL);
6027 }
6028
6029 static Eina_Error
_efl_ui_property_bind(Eo * widget,Eo * target,Efl_Ui_Widget_Data * pd,const char * part,const char * key,const char * property)6030 _efl_ui_property_bind(Eo *widget, Eo *target, Efl_Ui_Widget_Data *pd,
6031 const char *part, const char *key, const char *property)
6032 {
6033 Efl_Ui_Property_Bound *prop;
6034
6035 // Always check for a model and fetch a provider in case a bound property
6036 // is provided by a class down the hierarchy, but they still need to be notified
6037 // when a model change
6038 _efl_ui_widget_model_register(widget, pd);
6039
6040 // Check if the property is available from the reflection table of the object.
6041 if (!efl_property_reflection_exist(target, key)) return EFL_PROPERTY_ERROR_INVALID_KEY;
6042
6043 if (!pd->properties.model_lookup)
6044 {
6045 pd->properties.model_lookup = eina_hash_stringshared_new(_efl_ui_property_bind_free);
6046 pd->properties.view_lookup = eina_hash_stringshared_new(NULL);
6047 }
6048
6049 prop = calloc(1, sizeof (Efl_Ui_Property_Bound));
6050 if (!prop) return ENOMEM;
6051 prop->part = eina_stringshare_add(part);
6052 prop->key = eina_stringshare_add(key);
6053 prop->property = eina_stringshare_add(property);
6054
6055 eina_hash_direct_add(pd->properties.model_lookup, prop->property, prop);
6056 eina_hash_direct_add(pd->properties.view_lookup, prop->key, prop);
6057
6058 _efl_ui_property_bind_get(widget, pd, prop);
6059
6060 efl_event_callback_call(widget, EFL_UI_PROPERTY_BIND_EVENT_PROPERTY_BOUND, (void*) prop->key);
6061 // In case of part, we emit it also on the part so that the part too can act on it
6062 if (target)
6063 efl_event_callback_call(target, EFL_UI_PROPERTY_BIND_EVENT_PROPERTY_BOUND, (void*) prop->key);
6064
6065 return 0;
6066 }
6067
6068 static Eina_Error
_efl_ui_widget_efl_ui_property_bind_property_bind(Eo * obj,Efl_Ui_Widget_Data * pd,const char * key,const char * property)6069 _efl_ui_widget_efl_ui_property_bind_property_bind(Eo *obj, Efl_Ui_Widget_Data *pd,
6070 const char *key, const char *property)
6071 {
6072 return _efl_ui_property_bind(obj, obj, pd, NULL, key, property);
6073 }
6074
6075 static void
_efl_ui_widget_efl_ui_view_model_set(Eo * obj,Efl_Ui_Widget_Data * pd,Efl_Model * model)6076 _efl_ui_widget_efl_ui_view_model_set(Eo *obj,
6077 Efl_Ui_Widget_Data *pd,
6078 Efl_Model *model)
6079 {
6080 Efl_Model_Changed_Event ev;
6081
6082 ev.current = efl_ref(model);
6083 ev.previous = efl_ref(pd->properties.model);
6084
6085 _efl_ui_widget_model_unregister(obj, pd);
6086
6087 efl_replace(&pd->properties.model, model);
6088
6089 // Set the properties handler just in case
6090 _efl_ui_widget_model_register(obj, pd);
6091
6092 // In case the model set was NULL, but we did found a model provider
6093 // we shouldn't emit a second event. Otherwise we should.
6094 if (ev.current == pd->properties.model)
6095 efl_event_callback_call(obj, EFL_UI_VIEW_EVENT_MODEL_CHANGED, &ev);
6096
6097 if (pd->properties.model) _efl_ui_widget_model_update(obj, pd);
6098
6099 efl_unref(ev.current);
6100 efl_unref(ev.previous);
6101 }
6102
6103 static Efl_Model *
_efl_ui_widget_efl_ui_view_model_get(const Eo * obj EINA_UNUSED,Efl_Ui_Widget_Data * pd)6104 _efl_ui_widget_efl_ui_view_model_get(const Eo *obj EINA_UNUSED, Efl_Ui_Widget_Data *pd)
6105 {
6106 return pd->properties.model;
6107 }
6108
6109 static void
_efl_ui_widget_efl_object_invalidate(Eo * obj,Efl_Ui_Widget_Data * pd)6110 _efl_ui_widget_efl_object_invalidate(Eo *obj, Efl_Ui_Widget_Data *pd)
6111 {
6112 efl_invalidate(efl_super(obj, EFL_UI_WIDGET_CLASS));
6113
6114 _efl_ui_widget_model_unregister(obj, pd);
6115 efl_replace(&pd->properties.model, NULL);
6116
6117 if (pd->properties.view_lookup) eina_hash_free(pd->properties.view_lookup);
6118 pd->properties.view_lookup = NULL;
6119 if (pd->properties.model_lookup) eina_hash_free(pd->properties.model_lookup);
6120 pd->properties.model_lookup = NULL;
6121 }
6122
6123 #include "efl_ui_widget_part_bg.eo.c"
6124
6125 EAPI void
efl_ui_widget_internal_set(Eo * obj,Eina_Bool b)6126 efl_ui_widget_internal_set(Eo *obj, Eina_Bool b)
6127 {
6128 ELM_WIDGET_DATA_GET(obj, pd);
6129 EINA_SAFETY_ON_NULL_RETURN(pd);
6130
6131 pd->internal = b;
6132 }
6133
6134 EAPI Eina_Bool
efl_ui_widget_internal_get(Eo * obj)6135 efl_ui_widget_internal_get(Eo *obj)
6136 {
6137 ELM_WIDGET_DATA_GET(obj, pd);
6138 EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EINA_FALSE);
6139
6140 return pd->internal;
6141 }
6142
6143 /* Efl.Part Bg end */
6144
6145
6146 /* Internal EO APIs and hidden overrides */
6147
6148 EFL_FUNC_BODY_CONST(efl_ui_widget_default_content_part_get, const char *, NULL)
6149 EFL_FUNC_BODY_CONST(efl_ui_widget_default_text_part_get, const char *, NULL)
6150
6151 ELM_PART_CONTENT_DEFAULT_GET(efl_ui_widget, NULL)
6152 ELM_PART_TEXT_DEFAULT_GET(efl_ui_widget, NULL)
6153
6154 #define EFL_UI_WIDGET_EXTRA_OPS \
6155 EFL_CANVAS_GROUP_ADD_DEL_OPS(efl_ui_widget), \
6156 ELM_PART_CONTENT_DEFAULT_OPS(efl_ui_widget), \
6157 ELM_PART_TEXT_DEFAULT_OPS(efl_ui_widget), \
6158 EFL_OBJECT_OP_FUNC(efl_canvas_object_is_frame_object_set, _efl_ui_widget_efl_canvas_object_is_frame_object_set), \
6159 EFL_OBJECT_OP_FUNC(efl_dbg_info_get, _efl_ui_widget_efl_object_dbg_info_get)
6160
6161 #include "elm_widget_item_eo.c"
6162 #include "elm_widget_item_container_eo.c"
6163 #include "efl_ui_widget.eo.c"
6164 #include "efl_ui_widget_eo.legacy.c"
6165
6166 /* Others */
6167 #include "efl_ui_l10n.eo.c"
6168