1 #ifdef HAVE_CONFIG_H
2 # include "elementary_config.h"
3 #endif
4 
5 #define EFL_ACCESS_OBJECT_PROTECTED
6 #define ELM_LAYOUT_PROTECTED
7 #define EFL_UI_WIDGET_PART_BG_PROTECTED
8 #define EFL_PART_PROTECTED
9 #define EFL_LAYOUT_CALC_PROTECTED
10 
11 #include <Elementary.h>
12 
13 #include "elm_priv.h"
14 #include "elm_widget_layout.h"
15 #include "elm_part_helper.h"
16 #include "elm_entry_eo.h"
17 
18 #define MY_CLASS EFL_UI_LAYOUT_BASE_CLASS
19 #define MY_CLASS_PFX efl_ui_layout
20 
21 #define MY_CLASS_NAME "Efl.Ui.Layout"
22 
23 Eo *_efl_ui_layout_pack_proxy_get(Efl_Ui_Layout *obj, Edje_Part_Type type, const char *part);
24 static void _efl_model_properties_changed_cb(void *, const Efl_Event *);
25 static Eina_Bool _efl_ui_layout_part_cursor_unset(Efl_Ui_Layout_Data *sd, const char *part_name);
26 
27 static const char SIG_THEME_CHANGED[] = "theme,changed";
28 const char SIG_LAYOUT_FOCUSED[] = "focused";
29 const char SIG_LAYOUT_UNFOCUSED[] = "unfocused";
30 
31 const char SIGNAL_PREFIX[] = "signal/";
32 
33 /* smart callbacks coming from elm layout objects: */
34 static const Evas_Smart_Cb_Description _smart_callbacks[] = {
35    {SIG_THEME_CHANGED, ""},
36    {SIG_LAYOUT_FOCUSED, ""},
37    {SIG_LAYOUT_UNFOCUSED, ""},
38    {SIG_WIDGET_LANG_CHANGED, ""}, /**< handled by elm_widget */
39    {SIG_WIDGET_ACCESS_CHANGED, ""}, /**< handled by elm_widget */
40    {NULL, NULL}
41 };
42 
43 static const char efl_ui_default_text[] = "efl.text";
44 static const char efl_ui_default_content[] = "efl.content";
45 
46 static const Elm_Layout_Part_Alias_Description _text_aliases[] =
47 {
48    {"default", "elm.text"},
49    {NULL, NULL}
50 };
51 
52 static const Elm_Layout_Part_Alias_Description _content_aliases[] =
53 {
54    {"default", "elm.swallow.content"},
55    {NULL, NULL}
56 };
57 
58 static const char *_elm_legacy_layout_swallow_parts[] = {
59    "elm.swallow.icon",
60    "elm.swallow.end",
61    "elm.swallow.background",
62    NULL
63 };
64 
65 static const char *_efl_ui_layout_swallow_parts[] = {
66    "efl.content",
67    "efl.icon",
68    "efl.background",
69    "efl.extra",
70    NULL
71 };
72 
73 typedef struct _Deferred_Version_Signal
74 {
75    Eina_Stringshare *old_sig;
76    Eina_Stringshare *new_sig;
77    unsigned int version_threshold;
78 } Deferred_Version_Signal;
79 
80 typedef struct _Efl_Ui_Layout_Factory_Tracking Efl_Ui_Layout_Factory_Tracking;
81 
82 struct _Efl_Ui_Layout_Factory_Tracking
83 {
84    Efl_Ui_Factory *factory;
85    Eina_Future *in_flight;
86    Eina_Stringshare *key;
87 };
88 
89 
90 /* these are data operated by layout's class functions internally, and
91  * should not be messed up by inhering classes */
92 typedef struct _Efl_Ui_Layout_Sub_Object_Data   Efl_Ui_Layout_Sub_Object_Data;
93 typedef struct _Efl_Ui_Layout_Sub_Object_Cursor Efl_Ui_Layout_Sub_Object_Cursor;
94 typedef struct _Efl_Ui_Layout_Sub_Iterator      Efl_Ui_Layout_Sub_Iterator;
95 
96 struct _Efl_Ui_Layout_Sub_Iterator
97 {
98    Eina_Iterator  iterator;
99    Eina_Iterator *real_iterator;
100    Efl_Ui_Layout *object;
101 };
102 
103 struct _Efl_Ui_Layout_Sub_Object_Data
104 {
105    const char  *part;
106    Evas_Object *obj;
107 
108    enum {
109       SWALLOW,
110       BOX_APPEND,
111       BOX_PREPEND,
112       BOX_INSERT_BEFORE,
113       BOX_INSERT_AT,
114       TABLE_PACK,
115       TEXT
116    } type;
117 
118    union {
119       union {
120          const Evas_Object *reference;
121          unsigned int       pos;
122       } box;
123       struct
124       {
125          unsigned short col, row, colspan, rowspan;
126       } table;
127    } p;
128 };
129 
130 struct _Efl_Ui_Layout_Sub_Object_Cursor
131 {
132    Evas_Object *obj;
133    const char  *part;
134    const char  *cursor;
135    const char  *style;
136 
137    Eina_Bool    engine_only : 1;
138 };
139 
140 #define MY_CLASS_NAME_LEGACY "elm_layout"
141 
142 static void
_efl_ui_layout_base_class_constructor(Efl_Class * klass)143 _efl_ui_layout_base_class_constructor(Efl_Class *klass)
144 {
145    evas_smart_legacy_type_register(MY_CLASS_NAME_LEGACY, klass);
146 }
147 
148 static void
_on_sub_object_size_hint_change(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)149 _on_sub_object_size_hint_change(void *data,
150                                 Evas *e EINA_UNUSED,
151                                 Evas_Object *obj EINA_UNUSED,
152                                 void *event_info EINA_UNUSED)
153 {
154    if (!efl_alive_get(data)) return;
155    ELM_WIDGET_DATA_GET_OR_RETURN(data, wd);
156    efl_canvas_group_change(data);
157 }
158 
159 static void
_part_cursor_free(Efl_Ui_Layout_Sub_Object_Cursor * pc)160 _part_cursor_free(Efl_Ui_Layout_Sub_Object_Cursor *pc)
161 {
162    eina_stringshare_del(pc->part);
163    eina_stringshare_del(pc->style);
164    eina_stringshare_del(pc->cursor);
165 
166    free(pc);
167 }
168 
169 static void
_sizing_eval(Evas_Object * obj,Efl_Ui_Layout_Data * sd,Elm_Layout_Data * ld)170 _sizing_eval(Evas_Object *obj, Efl_Ui_Layout_Data *sd, Elm_Layout_Data *ld)
171 {
172    int minh = 0, minw = 0;
173    int rest_w = 0, rest_h = 0;
174    Eina_Size2D sz;
175    ELM_WIDGET_DATA_GET_OR_RETURN(sd->obj, wd);
176 
177    if (!efl_alive_get(obj)) return;
178    if (ld) ld->in_calc = EINA_TRUE;
179 
180    if (sd->calc_subobjs && !evas_smart_objects_calculating_get(evas_object_evas_get(obj)))
181      {
182         Eo *subobj;
183         /* user has manually triggered a smart calc and wants subobjs to also calc */
184         for (unsigned int i = 0; i < eina_array_count(wd->children); ++i)
185           {
186              subobj = eina_array_data_get(wd->children, i);
187              efl_canvas_group_calculate(subobj);
188           }
189      }
190    elm_coords_finger_size_adjust(sd->finger_size_multiplier_x, &rest_w,
191                                  sd->finger_size_multiplier_y, &rest_h);
192    if (ld && ld->user_min_sz)
193      sz = efl_gfx_hint_size_combined_min_get(obj);
194    else
195      sz = efl_gfx_hint_size_min_get(obj);
196    minw = sz.w;
197    minh = sz.h;
198 
199    rest_w = MAX(minw, rest_w);
200    rest_h = MAX(minh, rest_h);
201 
202    if (ld)
203      {
204         Eina_Size2D size = efl_gfx_entity_size_get(sd->obj);
205         if (ld->restricted_calc_w)
206           rest_w = MIN(size.w, rest_w);
207         if (ld->restricted_calc_h)
208           rest_h = MIN(size.h, rest_h);
209      }
210 
211    edje_object_size_min_restricted_calc(wd->resize_obj, &minw, &minh,
212                                         rest_w, rest_h);
213    /* if desired, scale layout by finger size */
214    if (sd->finger_size_multiplier_x)
215      elm_coords_finger_size_adjust(sd->finger_size_multiplier_x, &minw,
216                                    sd->finger_size_multiplier_y, NULL);
217    if (sd->finger_size_multiplier_y)
218      elm_coords_finger_size_adjust(sd->finger_size_multiplier_x, NULL,
219                                    sd->finger_size_multiplier_y, &minh);
220 
221    efl_gfx_hint_size_restricted_min_set(obj, EINA_SIZE2D(minw, minh));
222 
223    if (ld)
224      ld->in_calc = ld->restricted_calc_w = ld->restricted_calc_h = EINA_FALSE;
225 }
226 
227 void
_efl_ui_layout_subobjs_calc_set(Eo * obj,Eina_Bool set)228 _efl_ui_layout_subobjs_calc_set(Eo *obj, Eina_Bool set)
229 {
230    Efl_Ui_Layout_Data *sd = efl_data_scope_safe_get(obj, MY_CLASS);
231    EINA_SAFETY_ON_NULL_RETURN(sd);
232    sd->calc_subobjs = !!set;
233 }
234 
235 static void
_defer_version_signal(Efl_Ui_Layout_Data * sd,Eina_Stringshare * old_sig,Eina_Stringshare * new_sig,unsigned int version_threshold)236 _defer_version_signal(Efl_Ui_Layout_Data *sd, Eina_Stringshare *old_sig, Eina_Stringshare *new_sig, unsigned int version_threshold)
237 {
238    Deferred_Version_Signal dvs;
239    if (!sd->deferred_signals)
240      sd->deferred_signals = eina_inarray_new(sizeof(Deferred_Version_Signal), 5);
241    EINA_SAFETY_ON_NULL_RETURN(sd->deferred_signals);
242    dvs.old_sig = old_sig;
243    dvs.new_sig = new_sig;
244    dvs.version_threshold = version_threshold;
245    eina_inarray_push(sd->deferred_signals, &dvs);
246 }
247 
248 /* common content cases for layout objects: icon and text */
249 static inline void
_signals_emit(Efl_Ui_Layout_Data * sd,const char * type,Eina_Bool set)250 _signals_emit(Efl_Ui_Layout_Data *sd,
251               const char *type,
252               Eina_Bool set)
253 {
254    char buf[1024];
255 
256    if (elm_widget_is_legacy(sd->obj))
257      {
258         snprintf(buf, sizeof(buf), "elm,state,%s,%s", type,
259                  set ? "visible" : "hidden");
260         efl_layout_signal_emit(sd->obj, buf, "elm");
261      }
262    else
263      {
264         char buf2[1024];
265         char *use = buf;
266         if (sd->version >= 123) // efl,state,(content|text),(set|unset) -> efl,(content|text),(set|unset)
267           use = buf2;
268         snprintf(buf, sizeof(buf), "efl,state,%s,%s", type, set ? "set" : "unset");
269         snprintf(buf2, sizeof(buf2), "efl,%s,%s", type, set ? "set" : "unset");
270         if (efl_isa(sd->obj, EFL_UI_LAYOUT_CLASS) || efl_finalized_get(sd->obj))
271           efl_layout_signal_emit(sd->obj, use, "efl");
272         else
273           _defer_version_signal(sd, eina_stringshare_add(buf), eina_stringshare_add(buf2), 123);
274      }
275 }
276 
277 static inline void
_icon_signal_emit(Efl_Ui_Layout_Data * sd,Efl_Ui_Layout_Sub_Object_Data * sub_d,Eina_Bool visible)278 _icon_signal_emit(Efl_Ui_Layout_Data *sd,
279                   Efl_Ui_Layout_Sub_Object_Data *sub_d,
280                   Eina_Bool visible)
281 {
282    const char *type;
283    Eo *edje;
284    int i;
285 
286    edje = elm_widget_resize_object_get(sd->obj);
287    if (!edje) return;
288 
289    //FIXME: Don't limit to the icon and end here.
290    // send signals for all contents after elm 2.0
291    if (sub_d->type != SWALLOW) return;
292    if (elm_widget_is_legacy(sd->obj))
293      {
294         for (i = 0;; i++)
295           {
296               if (!_elm_legacy_layout_swallow_parts[i]) return;
297               if (!strcmp(sub_d->part, _elm_legacy_layout_swallow_parts[i])) break;
298           }
299      }
300    else
301      {
302         for (i = 0;; i++)
303           {
304               if (!_efl_ui_layout_swallow_parts[i]) return;
305               if (!strcmp(sub_d->part, _efl_ui_layout_swallow_parts[i])) break;
306           }
307      }
308 
309    if (elm_widget_is_legacy(sd->obj))
310      {
311         if (!strncmp(sub_d->part, "elm.swallow.", strlen("elm.swallow.")))
312           type = sub_d->part + strlen("elm.swallow.");
313         else
314           type = sub_d->part;
315      }
316    else
317      {
318         if (!strncmp(sub_d->part, "efl.", strlen("efl.")))
319           type = sub_d->part + strlen("efl.");
320         else
321           type = sub_d->part;
322      }
323 
324    _signals_emit(sd, type, visible);
325 
326    /* themes might need immediate action here */
327    efl_layout_signal_process(sd->obj, EINA_FALSE);
328 }
329 
330 static inline void
_text_signal_emit(Efl_Ui_Layout_Data * sd,Efl_Ui_Layout_Sub_Object_Data * sub_d,Eina_Bool visible)331 _text_signal_emit(Efl_Ui_Layout_Data *sd,
332                   Efl_Ui_Layout_Sub_Object_Data *sub_d,
333                   Eina_Bool visible)
334 {
335    char buf[1024];
336    const char *type;
337 
338    //FIXME: Don't limit to "elm.text" prefix.
339    //Send signals for all text parts after elm 2.0
340    if (sub_d->type != TEXT) return;
341 
342    if (elm_widget_is_legacy(sd->obj))
343      {
344         if (!((!strcmp("elm.text", sub_d->part)) ||
345               (!strncmp("elm.text.", sub_d->part, 9))))
346           return;
347      }
348    else
349      {
350         if (!((!strcmp("efl.text", sub_d->part)) ||
351               (!strncmp("efl.text.", sub_d->part, 9))))
352           return;
353      }
354 
355    ELM_WIDGET_DATA_GET_OR_RETURN(sd->obj, wd);
356 
357    if (elm_widget_is_legacy(sd->obj))
358      {
359         if (!strncmp(sub_d->part, "elm.text.", strlen("elm.text.")))
360           type = sub_d->part + strlen("elm.text.");
361         else
362           type = sub_d->part;
363      }
364    else
365      {
366         if (!strncmp(sub_d->part, "efl.", strlen("efl.")))
367           type = sub_d->part + strlen("efl.");
368         else
369           type = sub_d->part;
370      }
371 
372    _signals_emit(sd, type, visible);
373 
374    /* TODO: is this right? It was like that, but IMO it should be removed: */
375 
376    if (elm_widget_is_legacy(sd->obj))
377      {
378         snprintf(buf, sizeof(buf),
379                  visible ? "elm,state,text,visible" : "elm,state,text,hidden");
380         efl_layout_signal_emit(sd->obj, buf, "elm");
381      }
382 
383    /* themes might need immediate action here */
384    efl_layout_signal_process(sd->obj, EINA_FALSE);
385 }
386 
387 static void
_parts_signals_emit(Efl_Ui_Layout_Data * sd)388 _parts_signals_emit(Efl_Ui_Layout_Data *sd)
389 {
390    const Eina_List *l;
391    Efl_Ui_Layout_Sub_Object_Data *sub_d;
392 
393    EINA_LIST_FOREACH(sd->subs, l, sub_d)
394      {
395         _icon_signal_emit(sd, sub_d, EINA_TRUE);
396         _text_signal_emit(sd, sub_d, EINA_TRUE);
397      }
398 }
399 
400 static void
_part_cursor_part_apply(const Efl_Ui_Layout_Sub_Object_Cursor * pc)401 _part_cursor_part_apply(const Efl_Ui_Layout_Sub_Object_Cursor *pc)
402 {
403    elm_object_cursor_set(pc->obj, pc->cursor);
404    elm_object_cursor_style_set(pc->obj, pc->style);
405    elm_object_cursor_theme_search_enabled_set(pc->obj, !pc->engine_only);
406 }
407 
408 static void
_parts_cursors_apply(Efl_Ui_Layout_Data * sd)409 _parts_cursors_apply(Efl_Ui_Layout_Data *sd)
410 {
411    const Eina_List *l;
412    const char *file, *group;
413    Efl_Ui_Layout_Sub_Object_Cursor *pc;
414    ELM_WIDGET_DATA_GET_OR_RETURN(sd->obj, wd);
415 
416    edje_object_file_get(wd->resize_obj, &file, &group);
417 
418    EINA_LIST_FOREACH(sd->parts_cursors, l, pc)
419      {
420         Evas_Object *obj;
421 
422         edje_object_freeze(wd->resize_obj);
423         obj = (Evas_Object *)edje_object_part_object_get
424           (wd->resize_obj, pc->part);
425         edje_object_thaw(wd->resize_obj);
426 
427         if (!obj)
428           {
429              pc->obj = NULL;
430              WRN("no part '%s' in group '%s' of file '%s'. "
431                  "Cannot set cursor '%s'",
432                  pc->part, group, file, pc->cursor);
433              continue;
434           }
435         else if (evas_object_pass_events_get(obj))
436           {
437              pc->obj = NULL;
438              WRN("part '%s' in group '%s' of file '%s' has mouse_events: 0. "
439                  "Cannot set cursor '%s'",
440                  pc->part, group, file, pc->cursor);
441              continue;
442           }
443 
444         pc->obj = obj;
445         _part_cursor_part_apply(pc);
446      }
447 }
448 
449 static void
_efl_ui_layout_highlight_in_theme(Evas_Object * obj)450 _efl_ui_layout_highlight_in_theme(Evas_Object *obj)
451 {
452    const char *fh;
453 
454    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
455 
456    fh = edje_object_data_get
457        (wd->resize_obj, "focus_highlight");
458    if ((fh) && (!strcmp(fh, "on")))
459      elm_widget_highlight_in_theme_set(obj, EINA_TRUE);
460    else
461      elm_widget_highlight_in_theme_set(obj, EINA_FALSE);
462 
463    fh = edje_object_data_get
464        (wd->resize_obj, "access_highlight");
465    if ((fh) && (!strcmp(fh, "on")))
466      elm_widget_access_highlight_in_theme_set(obj, EINA_TRUE);
467    else
468      elm_widget_access_highlight_in_theme_set(obj, EINA_FALSE);
469 }
470 
471 static void
_flush_mirrored_state(Eo * obj)472 _flush_mirrored_state(Eo *obj)
473 {
474    char prefix[4], state[10], signal[100];
475    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
476 
477    if (!wd->resize_obj) return;
478 
479    if (efl_ui_widget_disabled_get(obj))
480      snprintf(state, sizeof(state), "disabled");
481    else
482      snprintf(state, sizeof(state), "enabled");
483 
484    if (!elm_widget_is_legacy(obj))
485      snprintf(prefix, sizeof(prefix), "efl");
486    else
487      snprintf(prefix, sizeof(prefix), "elm");
488 
489    snprintf(signal, sizeof(signal), "%s,state,%s", prefix, state);
490    efl_layout_signal_emit(obj, signal, prefix);
491 }
492 
493 static Eina_Bool
_visuals_refresh(Evas_Object * obj,Efl_Ui_Layout_Data * sd)494 _visuals_refresh(Evas_Object *obj,
495                  Efl_Ui_Layout_Data *sd)
496 {
497    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, EINA_FALSE);
498 
499    _parts_signals_emit(sd);
500    _parts_cursors_apply(sd);
501 
502    edje_object_mirrored_set
503      (wd->resize_obj, efl_ui_mirrored_get(obj));
504 
505    edje_object_scale_set
506      (wd->resize_obj,
507      efl_gfx_entity_scale_get(obj) * elm_config_scale_get());
508 
509    _efl_ui_layout_highlight_in_theme(obj);
510    _flush_mirrored_state(obj);
511 
512    efl_canvas_group_change(obj);
513 
514    return EINA_TRUE;
515 }
516 
517 EOLIAN static void
_efl_ui_layout_base_efl_ui_widget_disabled_set(Eo * obj,Efl_Ui_Layout_Data * _pd EINA_UNUSED,Eina_Bool disabled)518 _efl_ui_layout_base_efl_ui_widget_disabled_set(Eo *obj, Efl_Ui_Layout_Data *_pd EINA_UNUSED, Eina_Bool disabled)
519 {
520    efl_ui_widget_disabled_set(efl_super(obj, MY_CLASS), disabled);
521    _flush_mirrored_state(obj);
522 }
523 
524 static Eina_Error
_efl_ui_layout_theme_internal(Eo * obj,Efl_Ui_Layout_Data * sd,Elm_Widget_Smart_Data ** widget_data)525 _efl_ui_layout_theme_internal(Eo *obj, Efl_Ui_Layout_Data *sd, Elm_Widget_Smart_Data **widget_data)
526 {
527    Eina_Error ret = EFL_UI_THEME_APPLY_ERROR_GENERIC;
528 
529    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, EFL_UI_THEME_APPLY_ERROR_GENERIC);
530 
531    *widget_data = wd;
532    /* function already prints error messages, if any */
533    if (!sd->file_set)
534      {
535         ret = elm_widget_theme_object_set
536                 (obj, wd->resize_obj,
537                 elm_widget_theme_klass_get(obj),
538                 elm_widget_theme_element_get(obj),
539                 elm_widget_theme_style_get(obj));
540      }
541 
542    if (ret != EFL_UI_THEME_APPLY_ERROR_GENERIC)
543      {
544         if (sd->cb_theme_changed)
545           efl_event_callback_call(obj, EFL_UI_LAYOUT_EVENT_THEME_CHANGED, NULL);
546         if (elm_widget_is_legacy(obj))
547           evas_object_smart_callback_call(obj, "theme,changed", NULL);
548      }
549 
550    if (!_visuals_refresh(obj, sd))
551      ret = EFL_UI_THEME_APPLY_ERROR_GENERIC;
552 
553    return ret;
554 }
555 
556 static void
_deferred_signals_emit(Efl_Ui_Layout_Data * pd)557 _deferred_signals_emit(Efl_Ui_Layout_Data *pd)
558 {
559    do
560      {
561         Deferred_Version_Signal *dvs = eina_inarray_pop(pd->deferred_signals);
562 
563         if (pd->version < dvs->version_threshold)
564           efl_layout_signal_emit(pd->obj, dvs->old_sig, "efl");
565         else
566           efl_layout_signal_emit(pd->obj, dvs->new_sig, "efl");
567         eina_stringshare_del(dvs->old_sig);
568         eina_stringshare_del(dvs->new_sig);
569      } while (eina_inarray_count(pd->deferred_signals));
570    ELM_SAFE_FREE(pd->deferred_signals, eina_inarray_free);
571 }
572 
573 EOLIAN static Eina_Error
_efl_ui_layout_base_efl_ui_widget_theme_apply(Eo * obj,Efl_Ui_Layout_Data * sd)574 _efl_ui_layout_base_efl_ui_widget_theme_apply(Eo *obj, Efl_Ui_Layout_Data *sd)
575 {
576    Eina_Error theme_apply_ret, theme_apply_internal_ret;
577    Elm_Widget_Smart_Data *wd = NULL;
578    char buf[64];
579    Eina_Bool legacy;
580    static unsigned int version = 0;
581 
582    sd->needs_theme_apply = EINA_FALSE;
583 
584    theme_apply_ret = efl_ui_widget_theme_apply(efl_super(obj, MY_CLASS));
585    if (theme_apply_ret == EFL_UI_THEME_APPLY_ERROR_GENERIC) return EFL_UI_THEME_APPLY_ERROR_GENERIC;
586 
587    theme_apply_internal_ret = _efl_ui_layout_theme_internal(obj, sd, &wd);
588    if (theme_apply_internal_ret == EFL_UI_THEME_APPLY_ERROR_GENERIC)
589      return EFL_UI_THEME_APPLY_ERROR_GENERIC;
590 
591    if ((theme_apply_ret == EFL_UI_THEME_APPLY_ERROR_DEFAULT) ||
592        (theme_apply_internal_ret == EFL_UI_THEME_APPLY_ERROR_DEFAULT))
593      return EFL_UI_THEME_APPLY_ERROR_DEFAULT;
594 
595    legacy = elm_widget_is_legacy(obj);
596    /* unset existing size hints to force accurate recalc */
597    efl_gfx_hint_size_restricted_min_set(obj, EINA_SIZE2D(0, 0));
598    if (legacy)
599      efl_gfx_hint_size_min_set(obj, EINA_SIZE2D(0, 0));
600    else
601      {
602         const char *theme_version = edje_object_data_get(wd->resize_obj, "version");
603         if (!theme_version)
604           {
605              ERR("Widget(%p) with type '%s' is not providing a version in its theme!", obj,
606                  efl_class_name_get(efl_class_get(obj)));
607              ERR("Group '%s' should have data.item: \"version\" \"%d%d\";",
608                  efl_file_key_get(wd->resize_obj), EFL_VERSION_MAJOR, EFL_VERSION_MINOR);
609              return EFL_UI_THEME_APPLY_ERROR_VERSION;
610           }
611         else
612           {
613              errno = 0;
614              sd->version = strtoul(theme_version, NULL, 10);
615              if (errno)
616                {
617                   ERR("Widget(%p) with type '%s' is not providing a valid version in its theme!", obj,
618                       efl_class_name_get(efl_class_get(obj)));
619                   ERR("Group '%s' should have data.item: \"version\" \"%d%d\";",
620                        efl_file_key_get(wd->resize_obj), EFL_VERSION_MAJOR, EFL_VERSION_MINOR);
621                   sd->version = 0;
622                   return EFL_UI_THEME_APPLY_ERROR_VERSION;
623                }
624           }
625      }
626    if (sd->deferred_signals)
627      _deferred_signals_emit(sd);
628    if (legacy) return EFL_UI_THEME_APPLY_ERROR_NONE;
629 
630    if (!version)
631      {
632         snprintf(buf, sizeof(buf), "%d%d", EFL_VERSION_MAJOR, EFL_VERSION_MINOR + (EFL_VERSION_MICRO == 99 ? 1 : 0));
633         errno = 0;
634         version = strtoul(buf, NULL, 10);
635         if (errno)
636           {
637              ERR("something broke in theme parsing, this system is probably busted");
638              version = 0;
639           }
640      }
641    if (version && (!_running_in_tree))
642      {
643         if (sd->version < version)
644           WRN("Widget(%p) with type '%s' is providing a potentially old version in its theme: found %u, should be %u", obj,
645               efl_class_name_get(efl_class_get(obj)), sd->version, version);
646         else if (sd->version > version)
647           {
648              CRI("Widget(%p) with type '%s' is attempting to use a theme that is too new: found %u, should be %u", obj,
649               efl_class_name_get(efl_class_get(obj)), sd->version, version);
650              CRI("\tTheme file: %s\tTheme group: %s", efl_file_get(obj), efl_file_key_get(obj));
651              return EFL_UI_THEME_APPLY_ERROR_VERSION;
652           }
653      }
654 
655    return EFL_UI_THEME_APPLY_ERROR_NONE;
656 }
657 
658 EOLIAN static int
_efl_ui_layout_base_theme_version_get(const Eo * obj EINA_UNUSED,Efl_Ui_Layout_Data * pd)659 _efl_ui_layout_base_theme_version_get(const Eo *obj EINA_UNUSED, Efl_Ui_Layout_Data *pd)
660 {
661    return pd->version;
662 }
663 
664 EOLIAN static Eina_Bool
_efl_ui_layout_base_efl_ui_focus_object_on_focus_update(Eo * obj,Efl_Ui_Layout_Data * _pd EINA_UNUSED)665 _efl_ui_layout_base_efl_ui_focus_object_on_focus_update(Eo *obj, Efl_Ui_Layout_Data *_pd EINA_UNUSED)
666 {
667    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, EINA_FALSE);
668 
669    if (!elm_widget_can_focus_get(obj)) return EINA_FALSE;
670 
671    if (efl_ui_focus_object_focus_get(obj))
672      {
673         if (elm_widget_is_legacy(obj))
674           elm_layout_signal_emit(obj, "elm,action,focus", "elm");
675         else
676           elm_layout_signal_emit(obj, "efl,action,focus", "efl");
677         evas_object_focus_set(wd->resize_obj, EINA_TRUE);
678      }
679    else
680      {
681         if (elm_widget_is_legacy(obj))
682           elm_layout_signal_emit(obj, "elm,action,unfocus", "elm");
683         else
684           elm_layout_signal_emit(obj, "efl,action,unfocus", "efl");
685         evas_object_focus_set(wd->resize_obj, EINA_FALSE);
686      }
687 
688    efl_ui_focus_object_on_focus_update(efl_super(obj, MY_CLASS));
689 
690    if (efl_isa(wd->resize_obj, EFL_CANVAS_LAYOUT_CLASS))
691      edje_object_message_signal_process(wd->resize_obj);
692 
693    return EINA_TRUE;
694 }
695 
696 EOLIAN static Eina_Bool
_efl_ui_layout_base_efl_ui_widget_widget_sub_object_add(Eo * obj,Efl_Ui_Layout_Data * _pd EINA_UNUSED,Evas_Object * sobj)697 _efl_ui_layout_base_efl_ui_widget_widget_sub_object_add(Eo *obj, Efl_Ui_Layout_Data *_pd EINA_UNUSED, Evas_Object *sobj)
698 {
699    Eina_Bool int_ret = EINA_FALSE;
700 
701    if (evas_object_data_get(sobj, "elm-parent") == obj) return EINA_TRUE;
702 
703    int_ret = elm_widget_sub_object_add(efl_super(obj, MY_CLASS), sobj);
704    if (!int_ret) return EINA_FALSE;
705 
706    evas_object_event_callback_add
707          (sobj, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
708           _on_sub_object_size_hint_change, obj);
709 
710    return EINA_TRUE;
711 }
712 
713 EOLIAN static Eina_Bool
_efl_ui_layout_base_efl_ui_widget_widget_sub_object_del(Eo * obj,Efl_Ui_Layout_Data * sd,Evas_Object * sobj)714 _efl_ui_layout_base_efl_ui_widget_widget_sub_object_del(Eo *obj, Efl_Ui_Layout_Data *sd, Evas_Object *sobj)
715 {
716    Eina_List *l;
717    Efl_Ui_Layout_Sub_Object_Data *sub_d;
718 
719    Eina_Bool int_ret = EINA_FALSE;
720 
721    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, EINA_FALSE);
722 
723    evas_object_event_callback_del_full
724      (sobj, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
725      _on_sub_object_size_hint_change, obj);
726 
727    int_ret = elm_widget_sub_object_del(efl_super(obj, MY_CLASS), sobj);
728    if (!int_ret) return EINA_FALSE;
729    if (sd->destructed_is) return EINA_TRUE;
730 
731    EINA_LIST_FOREACH(sd->subs, l, sub_d)
732      {
733         if (sub_d->obj != sobj) continue;
734 
735         sd->subs = eina_list_remove_list(sd->subs, l);
736 
737         _icon_signal_emit(sd, sub_d, EINA_FALSE);
738 
739         eina_stringshare_del(sub_d->part);
740         free(sub_d);
741 
742         break;
743      }
744 
745    // No need to resize object during destruction
746    if (wd->resize_obj && efl_alive_get(obj))
747      efl_canvas_group_change(obj);
748 
749    return EINA_TRUE;
750 }
751 
752 static void
_edje_signal_callback(void * data,Evas_Object * obj EINA_UNUSED,const char * emission,const char * source)753 _edje_signal_callback(void *data,
754                       Evas_Object *obj EINA_UNUSED,
755                       const char *emission,
756                       const char *source)
757 {
758    Edje_Signal_Data *esd = data;
759 
760    esd->func(esd->data, esd->obj, emission, source);
761 }
762 
763 EAPI Eina_Bool
_elm_layout_part_aliasing_eval(const Evas_Object * obj,const char ** part,Eina_Bool is_text)764 _elm_layout_part_aliasing_eval(const Evas_Object *obj,
765                                const char **part,
766                                Eina_Bool is_text)
767 {
768    const Elm_Layout_Part_Alias_Description *aliases = NULL;
769 
770    if (!elm_widget_is_legacy(obj))
771      {
772         if (!*part)
773           {
774              if (is_text)
775                *part = efl_ui_default_text;
776              else
777                *part = efl_ui_default_content;
778              return EINA_TRUE;
779           }
780      }
781 
782    if (is_text)
783      aliases = efl_ui_layout_text_aliases_get(obj);
784    else
785      aliases =  efl_ui_layout_content_aliases_get(obj);
786 
787    while (aliases && aliases->alias && aliases->real_part)
788      {
789         /* NULL matches the 1st */
790         if ((!*part) || (!strcmp(*part, aliases->alias)))
791           {
792              *part = aliases->real_part;
793              break;
794           }
795 
796         aliases++;
797      }
798 
799    if (!*part)
800      {
801         ERR("no default content part set for object %p -- "
802             "part must not be NULL", obj);
803         return EINA_FALSE;
804      }
805 
806    /* if no match, part goes on with the same value */
807 
808    return EINA_TRUE;
809 }
810 
811 static void
_eo_unparent_helper(Eo * child,Eo * parent)812 _eo_unparent_helper(Eo *child, Eo *parent)
813 {
814    if (efl_parent_get(child) == parent)
815      {
816         efl_parent_set(child, evas_object_evas_get(parent));
817      }
818 }
819 
820 static void
_box_reference_del(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)821 _box_reference_del(void *data,
822                    Evas *e EINA_UNUSED,
823                    Evas_Object *obj EINA_UNUSED,
824                    void *event_info EINA_UNUSED)
825 {
826    Efl_Ui_Layout_Sub_Object_Data *sub_d = data;
827    sub_d->p.box.reference = NULL;
828 }
829 
830 static Evas_Object *
_sub_box_remove(Evas_Object * obj,Efl_Ui_Layout_Data * sd,Efl_Ui_Layout_Sub_Object_Data * sub_d)831 _sub_box_remove(Evas_Object *obj,
832                 Efl_Ui_Layout_Data *sd,
833                 Efl_Ui_Layout_Sub_Object_Data *sub_d)
834 {
835    Evas_Object *child = sub_d->obj; /* sub_d will die in
836                                      * _efl_ui_layout_smart_widget_sub_object_del */
837 
838    if (sub_d->type == BOX_INSERT_BEFORE)
839      evas_object_event_callback_del_full
840        ((Evas_Object *)sub_d->p.box.reference,
841        EVAS_CALLBACK_DEL, _box_reference_del, sub_d);
842 
843    ELM_WIDGET_DATA_GET_OR_RETURN(sd->obj, wd, NULL);
844    edje_object_part_box_remove
845      (wd->resize_obj, sub_d->part, child);
846 
847    _eo_unparent_helper(child, obj);
848    if (!_elm_widget_sub_object_redirect_to_top(obj, child))
849      {
850         ERR("could not remove sub object %p from %p", child, obj);
851         return NULL;
852      }
853 
854    return child;
855 }
856 
857 static Eina_Bool
_sub_box_is(const Efl_Ui_Layout_Sub_Object_Data * sub_d)858 _sub_box_is(const Efl_Ui_Layout_Sub_Object_Data *sub_d)
859 {
860    switch (sub_d->type)
861      {
862       case BOX_APPEND:
863       case BOX_PREPEND:
864       case BOX_INSERT_BEFORE:
865       case BOX_INSERT_AT:
866         return EINA_TRUE;
867 
868       default:
869         return EINA_FALSE;
870      }
871 }
872 
873 static Evas_Object *
_sub_table_remove(Evas_Object * obj,Efl_Ui_Layout_Data * sd,Efl_Ui_Layout_Sub_Object_Data * sub_d)874 _sub_table_remove(Evas_Object *obj,
875                   Efl_Ui_Layout_Data *sd,
876                   Efl_Ui_Layout_Sub_Object_Data *sub_d)
877 {
878    Evas_Object *child;
879    ELM_WIDGET_DATA_GET_OR_RETURN(sd->obj, wd, NULL);
880 
881    child = sub_d->obj; /* sub_d will die in _efl_ui_layout_smart_widget_sub_object_del */
882 
883    edje_object_part_table_unpack
884      (wd->resize_obj, sub_d->part, child);
885 
886    _eo_unparent_helper(child, obj);
887 
888    if (!_elm_widget_sub_object_redirect_to_top(obj, child))
889      {
890         ERR("could not remove sub object %p from %p", child, obj);
891         return NULL;
892      }
893 
894    return child;
895 }
896 
897 static void
_on_size_evaluate_signal(void * data,Evas_Object * obj EINA_UNUSED,const char * emission EINA_UNUSED,const char * source EINA_UNUSED)898 _on_size_evaluate_signal(void *data,
899                          Evas_Object *obj EINA_UNUSED,
900                          const char *emission EINA_UNUSED,
901                          const char *source EINA_UNUSED)
902 {
903    efl_canvas_group_change(data);
904    efl_canvas_group_calculate(data);
905 }
906 
907 EOLIAN static void
_efl_ui_layout_base_efl_canvas_group_group_add(Eo * obj,Efl_Ui_Layout_Data * _pd EINA_UNUSED)908 _efl_ui_layout_base_efl_canvas_group_group_add(Eo *obj, Efl_Ui_Layout_Data *_pd EINA_UNUSED)
909 {
910    Evas_Object *edje;
911 
912    /* has to be there *before* parent's smart_add() */
913    edje = edje_object_add(evas_object_evas_get(obj));
914    elm_widget_resize_object_set(obj, edje);
915 
916    efl_canvas_group_add(efl_super(obj, MY_CLASS));
917 
918    elm_widget_can_focus_set(obj, EINA_FALSE);
919 
920    if (elm_widget_is_legacy(obj))
921      edje_object_signal_callback_add
922         (edje, "size,eval", "elm", _on_size_evaluate_signal, obj);
923    else
924      edje_object_signal_callback_add
925         (edje, "size,eval", "efl", _on_size_evaluate_signal, obj);
926 }
927 
928 EOLIAN static void
_efl_ui_layout_base_efl_canvas_group_group_del(Eo * obj,Efl_Ui_Layout_Data * sd)929 _efl_ui_layout_base_efl_canvas_group_group_del(Eo *obj, Efl_Ui_Layout_Data *sd)
930 {
931    Efl_Ui_Layout_Sub_Object_Data *sub_d;
932    Efl_Ui_Layout_Sub_Object_Cursor *pc;
933    Edje_Signal_Data *esd;
934    Efl_Model *model;
935 
936    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
937 
938    /* freeze edje object if it exists */
939    if (wd->resize_obj)
940      elm_layout_freeze(obj);
941 
942    EINA_LIST_FREE(sd->subs, sub_d)
943      {
944         eina_stringshare_del(sub_d->part);
945         free(sub_d);
946      }
947 
948    EINA_LIST_FREE(sd->parts_cursors, pc)
949      _part_cursor_free(pc);
950 
951    EINA_LIST_FREE(sd->edje_signals, esd)
952      {
953         edje_object_signal_callback_del_full
954            (wd->resize_obj, esd->emission, esd->source,
955             _edje_signal_callback, esd);
956         eina_stringshare_del(esd->emission);
957         eina_stringshare_del(esd->source);
958         free(esd);
959      }
960 
961    model = efl_ui_view_model_get(obj);
962    if(model)
963      {
964          efl_event_callback_del(model, EFL_MODEL_EVENT_PROPERTIES_CHANGED,
965                                 _efl_model_properties_changed_cb, sd);
966      }
967 
968    eina_hash_free(sd->connect.properties);
969    sd->connect.properties = NULL;
970    eina_hash_free(sd->connect.signals);
971    sd->connect.signals = NULL;
972    eina_hash_free(sd->connect.factories);
973    sd->connect.factories = NULL;
974    if (sd->deferred_signals)
975      {
976         do
977           {
978              Deferred_Version_Signal *dvs = eina_inarray_pop(sd->deferred_signals);
979 
980              eina_stringshare_del(dvs->old_sig);
981              eina_stringshare_del(dvs->new_sig);
982           } while (eina_inarray_count(sd->deferred_signals));
983         ELM_SAFE_FREE(sd->deferred_signals, eina_inarray_free);
984      }
985 
986    /* let's make our Edje object the *last* to be processed, since it
987     * may (smart) parent other sub objects here */
988    {
989       unsigned int resize_id = 0;
990       if (eina_array_find(wd->children, wd->resize_obj, &resize_id))
991         {
992            //exchange with last
993            eina_array_data_set(wd->children, resize_id, eina_array_data_get(wd->children, eina_array_count(wd->children) - 1));
994            eina_array_data_set(wd->children, eina_array_count(wd->children) - 1, wd->resize_obj);
995         }
996    }
997 
998    sd->destructed_is = EINA_TRUE;
999 
1000    efl_canvas_group_del(efl_super(obj, MY_CLASS));
1001 }
1002 
1003 /* rewrite or extend this one on your derived class as to suit your
1004  * needs */
1005 EOLIAN static void
_efl_ui_layout_base_efl_canvas_group_group_calculate(Eo * obj,Efl_Ui_Layout_Data * sd)1006 _efl_ui_layout_base_efl_canvas_group_group_calculate(Eo *obj, Efl_Ui_Layout_Data *sd)
1007 {
1008    Elm_Layout_Data *ld = efl_data_scope_safe_get(obj, ELM_LAYOUT_MIXIN);
1009    efl_canvas_group_need_recalculate_set(obj, EINA_FALSE);
1010    if ((!ld) || ld->needs_size_calc)
1011      _sizing_eval(obj, sd, ld);
1012    if (ld) ld->needs_size_calc = EINA_FALSE;
1013 }
1014 
1015 EOLIAN static void
_efl_ui_layout_base_finger_size_multiplier_get(const Eo * obj EINA_UNUSED,Efl_Ui_Layout_Data * sd,unsigned int * mult_x,unsigned int * mult_y)1016 _efl_ui_layout_base_finger_size_multiplier_get(const Eo *obj EINA_UNUSED, Efl_Ui_Layout_Data *sd, unsigned int *mult_x, unsigned int *mult_y)
1017 {
1018    if (mult_x)
1019      *mult_x = sd->finger_size_multiplier_x;
1020    if (mult_y)
1021      *mult_y = sd->finger_size_multiplier_y;
1022 }
1023 
1024 EOLIAN static void
_efl_ui_layout_base_finger_size_multiplier_set(Eo * obj,Efl_Ui_Layout_Data * sd,unsigned int mult_x,unsigned int mult_y)1025 _efl_ui_layout_base_finger_size_multiplier_set(Eo *obj, Efl_Ui_Layout_Data *sd, unsigned int mult_x, unsigned int mult_y)
1026 {
1027    if ((sd->finger_size_multiplier_x == mult_x) &&
1028        (sd->finger_size_multiplier_y == mult_y))
1029      return;
1030    sd->finger_size_multiplier_x = mult_x;
1031    sd->finger_size_multiplier_y = mult_y;
1032    if (efl_alive_get(obj))
1033      efl_canvas_group_change(obj);
1034 }
1035 
1036 static Efl_Ui_Layout_Sub_Object_Cursor *
_parts_cursors_find(Efl_Ui_Layout_Data * sd,const char * part)1037 _parts_cursors_find(Efl_Ui_Layout_Data *sd,
1038                     const char *part)
1039 {
1040    const Eina_List *l;
1041    Efl_Ui_Layout_Sub_Object_Cursor *pc;
1042 
1043    EINA_LIST_FOREACH(sd->parts_cursors, l, pc)
1044      {
1045         if (!strcmp(pc->part, part))
1046           return pc;
1047      }
1048 
1049    return NULL;
1050 }
1051 
1052 /* The public functions down here are meant to operate on whichever
1053  * widget inheriting from elm_layout */
1054 
1055 EOLIAN static void
_efl_ui_layout_efl_file_unload(Eo * obj,void * _pd EINA_UNUSED)1056 _efl_ui_layout_efl_file_unload(Eo *obj, void *_pd EINA_UNUSED)
1057 {
1058    Efl_Ui_Layout_Data *sd = efl_data_scope_get(obj, MY_CLASS);
1059 
1060    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
1061 
1062    efl_file_unload(wd->resize_obj);
1063    sd->file_set = EINA_FALSE;
1064 }
1065 
1066 EOLIAN static Eina_Error
_efl_ui_layout_efl_file_load(Eo * obj,void * _pd EINA_UNUSED)1067 _efl_ui_layout_efl_file_load(Eo *obj, void *_pd EINA_UNUSED)
1068 {
1069    Eina_Error err;
1070    Efl_Ui_Layout_Data *sd = efl_data_scope_get(obj, MY_CLASS);
1071 
1072    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, EINA_FALSE);
1073 
1074    if (efl_file_loaded_get(obj)) return 0;
1075    err = efl_file_load(wd->resize_obj);
1076 
1077    if (!err)
1078      {
1079         sd->file_set = EINA_TRUE;
1080         _visuals_refresh(obj, sd);
1081      }
1082    else
1083      ERR("failed to set edje file '%s', group '%s': %s",
1084          efl_file_get(wd->resize_obj), efl_file_key_get(wd->resize_obj),
1085          edje_load_error_str
1086            (edje_object_load_error_get(wd->resize_obj)));
1087 
1088    return err;
1089 }
1090 
1091 EOLIAN static Eina_Error
_efl_ui_layout_efl_file_file_set(Eo * obj,void * _pd EINA_UNUSED,const char * file)1092 _efl_ui_layout_efl_file_file_set(Eo *obj, void *_pd EINA_UNUSED, const char *file)
1093 {
1094    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, EFL_GFX_IMAGE_LOAD_ERROR_GENERIC);
1095    return efl_file_set(wd->resize_obj, file);
1096 }
1097 
1098 EOLIAN static const char *
_efl_ui_layout_efl_file_file_get(const Eo * obj,void * _pd EINA_UNUSED)1099 _efl_ui_layout_efl_file_file_get(const Eo *obj, void *_pd EINA_UNUSED)
1100 {
1101    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, NULL);
1102    return efl_file_get(wd->resize_obj);
1103 }
1104 
1105 EOLIAN static void
_efl_ui_layout_efl_file_key_set(Eo * obj,void * _pd EINA_UNUSED,const char * key)1106 _efl_ui_layout_efl_file_key_set(Eo *obj, void *_pd EINA_UNUSED, const char *key)
1107 {
1108    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
1109    return efl_file_key_set(wd->resize_obj, key);
1110 }
1111 
1112 EOLIAN static const char *
_efl_ui_layout_efl_file_key_get(const Eo * obj,void * _pd EINA_UNUSED)1113 _efl_ui_layout_efl_file_key_get(const Eo *obj, void *_pd EINA_UNUSED)
1114 {
1115    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, NULL);
1116    return efl_file_key_get(wd->resize_obj);
1117 }
1118 
1119 EOLIAN static Eina_Error
_efl_ui_layout_efl_file_mmap_set(Eo * obj,void * _pd EINA_UNUSED,const Eina_File * file)1120 _efl_ui_layout_efl_file_mmap_set(Eo *obj, void *_pd EINA_UNUSED, const Eina_File *file)
1121 {
1122    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, EINA_FALSE);
1123    return efl_file_mmap_set(wd->resize_obj, file);
1124 }
1125 
1126 EOLIAN static const Eina_File *
_efl_ui_layout_efl_file_mmap_get(const Eo * obj,void * _pd EINA_UNUSED)1127 _efl_ui_layout_efl_file_mmap_get(const Eo *obj, void *_pd EINA_UNUSED)
1128 {
1129    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, NULL);
1130    return efl_file_mmap_get(wd->resize_obj);
1131 }
1132 
1133 EOLIAN static void
_efl_ui_layout_base_theme_get(const Eo * obj,Efl_Ui_Layout_Data * sd EINA_UNUSED,const char ** klass,const char ** group,const char ** style)1134 _efl_ui_layout_base_theme_get(const Eo *obj, Efl_Ui_Layout_Data *sd EINA_UNUSED, const char **klass, const char **group, const char **style)
1135 {
1136    if (klass) *klass = elm_widget_theme_klass_get(obj);
1137    if (group) *group = elm_widget_theme_element_get(obj);
1138    if (style) *style = elm_widget_theme_style_get(obj);
1139 }
1140 
1141 EOLIAN static Eina_Error
_efl_ui_layout_base_theme_set(Eo * obj,Efl_Ui_Layout_Data * sd,const char * klass,const char * group,const char * style)1142 _efl_ui_layout_base_theme_set(Eo *obj, Efl_Ui_Layout_Data *sd, const char *klass, const char *group, const char *style)
1143 {
1144    Eina_Bool changed = EINA_FALSE;
1145 
1146    if (!elm_widget_is_legacy(obj) && efl_finalized_get(obj))
1147      {
1148         ERR("Efl.Ui.Layout_theme can only be set before finalize!");
1149         return EFL_UI_THEME_APPLY_ERROR_GENERIC;
1150      }
1151 
1152    if (sd->file_set) sd->file_set = EINA_FALSE;
1153 
1154    changed |= elm_widget_theme_klass_set(obj, klass);
1155    changed |= elm_widget_theme_element_set(obj, group);
1156    changed |= elm_widget_theme_style_set(obj, style);
1157 
1158    if (changed)
1159      return efl_ui_widget_theme_apply(obj);
1160    return EFL_UI_THEME_APPLY_ERROR_NONE;
1161 }
1162 
1163 EOLIAN static void
_efl_ui_layout_base_efl_layout_signal_signal_emit(Eo * obj,Efl_Ui_Layout_Data * _pd EINA_UNUSED,const char * emission,const char * source)1164 _efl_ui_layout_base_efl_layout_signal_signal_emit(Eo *obj, Efl_Ui_Layout_Data *_pd EINA_UNUSED, const char *emission, const char *source)
1165 {
1166    // Don't do anything else than call forward here
1167    EINA_SAFETY_ON_TRUE_RETURN(efl_invalidated_get(obj));
1168    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
1169    efl_layout_signal_emit(wd->resize_obj, emission, source);
1170 }
1171 
1172 static Eina_Bool
_efl_ui_layout_base_efl_layout_signal_signal_callback_add(Eo * obj,Efl_Ui_Layout_Data * pd EINA_UNUSED,const char * emission,const char * source,void * func_data,EflLayoutSignalCb func,Eina_Free_Cb func_free_cb)1173 _efl_ui_layout_base_efl_layout_signal_signal_callback_add(Eo *obj, Efl_Ui_Layout_Data *pd EINA_UNUSED, const char *emission, const char *source, void *func_data, EflLayoutSignalCb func, Eina_Free_Cb func_free_cb)
1174 {
1175    // Don't do anything else than call forward here
1176    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, EINA_FALSE);
1177    return efl_layout_signal_callback_add(wd->resize_obj, emission, source, func_data, func, func_free_cb);
1178 }
1179 
1180 static Eina_Bool
_efl_ui_layout_base_efl_layout_signal_signal_callback_del(Eo * obj,Efl_Ui_Layout_Data * pd EINA_UNUSED,const char * emission,const char * source,void * func_data,EflLayoutSignalCb func,Eina_Free_Cb func_free_cb)1181 _efl_ui_layout_base_efl_layout_signal_signal_callback_del(Eo *obj, Efl_Ui_Layout_Data *pd EINA_UNUSED, const char *emission, const char *source, void *func_data, EflLayoutSignalCb func, Eina_Free_Cb func_free_cb)
1182 {
1183    // Don't do anything else than call forward here
1184    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, EINA_FALSE);
1185    return efl_layout_signal_callback_del(wd->resize_obj, emission, source, func_data, func, func_free_cb);
1186 }
1187 
1188 // TODO:
1189 // - message_send
1190 // - message_signal_process
1191 // and also message handler (not implemented yet as an EO interface!)
1192 
1193 EAPI Eina_Bool
elm_layout_content_set(Evas_Object * obj,const char * swallow,Evas_Object * content)1194 elm_layout_content_set(Evas_Object *obj, const char *swallow, Evas_Object *content)
1195 {
1196    EFL_UI_LAYOUT_CHECK(obj) EINA_FALSE;
1197    if (!swallow)
1198      {
1199         swallow = efl_ui_widget_default_content_part_get(obj);
1200         if (!swallow) return EINA_FALSE;
1201      }
1202    else if (!_elm_layout_part_aliasing_eval(obj, &swallow, EINA_FALSE))
1203      return EINA_FALSE;
1204 
1205    return efl_content_set(efl_part(obj, swallow), content);
1206 }
1207 
1208 static Eina_Bool
_efl_ui_layout_content_set(Eo * obj,Efl_Ui_Layout_Data * sd,const char * part,Evas_Object * content)1209 _efl_ui_layout_content_set(Eo *obj, Efl_Ui_Layout_Data *sd, const char *part, Evas_Object *content)
1210 {
1211    Efl_Ui_Layout_Sub_Object_Data *sub_d;
1212    Eina_List *l;
1213 
1214    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, EINA_FALSE);
1215 
1216    EINA_LIST_FOREACH(sd->subs, l, sub_d)
1217      {
1218         if (sub_d->type == SWALLOW)
1219           {
1220              if (!strcmp(part, sub_d->part))
1221                {
1222                   if (content == sub_d->obj) goto end;
1223                   if (efl_alive_get(sub_d->obj))
1224                     {
1225                        _eo_unparent_helper(sub_d->obj, obj);
1226                        evas_object_del(sub_d->obj);
1227                     }
1228                   break;
1229                }
1230              /* was previously swallowed at another part -- mimic
1231               * edje_object_part_swallow()'s behavior, then */
1232              else if (content == sub_d->obj)
1233                {
1234                   sd->subs = eina_list_remove_list(sd->subs, l);
1235                   _icon_signal_emit(sd, sub_d, EINA_FALSE);
1236                   eina_stringshare_del(sub_d->part);
1237                   free(sub_d);
1238 
1239                   _elm_widget_sub_object_redirect_to_top(obj, content);
1240                   break;
1241                }
1242           }
1243      }
1244 
1245    if (content)
1246      {
1247         if (!elm_widget_sub_object_add(obj, content))
1248           return EINA_FALSE;
1249 
1250         if (!edje_object_part_swallow
1251               (wd->resize_obj, part, content))
1252           {
1253              ERR("could not swallow %p into part '%s'", content, part);
1254              _elm_widget_sub_object_redirect_to_top(obj, content);
1255              return EINA_FALSE;
1256           }
1257         sub_d = ELM_NEW(Efl_Ui_Layout_Sub_Object_Data);
1258         if (!sub_d)
1259           {
1260              ERR("failed to allocate memory!");
1261              edje_object_part_unswallow(wd->resize_obj, content);
1262              _elm_widget_sub_object_redirect_to_top(obj, content);
1263              return EINA_FALSE;
1264           }
1265         sub_d->type = SWALLOW;
1266         sub_d->part = eina_stringshare_add(part);
1267         sub_d->obj = content;
1268         sd->subs = eina_list_append(sd->subs, sub_d);
1269 
1270         efl_parent_set(content, obj);
1271         _icon_signal_emit(sd, sub_d, EINA_TRUE);
1272      }
1273 
1274    efl_canvas_group_change(obj);
1275 
1276 end:
1277    return EINA_TRUE;
1278 }
1279 
1280 EAPI Evas_Object *
elm_layout_content_get(const Evas_Object * obj,const char * swallow)1281 elm_layout_content_get(const Evas_Object *obj, const char *swallow)
1282 {
1283    EFL_UI_LAYOUT_CHECK(obj) NULL;
1284    // If the object is already dead, their shouldn't be any part in it
1285    if (efl_invalidated_get(obj)) return NULL;
1286    if (!swallow)
1287      {
1288         swallow = efl_ui_widget_default_content_part_get(obj);
1289         if (!swallow) return NULL;
1290      }
1291    else if (!_elm_layout_part_aliasing_eval(obj, &swallow, EINA_FALSE))
1292      return NULL;
1293 
1294    return efl_content_get(efl_part(obj, swallow));
1295 }
1296 
1297 static Evas_Object*
_efl_ui_layout_content_get(Eo * obj,Efl_Ui_Layout_Data * sd,const char * part)1298 _efl_ui_layout_content_get(Eo *obj, Efl_Ui_Layout_Data *sd, const char *part)
1299 {
1300    const Eina_List *l;
1301    Efl_Ui_Layout_Sub_Object_Data *sub_d;
1302 
1303    EINA_LIST_FOREACH(sd->subs, l, sub_d)
1304      {
1305         if ((sub_d->type != TEXT) && !strcmp(part, sub_d->part))
1306           {
1307              if (sub_d->type == SWALLOW)
1308                return sub_d->obj;
1309           }
1310      }
1311 
1312    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, NULL);
1313    return efl_content_get(efl_part(wd->resize_obj, part));
1314 }
1315 
1316 EAPI Evas_Object *
elm_layout_content_unset(Evas_Object * obj,const char * swallow)1317 elm_layout_content_unset(Evas_Object *obj, const char *swallow)
1318 {
1319    EFL_UI_LAYOUT_CHECK(obj) NULL;
1320    if (!swallow)
1321      {
1322         swallow = efl_ui_widget_default_content_part_get(obj);
1323         if (!swallow) return NULL;
1324      }
1325    else if (!_elm_layout_part_aliasing_eval(obj, &swallow, EINA_FALSE))
1326      return NULL;
1327 
1328    return efl_content_unset(efl_part(obj, swallow));
1329 }
1330 
1331 static Evas_Object*
_efl_ui_layout_content_unset(Eo * obj,Efl_Ui_Layout_Data * sd,const char * part)1332 _efl_ui_layout_content_unset(Eo *obj, Efl_Ui_Layout_Data *sd, const char *part)
1333 {
1334    Efl_Ui_Layout_Sub_Object_Data *sub_d;
1335    Eina_List *l;
1336 
1337    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, NULL);
1338 
1339    EINA_LIST_FOREACH(sd->subs, l, sub_d)
1340      {
1341         if ((sub_d->type == SWALLOW) && (!strcmp(part, sub_d->part)))
1342           {
1343              Evas_Object *content;
1344 
1345              if (!sub_d->obj) return NULL;
1346 
1347              content = sub_d->obj; /* sub_d will die in
1348                                     * _efl_ui_layout_smart_widget_sub_object_del */
1349 
1350              if (!_elm_widget_sub_object_redirect_to_top(obj, content))
1351                {
1352                   ERR("could not remove sub object %p from %p", content, obj);
1353                   return NULL;
1354                }
1355 
1356              edje_object_part_unswallow
1357                (wd->resize_obj, content);
1358              EINA_LIST_FOREACH(sd->subs, l, sub_d)
1359                {
1360                   if (sub_d->obj == content)
1361                     {
1362                        sd->subs = eina_list_remove_list(sd->subs, l);
1363                        _icon_signal_emit(sd, sub_d, EINA_FALSE);
1364                        eina_stringshare_del(sub_d->part);
1365                        free(sub_d);
1366                        break;
1367                     }
1368                }
1369              _eo_unparent_helper(content, obj);
1370              return content;
1371           }
1372      }
1373 
1374    return NULL;
1375 }
1376 
1377 /* legacy only - eo is iterator */
1378 EAPI Eina_List *
elm_layout_content_swallow_list_get(const Evas_Object * obj)1379 elm_layout_content_swallow_list_get(const Evas_Object *obj)
1380 {
1381    EFL_UI_LAYOUT_CHECK(obj) NULL;
1382    Eina_List *ret = NULL;
1383    Efl_Ui_Layout_Sub_Object_Data *sub_d = NULL;
1384    Efl_Ui_Layout_Data *sd = efl_data_scope_get(obj, MY_CLASS);
1385    Eina_List *l = NULL;
1386 
1387    EINA_LIST_FOREACH(sd->subs, l, sub_d)
1388      {
1389         if (sub_d->type == SWALLOW)
1390           ret = eina_list_append(ret, sub_d->obj);
1391      }
1392 
1393    return ret;
1394 }
1395 
1396 static Eina_Bool
_sub_iterator_next(Efl_Ui_Layout_Sub_Iterator * it,void ** data)1397 _sub_iterator_next(Efl_Ui_Layout_Sub_Iterator *it, void **data)
1398 {
1399    Efl_Ui_Layout_Sub_Object_Data *sub;
1400 
1401    if (!eina_iterator_next(it->real_iterator, (void **)&sub))
1402      return EINA_FALSE;
1403 
1404    if (data) *data = sub->obj;
1405    return EINA_TRUE;
1406 }
1407 
1408 static Efl_Ui_Layout *
_sub_iterator_get_container(Efl_Ui_Layout_Sub_Iterator * it)1409 _sub_iterator_get_container(Efl_Ui_Layout_Sub_Iterator *it)
1410 {
1411    return it->object;
1412 }
1413 
1414 static void
_sub_iterator_free(Efl_Ui_Layout_Sub_Iterator * it)1415 _sub_iterator_free(Efl_Ui_Layout_Sub_Iterator *it)
1416 {
1417    eina_iterator_free(it->real_iterator);
1418    free(it);
1419 }
1420 
1421 static Eina_Iterator *
_sub_iterator_create(Eo * eo_obj,Efl_Ui_Layout_Data * sd)1422 _sub_iterator_create(Eo *eo_obj, Efl_Ui_Layout_Data *sd)
1423 {
1424    Efl_Ui_Layout_Sub_Iterator *it;
1425 
1426    it = calloc(1, sizeof(*it));
1427    if (!it) return NULL;
1428 
1429    EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
1430 
1431    it->real_iterator = eina_list_iterator_new(sd->subs);
1432    it->iterator.version = EINA_ITERATOR_VERSION;
1433    it->iterator.next = FUNC_ITERATOR_NEXT(_sub_iterator_next);
1434    it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(_sub_iterator_get_container);
1435    it->iterator.free = FUNC_ITERATOR_FREE(_sub_iterator_free);
1436    it->object = eo_obj;
1437 
1438    return &it->iterator;
1439 }
1440 
1441 EOLIAN static Eina_Iterator *
_efl_ui_layout_base_efl_container_content_iterate(Eo * eo_obj EINA_UNUSED,Efl_Ui_Layout_Data * sd)1442 _efl_ui_layout_base_efl_container_content_iterate(Eo *eo_obj EINA_UNUSED, Efl_Ui_Layout_Data *sd)
1443 {
1444    return _sub_iterator_create(eo_obj, sd);
1445 }
1446 
1447 EOLIAN static int
_efl_ui_layout_base_efl_container_content_count(Eo * eo_obj EINA_UNUSED,Efl_Ui_Layout_Data * sd)1448 _efl_ui_layout_base_efl_container_content_count(Eo *eo_obj EINA_UNUSED, Efl_Ui_Layout_Data *sd)
1449 {
1450    return eina_list_count(sd->subs);
1451 }
1452 
1453 static Eina_Bool
_efl_ui_layout_text_generic_set(Eo * obj,Efl_Ui_Layout_Data * sd,const char * part,const char * text,Eina_Bool is_markup)1454 _efl_ui_layout_text_generic_set(Eo *obj, Efl_Ui_Layout_Data *sd, const char *part, const char *text, Eina_Bool is_markup)
1455 {
1456    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, EINA_FALSE);
1457 
1458    Efl_Ui_Layout_Sub_Object_Data *sub_d = NULL;
1459    Eina_List *l;
1460    Efl_Model *model;
1461 
1462    EINA_LIST_FOREACH(sd->subs, l, sub_d)
1463      {
1464         if ((sub_d->type == TEXT) && (!strcmp(part, sub_d->part)))
1465           {
1466              if (!text)
1467                {
1468                   _text_signal_emit(sd, sub_d, EINA_FALSE);
1469                   eina_stringshare_del(sub_d->part);
1470                   free(sub_d);
1471                   edje_object_part_text_escaped_set
1472                     (wd->resize_obj, part, NULL);
1473                   sd->subs = eina_list_remove_list(sd->subs, l);
1474                   efl_canvas_group_change(obj);
1475                   return EINA_TRUE;
1476                }
1477              else
1478                break;
1479           }
1480      }
1481 
1482    if (!text) return EINA_TRUE;
1483 
1484    if (elm_widget_is_legacy(obj))
1485      {
1486         if (!edje_object_part_text_escaped_set
1487          (wd->resize_obj, part, text))
1488            return EINA_FALSE;
1489      }
1490    else if (is_markup)
1491      {
1492         efl_text_markup_set(efl_part(wd->resize_obj, part), text);
1493      }
1494    else
1495      {
1496         efl_text_set(efl_part(wd->resize_obj, part), text);
1497      }
1498 
1499    if (!sub_d)
1500      {
1501         sub_d = ELM_NEW(Efl_Ui_Layout_Sub_Object_Data);
1502         if (!sub_d) return EINA_FALSE;
1503         sub_d->type = TEXT;
1504         sub_d->part = eina_stringshare_add(part);
1505         sd->subs = eina_list_append(sd->subs, sub_d);
1506      }
1507 
1508    _text_signal_emit(sd, sub_d, EINA_TRUE);
1509 
1510    efl_canvas_group_change(obj);
1511 
1512    if (_elm_config->access_mode == ELM_ACCESS_MODE_ON &&
1513        sd->can_access && !(sub_d->obj))
1514      sub_d->obj = _elm_access_edje_object_part_object_register
1515          (obj, elm_layout_edje_get(obj), part);
1516 
1517    model = efl_ui_view_model_get(obj);
1518    if (model && !sd->connect.updating)
1519      {
1520         char *property = eina_hash_find(sd->connect.properties, sub_d->part);
1521 
1522         if (property)
1523           {
1524              Eina_Value v = EINA_VALUE_EMPTY;
1525 
1526              eina_value_setup(&v, EINA_VALUE_TYPE_STRING);
1527              eina_value_set(&v, text);
1528 
1529              efl_model_property_set(model, property, &v);
1530           }
1531      }
1532 
1533    return EINA_TRUE;
1534 }
1535 
1536 static Eina_Bool
_efl_ui_layout_text_set(Eo * obj,Efl_Ui_Layout_Data * sd,const char * part,const char * text)1537 _efl_ui_layout_text_set(Eo *obj, Efl_Ui_Layout_Data *sd, const char *part, const char *text)
1538 {
1539    return _efl_ui_layout_text_generic_set(obj, sd, part, text, EINA_FALSE);
1540 }
1541 
1542 static const char*
_efl_ui_layout_text_get(Eo * obj,Efl_Ui_Layout_Data * sd EINA_UNUSED,const char * part)1543 _efl_ui_layout_text_get(Eo *obj, Efl_Ui_Layout_Data *sd EINA_UNUSED, const char *part)
1544 {
1545    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, NULL);
1546 
1547    if (elm_widget_is_legacy(obj))
1548      {
1549         return edje_object_part_text_get(wd->resize_obj, part);
1550      }
1551    return efl_text_get(efl_part(wd->resize_obj, part));
1552 }
1553 
1554 static const char*
_efl_ui_layout_text_markup_get(Eo * obj,Efl_Ui_Layout_Data * sd EINA_UNUSED,const char * part)1555 _efl_ui_layout_text_markup_get(Eo *obj, Efl_Ui_Layout_Data *sd EINA_UNUSED, const char *part)
1556 {
1557    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, NULL);
1558 
1559    return efl_text_markup_get(efl_part(wd->resize_obj, part));
1560 }
1561 
1562 static Eina_Bool
_efl_ui_layout_text_markup_set(Eo * obj,Efl_Ui_Layout_Data * sd,const char * part,const char * text)1563 _efl_ui_layout_text_markup_set(Eo *obj, Efl_Ui_Layout_Data *sd, const char *part, const char *text)
1564 {
1565    return _efl_ui_layout_text_generic_set(obj, sd, part, text, EINA_TRUE);
1566 }
1567 
1568 static void
_layout_box_subobj_init(Efl_Ui_Layout_Data * sd,Efl_Ui_Layout_Sub_Object_Data * sub_d,const char * part,Evas_Object * child)1569 _layout_box_subobj_init(Efl_Ui_Layout_Data *sd, Efl_Ui_Layout_Sub_Object_Data *sub_d, const char *part, Evas_Object *child)
1570 {
1571    sub_d->part = eina_stringshare_add(part);
1572    sub_d->obj = child;
1573    sd->subs = eina_list_append(sd->subs, sub_d);
1574    efl_parent_set(child, sd->obj);
1575 }
1576 
1577 Eina_Bool
_efl_ui_layout_box_append(Eo * obj,Efl_Ui_Layout_Data * sd,const char * part,Evas_Object * child)1578 _efl_ui_layout_box_append(Eo *obj, Efl_Ui_Layout_Data *sd, const char *part, Evas_Object *child)
1579 {
1580    Efl_Ui_Layout_Sub_Object_Data *sub_d;
1581 
1582    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, EINA_FALSE);
1583 
1584    if (!edje_object_part_box_append
1585          (wd->resize_obj, part, child))
1586      {
1587         ERR("child %p could not be appended to box part '%s'", child, part);
1588         return EINA_FALSE;
1589      }
1590 
1591    if (!elm_widget_sub_object_add(obj, child))
1592      {
1593         edje_object_part_box_remove
1594           (wd->resize_obj, part, child);
1595         return EINA_FALSE;
1596      }
1597 
1598    sub_d = ELM_NEW(Efl_Ui_Layout_Sub_Object_Data);
1599    if (!sub_d)
1600      {
1601         ERR("failed to allocate memory!");
1602         _elm_widget_sub_object_redirect_to_top(obj, child);
1603         edje_object_part_box_remove(wd->resize_obj, part, child);
1604         return EINA_FALSE;
1605      }
1606    sub_d->type = BOX_APPEND;
1607    _layout_box_subobj_init(sd, sub_d, part, child);
1608 
1609    efl_canvas_group_change(obj);
1610 
1611    return EINA_TRUE;
1612 }
1613 
1614 Eina_Bool
_efl_ui_layout_box_prepend(Eo * obj,Efl_Ui_Layout_Data * sd,const char * part,Evas_Object * child)1615 _efl_ui_layout_box_prepend(Eo *obj, Efl_Ui_Layout_Data *sd, const char *part, Evas_Object *child)
1616 {
1617    Efl_Ui_Layout_Sub_Object_Data *sub_d;
1618 
1619    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, EINA_FALSE);
1620 
1621    if (!edje_object_part_box_prepend
1622          (wd->resize_obj, part, child))
1623      {
1624         ERR("child %p could not be prepended to box part '%s'", child, part);
1625         return EINA_FALSE;
1626      }
1627 
1628    if (!elm_widget_sub_object_add(obj, child))
1629      {
1630         edje_object_part_box_remove
1631           (wd->resize_obj, part, child);
1632         return EINA_FALSE;
1633      }
1634 
1635    sub_d = ELM_NEW(Efl_Ui_Layout_Sub_Object_Data);
1636    if (!sub_d)
1637      {
1638         ERR("failed to allocate memory!");
1639         _elm_widget_sub_object_redirect_to_top(obj, child);
1640         edje_object_part_box_remove(wd->resize_obj, part, child);
1641         return EINA_FALSE;
1642      }
1643    sub_d->type = BOX_PREPEND;
1644    _layout_box_subobj_init(sd, sub_d, part, child);
1645 
1646    efl_canvas_group_change(obj);
1647 
1648    return EINA_TRUE;
1649 }
1650 
1651 Eina_Bool
_efl_ui_layout_box_insert_before(Eo * obj,Efl_Ui_Layout_Data * sd,const char * part,Evas_Object * child,const Evas_Object * reference)1652 _efl_ui_layout_box_insert_before(Eo *obj, Efl_Ui_Layout_Data *sd, const char *part, Evas_Object *child, const Evas_Object *reference)
1653 {
1654    Efl_Ui_Layout_Sub_Object_Data *sub_d;
1655 
1656    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, EINA_FALSE);
1657 
1658    if (!edje_object_part_box_insert_before
1659          (wd->resize_obj, part, child, reference))
1660      {
1661         ERR("child %p could not be inserted before %p inf box part '%s'",
1662             child, reference, part);
1663         return EINA_FALSE;
1664      }
1665 
1666    if (!elm_widget_sub_object_add(obj, child))
1667      {
1668         edje_object_part_box_remove
1669           (wd->resize_obj, part, child);
1670         return EINA_FALSE;
1671      }
1672 
1673    sub_d = ELM_NEW(Efl_Ui_Layout_Sub_Object_Data);
1674    if (!sub_d)
1675      {
1676         ERR("failed to allocate memory!");
1677         _elm_widget_sub_object_redirect_to_top(obj, child);
1678         edje_object_part_box_remove(wd->resize_obj, part, child);
1679         return EINA_FALSE;
1680      }
1681    sub_d->type = BOX_INSERT_BEFORE;
1682    sub_d->p.box.reference = reference;
1683    _layout_box_subobj_init(sd, sub_d, part, child);
1684 
1685    evas_object_event_callback_add
1686      ((Evas_Object *)reference, EVAS_CALLBACK_DEL, _box_reference_del, sub_d);
1687 
1688    efl_canvas_group_change(obj);
1689 
1690    return EINA_TRUE;
1691 }
1692 
1693 Eina_Bool
_efl_ui_layout_box_insert_at(Eo * obj,Efl_Ui_Layout_Data * sd,const char * part,Evas_Object * child,unsigned int pos)1694 _efl_ui_layout_box_insert_at(Eo *obj, Efl_Ui_Layout_Data *sd, const char *part, Evas_Object *child, unsigned int pos)
1695 {
1696    Efl_Ui_Layout_Sub_Object_Data *sub_d;
1697    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, EINA_FALSE);
1698 
1699    if (!edje_object_part_box_insert_at
1700          (wd->resize_obj, part, child, pos))
1701      {
1702         ERR("child %p could not be inserted at %u to box part '%s'",
1703             child, pos, part);
1704         return EINA_FALSE;
1705      }
1706 
1707    if (!elm_widget_sub_object_add(obj, child))
1708      {
1709         edje_object_part_box_remove
1710           (wd->resize_obj, part, child);
1711         return EINA_FALSE;
1712      }
1713 
1714    sub_d = ELM_NEW(Efl_Ui_Layout_Sub_Object_Data);
1715    if (!sub_d)
1716      {
1717         ERR("failed to allocate memory!");
1718         _elm_widget_sub_object_redirect_to_top(obj, child);
1719         edje_object_part_box_remove(wd->resize_obj, part, child);
1720         return EINA_FALSE;
1721      }
1722    sub_d->type = BOX_INSERT_AT;
1723    sub_d->p.box.pos = pos;
1724    _layout_box_subobj_init(sd, sub_d, part, child);
1725 
1726    efl_canvas_group_change(obj);
1727 
1728    return EINA_TRUE;
1729 }
1730 
1731 Evas_Object *
_efl_ui_layout_box_remove(Eo * obj,Efl_Ui_Layout_Data * sd,const char * part,Evas_Object * child)1732 _efl_ui_layout_box_remove(Eo *obj, Efl_Ui_Layout_Data *sd, const char *part, Evas_Object *child)
1733 {
1734 
1735    EINA_SAFETY_ON_NULL_RETURN_VAL(part, NULL);
1736    EINA_SAFETY_ON_NULL_RETURN_VAL(child, NULL);
1737 
1738 
1739    const Eina_List *l;
1740    Efl_Ui_Layout_Sub_Object_Data *sub_d;
1741 
1742    EINA_LIST_FOREACH(sd->subs, l, sub_d)
1743      {
1744         if (!_sub_box_is(sub_d)) continue;
1745         if ((sub_d->obj == child) && (!strcmp(sub_d->part, part)))
1746            return _sub_box_remove(obj, sd, sub_d);
1747      }
1748 
1749    return NULL;
1750 }
1751 
1752 Eina_Bool
_efl_ui_layout_box_remove_all(Eo * obj,Efl_Ui_Layout_Data * sd,const char * part,Eina_Bool clear)1753 _efl_ui_layout_box_remove_all(Eo *obj, Efl_Ui_Layout_Data *sd, const char *part, Eina_Bool clear)
1754 {
1755    EINA_SAFETY_ON_NULL_RETURN_VAL(part, EINA_FALSE);
1756 
1757    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, EINA_FALSE);
1758 
1759    Efl_Ui_Layout_Sub_Object_Data *sub_d;
1760    Eina_List *lst;
1761 
1762    lst = eina_list_clone(sd->subs);
1763    EINA_LIST_FREE(lst, sub_d)
1764      {
1765         if (!_sub_box_is(sub_d)) continue;
1766         if (!strcmp(sub_d->part, part))
1767           {
1768              /* original item's deletion handled at sub-obj-del */
1769              Evas_Object *child = _sub_box_remove(obj, sd, sub_d);
1770              if ((clear) && (child)) evas_object_del(child);
1771           }
1772      }
1773 
1774    /* eventually something may not be added with elm_layout, delete them
1775     * as well */
1776    edje_object_part_box_remove_all
1777      (wd->resize_obj, part, clear);
1778 
1779    return EINA_TRUE;
1780 }
1781 
1782 Eina_Bool
_efl_ui_layout_table_pack(Eo * obj,Efl_Ui_Layout_Data * sd,const char * part,Evas_Object * child,unsigned short col,unsigned short row,unsigned short colspan,unsigned short rowspan)1783 _efl_ui_layout_table_pack(Eo *obj, Efl_Ui_Layout_Data *sd, const char *part, Evas_Object *child, unsigned short col, unsigned short row, unsigned short colspan, unsigned short rowspan)
1784 {
1785    Efl_Ui_Layout_Sub_Object_Data *sub_d;
1786 
1787    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, EINA_FALSE);
1788 
1789    if (!edje_object_part_table_pack
1790          (wd->resize_obj, part, child, col,
1791          row, colspan, rowspan))
1792      {
1793         ERR("child %p could not be packed into table part '%s' col=%uh, row=%hu,"
1794             " colspan=%hu, rowspan=%hu", child, part, col, row, colspan,
1795             rowspan);
1796         return EINA_FALSE;
1797      }
1798 
1799    if (!elm_widget_sub_object_add(obj, child))
1800      {
1801         edje_object_part_table_unpack
1802           (wd->resize_obj, part, child);
1803         return EINA_FALSE;
1804      }
1805 
1806    sub_d = ELM_NEW(Efl_Ui_Layout_Sub_Object_Data);
1807    if (!sub_d)
1808      {
1809         ERR("failed to allocate memory!");
1810         _elm_widget_sub_object_redirect_to_top(obj, child);
1811         edje_object_part_table_unpack(wd->resize_obj, part, child);
1812         return EINA_FALSE;
1813      }
1814    sub_d->type = TABLE_PACK;
1815    sub_d->part = eina_stringshare_add(part);
1816    sub_d->obj = child;
1817    sub_d->p.table.col = col;
1818    sub_d->p.table.row = row;
1819    sub_d->p.table.colspan = colspan;
1820    sub_d->p.table.rowspan = rowspan;
1821    sd->subs = eina_list_append(sd->subs, sub_d);
1822    efl_parent_set(child, obj);
1823 
1824    efl_canvas_group_change(obj);
1825 
1826    return EINA_TRUE;
1827 }
1828 
1829 Evas_Object *
_efl_ui_layout_table_unpack(Eo * obj,Efl_Ui_Layout_Data * sd,const char * part,Evas_Object * child)1830 _efl_ui_layout_table_unpack(Eo *obj, Efl_Ui_Layout_Data *sd, const char *part, Evas_Object *child)
1831 {
1832 
1833    EINA_SAFETY_ON_NULL_RETURN_VAL(part, NULL);
1834    EINA_SAFETY_ON_NULL_RETURN_VAL(child, NULL);
1835 
1836    const Eina_List *l;
1837    Efl_Ui_Layout_Sub_Object_Data *sub_d;
1838 
1839    EINA_LIST_FOREACH(sd->subs, l, sub_d)
1840      {
1841         if (sub_d->type != TABLE_PACK) continue;
1842         if ((sub_d->obj == child) && (!strcmp(sub_d->part, part)))
1843           {
1844              return _sub_table_remove(obj, sd, sub_d);
1845           }
1846      }
1847 
1848    return NULL;
1849 }
1850 
1851 Eina_Bool
_efl_ui_layout_table_clear(Eo * obj,Efl_Ui_Layout_Data * sd,const char * part,Eina_Bool clear)1852 _efl_ui_layout_table_clear(Eo *obj, Efl_Ui_Layout_Data *sd, const char *part, Eina_Bool clear)
1853 {
1854    EINA_SAFETY_ON_NULL_RETURN_VAL(part, EINA_FALSE);
1855 
1856    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, EINA_FALSE);
1857 
1858    Efl_Ui_Layout_Sub_Object_Data *sub_d;
1859    Eina_List *lst;
1860 
1861    lst = eina_list_clone(sd->subs);
1862    EINA_LIST_FREE(lst, sub_d)
1863      {
1864         if (sub_d->type != TABLE_PACK) continue;
1865         if (!strcmp(sub_d->part, part))
1866           {
1867              /* original item's deletion handled at sub-obj-del */
1868              Evas_Object *child = _sub_table_remove(obj, sd, sub_d);
1869              if ((clear) && (child)) evas_object_del(child);
1870           }
1871      }
1872 
1873    /* eventually something may not be added with elm_layout, delete them
1874     * as well */
1875    edje_object_part_table_clear(wd->resize_obj, part, clear);
1876 
1877    return EINA_TRUE;
1878 }
1879 
1880 EAPI Evas_Object*
elm_layout_edje_get(const Eo * obj)1881 elm_layout_edje_get(const Eo *obj)
1882 {
1883    EINA_SAFETY_ON_FALSE_RETURN_VAL(efl_isa(obj, MY_CLASS), NULL);
1884    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, NULL);
1885 
1886    return wd->resize_obj;
1887 }
1888 
1889 EOLIAN static const char *
_efl_ui_layout_base_efl_layout_group_group_data_get(const Eo * obj,Efl_Ui_Layout_Data * _pd EINA_UNUSED,const char * key)1890 _efl_ui_layout_base_efl_layout_group_group_data_get(const Eo *obj, Efl_Ui_Layout_Data *_pd EINA_UNUSED, const char *key)
1891 {
1892    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, NULL);
1893 
1894    return efl_layout_group_data_get(wd->resize_obj, key);
1895 }
1896 
1897 EOLIAN static Eina_Size2D
_efl_ui_layout_base_efl_layout_group_group_size_min_get(const Eo * obj,Efl_Ui_Layout_Data * _pd EINA_UNUSED)1898 _efl_ui_layout_base_efl_layout_group_group_size_min_get(const Eo *obj, Efl_Ui_Layout_Data *_pd EINA_UNUSED)
1899 {
1900    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, EINA_SIZE2D(0, 0));
1901 
1902    return efl_layout_group_size_min_get(wd->resize_obj);
1903 }
1904 
1905 EOLIAN static Eina_Size2D
_efl_ui_layout_base_efl_layout_group_group_size_max_get(const Eo * obj,Efl_Ui_Layout_Data * _pd EINA_UNUSED)1906 _efl_ui_layout_base_efl_layout_group_group_size_max_get(const Eo *obj, Efl_Ui_Layout_Data *_pd EINA_UNUSED)
1907 {
1908    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, EINA_SIZE2D(0, 0));
1909 
1910    return efl_layout_group_size_max_get(wd->resize_obj);
1911 }
1912 
1913 EOLIAN static Eina_Bool
_efl_ui_layout_base_efl_layout_group_part_exist_get(const Eo * obj,Efl_Ui_Layout_Data * _pd EINA_UNUSED,const char * part)1914 _efl_ui_layout_base_efl_layout_group_part_exist_get(const Eo *obj, Efl_Ui_Layout_Data *_pd EINA_UNUSED, const char *part)
1915 {
1916    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, EINA_FALSE);
1917 
1918    return efl_layout_group_part_exist_get(wd->resize_obj, part);
1919 }
1920 
1921 EOLIAN static void
_efl_ui_layout_base_efl_canvas_group_group_change(Eo * obj,Efl_Ui_Layout_Data * sd)1922 _efl_ui_layout_base_efl_canvas_group_group_change(Eo *obj, Efl_Ui_Layout_Data *sd)
1923 {
1924    if (sd->frozen)
1925      /* cleared in thaw */
1926      sd->frozen_changed = EINA_TRUE;
1927    else
1928      efl_canvas_group_change(efl_super(obj, MY_CLASS));
1929 }
1930 
1931 EOLIAN static void
_elm_layout_efl_canvas_group_change(Eo * obj,Elm_Layout_Data * ld)1932 _elm_layout_efl_canvas_group_change(Eo *obj, Elm_Layout_Data *ld)
1933 {
1934    Efl_Ui_Layout_Data *sd;
1935 
1936    sd = efl_data_scope_safe_get(obj, EFL_UI_LAYOUT_BASE_CLASS);
1937    EINA_SAFETY_ON_NULL_RETURN(sd);
1938    if (sd->frozen) return;
1939    ld->needs_size_calc = EINA_TRUE;
1940    efl_canvas_group_change(efl_super(obj, ELM_LAYOUT_MIXIN));
1941 }
1942 
1943 EOLIAN static void
_elm_layout_efl_gfx_hint_size_restricted_min_set(Eo * obj,Elm_Layout_Data * ld,Eina_Size2D sz)1944 _elm_layout_efl_gfx_hint_size_restricted_min_set(Eo *obj, Elm_Layout_Data *ld, Eina_Size2D sz)
1945 {
1946    /* correctly handle legacy case where the user has set a min size hint on the object:
1947     * in legacy code, only restricted_min existed, which resulted in conflicts between
1948     * internal sizing and user-expected sizing. we attempt to simulate this now in a more controlled
1949     * manner by only checking this hint during sizing calcs if the user has set it
1950     */
1951    if (!ld->in_calc)
1952      ld->user_min_sz = (sz.w > 0) || (sz.h > 0);
1953    efl_gfx_hint_size_restricted_min_set(efl_super(obj, ELM_LAYOUT_MIXIN), sz);
1954 }
1955 
1956 /* layout's sizing evaluation is deferred. evaluation requests are
1957  * queued up and only flag the object as 'changed'. when it comes to
1958  * Evas's rendering phase, it will be addressed, finally (see
1959  * _efl_ui_layout_smart_calculate()). */
1960 EOLIAN static void
_elm_layout_sizing_eval(Eo * obj,Elm_Layout_Data * ld)1961 _elm_layout_sizing_eval(Eo *obj, Elm_Layout_Data *ld)
1962 {
1963    _elm_layout_efl_canvas_group_change(obj, ld);
1964 }
1965 
1966 EAPI void
elm_layout_sizing_restricted_eval(Eo * obj,Eina_Bool w,Eina_Bool h)1967 elm_layout_sizing_restricted_eval(Eo *obj, Eina_Bool w, Eina_Bool h)
1968 {
1969    Elm_Layout_Data *ld = efl_data_scope_safe_get(obj, ELM_LAYOUT_MIXIN);
1970 
1971    EINA_SAFETY_ON_NULL_RETURN(ld);
1972    ld->restricted_calc_w = !!w;
1973    ld->restricted_calc_h = !!h;
1974 
1975    efl_canvas_group_change(obj);
1976 }
1977 
1978 EOLIAN static int
_efl_ui_layout_base_efl_layout_calc_calc_freeze(Eo * obj,Efl_Ui_Layout_Data * sd)1979 _efl_ui_layout_base_efl_layout_calc_calc_freeze(Eo *obj, Efl_Ui_Layout_Data *sd)
1980 {
1981    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, 0);
1982    sd->frozen = EINA_TRUE;
1983    return edje_object_freeze(wd->resize_obj);
1984 }
1985 
1986 EOLIAN static int
_efl_ui_layout_base_efl_layout_calc_calc_thaw(Eo * obj,Efl_Ui_Layout_Data * sd)1987 _efl_ui_layout_base_efl_layout_calc_calc_thaw(Eo *obj, Efl_Ui_Layout_Data *sd)
1988 {
1989    int ret;
1990    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, 0);
1991 
1992    ret = edje_object_thaw(wd->resize_obj);
1993 
1994    if (!ret)
1995      {
1996         sd->frozen = EINA_FALSE;
1997         if (sd->frozen_changed)
1998           efl_canvas_group_change(obj);
1999         sd->frozen_changed = EINA_FALSE;
2000      }
2001 
2002    return ret;
2003 }
2004 
2005 EOLIAN void
_efl_ui_layout_base_efl_layout_calc_calc_auto_update_hints_set(Eo * obj EINA_UNUSED,Efl_Ui_Layout_Data * sd EINA_UNUSED,Eina_Bool update)2006 _efl_ui_layout_base_efl_layout_calc_calc_auto_update_hints_set(Eo *obj EINA_UNUSED, Efl_Ui_Layout_Data *sd EINA_UNUSED, Eina_Bool update)
2007 {
2008    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
2009    efl_layout_calc_auto_update_hints_set(wd->resize_obj, update);
2010 }
2011 
2012 EOLIAN Eina_Bool
_efl_ui_layout_base_efl_layout_calc_calc_auto_update_hints_get(const Eo * obj EINA_UNUSED,Efl_Ui_Layout_Data * sd EINA_UNUSED)2013 _efl_ui_layout_base_efl_layout_calc_calc_auto_update_hints_get(const Eo *obj EINA_UNUSED, Efl_Ui_Layout_Data *sd EINA_UNUSED)
2014 {
2015    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, EINA_FALSE);
2016    return efl_layout_calc_auto_update_hints_get(wd->resize_obj);
2017 }
2018 
2019 EOLIAN Eina_Size2D
_efl_ui_layout_base_efl_layout_calc_calc_size_min(Eo * obj EINA_UNUSED,Efl_Ui_Layout_Data * sd EINA_UNUSED,Eina_Size2D restricted)2020 _efl_ui_layout_base_efl_layout_calc_calc_size_min(Eo *obj EINA_UNUSED, Efl_Ui_Layout_Data *sd EINA_UNUSED, Eina_Size2D restricted)
2021 {
2022    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, restricted);
2023    return efl_layout_calc_size_min(wd->resize_obj, restricted);
2024 }
2025 
2026 EOLIAN Eina_Rect
_efl_ui_layout_base_efl_layout_calc_calc_parts_extends(Eo * obj EINA_UNUSED,Efl_Ui_Layout_Data * sd EINA_UNUSED)2027 _efl_ui_layout_base_efl_layout_calc_calc_parts_extends(Eo *obj EINA_UNUSED, Efl_Ui_Layout_Data *sd EINA_UNUSED)
2028 {
2029    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, (Eina_Rect){.rect = {0, 0, 0, 0}});
2030    return efl_layout_calc_parts_extends(wd->resize_obj);
2031 }
2032 
2033 EOLIAN void
_efl_ui_layout_base_efl_layout_calc_calc_force(Eo * obj EINA_UNUSED,Efl_Ui_Layout_Data * sd)2034 _efl_ui_layout_base_efl_layout_calc_calc_force(Eo *obj EINA_UNUSED, Efl_Ui_Layout_Data *sd)
2035 {
2036    Eina_Bool prev_frozen = sd->frozen;
2037    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
2038    sd->frozen = EINA_FALSE;
2039    efl_layout_calc_force(wd->resize_obj);
2040    sd->frozen = prev_frozen;
2041 }
2042 
2043 static Eina_Bool
_efl_ui_layout_part_cursor_set(Efl_Ui_Layout_Data * sd,const char * part_name,const char * cursor)2044 _efl_ui_layout_part_cursor_set(Efl_Ui_Layout_Data *sd, const char *part_name, const char *cursor)
2045 {
2046    Evas_Object *part_obj;
2047    Efl_Ui_Layout_Sub_Object_Cursor *pc;
2048    Eo *obj = sd->obj;
2049 
2050    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, EINA_FALSE);
2051    EINA_SAFETY_ON_NULL_RETURN_VAL(part_name, EINA_FALSE);
2052 
2053    if (!cursor) return _efl_ui_layout_part_cursor_unset(sd, part_name);
2054 
2055    edje_object_freeze(wd->resize_obj);
2056    part_obj = (Evas_Object *)edje_object_part_object_get
2057        (wd->resize_obj, part_name);
2058    edje_object_thaw(wd->resize_obj);
2059 
2060    if (!part_obj)
2061      {
2062         const char *group, *file;
2063 
2064         edje_object_file_get(wd->resize_obj, &file, &group);
2065         ERR("no part '%s' in group '%s' of file '%s'. Cannot set cursor '%s'",
2066             part_name, group, file, cursor);
2067         return EINA_FALSE;
2068      }
2069    if (evas_object_pass_events_get(part_obj))
2070      {
2071         const char *group, *file;
2072 
2073         edje_object_file_get(wd->resize_obj, &file, &group);
2074         ERR("part '%s' in group '%s' of file '%s' has mouse_events: 0. "
2075             "Cannot set cursor '%s'",
2076             part_name, group, file, cursor);
2077         return EINA_FALSE;
2078      }
2079 
2080    pc = _parts_cursors_find(sd, part_name);
2081    if (pc) eina_stringshare_replace(&pc->cursor, cursor);
2082    else
2083      {
2084         pc = calloc(1, sizeof(*pc));
2085         if (!pc)
2086           {
2087              ERR("failed to allocate memory!");
2088              return EINA_FALSE;
2089           }
2090         pc->part = eina_stringshare_add(part_name);
2091         pc->cursor = eina_stringshare_add(cursor);
2092         pc->style = eina_stringshare_add("default");
2093         sd->parts_cursors = eina_list_append(sd->parts_cursors, pc);
2094      }
2095 
2096    pc->obj = part_obj;
2097    elm_object_sub_cursor_set(part_obj, obj, pc->cursor);
2098 
2099    return EINA_TRUE;
2100 }
2101 
2102 static const char *
_efl_ui_layout_part_cursor_get(Efl_Ui_Layout_Data * sd,const char * part_name)2103 _efl_ui_layout_part_cursor_get(Efl_Ui_Layout_Data *sd, const char *part_name)
2104 {
2105    EINA_SAFETY_ON_NULL_RETURN_VAL(part_name, NULL);
2106 
2107    Efl_Ui_Layout_Sub_Object_Cursor *pc = _parts_cursors_find(sd, part_name);
2108    EINA_SAFETY_ON_NULL_RETURN_VAL(pc, NULL);
2109    EINA_SAFETY_ON_NULL_RETURN_VAL(pc->obj, NULL);
2110 
2111    return elm_object_cursor_get(pc->obj);
2112 }
2113 
2114 static Eina_Bool
_efl_ui_layout_part_cursor_unset(Efl_Ui_Layout_Data * sd,const char * part_name)2115 _efl_ui_layout_part_cursor_unset(Efl_Ui_Layout_Data *sd, const char *part_name)
2116 {
2117    EINA_SAFETY_ON_NULL_RETURN_VAL(part_name, EINA_FALSE);
2118 
2119    Eina_List *l;
2120    Efl_Ui_Layout_Sub_Object_Cursor *pc;
2121 
2122    EINA_LIST_FOREACH(sd->parts_cursors, l, pc)
2123      {
2124         if (!strcmp(part_name, pc->part))
2125           {
2126              if (pc->obj) elm_object_cursor_unset(pc->obj);
2127              _part_cursor_free(pc);
2128              sd->parts_cursors = eina_list_remove_list(sd->parts_cursors, l);
2129              return EINA_TRUE;
2130           }
2131      }
2132 
2133    return EINA_FALSE;
2134 }
2135 
2136 static Eina_Bool
_efl_ui_layout_part_cursor_style_set(Efl_Ui_Layout_Data * sd,const char * part_name,const char * style)2137 _efl_ui_layout_part_cursor_style_set(Efl_Ui_Layout_Data *sd, const char *part_name, const char *style)
2138 {
2139    EINA_SAFETY_ON_NULL_RETURN_VAL(part_name, EINA_FALSE);
2140 
2141    Efl_Ui_Layout_Sub_Object_Cursor *pc = _parts_cursors_find(sd, part_name);
2142    EINA_SAFETY_ON_NULL_RETURN_VAL(pc, EINA_FALSE);
2143    EINA_SAFETY_ON_NULL_RETURN_VAL(pc->obj, EINA_FALSE);
2144 
2145    eina_stringshare_replace(&pc->style, style);
2146    elm_object_cursor_style_set(pc->obj, pc->style);
2147 
2148    return EINA_TRUE;
2149 }
2150 
2151 static const char*
_efl_ui_layout_part_cursor_style_get(Efl_Ui_Layout_Data * sd,const char * part_name)2152 _efl_ui_layout_part_cursor_style_get(Efl_Ui_Layout_Data *sd, const char *part_name)
2153 {
2154    EINA_SAFETY_ON_NULL_RETURN_VAL(part_name, NULL);
2155 
2156    Efl_Ui_Layout_Sub_Object_Cursor *pc = _parts_cursors_find(sd, part_name);
2157    EINA_SAFETY_ON_NULL_RETURN_VAL(pc, NULL);
2158    EINA_SAFETY_ON_NULL_RETURN_VAL(pc->obj, NULL);
2159 
2160    return elm_object_cursor_style_get(pc->obj);
2161 }
2162 
2163 static Eina_Bool
_efl_ui_layout_part_cursor_engine_only_set(Efl_Ui_Layout_Data * sd,const char * part_name,Eina_Bool engine_only)2164 _efl_ui_layout_part_cursor_engine_only_set(Efl_Ui_Layout_Data *sd, const char *part_name, Eina_Bool engine_only)
2165 {
2166    EINA_SAFETY_ON_NULL_RETURN_VAL(part_name, EINA_FALSE);
2167 
2168    Efl_Ui_Layout_Sub_Object_Cursor *pc = _parts_cursors_find(sd, part_name);
2169    EINA_SAFETY_ON_NULL_RETURN_VAL(pc, EINA_FALSE);
2170    EINA_SAFETY_ON_NULL_RETURN_VAL(pc->obj, EINA_FALSE);
2171 
2172    pc->engine_only = !!engine_only;
2173    elm_object_cursor_theme_search_enabled_set(pc->obj, !pc->engine_only);
2174 
2175    return EINA_TRUE;
2176 }
2177 
2178 static Eina_Bool
_efl_ui_layout_part_cursor_engine_only_get(Efl_Ui_Layout_Data * sd,const char * part_name)2179 _efl_ui_layout_part_cursor_engine_only_get(Efl_Ui_Layout_Data *sd, const char *part_name)
2180 {
2181    EINA_SAFETY_ON_NULL_RETURN_VAL(part_name, EINA_FALSE);
2182 
2183    Efl_Ui_Layout_Sub_Object_Cursor *pc = _parts_cursors_find(sd, part_name);
2184    EINA_SAFETY_ON_NULL_RETURN_VAL(pc, EINA_FALSE);
2185    EINA_SAFETY_ON_NULL_RETURN_VAL(pc->obj, EINA_FALSE);
2186 
2187    return !elm_object_cursor_theme_search_enabled_get(pc->obj);
2188 }
2189 
2190 EAPI Eina_Bool
elm_layout_edje_object_can_access_set(Eo * obj,Eina_Bool can_access)2191 elm_layout_edje_object_can_access_set(Eo *obj, Eina_Bool can_access)
2192 {
2193    Efl_Ui_Layout_Data *sd = efl_data_scope_safe_get(obj, MY_CLASS);
2194    EINA_SAFETY_ON_NULL_RETURN_VAL(sd, EINA_FALSE);
2195    sd->can_access = !!can_access;
2196    return EINA_TRUE;
2197 }
2198 
2199 EAPI Eina_Bool
elm_layout_edje_object_can_access_get(const Eo * obj)2200 elm_layout_edje_object_can_access_get(const Eo *obj)
2201 {
2202    Efl_Ui_Layout_Data *sd = efl_data_scope_safe_get(obj, MY_CLASS);
2203    EINA_SAFETY_ON_NULL_RETURN_VAL(sd, EINA_FALSE);
2204    return sd->can_access;
2205 }
2206 
2207 EOLIAN static void
_efl_ui_layout_base_efl_object_dbg_info_get(Eo * eo_obj,Efl_Ui_Layout_Data * _pd EINA_UNUSED,Efl_Dbg_Info * root)2208 _efl_ui_layout_base_efl_object_dbg_info_get(Eo *eo_obj, Efl_Ui_Layout_Data *_pd EINA_UNUSED, Efl_Dbg_Info *root)
2209 {
2210    efl_dbg_info_get(efl_super(eo_obj, MY_CLASS), root);
2211    ELM_WIDGET_DATA_GET_OR_RETURN(eo_obj, wd);
2212 
2213    if (wd->resize_obj && efl_isa(wd->resize_obj, EFL_CANVAS_LAYOUT_CLASS))
2214      {
2215         Efl_Dbg_Info *group = EFL_DBG_INFO_LIST_APPEND(root, MY_CLASS_NAME);
2216         const char *file, *edje_group;
2217         Evas_Object *edje_obj = wd->resize_obj;
2218         Edje_Load_Error error;
2219 
2220         efl_file_simple_get(edje_obj, &file, &edje_group);
2221         EFL_DBG_INFO_APPEND(group, "File", EINA_VALUE_TYPE_STRING, file);
2222         EFL_DBG_INFO_APPEND(group, "Group", EINA_VALUE_TYPE_STRING, edje_group);
2223 
2224         error = edje_object_load_error_get(edje_obj);
2225         if (error != EDJE_LOAD_ERROR_NONE)
2226           {
2227              EFL_DBG_INFO_APPEND(group, "Error", EINA_VALUE_TYPE_STRING,
2228                                 edje_load_error_str(error));
2229           }
2230      }
2231 }
2232 
2233 static void
_efl_ui_layout_view_model_property_update(Efl_Ui_Layout_Data * pd,const char * part,const char * fetch)2234 _efl_ui_layout_view_model_property_update(Efl_Ui_Layout_Data *pd, const char *part, const char *fetch)
2235 {
2236    Eina_Value *v = NULL;
2237    char *value = NULL;
2238    Efl_Model *model;
2239 
2240    model = efl_ui_view_model_get(pd->obj);
2241    v = efl_model_property_get(model, fetch);
2242    if (!v) return;
2243 
2244    if (eina_value_type_get(v) != EINA_VALUE_TYPE_ERROR)
2245        value = eina_value_to_string(v);
2246 
2247    pd->connect.updating = EINA_TRUE; // Prevent recursive call to property_set while updating text
2248    efl_text_set(efl_part(pd->obj, part), value);
2249    pd->connect.updating = EINA_FALSE;
2250 
2251    eina_value_free(v);
2252    free(value);
2253 }
2254 
2255 static void
_efl_ui_layout_view_model_signal_update(Efl_Ui_Layout_Data * pd,const char * signal,const char * fetch)2256 _efl_ui_layout_view_model_signal_update(Efl_Ui_Layout_Data *pd, const char *signal, const char *fetch)
2257 {
2258    Eina_Value *v = NULL;
2259    Eina_Strbuf *buf;
2260    char *value = NULL;
2261    Efl_Model *model;
2262    Eina_Bool eval = EINA_FALSE;
2263    Eina_Bool is_bool = EINA_FALSE;
2264 
2265    model = efl_ui_view_model_get(pd->obj);
2266    v = efl_model_property_get(model, fetch);
2267    if (!v) return;
2268 
2269    if (eina_value_type_get(v) == EINA_VALUE_TYPE_ERROR)
2270      {
2271         Eina_Error error;
2272 
2273         eina_value_get(v, &error);
2274         if (error != EAGAIN) ERR("Failed to fetch signal value %s for property %s got error: %s", signal, fetch, eina_error_msg_get(error));
2275         return;
2276      }
2277 
2278    is_bool = (eina_value_type_get(v) == EINA_VALUE_TYPE_BOOL);
2279    if (is_bool)
2280      {
2281         eina_value_bool_get(v, &eval);
2282      }
2283    value = eina_value_to_string(v);
2284 
2285    buf = eina_strbuf_new();
2286    // FIXME: is it really the form of signal we want to send ?
2287    const char *ini = signal;
2288    for (;;)
2289      {
2290         const char *last = ini;
2291         ini = strstr(last, "%{");
2292         if (!ini)
2293           {
2294              eina_strbuf_append(buf, last);
2295              break;
2296           }
2297         if (!is_bool)
2298           {
2299              ERR("Using signal connection `%%{;}' with a property that is not boolean. Signal: `%s'; Property: `%s'.", signal, fetch);
2300              goto on_error;
2301           }
2302         eina_strbuf_append_length(buf, last, (size_t)(ini-last));
2303         const char *sep = strchr(ini+2, ';');
2304         if (!sep)
2305           {
2306              ERR("Could not find separator `;'.");
2307              goto on_error;
2308           }
2309         const char *fin = strchr(sep+1, '}');
2310         if (!fin)
2311           {
2312              ERR("Could not find terminator `}'.");
2313              goto on_error;
2314           }
2315         if (eval)
2316           eina_strbuf_append_length(buf, ini+2, (size_t)(sep-(ini+2)));
2317         else
2318           eina_strbuf_append_length(buf, sep+1, (size_t)(fin-(sep+1)));
2319         ini = fin+1;
2320      }
2321    eina_strbuf_replace_all(buf, "%v", value);
2322 
2323    elm_layout_signal_emit(pd->obj, eina_strbuf_string_get(buf),
2324                           elm_widget_is_legacy(pd->obj) ? "elm" : "efl");
2325 
2326 on_error:
2327    eina_strbuf_free(buf);
2328    eina_value_free(v);
2329    free(value);
2330 }
2331 
2332 typedef struct _Efl_Ui_Layout_Factory_Request Efl_Ui_Layout_Factory_Request;
2333 struct _Efl_Ui_Layout_Factory_Request
2334 {
2335    Efl_Ui_Layout_Factory_Tracking *tracking;
2336    Efl_Ui_Layout_Data *pd;
2337    Efl_Ui_Factory *factory;
2338    const char *key;
2339 };
2340 
2341 static Eina_Value
_content_created(Eo * obj,void * data,const Eina_Value value)2342 _content_created(Eo *obj, void *data, const Eina_Value value)
2343 {
2344    Efl_Ui_Layout_Factory_Request *request = data;
2345    Efl_Gfx_Entity *content = NULL;
2346    Efl_Gfx_Entity *old_content[1];
2347    int len, i;
2348 
2349    EINA_VALUE_ARRAY_FOREACH(&value, len, i, content)
2350      {
2351         // Recycle old content
2352         old_content[0] = efl_content_get(efl_part(obj, request->key));
2353         if (old_content[0]) efl_ui_factory_release(request->factory, EINA_C_ARRAY_ITERATOR_NEW(old_content));
2354 
2355         // Set new content
2356         efl_content_set(efl_part(obj, request->key), content);
2357      }
2358 
2359    return value;
2360 }
2361 
2362 static void
_clean_request(Eo * obj EINA_UNUSED,void * data,const Eina_Future * dead_future EINA_UNUSED)2363 _clean_request(Eo *obj EINA_UNUSED, void *data, const Eina_Future *dead_future EINA_UNUSED)
2364 {
2365    Efl_Ui_Layout_Factory_Request *request = data;
2366 
2367    request->tracking->in_flight = NULL;
2368    eina_stringshare_del(request->key);
2369    efl_unref(request->factory);
2370    free(request);
2371 }
2372 
2373 static void
_efl_ui_layout_view_model_content_update(Efl_Ui_Layout_Data * pd,Efl_Ui_Layout_Factory_Tracking * tracking,const char * key)2374 _efl_ui_layout_view_model_content_update(Efl_Ui_Layout_Data *pd, Efl_Ui_Layout_Factory_Tracking *tracking, const char *key)
2375 {
2376    Efl_Ui_Layout_Factory_Request *request;
2377    Eina_Future *f;
2378    Efl_Model *models[1];
2379 
2380    request = calloc(1, sizeof (Efl_Ui_Layout_Factory_Request));
2381    if (!request) return ;
2382 
2383    if (tracking->in_flight) eina_future_cancel(tracking->in_flight);
2384 
2385    request->key = eina_stringshare_ref(key);
2386    request->pd = pd;
2387    request->factory = efl_ref(tracking->factory);
2388    request->tracking = tracking;
2389 
2390    models[0] = efl_ui_view_model_get(pd->obj);
2391    f = efl_ui_view_factory_create_with_event(tracking->factory, EINA_C_ARRAY_ITERATOR_NEW(models));
2392    f = efl_future_then(pd->obj, f,
2393                        .success = _content_created,
2394                        .success_type = EINA_VALUE_TYPE_ARRAY,
2395                        .data = request,
2396                        .free = _clean_request);
2397 }
2398 
2399 static void
_efl_ui_layout_view_model_update(Efl_Ui_Layout_Data * pd)2400 _efl_ui_layout_view_model_update(Efl_Ui_Layout_Data *pd)
2401 {
2402    Eina_Hash_Tuple *tuple;
2403    Eina_Iterator *it;
2404 
2405    if (!efl_ui_view_model_get(pd->obj)) return ;
2406 
2407    it = eina_hash_iterator_tuple_new(pd->connect.properties);
2408    EINA_ITERATOR_FOREACH(it, tuple)
2409      _efl_ui_layout_view_model_property_update(pd, tuple->data, tuple->key);
2410    eina_iterator_free(it);
2411 
2412    it = eina_hash_iterator_tuple_new(pd->connect.signals);
2413    EINA_ITERATOR_FOREACH(it, tuple)
2414      _efl_ui_layout_view_model_signal_update(pd, tuple->data, tuple->key);
2415    eina_iterator_free(it);
2416 
2417    it = eina_hash_iterator_tuple_new(pd->connect.factories);
2418    EINA_ITERATOR_FOREACH(it, tuple)
2419      {
2420         Efl_Ui_Layout_Factory_Tracking *factory = tuple->data;
2421 
2422         _efl_ui_layout_view_model_content_update(pd, factory, tuple->key);
2423      }
2424    eina_iterator_free(it);
2425 }
2426 
2427 static void
_efl_model_properties_changed_cb(void * data,const Efl_Event * event)2428 _efl_model_properties_changed_cb(void *data, const Efl_Event *event)
2429 {
2430    Efl_Model_Property_Event *evt = event->info;
2431    Efl_Ui_Layout_Data *pd = data;
2432    const char *prop;
2433    Eina_Array_Iterator it;
2434    unsigned int i;
2435 
2436    if (!evt->changed_properties) return ;
2437 
2438    EINA_ARRAY_ITER_NEXT(evt->changed_properties, i, prop, it)
2439      {
2440         const char *part;
2441         const char *signal;
2442         Efl_Ui_Layout_Factory_Tracking *factory;
2443 
2444         part = eina_hash_find(pd->connect.properties, prop);
2445         if (part) _efl_ui_layout_view_model_property_update(pd, part, prop);
2446 
2447         signal = eina_hash_find(pd->connect.signals, prop);
2448         if (signal) _efl_ui_layout_view_model_signal_update(pd, signal, prop);
2449 
2450         factory = eina_hash_find(pd->connect.factories, prop);
2451         if (factory) _efl_ui_layout_view_model_content_update(pd, factory, prop);
2452      }
2453 }
2454 
2455 static void
_efl_ui_layout_factory_free(Efl_Ui_Layout_Factory_Tracking * tracking)2456 _efl_ui_layout_factory_free(Efl_Ui_Layout_Factory_Tracking *tracking)
2457 {
2458    if (tracking->in_flight) eina_future_cancel(tracking->in_flight);
2459    efl_unref(tracking->factory);
2460    eina_stringshare_del(tracking->key);
2461    free(tracking);
2462 }
2463 
2464 static void
_efl_ui_layout_connect_hash(Efl_Ui_Layout_Data * pd)2465 _efl_ui_layout_connect_hash(Efl_Ui_Layout_Data *pd)
2466 {
2467    if (pd->connect.properties) return ;
2468 
2469    pd->connect.properties = eina_hash_stringshared_new(EINA_FREE_CB(free)); // Hash of property targeting a part
2470    pd->connect.signals = eina_hash_stringshared_new(EINA_FREE_CB(free)); // Hash of property triggering a signal
2471    pd->connect.factories = eina_hash_stringshared_new(EINA_FREE_CB(_efl_ui_layout_factory_free)); // Hash of property triggering a content creation
2472 }
2473 
2474 
2475 static void
_efl_ui_layout_base_model_unregister(Eo * obj EINA_UNUSED,Efl_Ui_Layout_Data * pd,Efl_Model * model)2476 _efl_ui_layout_base_model_unregister(Eo *obj EINA_UNUSED, Efl_Ui_Layout_Data *pd,
2477                                      Efl_Model *model)
2478 {
2479    if (!model) return ;
2480    if (!pd->model_bound) return ;
2481 
2482    efl_event_callback_del(model, EFL_MODEL_EVENT_PROPERTIES_CHANGED,
2483                           _efl_model_properties_changed_cb, pd);
2484 
2485    pd->model_bound = EINA_FALSE;
2486 }
2487 
2488 static void
_efl_ui_layout_base_model_register(Eo * obj,Efl_Ui_Layout_Data * pd,Efl_Model * model)2489 _efl_ui_layout_base_model_register(Eo *obj, Efl_Ui_Layout_Data *pd,
2490                                    Efl_Model *model)
2491 {
2492    Eina_Stringshare *key;
2493    Eina_Hash_Tuple *tuple;
2494    Eina_Iterator *it;
2495 
2496    if (!model) return ;
2497    if (pd->model_bound) return;
2498    pd->model_bound = EINA_TRUE;
2499 
2500    efl_event_callback_add(model, EFL_MODEL_EVENT_PROPERTIES_CHANGED,
2501                           _efl_model_properties_changed_cb, pd);
2502 
2503    _efl_ui_layout_connect_hash(pd);
2504 
2505    // Reset to empty state
2506    it = eina_hash_iterator_key_new(pd->connect.properties);
2507    EINA_ITERATOR_FOREACH(it, key)
2508      {
2509         efl_text_set(efl_part(obj, key), NULL);
2510      }
2511    eina_iterator_free(it);
2512 
2513    it = eina_hash_iterator_tuple_new(pd->connect.factories);
2514    EINA_ITERATOR_FOREACH(it, tuple)
2515      {
2516         Efl_Ui_Layout_Factory_Tracking *factory;
2517         Efl_Gfx_Entity *content[1];
2518 
2519         key = tuple->key;
2520         factory = tuple->data;
2521 
2522         // Cancel in flight creation request
2523         if (factory->in_flight) eina_future_cancel(factory->in_flight);
2524 
2525         // Cleanup content
2526         content[0] = efl_content_get(efl_part(obj, key));
2527         efl_content_unset(efl_part(obj, key));
2528 
2529         // And recycle it
2530         if (content[0]) efl_ui_factory_release(factory->factory, EINA_C_ARRAY_ITERATOR_NEW(content));
2531      }
2532    eina_iterator_free(it);
2533 
2534    // Refresh content if necessary
2535    _efl_ui_layout_view_model_update(pd);
2536 }
2537 
2538 static void
_efl_ui_layout_base_model_update(void * data,const Efl_Event * event)2539 _efl_ui_layout_base_model_update(void *data, const Efl_Event *event)
2540 {
2541    Efl_Ui_Layout_Data *pd = data;
2542    Efl_Model_Changed_Event *ev = event->info;
2543 
2544    _efl_ui_layout_base_model_unregister(event->object, pd, ev->previous);
2545    _efl_ui_layout_base_model_register(event->object, pd, ev->current);
2546 }
2547 
2548 static void
_efl_ui_layout_base_model_watch(Eo * obj,Efl_Ui_Layout_Data * pd)2549 _efl_ui_layout_base_model_watch(Eo *obj, Efl_Ui_Layout_Data *pd)
2550 {
2551    Efl_Model *model;
2552 
2553    if (pd->model_watch) return ;
2554    pd->model_watch = EINA_TRUE;
2555 
2556    efl_event_callback_add(obj, EFL_UI_VIEW_EVENT_MODEL_CHANGED,
2557                           _efl_ui_layout_base_model_update, pd);
2558    model = efl_ui_view_model_get(obj);
2559    if (!model) return ;
2560    _efl_ui_layout_base_model_register(obj, pd, model);
2561 }
2562 
2563 EOLIAN static Eina_Error
_efl_ui_layout_base_efl_ui_property_bind_property_bind(Eo * obj,Efl_Ui_Layout_Data * pd,const char * key,const char * property)2564 _efl_ui_layout_base_efl_ui_property_bind_property_bind(Eo *obj, Efl_Ui_Layout_Data *pd, const char *key, const char *property)
2565 {
2566    EINA_SAFETY_ON_NULL_RETURN_VAL(key, EFL_PROPERTY_ERROR_INVALID_KEY);
2567    Eina_Stringshare *sprop;
2568    Eina_Stringshare *sk;
2569    Eina_Hash *hash = NULL;
2570    char *data = NULL;
2571    Efl_Model *model;
2572    Eina_Error r;
2573 
2574    // First try binding with property on the Widget
2575    r = efl_ui_property_bind(efl_super(obj, EFL_UI_LAYOUT_BASE_CLASS), key, property);
2576    if (!r) return r;
2577 
2578    // Before trying to bind on the part of this object.
2579    if (!_elm_layout_part_aliasing_eval(obj, &key, EINA_TRUE))
2580      return EFL_PROPERTY_ERROR_INVALID_KEY;
2581 
2582    // Check if there is a model and register it
2583    _efl_ui_layout_base_model_watch(obj, pd);
2584 
2585    _efl_ui_layout_connect_hash(pd);
2586 
2587    sprop = eina_stringshare_add(property);
2588 
2589    // FIXME: prevent double connect of key to multiple property ?
2590    if (strncmp(SIGNAL_PREFIX, key, sizeof(SIGNAL_PREFIX) - 1) == 0)
2591      {
2592         hash = pd->connect.signals;
2593         data = strdup(key + sizeof(SIGNAL_PREFIX) - 1);
2594      }
2595    else
2596      {
2597         hash = pd->connect.properties;
2598         data = strdup(key);
2599      }
2600 
2601    if (!sprop)
2602      {
2603         // FIXME: remove the entry from the hash ?
2604      }
2605    else
2606      {
2607         eina_hash_add(hash, sprop, data);
2608      }
2609 
2610    // Update display right away if possible
2611    model = efl_ui_view_model_get(obj);
2612    if (model)
2613      {
2614         if (hash == pd->connect.signals)
2615           _efl_ui_layout_view_model_signal_update(pd, data, sprop);
2616         else
2617           _efl_ui_layout_view_model_property_update(pd, data, sprop);
2618      }
2619 
2620    sk = eina_stringshare_add(key);
2621    efl_event_callback_call(obj, EFL_UI_PROPERTY_BIND_EVENT_PROPERTY_BOUND, (void*) sk);
2622    eina_stringshare_del(sk);
2623 
2624    if (!sprop)
2625      free(data);
2626 
2627    return 0;
2628 }
2629 
2630 EOLIAN static Eina_Error
_efl_ui_layout_base_efl_ui_factory_bind_factory_bind(Eo * obj EINA_UNUSED,Efl_Ui_Layout_Data * pd,const char * key,Efl_Ui_Factory * factory)2631 _efl_ui_layout_base_efl_ui_factory_bind_factory_bind(Eo *obj EINA_UNUSED, Efl_Ui_Layout_Data *pd,
2632                                                 const char *key, Efl_Ui_Factory *factory)
2633 {
2634    EINA_SAFETY_ON_NULL_RETURN_VAL(key, EFL_PROPERTY_ERROR_INVALID_KEY);
2635    Efl_Ui_Layout_Factory_Tracking *tracking;
2636    Eina_Stringshare *ss_key;
2637 
2638    if (!_elm_layout_part_aliasing_eval(obj, &key, EINA_TRUE))
2639      return EFL_PROPERTY_ERROR_INVALID_KEY;
2640 
2641    // Check if there is a model and register it
2642    _efl_ui_layout_base_model_watch(obj, pd);
2643 
2644    if (!pd->connect.factories)
2645      pd->connect.factories = eina_hash_stringshared_new(EINA_FREE_CB(_efl_ui_layout_factory_free));
2646 
2647    ss_key = eina_stringshare_add(key);
2648 
2649    // First undo the old one if there is one
2650    tracking = eina_hash_find(pd->connect.factories, ss_key);
2651    if (tracking)
2652      {
2653         Efl_Gfx_Entity *old[1];
2654 
2655         // Unset and recycle
2656         old[0] = efl_content_get(efl_part(obj, ss_key));
2657         efl_content_unset(efl_part(obj, ss_key));
2658         if (old[0]) efl_ui_factory_release(tracking->factory, EINA_C_ARRAY_ITERATOR_NEW(old));
2659 
2660         // Stop in flight request
2661         if (tracking->in_flight) eina_future_cancel(tracking->in_flight);
2662 
2663         // Release previous factory
2664         efl_replace(&tracking->factory, NULL);
2665      }
2666    else
2667      {
2668         tracking = calloc(1, sizeof (Efl_Ui_Layout_Factory_Tracking));
2669         if (!tracking) return ENOMEM;
2670 
2671         tracking->key = ss_key;
2672 
2673         eina_hash_add(pd->connect.factories, ss_key, tracking);
2674      }
2675 
2676    // And update content with the new factory
2677    tracking->factory = efl_ref(factory);
2678 
2679    _efl_ui_layout_view_model_content_update(pd, tracking, ss_key);
2680 
2681    return EINA_ERROR_NO_ERROR;
2682 }
2683 
2684 EOLIAN void
_efl_ui_layout_base_efl_ui_i18n_language_set(Eo * obj,Efl_Ui_Layout_Data * sd EINA_UNUSED,const char * locale)2685 _efl_ui_layout_base_efl_ui_i18n_language_set(Eo *obj, Efl_Ui_Layout_Data *sd EINA_UNUSED, const char *locale)
2686 {
2687    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
2688    efl_ui_language_set(wd->resize_obj, locale);
2689 }
2690 
2691 EOLIAN const char *
_efl_ui_layout_base_efl_ui_i18n_language_get(const Eo * obj,Efl_Ui_Layout_Data * sd EINA_UNUSED)2692 _efl_ui_layout_base_efl_ui_i18n_language_get(const Eo *obj, Efl_Ui_Layout_Data *sd EINA_UNUSED)
2693 {
2694    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, NULL);
2695    return efl_ui_language_get(wd->resize_obj);
2696 }
2697 
2698 EOLIAN static void
_efl_ui_layout_base_efl_ui_l10n_l10n_text_set(Eo * obj,Efl_Ui_Layout_Data * sd EINA_UNUSED,const char * label,const char * domain)2699 _efl_ui_layout_base_efl_ui_l10n_l10n_text_set(Eo *obj, Efl_Ui_Layout_Data *sd EINA_UNUSED, const char *label, const char *domain)
2700 {
2701    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
2702    efl_ui_l10n_text_set(efl_part(obj, efl_ui_widget_default_text_part_get(obj)), label, domain);
2703 }
2704 
2705 EOLIAN static const char *
_efl_ui_layout_base_efl_ui_l10n_l10n_text_get(const Eo * obj,Efl_Ui_Layout_Data * sd EINA_UNUSED,const char ** domain)2706 _efl_ui_layout_base_efl_ui_l10n_l10n_text_get(const Eo *obj, Efl_Ui_Layout_Data *sd EINA_UNUSED, const char **domain)
2707 {
2708   ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, NULL);
2709   return efl_ui_l10n_text_get(efl_part(obj, efl_ui_widget_default_text_part_get(obj)), domain);
2710 }
2711 
2712 EOLIAN static Eo *
_efl_ui_layout_efl_object_constructor(Eo * obj,void * _pd EINA_UNUSED)2713 _efl_ui_layout_efl_object_constructor(Eo *obj, void *_pd EINA_UNUSED)
2714 {
2715    obj = efl_constructor(efl_super(obj, EFL_UI_LAYOUT_CLASS));
2716    Efl_Ui_Layout_Data *sd = efl_data_scope_get(obj, MY_CLASS);
2717 
2718    /* basic layouts should not obey finger size */
2719    sd->finger_size_multiplier_x = sd->finger_size_multiplier_y = 0;
2720 
2721    return obj;
2722 }
2723 
2724 EOLIAN static Eo *
_efl_ui_layout_base_efl_object_constructor(Eo * obj,Efl_Ui_Layout_Data * sd)2725 _efl_ui_layout_base_efl_object_constructor(Eo *obj, Efl_Ui_Layout_Data *sd)
2726 {
2727    sd->obj = obj;
2728    sd->needs_theme_apply = EINA_TRUE;
2729    sd->finger_size_multiplier_x = sd->finger_size_multiplier_y = 1;
2730    obj = efl_constructor(efl_super(obj, MY_CLASS));
2731    evas_object_smart_callbacks_descriptions_set(obj, _smart_callbacks);
2732    efl_access_object_role_set(obj, EFL_ACCESS_ROLE_FILLER);
2733 
2734    return obj;
2735 }
2736 
2737 EOLIAN static Efl_Object*
_efl_ui_layout_base_efl_object_finalize(Eo * obj,Efl_Ui_Layout_Data * pd)2738 _efl_ui_layout_base_efl_object_finalize(Eo *obj, Efl_Ui_Layout_Data *pd)
2739 {
2740    Eo *eo, *win;
2741    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, NULL);
2742    eo = efl_finalize(efl_super(obj, MY_CLASS));
2743    if (pd->needs_theme_apply)
2744      {
2745         efl_ui_widget_theme_apply(eo);
2746         /* handle case where subclass does not call into layout */
2747         pd->needs_theme_apply = EINA_FALSE;
2748      }
2749    else if (pd->deferred_signals)
2750      _deferred_signals_emit(pd);
2751    efl_canvas_group_change(obj);
2752 
2753    Elm_Layout_Data *ld = efl_data_scope_safe_get(obj, ELM_LAYOUT_MIXIN);
2754    /* need to explicitly set this here to permit group_calc since efl_canvas_group_change
2755     * blocks non-finalized objects and the object will not be finalized until after this
2756     * function returns
2757     */
2758    if (ld) ld->needs_size_calc = EINA_TRUE;
2759 
2760    win = elm_widget_top_get(obj);
2761    if (efl_isa(win, EFL_UI_WIN_CLASS))
2762      efl_ui_layout_theme_rotation_apply(obj, efl_ui_win_rotation_get(win));
2763 
2764    if (efl_file_get(wd->resize_obj) || efl_file_mmap_get(wd->resize_obj))
2765      efl_file_load(wd->resize_obj);
2766 
2767    return eo;
2768 }
2769 
2770 static void
_efl_ui_layout_base_efl_object_invalidate(Eo * obj,Efl_Ui_Layout_Data * pd)2771 _efl_ui_layout_base_efl_object_invalidate(Eo *obj, Efl_Ui_Layout_Data *pd)
2772 {
2773    if (pd->model_watch)
2774      {
2775         Efl_Model *model;
2776 
2777         pd->model_watch = EINA_FALSE;
2778         efl_event_callback_del(obj, EFL_UI_VIEW_EVENT_MODEL_CHANGED,
2779                                _efl_ui_layout_base_model_update, pd);
2780 
2781         model = efl_ui_view_model_get(obj);
2782         if (!model)
2783           {
2784              _efl_ui_layout_base_model_unregister(obj, pd, model);
2785           }
2786      }
2787 
2788    efl_invalidate(efl_super(obj, EFL_UI_LAYOUT_BASE_CLASS));
2789 }
2790 
2791 EOLIAN static void
_efl_ui_layout_base_efl_layout_signal_message_send(Eo * obj,Efl_Ui_Layout_Data * pd EINA_UNUSED,int id,const Eina_Value msg)2792 _efl_ui_layout_base_efl_layout_signal_message_send(Eo *obj, Efl_Ui_Layout_Data *pd EINA_UNUSED, int id, const Eina_Value msg)
2793 {
2794    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
2795    efl_layout_signal_message_send(wd->resize_obj, id, msg);
2796 }
2797 
2798 EOLIAN static void
_efl_ui_layout_base_efl_layout_signal_signal_process(Eo * obj,Efl_Ui_Layout_Data * pd EINA_UNUSED,Eina_Bool recurse)2799 _efl_ui_layout_base_efl_layout_signal_signal_process(Eo *obj, Efl_Ui_Layout_Data *pd EINA_UNUSED, Eina_Bool recurse)
2800 {
2801    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
2802    efl_layout_signal_process(wd->resize_obj, recurse);
2803 }
2804 
2805 /* Efl.Part implementation */
2806 
2807 EOLIAN static Eo *
_efl_ui_layout_base_efl_part_part_get(const Eo * obj,Efl_Ui_Layout_Data * sd EINA_UNUSED,const char * part)2808 _efl_ui_layout_base_efl_part_part_get(const Eo *obj, Efl_Ui_Layout_Data *sd EINA_UNUSED, const char *part)
2809 {
2810    Efl_Canvas_Layout_Part_Type type = EFL_CANVAS_LAYOUT_PART_TYPE_NONE;
2811 
2812    EINA_SAFETY_ON_NULL_RETURN_VAL(part, NULL);
2813    ELM_WIDGET_DATA_GET_OR_RETURN((Eo *) obj, wd, NULL);
2814 
2815    // Check part type without using edje_object_part_object_get(), as this
2816    // can cause recalc, which has side effects... and could be slow.
2817 
2818    if (!elm_widget_is_legacy(obj))
2819      {
2820         if (eina_streq(part, "background"))
2821           {
2822              if (efl_layout_group_part_exist_get(wd->resize_obj, "efl.background"))
2823                type = efl_canvas_layout_part_type_get(efl_part(wd->resize_obj, "efl.background"));
2824              if (type != EFL_CANVAS_LAYOUT_PART_TYPE_SWALLOW)
2825                {
2826                   if (type < EFL_CANVAS_LAYOUT_PART_TYPE_LAST &&
2827                       type > EFL_CANVAS_LAYOUT_PART_TYPE_NONE)
2828                     {
2829                        const char *file = NULL, *key = NULL;
2830                        efl_file_simple_get(wd->resize_obj, &file, &key);
2831                        WRN("Layout has a background but it's not a swallow: '%s'",
2832                            elm_widget_theme_element_get(obj));
2833                     }
2834                   return efl_part_get(efl_super(obj, MY_CLASS), part);
2835                }
2836 
2837              return ELM_PART_IMPLEMENT(EFL_UI_LAYOUT_PART_BG_CLASS, obj, part);
2838           }
2839         else if (eina_streq(part, "shadow"))
2840           return efl_part_get(efl_super(obj, MY_CLASS), part);
2841      }
2842 
2843    if (!efl_layout_group_part_exist_get(wd->resize_obj, part))
2844      {
2845         // edje part will handle the error message
2846         return efl_part_get(wd->resize_obj, part);
2847      }
2848 
2849    type = efl_canvas_layout_part_type_get(efl_part(wd->resize_obj, part));
2850    if (type >= EFL_CANVAS_LAYOUT_PART_TYPE_LAST)
2851      {
2852         ERR("Invalid type found for part '%s' in group '%s'",
2853             part, elm_widget_theme_element_get(obj));
2854         return NULL;
2855      }
2856 
2857    switch (type)
2858      {
2859       case EFL_CANVAS_LAYOUT_PART_TYPE_BOX:
2860       case EFL_CANVAS_LAYOUT_PART_TYPE_TABLE:
2861         return _efl_ui_layout_pack_proxy_get((Eo *) obj, (Edje_Part_Type)type, part);
2862       case EFL_CANVAS_LAYOUT_PART_TYPE_TEXT:
2863       case EFL_CANVAS_LAYOUT_PART_TYPE_TEXTBLOCK:
2864         return ELM_PART_IMPLEMENT(EFL_UI_LAYOUT_PART_TEXT_CLASS, obj, part);
2865       case EFL_CANVAS_LAYOUT_PART_TYPE_SWALLOW:
2866         return ELM_PART_IMPLEMENT(EFL_UI_LAYOUT_PART_CONTENT_CLASS, obj, part);
2867       default:
2868         return ELM_PART_IMPLEMENT(EFL_UI_LAYOUT_PART_CLASS, obj, part);
2869      }
2870 }
2871 
2872 static const char *
_efl_ui_layout_base_default_content_part_get(const Eo * obj,Efl_Ui_Layout_Data * sd EINA_UNUSED)2873 _efl_ui_layout_base_default_content_part_get(const Eo *obj, Efl_Ui_Layout_Data *sd EINA_UNUSED)
2874 {
2875    const char *part = NULL;
2876    if (!_elm_layout_part_aliasing_eval(obj, &part, EINA_FALSE))
2877      return NULL;
2878    return part;
2879 }
2880 
2881 static const char *
_efl_ui_layout_base_default_text_part_get(const Eo * obj,Efl_Ui_Layout_Data * sd EINA_UNUSED)2882 _efl_ui_layout_base_default_text_part_get(const Eo *obj, Efl_Ui_Layout_Data *sd EINA_UNUSED)
2883 {
2884    const char *part = NULL;
2885    if (!_elm_layout_part_aliasing_eval(obj, &part, EINA_TRUE))
2886      return NULL;
2887    return part;
2888 }
2889 
2890 #define CONTENT_FULL(part_typename, typename, CLASS, TYPENAME) \
2891   ELM_PART_OVERRIDE_CONTENT_GET_FULL(part_typename, typename, ELM_PART_OVERRIDE_INTERNALS_FETCH(CLASS, TYPENAME)) \
2892   ELM_PART_OVERRIDE_CONTENT_SET_FULL(part_typename, typename, ELM_PART_OVERRIDE_INTERNALS_FETCH(CLASS, TYPENAME)) \
2893   ELM_PART_OVERRIDE_CONTENT_UNSET_FULL(part_typename, typename, ELM_PART_OVERRIDE_INTERNALS_FETCH(CLASS, TYPENAME))
2894 
2895 
2896 #define TEXT_FULL(part_typename, typename, CLASS, TYPENAME) \
2897   ELM_PART_OVERRIDE_TEXT_TEXT_GET_FULL(part_typename, typename, ELM_PART_OVERRIDE_INTERNALS_FETCH(CLASS, TYPENAME)) \
2898   ELM_PART_OVERRIDE_TEXT_TEXT_SET_FULL(part_typename, typename, ELM_PART_OVERRIDE_INTERNALS_FETCH(CLASS, TYPENAME)) \
2899 
2900 
2901 #define MARKUP_FULL(part_typename, typename, CLASS, TYPENAME) \
2902   ELM_PART_OVERRIDE_TEXT_MARKUP_GET_FULL(part_typename, typename, ELM_PART_OVERRIDE_INTERNALS_FETCH(CLASS, TYPENAME)) \
2903   ELM_PART_OVERRIDE_TEXT_MARKUP_SET_FULL(part_typename, typename, ELM_PART_OVERRIDE_INTERNALS_FETCH(CLASS, TYPENAME)) \
2904 
2905 /* Efl.Ui.Layout_Part_Content */
CONTENT_FULL(efl_ui_layout_part_content,efl_ui_layout,EFL_UI_LAYOUT_BASE,Efl_Ui_Layout_Data)2906 CONTENT_FULL(efl_ui_layout_part_content, efl_ui_layout, EFL_UI_LAYOUT_BASE, Efl_Ui_Layout_Data)
2907 
2908 /* Efl.Ui.Layout_Part_Text */
2909 TEXT_FULL(efl_ui_layout_part_text, efl_ui_layout, EFL_UI_LAYOUT_BASE, Efl_Ui_Layout_Data)
2910 MARKUP_FULL(efl_ui_layout_part_text, efl_ui_layout, EFL_UI_LAYOUT_BASE, Efl_Ui_Layout_Data)
2911 
2912 EOLIAN static const char *
2913 _efl_ui_layout_part_text_efl_ui_l10n_l10n_text_get(const Eo *obj, void *_pd EINA_UNUSED, const char **domain)
2914 {
2915    Elm_Part_Data *pd = efl_data_scope_get(obj, EFL_UI_WIDGET_PART_CLASS);
2916    return elm_widget_part_translatable_text_get(pd->obj, pd->part, domain);
2917 }
2918 
2919 EOLIAN static void
_efl_ui_layout_part_text_efl_ui_l10n_l10n_text_set(Eo * obj,void * _pd EINA_UNUSED,const char * label,const char * domain)2920 _efl_ui_layout_part_text_efl_ui_l10n_l10n_text_set(Eo *obj, void *_pd EINA_UNUSED, const char *label, const char *domain)
2921 {
2922    Elm_Part_Data *pd = efl_data_scope_get(obj, EFL_UI_WIDGET_PART_CLASS);
2923    elm_widget_part_translatable_text_set(pd->obj, pd->part, label, domain);
2924 }
2925 
2926 /* Efl.Ui.Layout_Part_Legacy */
CONTENT_FULL(efl_ui_layout_part_legacy,efl_ui_layout,EFL_UI_LAYOUT_BASE,Efl_Ui_Layout_Data)2927 CONTENT_FULL(efl_ui_layout_part_legacy, efl_ui_layout, EFL_UI_LAYOUT_BASE, Efl_Ui_Layout_Data)
2928 TEXT_FULL(efl_ui_layout_part_legacy, efl_ui_layout, EFL_UI_LAYOUT_BASE, Efl_Ui_Layout_Data)
2929 MARKUP_FULL(efl_ui_layout_part_legacy, efl_ui_layout, EFL_UI_LAYOUT_BASE, Efl_Ui_Layout_Data)
2930 
2931 EOLIAN static const char *
2932 _efl_ui_layout_part_legacy_efl_ui_l10n_l10n_text_get(const Eo *obj, void *_pd EINA_UNUSED, const char **domain)
2933 {
2934    Elm_Part_Data *pd = efl_data_scope_get(obj, EFL_UI_WIDGET_PART_CLASS);
2935    return elm_widget_part_translatable_text_get(pd->obj, pd->part, domain);
2936 }
2937 
2938 EOLIAN static void
_efl_ui_layout_part_legacy_efl_ui_l10n_l10n_text_set(Eo * obj,void * _pd EINA_UNUSED,const char * label,const char * domain)2939 _efl_ui_layout_part_legacy_efl_ui_l10n_l10n_text_set(Eo *obj, void *_pd EINA_UNUSED, const char *label, const char *domain)
2940 {
2941    Elm_Part_Data *pd = efl_data_scope_get(obj, EFL_UI_WIDGET_PART_CLASS);
2942    elm_widget_part_translatable_text_set(pd->obj, pd->part, label, domain);
2943 }
2944 
2945 /* Efl.Ui.Layout_Part_Bg (common) */
2946 
2947 EOLIAN static Efl_Object *
_efl_ui_layout_part_bg_efl_object_finalize(Eo * obj,void * _pd EINA_UNUSED)2948 _efl_ui_layout_part_bg_efl_object_finalize(Eo *obj, void *_pd EINA_UNUSED)
2949 {
2950    Efl_Ui_Layout_Data *sd;
2951    Elm_Part_Data *pd;
2952    Eo *bg;
2953 
2954    obj = efl_finalize(efl_super(obj, EFL_UI_LAYOUT_PART_BG_CLASS));
2955    if (!obj) return NULL;
2956 
2957    pd = efl_data_scope_get(obj, EFL_UI_WIDGET_PART_CLASS);
2958    sd = efl_data_scope_get(pd->obj, MY_CLASS);
2959    bg = _efl_ui_widget_bg_get(pd->obj);
2960    if (!_efl_ui_layout_content_set(pd->obj, sd, "efl.background", bg))
2961      {
2962         ERR("Failed to swallow new background object!");
2963         // Shouldn't happen. What now? del bg? call super? return null?
2964      }
2965 
2966    return obj;
2967 }
2968 
2969 EOLIAN static void
_efl_ui_layout_base_automatic_theme_rotation_set(Eo * obj,Efl_Ui_Layout_Data * pd,Eina_Bool automatic)2970 _efl_ui_layout_base_automatic_theme_rotation_set(Eo *obj, Efl_Ui_Layout_Data *pd, Eina_Bool automatic)
2971 {
2972    if (pd->automatic_orientation_apply == automatic) return;
2973    pd->automatic_orientation_apply = automatic;
2974 
2975    efl_ui_layout_theme_rotation_apply(obj, efl_ui_win_rotation_get(elm_widget_top_get(obj)));
2976 }
2977 
2978 EOLIAN static Eina_Bool
_efl_ui_layout_base_automatic_theme_rotation_get(const Eo * obj EINA_UNUSED,Efl_Ui_Layout_Data * pd)2979 _efl_ui_layout_base_automatic_theme_rotation_get(const Eo *obj EINA_UNUSED, Efl_Ui_Layout_Data *pd)
2980 {
2981    return pd->automatic_orientation_apply;
2982 }
2983 
2984 EOLIAN static void
_efl_ui_layout_base_theme_rotation_apply(Eo * obj,Efl_Ui_Layout_Data * pd EINA_UNUSED,int orientation)2985 _efl_ui_layout_base_theme_rotation_apply(Eo *obj, Efl_Ui_Layout_Data *pd EINA_UNUSED, int orientation)
2986 {
2987    char prefix[4], buf[128];
2988 
2989    if (elm_widget_is_legacy(obj))
2990      snprintf(prefix, sizeof(prefix), "elm");
2991    else
2992      snprintf(prefix, sizeof(prefix), "efl");
2993    snprintf(buf, sizeof(buf), "%s,state,orient,%d", prefix, (int)orientation);
2994    efl_layout_signal_emit(obj, buf, prefix);
2995 }
2996 
2997 
2998 /* Efl.Ui.Layout_Part_Xxx includes */
2999 #include "efl_ui_layout_part.eo.c"
3000 #include "efl_ui_layout_part_content.eo.c"
3001 #include "efl_ui_layout_part_bg.eo.c"
3002 #include "efl_ui_layout_part_text.eo.c"
3003 #include "efl_ui_layout_part_legacy.eo.c"
3004 
3005 /* Efl.Part end */
3006 
3007 
3008 /* Internal EO APIs and hidden overrides */
3009 EOLIAN static Eina_Bool
_efl_ui_layout_base_efl_object_event_callback_priority_add(Eo * obj,Efl_Ui_Layout_Data * pd,const Efl_Event_Description * desc,Efl_Callback_Priority priority,Efl_Event_Cb func,const void * user_data)3010 _efl_ui_layout_base_efl_object_event_callback_priority_add(Eo *obj, Efl_Ui_Layout_Data *pd, const Efl_Event_Description *desc, Efl_Callback_Priority priority, Efl_Event_Cb func, const void *user_data)
3011 {
3012   if (desc == EFL_UI_LAYOUT_EVENT_THEME_CHANGED)
3013     {
3014        pd->cb_theme_changed = EINA_TRUE;
3015     }
3016 
3017   return efl_event_callback_priority_add(efl_super(obj, MY_CLASS), desc, priority, func, user_data);
3018 }
3019 
3020 EOLIAN static Eina_Bool
_efl_ui_layout_base_efl_object_event_callback_array_priority_add(Eo * obj,Efl_Ui_Layout_Data * pd,const Efl_Callback_Array_Item * array,Efl_Callback_Priority priority,const void * user_data)3021 _efl_ui_layout_base_efl_object_event_callback_array_priority_add(Eo *obj, Efl_Ui_Layout_Data *pd, const Efl_Callback_Array_Item *array, Efl_Callback_Priority priority, const void *user_data)
3022 {
3023    for (int i = 0; array[i].desc; ++i)
3024      {
3025         if (array[i].desc == EFL_UI_LAYOUT_EVENT_THEME_CHANGED)
3026           {
3027              pd->cb_theme_changed = EINA_TRUE;
3028           }
3029      }
3030    return efl_event_callback_array_priority_add(efl_super(obj, MY_CLASS), array, priority, user_data);
3031 }
3032 
EFL_FUNC_BODY_CONST(efl_ui_layout_text_aliases_get,const Elm_Layout_Part_Alias_Description *,NULL)3033 EFL_FUNC_BODY_CONST(efl_ui_layout_text_aliases_get, const Elm_Layout_Part_Alias_Description *, NULL)
3034 EFL_FUNC_BODY_CONST(efl_ui_layout_content_aliases_get, const Elm_Layout_Part_Alias_Description *, NULL)
3035 
3036 EFL_UI_LAYOUT_CONTENT_ALIASES_IMPLEMENT(MY_CLASS_PFX)
3037 EFL_UI_LAYOUT_TEXT_ALIASES_IMPLEMENT(MY_CLASS_PFX)
3038 
3039 #define EFL_UI_LAYOUT_BASE_EXTRA_OPS \
3040    EFL_CANVAS_GROUP_ADD_DEL_OPS(efl_ui_layout_base), \
3041    ELM_PART_CONTENT_DEFAULT_OPS(efl_ui_layout_base), \
3042    ELM_PART_TEXT_DEFAULT_OPS(efl_ui_layout_base), \
3043    EFL_UI_LAYOUT_CONTENT_ALIASES_OPS(MY_CLASS_PFX), \
3044    EFL_UI_LAYOUT_TEXT_ALIASES_OPS(MY_CLASS_PFX), \
3045    EFL_OBJECT_OP_FUNC(efl_event_callback_priority_add, _efl_ui_layout_base_efl_object_event_callback_priority_add), \
3046    EFL_OBJECT_OP_FUNC(efl_event_callback_array_priority_add, _efl_ui_layout_base_efl_object_event_callback_array_priority_add), \
3047    EFL_OBJECT_OP_FUNC(efl_dbg_info_get, _efl_ui_layout_base_efl_object_dbg_info_get)
3048 
3049 
3050 #include "efl_ui_layout_base.eo.c"
3051 #include "efl_ui_layout.eo.c"
3052 
3053 #include "efl_ui_layout_legacy_eo.h"
3054 
3055 
3056 EOLIAN static Eo *
3057 _efl_ui_layout_legacy_efl_object_constructor(Eo *obj, void *pd EINA_UNUSED)
3058 {
3059    obj = efl_constructor(efl_super(obj, EFL_UI_LAYOUT_LEGACY_CLASS));
3060    efl_canvas_object_type_set(obj, MY_CLASS_NAME_LEGACY);
3061    return obj;
3062 }
3063 
3064 EAPI Evas_Object *
elm_layout_add(Evas_Object * parent)3065 elm_layout_add(Evas_Object *parent)
3066 {
3067    EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
3068    return elm_legacy_add(EFL_UI_LAYOUT_LEGACY_CLASS, parent);
3069 }
3070 
3071 EAPI Eina_Bool
elm_layout_file_set(Eo * obj,const char * file,const char * group)3072 elm_layout_file_set(Eo *obj, const char *file, const char *group)
3073 {
3074    return efl_file_simple_load((Eo *) obj, file, group);
3075 }
3076 
3077 EAPI void
elm_layout_file_get(Eo * obj,const char ** file,const char ** group)3078 elm_layout_file_get(Eo *obj, const char **file, const char **group)
3079 {
3080    efl_file_simple_get((Eo *) obj, file, group);
3081 }
3082 
3083 EAPI Eina_Bool
elm_layout_mmap_set(Eo * obj,const Eina_File * file,const char * group)3084 elm_layout_mmap_set(Eo *obj, const Eina_File *file, const char *group)
3085 {
3086    return efl_file_simple_mmap_load((Eo *) obj, file, group);
3087 }
3088 
3089 EAPI void
elm_layout_mmap_get(Eo * obj,const Eina_File ** file,const char ** group)3090 elm_layout_mmap_get(Eo *obj, const Eina_File **file, const char **group)
3091 {
3092    efl_file_simple_mmap_get((Eo *) obj, file, group);
3093 }
3094 
3095 EAPI Eina_Bool
elm_layout_box_append(Eo * obj,const char * part,Evas_Object * child)3096 elm_layout_box_append(Eo *obj, const char *part, Evas_Object *child)
3097 {
3098    return efl_pack(efl_part(obj, part), child);
3099 }
3100 
3101 EAPI Eina_Bool
elm_layout_box_prepend(Eo * obj,const char * part,Evas_Object * child)3102 elm_layout_box_prepend(Eo *obj, const char *part, Evas_Object *child)
3103 {
3104    return efl_pack_begin(efl_part(obj, part), child);
3105 }
3106 
3107 EAPI Eina_Bool
elm_layout_box_insert_before(Eo * obj,const char * part,Evas_Object * child,const Evas_Object * reference)3108 elm_layout_box_insert_before(Eo *obj, const char *part, Evas_Object *child, const Evas_Object *reference)
3109 {
3110    return efl_pack_before(efl_part(obj, part), child, reference);
3111 }
3112 
3113 EAPI Eina_Bool
elm_layout_box_insert_at(Eo * obj,const char * part,Evas_Object * child,unsigned int pos)3114 elm_layout_box_insert_at(Eo *obj, const char *part, Evas_Object *child, unsigned int pos)
3115 {
3116    return efl_pack_at(efl_part(obj, part), child, pos);
3117 }
3118 
3119 EAPI Evas_Object *
elm_layout_box_remove(Eo * obj,const char * part,Evas_Object * child)3120 elm_layout_box_remove(Eo *obj, const char *part, Evas_Object *child)
3121 {
3122    if (!efl_pack_unpack(efl_part(obj, part), child))
3123      return NULL;
3124    return child;
3125 }
3126 
3127 EAPI Eina_Bool
elm_layout_box_remove_all(Eo * obj,const char * part,Eina_Bool clear)3128 elm_layout_box_remove_all(Eo *obj, const char *part, Eina_Bool clear)
3129 {
3130    if (clear)
3131      return efl_pack_clear(efl_part(obj, part));
3132    else
3133      return efl_pack_unpack_all(efl_part(obj, part));
3134 }
3135 
3136 EAPI Eina_Bool
elm_layout_table_pack(Eo * obj,const char * part,Evas_Object * child,unsigned short col,unsigned short row,unsigned short colspan,unsigned short rowspan)3137 elm_layout_table_pack(Eo *obj, const char *part, Evas_Object *child, unsigned short col, unsigned short row, unsigned short colspan, unsigned short rowspan)
3138 {
3139    return efl_pack_table(efl_part(obj, part), child, col, row, colspan, rowspan);
3140 }
3141 
3142 EAPI Evas_Object *
elm_layout_table_unpack(Eo * obj,const char * part,Evas_Object * child)3143 elm_layout_table_unpack(Eo *obj, const char *part, Evas_Object *child)
3144 {
3145    if (!efl_pack_unpack(efl_part(obj, part), child))
3146      return NULL;
3147    return child;
3148 }
3149 
3150 EAPI Eina_Bool
elm_layout_table_clear(Eo * obj,const char * part,Eina_Bool clear)3151 elm_layout_table_clear(Eo *obj, const char *part, Eina_Bool clear)
3152 {
3153    if (clear)
3154      return efl_pack_clear(efl_part(obj, part));
3155    else
3156      return efl_pack_unpack_all(efl_part(obj, part));
3157 }
3158 
3159 EAPI Eina_Bool
elm_layout_text_set(Eo * obj,const char * part,const char * text)3160 elm_layout_text_set(Eo *obj, const char *part, const char *text)
3161 {
3162    Eo *part_obj;
3163 
3164    if (efl_invalidating_get(obj) || efl_invalidated_get(obj)) return EINA_FALSE;
3165 
3166    if (!part)
3167      {
3168         part = efl_ui_widget_default_text_part_get(obj);
3169         if (!part) return EINA_FALSE;
3170      }
3171    else if (!_elm_layout_part_aliasing_eval(obj, &part, EINA_TRUE))
3172      return EINA_FALSE;
3173 
3174    part_obj = efl_ref(efl_part(obj, part));
3175 
3176    if (!efl_isa(part_obj, EFL_TEXT_INTERFACE) ||
3177        !efl_isa(part_obj, EFL_UI_LAYOUT_PART_CLASS))
3178      {
3179         efl_unref(part_obj);
3180         return EINA_FALSE;
3181      }
3182 
3183    efl_text_set(part_obj, text);
3184 
3185    efl_unref(part_obj);
3186 
3187    return EINA_TRUE;
3188 }
3189 
3190 EAPI const char *
elm_layout_text_get(const Eo * obj,const char * part)3191 elm_layout_text_get(const Eo *obj, const char *part)
3192 {
3193    if (!part)
3194      {
3195         part = efl_ui_widget_default_text_part_get(obj);
3196         if (!part) return NULL;
3197      }
3198    else if (!_elm_layout_part_aliasing_eval(obj, &part, EINA_TRUE))
3199      return NULL;
3200 
3201    return efl_text_get(efl_part(obj, part));
3202 }
3203 
3204 EAPI Eina_Bool
elm_layout_part_cursor_engine_only_set(Eo * obj,const char * part,Eina_Bool engine_only)3205 elm_layout_part_cursor_engine_only_set(Eo *obj, const char *part, Eina_Bool engine_only)
3206 {
3207    Efl_Ui_Layout_Data *sd = efl_data_scope_get(obj, MY_CLASS);
3208    EINA_SAFETY_ON_NULL_RETURN_VAL(sd, EINA_FALSE);
3209    return _efl_ui_layout_part_cursor_engine_only_set(sd, part, engine_only);
3210 }
3211 
3212 EAPI Eina_Bool
elm_layout_part_cursor_engine_only_get(const Eo * obj,const char * part)3213 elm_layout_part_cursor_engine_only_get(const Eo *obj, const char *part)
3214 {
3215    Efl_Ui_Layout_Data *sd = efl_data_scope_get(obj, MY_CLASS);
3216    EINA_SAFETY_ON_NULL_RETURN_VAL(sd, EINA_FALSE);
3217    return _efl_ui_layout_part_cursor_engine_only_get(sd, part);
3218 }
3219 
3220 EAPI Eina_Bool
elm_layout_part_cursor_set(Eo * obj,const char * part,const char * cursor)3221 elm_layout_part_cursor_set(Eo *obj, const char *part, const char *cursor)
3222 {
3223    Efl_Ui_Layout_Data *sd = efl_data_scope_get(obj, MY_CLASS);
3224    EINA_SAFETY_ON_NULL_RETURN_VAL(sd, EINA_FALSE);
3225    return _efl_ui_layout_part_cursor_set(sd, part, cursor);
3226 }
3227 
3228 EAPI const char *
elm_layout_part_cursor_get(const Eo * obj,const char * part)3229 elm_layout_part_cursor_get(const Eo *obj, const char *part)
3230 {
3231    Efl_Ui_Layout_Data *sd = efl_data_scope_get(obj, MY_CLASS);
3232    EINA_SAFETY_ON_NULL_RETURN_VAL(sd, NULL);
3233    return _efl_ui_layout_part_cursor_get(sd, part);
3234 }
3235 
3236 EAPI Eina_Bool
elm_layout_part_cursor_style_set(Eo * obj,const char * part,const char * style)3237 elm_layout_part_cursor_style_set(Eo *obj, const char *part, const char *style)
3238 {
3239    Efl_Ui_Layout_Data *sd = efl_data_scope_get(obj, MY_CLASS);
3240    EINA_SAFETY_ON_NULL_RETURN_VAL(sd, EINA_FALSE);
3241    return _efl_ui_layout_part_cursor_style_set(sd, part, style);
3242 }
3243 
3244 EAPI const char *
elm_layout_part_cursor_style_get(const Eo * obj,const char * part)3245 elm_layout_part_cursor_style_get(const Eo *obj, const char *part)
3246 {
3247    Efl_Ui_Layout_Data *sd = efl_data_scope_get(obj, MY_CLASS);
3248    EINA_SAFETY_ON_NULL_RETURN_VAL(sd, NULL);
3249    return _efl_ui_layout_part_cursor_style_get(sd, part);
3250 }
3251 
3252 EAPI Eina_Bool
elm_layout_part_cursor_unset(Eo * obj,const char * part)3253 elm_layout_part_cursor_unset(Eo *obj, const char *part)
3254 {
3255    Efl_Ui_Layout_Data *sd = efl_data_scope_get(obj, MY_CLASS);
3256    EINA_SAFETY_ON_NULL_RETURN_VAL(sd, EINA_FALSE);
3257    return _efl_ui_layout_part_cursor_set(sd, part, NULL);
3258 }
3259 
3260 EAPI int
elm_layout_freeze(Evas_Object * obj)3261 elm_layout_freeze(Evas_Object *obj)
3262 {
3263    return efl_layout_calc_freeze(obj);
3264 }
3265 
3266 EAPI int
elm_layout_thaw(Evas_Object * obj)3267 elm_layout_thaw(Evas_Object *obj)
3268 {
3269    return efl_layout_calc_thaw(obj);
3270 }
3271 
3272 void
_elm_layout_signal_callback_add_legacy(Eo * obj,Eo * edje,Eina_List ** p_edje_signals,const char * emission,const char * source,Edje_Signal_Cb func,void * data)3273 _elm_layout_signal_callback_add_legacy(Eo *obj, Eo *edje, Eina_List **p_edje_signals,
3274                                        const char *emission, const char *source,
3275                                        Edje_Signal_Cb func, void *data)
3276 {
3277    Edje_Signal_Data *esd;
3278 
3279    esd = ELM_NEW(Edje_Signal_Data);
3280    if (!esd) return;
3281 
3282    esd->obj = obj;
3283    esd->func = func;
3284    esd->emission = eina_stringshare_add(emission);
3285    esd->source = eina_stringshare_add(source);
3286    esd->data = data;
3287    *p_edje_signals = eina_list_append(*p_edje_signals, esd);
3288 
3289    edje_object_signal_callback_add(edje, emission, source,
3290                                          _edje_signal_callback, esd);
3291 }
3292 
3293 /* replicated from elm_layout just because legacy widget's icon spot
3294  * is elm.swallow.content, not elm.swallow.icon.
3295  */
3296 void
_elm_layout_legacy_icon_signal_emit(Evas_Object * obj)3297 _elm_layout_legacy_icon_signal_emit(Evas_Object *obj)
3298 {
3299    char buf[63];
3300    Eo *edje;
3301 
3302    edje = elm_layout_edje_get(obj);
3303    if (!edje) return;
3304    if (!edje_object_part_exists(obj, "elm.swallow.content")) return;
3305    snprintf(buf, sizeof(buf), "elm,state,icon,%s",
3306             elm_layout_content_get(obj, "icon") ? "visible" : "hidden");
3307 
3308    elm_layout_signal_emit(obj, buf, "elm");
3309    edje_object_message_signal_process(edje);
3310    efl_canvas_group_change(obj);
3311 }
3312 
3313 EAPI void
elm_layout_signal_callback_add(Eo * obj,const char * emission,const char * source,Edje_Signal_Cb func,void * data)3314 elm_layout_signal_callback_add(Eo *obj, const char *emission, const char *source, Edje_Signal_Cb func, void *data)
3315 {
3316    Efl_Ui_Layout_Data *sd;
3317 
3318    if (!emission || !source) return;
3319 
3320    if (efl_isa(obj, ELM_ENTRY_CLASS))
3321      {
3322         _elm_entry_signal_callback_add_legacy(obj, emission, source, func, data);
3323         return;
3324      }
3325 
3326    sd = efl_data_scope_safe_get(obj, MY_CLASS);
3327    if (!sd) return;
3328    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
3329 
3330    _elm_layout_signal_callback_add_legacy(obj, wd->resize_obj, &sd->edje_signals,
3331                                           emission, source, func, data);
3332 }
3333 
3334 void *
_elm_layout_signal_callback_del_legacy(Eo * obj EINA_UNUSED,Eo * edje,Eina_List ** p_edje_signals,const char * emission,const char * source,Edje_Signal_Cb func)3335 _elm_layout_signal_callback_del_legacy(Eo *obj EINA_UNUSED, Eo *edje, Eina_List **p_edje_signals,
3336                                        const char *emission, const char *source,
3337                                        Edje_Signal_Cb func)
3338 {
3339    Edje_Signal_Data *esd = NULL;
3340    void *data = NULL;
3341    Eina_List *l;
3342 
3343    if (!emission || !source) return NULL;
3344 
3345    EINA_LIST_FOREACH(*p_edje_signals, l, esd)
3346      {
3347         if ((esd->func == func) && (!strcmp(esd->emission, emission)) &&
3348             (!strcmp(esd->source, source)))
3349           {
3350              *p_edje_signals = eina_list_remove_list(*p_edje_signals, l);
3351 
3352              edje_object_signal_callback_del_full(edje, emission, source,
3353                                                   _edje_signal_callback, esd);
3354 
3355              eina_stringshare_del(esd->emission);
3356              eina_stringshare_del(esd->source);
3357              data = esd->data;
3358              free(esd);
3359 
3360              return data; /* stop at 1st match */
3361           }
3362      }
3363 
3364    return NULL;
3365 }
3366 
3367 EAPI void *
elm_layout_signal_callback_del(Eo * obj,const char * emission,const char * source,Edje_Signal_Cb func)3368 elm_layout_signal_callback_del(Eo *obj, const char *emission, const char *source, Edje_Signal_Cb func)
3369 {
3370    Efl_Ui_Layout_Data *sd;
3371 
3372    if (!emission || !source) return NULL;
3373 
3374    if (efl_isa(obj, ELM_ENTRY_CLASS))
3375      return _elm_entry_signal_callback_del_legacy(obj, emission, source, func);
3376 
3377    sd = efl_data_scope_safe_get(obj, MY_CLASS);
3378    if (!sd) return NULL;
3379    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, NULL);
3380 
3381    return _elm_layout_signal_callback_del_legacy(obj, wd->resize_obj, &sd->edje_signals,
3382                                                  emission, source, func);
3383 }
3384 
3385 EAPI void
elm_layout_signal_emit(Eo * obj,const char * emission,const char * source)3386 elm_layout_signal_emit(Eo *obj, const char *emission, const char *source)
3387 {
3388    efl_layout_signal_emit(obj, emission, source);
3389 }
3390 
3391 EAPI const char *
elm_layout_data_get(const Evas_Object * obj,const char * key)3392 elm_layout_data_get(const Evas_Object *obj, const char *key)
3393 {
3394    return efl_layout_group_data_get(obj, key);
3395 }
3396 
3397 EAPI Eina_Bool
elm_layout_theme_set(Evas_Object * obj,const char * klass,const char * group,const char * style)3398 elm_layout_theme_set(Evas_Object *obj, const char *klass, const char *group, const char *style)
3399 {
3400    Eina_Error theme_apply_ret;
3401 
3402    theme_apply_ret = efl_ui_layout_theme_set(obj, klass, group, style);
3403    return (theme_apply_ret != EFL_UI_THEME_APPLY_ERROR_GENERIC);
3404 }
3405 
3406 #include "efl_ui_layout_legacy_eo.c"
3407