1 #ifdef HAVE_CONFIG_H
2 # include "elementary_config.h"
3 #endif
4 
5 #define EFL_ACCESS_OBJECT_PROTECTED
6 #define EFL_ACCESS_WIDGET_ACTION_PROTECTED
7 #define ELM_WIDGET_ITEM_PROTECTED
8 #define ELM_WIDGET_PROTECTED
9 #define EFL_UI_L10N_PROTECTED
10 #define EFL_PART_PROTECTED
11 
12 #include <Elementary.h>
13 #include "elm_priv.h"
14 #include "elm_naviframe_eo.h"
15 #include "elm_naviframe_item_eo.h"
16 #include "elm_widget_naviframe.h"
17 #include "elm_widget_container.h"
18 
19 #include "elm_naviframe_part.eo.h"
20 #include "elm_part_helper.h"
21 
22 #define MY_CLASS ELM_NAVIFRAME_CLASS
23 
24 #define MY_CLASS_NAME "Elm_Naviframe"
25 #define MY_CLASS_NAME_LEGACY "elm_naviframe"
26 
27 static const char CONTENT_PART[] = "elm.swallow.content";
28 static const char PREV_BTN_PART[] = "elm.swallow.prev_btn";
29 static const char NEXT_BTN_PART[] = "elm.swallow.next_btn";
30 static const char ICON_PART[] = "elm.swallow.icon";
31 static const char TITLE_PART[] = "elm.text.title";
32 static const char SUBTITLE_PART[] = "elm.text.subtitle";
33 static const char TITLE_ACCESS_PART[] = "access.title";
34 
35 static const char SIG_TRANSITION_FINISHED[] = "transition,finished";
36 static const char SIG_TITLE_TRANSITION_FINISHED[] = "title,transition,finished";
37 static const char SIG_TITLE_CLICKED[] = "title,clicked";
38 static const char SIG_ITEM_ACTIVATED[] = "item,activated";
39 
40 static const Evas_Smart_Cb_Description _smart_callbacks[] = {
41    {SIG_TRANSITION_FINISHED, ""},
42    {SIG_TITLE_TRANSITION_FINISHED, ""},
43    {SIG_TITLE_CLICKED, ""},
44    {SIG_WIDGET_LANG_CHANGED, ""}, /**< handled by elm_widget */
45    {SIG_WIDGET_ACCESS_CHANGED, ""}, /**< handled by elm_widget */
46    {SIG_LAYOUT_FOCUSED, ""}, /**< handled by elm_layout */
47    {SIG_LAYOUT_UNFOCUSED, ""}, /**< handled by elm_layout */
48    {SIG_ITEM_ACTIVATED, ""},
49    {NULL, NULL}
50 };
51 
52 static void _on_item_back_btn_clicked(void *data, Evas_Object *obj, void *event_info EINA_UNUSED);
53 
54 static Eina_Bool _key_action_top_item_get(Evas_Object *obj, const char *params);
55 static Eina_Bool _key_action_item_pop(Evas_Object *obj, const char *params);
56 
57 static const Elm_Action key_actions[] = {
58    {"top_item_get", _key_action_top_item_get},
59    {"item_pop", _key_action_item_pop},
60    {NULL, NULL}
61 };
62 
63 EOLIAN static void
_elm_naviframe_efl_ui_widget_resize_object_set(Eo * obj,Elm_Naviframe_Data * pd EINA_UNUSED,Efl_Canvas_Object * sobj)64 _elm_naviframe_efl_ui_widget_resize_object_set(Eo *obj, Elm_Naviframe_Data *pd EINA_UNUSED,
65                                             Efl_Canvas_Object *sobj)
66 {
67    if (!sobj || !efl_finalized_get(obj)) goto super;
68    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
69 
70    if (wd->resize_obj == sobj) return;
71 
72    // Detach the previous page as resize object to avoid any modifications to
73    // it by the widget implementation. This preserves clip, smart membership,
74    // focus, etc...
75    wd->resize_obj = NULL;
76 
77 super:
78    efl_ui_widget_resize_object_set(efl_super(obj, MY_CLASS), sobj);
79 }
80 
81 static void
_resize_object_reset(Evas_Object * obj,Elm_Naviframe_Item_Data * it)82 _resize_object_reset(Evas_Object *obj, Elm_Naviframe_Item_Data *it)
83 {
84    if (it)
85      {
86         elm_widget_resize_object_set(obj, VIEW(it));
87         evas_object_raise(VIEW(it));
88      }
89 }
90 
91 static void
_prev_page_focus_recover(Elm_Naviframe_Item_Data * it)92 _prev_page_focus_recover(Elm_Naviframe_Item_Data *it)
93 {
94    Elm_Naviframe *n = it->base->widget;
95 
96    efl_ui_focus_manager_focus_set(efl_ui_focus_object_focus_manager_get(n), n);
97 }
98 
99 EOLIAN static void
_elm_naviframe_efl_ui_l10n_translation_update(Eo * obj EINA_UNUSED,Elm_Naviframe_Data * sd)100 _elm_naviframe_efl_ui_l10n_translation_update(Eo *obj EINA_UNUSED, Elm_Naviframe_Data *sd)
101 {
102    Elm_Naviframe_Item_Data *it;
103 
104    EINA_INLIST_FOREACH(sd->stack, it)
105      elm_wdg_item_translate(EO_OBJ(it));
106 
107    efl_ui_l10n_translation_update(efl_super(obj, MY_CLASS));
108 }
109 
110 static void
_item_content_del_cb(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)111 _item_content_del_cb(void *data,
112                      Evas *e EINA_UNUSED,
113                      Evas_Object *obj EINA_UNUSED,
114                      void *event_info EINA_UNUSED)
115 {
116    Elm_Naviframe_Item_Data *it = data;
117 
118    it->content = NULL;
119    elm_object_signal_emit(VIEW(it), "elm,state,content,hide", "elm");
120 }
121 
122 static void
_item_title_prev_btn_del_cb(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)123 _item_title_prev_btn_del_cb(void *data,
124                             Evas *e EINA_UNUSED,
125                             Evas_Object *obj EINA_UNUSED,
126                             void *event_info EINA_UNUSED)
127 {
128    Elm_Naviframe_Item_Data *it = data;
129 
130    it->title_prev_btn = NULL;
131    if (it->auto_pushed_btn) it->auto_pushed_btn = NULL;
132    elm_object_signal_emit(VIEW(it), "elm,state,prev_btn,hide", "elm");
133 }
134 
135 static void
_item_title_next_btn_del_cb(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)136 _item_title_next_btn_del_cb(void *data,
137                             Evas *e EINA_UNUSED,
138                             Evas_Object *obj EINA_UNUSED,
139                             void *event_info EINA_UNUSED)
140 {
141    Elm_Naviframe_Item_Data *it = data;
142 
143    it->title_next_btn = NULL;
144    elm_object_signal_emit(VIEW(it), "elm,state,next_btn,hide", "elm");
145 }
146 
147 static void
_item_title_icon_del_cb(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)148 _item_title_icon_del_cb(void *data,
149                         Evas *e EINA_UNUSED,
150                         Evas_Object *obj EINA_UNUSED,
151                         void *event_info EINA_UNUSED)
152 {
153    Elm_Naviframe_Item_Data *it = data;
154 
155    it->title_icon = NULL;
156    elm_object_signal_emit(VIEW(it), "elm,state,icon,hide", "elm");
157 }
158 
159 static void
_title_content_del(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)160 _title_content_del(void *data,
161                    Evas *e EINA_UNUSED,
162                    Evas_Object *obj EINA_UNUSED,
163                    void *event_info EINA_UNUSED)
164 {
165    char buf[1024];
166    Elm_Naviframe_Content_Item_Pair *pair = data;
167    Elm_Naviframe_Item_Data *it = pair->it;
168    snprintf(buf, sizeof(buf), "elm,state,%s,hide", pair->part);
169    elm_object_signal_emit(VIEW(it), buf, "elm");
170    it->content_list = eina_inlist_remove(it->content_list,
171                                          EINA_INLIST_GET(pair));
172    eina_stringshare_del(pair->part);
173    free(pair);
174 }
175 
176 static void
_item_free(Elm_Naviframe_Item_Data * it)177 _item_free(Elm_Naviframe_Item_Data *it)
178 {
179    Eina_Inlist *l;
180    Elm_Naviframe_Text_Item_Pair *text_pair;
181 
182    eina_stringshare_del(it->title_label);
183    eina_stringshare_del(it->subtitle_label);
184 
185 
186    EINA_INLIST_FOREACH_SAFE(it->text_list, l, text_pair)
187      {
188         eina_stringshare_del(text_pair->part);
189         free(text_pair);
190      }
191 }
192 
193 static void
_item_content_signals_emit(Elm_Naviframe_Item_Data * it)194 _item_content_signals_emit(Elm_Naviframe_Item_Data *it)
195 {
196    Elm_Naviframe_Content_Item_Pair *content_pair;
197    char buf[1024];
198    //content
199    if (it->content)
200      elm_object_signal_emit(VIEW(it), "elm,state,content,show", "elm");
201    else
202      elm_object_signal_emit(VIEW(it), "elm,state,content,hide", "elm");
203 
204    //prev button
205    if (it->title_prev_btn)
206      elm_object_signal_emit(VIEW(it), "elm,state,prev_btn,show", "elm");
207    else
208      elm_object_signal_emit(VIEW(it), "elm,state,prev_btn,hide", "elm");
209 
210    //next button
211    if (it->title_next_btn)
212      elm_object_signal_emit(VIEW(it), "elm,state,next_btn,show", "elm");
213    else
214      elm_object_signal_emit(VIEW(it), "elm,state,next_btn,hide", "elm");
215 
216    if (it->title_icon)
217      elm_object_signal_emit(VIEW(it), "elm,state,icon,show", "elm");
218    else
219      elm_object_signal_emit(VIEW(it), "elm,state,icon,hide", "elm");
220 
221    EINA_INLIST_FOREACH(it->content_list, content_pair)
222      {
223         if (content_pair->content)
224           snprintf(buf, sizeof(buf), "elm,state,%s,show", content_pair->part);
225         else
226           snprintf(buf, sizeof(buf), "elm,state,%s,hide", content_pair->part);
227         elm_object_signal_emit(VIEW(it), buf, "elm");
228      }
229 }
230 
231 static void
_item_text_signals_emit(Elm_Naviframe_Item_Data * it)232 _item_text_signals_emit(Elm_Naviframe_Item_Data *it)
233 {
234    Elm_Naviframe_Text_Item_Pair *text_pair;
235    char buf[1024];
236 
237    if ((it->title_label) && (it->title_label[0]))
238      elm_object_signal_emit(VIEW(it), "elm,state,title_label,show", "elm");
239    else
240      elm_object_signal_emit(VIEW(it), "elm,state,title_label,hide", "elm");
241 
242    if ((it->subtitle_label) && (it->subtitle_label[0]))
243      elm_object_signal_emit(VIEW(it), "elm,state,subtitle,show", "elm");
244    else
245      elm_object_signal_emit(VIEW(it), "elm,state,subtitle,hide", "elm");
246 
247    EINA_INLIST_FOREACH(it->text_list, text_pair)
248      {
249         if (elm_object_part_text_get(VIEW(it), text_pair->part))
250           snprintf(buf, sizeof(buf), "elm,state,%s,show", text_pair->part);
251         else
252           snprintf(buf, sizeof(buf), "elm,state,%s,hide", text_pair->part);
253         elm_object_signal_emit(VIEW(it), buf, "elm");
254      }
255 }
256 
257 static Evas_Object *
_access_object_get(Elm_Naviframe_Item_Data * it,const char * part)258 _access_object_get(Elm_Naviframe_Item_Data *it, const char* part)
259 {
260    Evas_Object *po, *ao, *o;
261 
262    o = elm_layout_edje_get(VIEW(it));
263    edje_object_freeze(o);
264    po = (Evas_Object *)edje_object_part_object_get(o, part);
265    edje_object_thaw(o);
266    ao = evas_object_data_get(po, "_part_access_obj");
267 
268    return ao;
269 }
270 
271 static Eina_Bool
_access_info_has(Evas_Object * obj,int type)272 _access_info_has(Evas_Object *obj, int type)
273 {
274    Elm_Access_Info *ac;
275    Elm_Access_Item *ai;
276    Eina_List *l;
277 
278    ac = _elm_access_info_get(obj);
279    if (!ac) return EINA_FALSE;
280 
281    EINA_LIST_FOREACH(ac->items, l, ai)
282      {
283         if (ai->type == type)
284           {
285              if (ai->func || ai->data) return EINA_TRUE;
286           }
287      }
288 
289    return EINA_FALSE;
290 }
291 
292 static void
_item_signals_emit(Elm_Naviframe_Item_Data * it)293 _item_signals_emit(Elm_Naviframe_Item_Data *it)
294 {
295    _item_text_signals_emit(it);
296    _item_content_signals_emit(it);
297 }
298 
299 /* FIXME: we need to handle the case when this function is called
300  * during a transition */
301 static void
_item_style_set(Elm_Naviframe_Item_Data * it,const char * item_style)302 _item_style_set(Elm_Naviframe_Item_Data *it,
303                 const char *item_style)
304 {
305    char buf[256];
306 
307    ELM_NAVIFRAME_DATA_GET(WIDGET(it), sd);
308 
309    if (!item_style)
310      {
311         strcpy(buf, "item/basic");
312         elm_wdg_item_style_set(efl_super(EO_OBJ(it), ELM_NAVIFRAME_ITEM_CLASS), "basic");
313      }
314    else
315      {
316         snprintf(buf, sizeof(buf), "item/%s", item_style);
317         elm_wdg_item_style_set(efl_super(EO_OBJ(it), ELM_NAVIFRAME_ITEM_CLASS),  item_style);
318      }
319 
320    if (!elm_layout_theme_set(VIEW(it), "naviframe", buf,
321                              elm_widget_style_get(WIDGET(it))))
322      {
323         /* Naviframe item theme name is combined with item style name and widget
324          * style name.
325          * Therefore, if the item theme name is not found, then set "item/basic"
326          * item style name as a default item style name. */
327         if (!elm_layout_theme_set(VIEW(it), "naviframe", "item/basic",
328                                   elm_widget_style_get(WIDGET(it))))
329           CRI("Failed to set layout!");
330      }
331 
332    if (sd->freeze_events)
333      evas_object_freeze_events_set(VIEW(it), EINA_FALSE);
334 }
335 
336 static void
_on_item_title_transition_finished(void * data,Evas_Object * obj EINA_UNUSED,const char * emission EINA_UNUSED,const char * source EINA_UNUSED)337 _on_item_title_transition_finished(void *data,
338                                    Evas_Object *obj EINA_UNUSED,
339                                    const char *emission EINA_UNUSED,
340                                    const char *source EINA_UNUSED)
341 {
342    Elm_Naviframe_Item_Data *it = data;
343 
344    efl_event_callback_legacy_call
345          (WIDGET(it), ELM_NAVIFRAME_EVENT_TITLE_TRANSITION_FINISHED, EO_OBJ(it));
346 }
347 
348 static void
_item_title_enabled_update(Elm_Naviframe_Item_Data * nit,Eina_Bool transition)349 _item_title_enabled_update(Elm_Naviframe_Item_Data *nit, Eina_Bool transition)
350 {
351    transition = !!transition;
352    if (transition)
353      {
354         if (nit->title_enabled)
355           elm_object_signal_emit(VIEW(nit), "elm,action,title,show", "elm");
356         else
357           elm_object_signal_emit(VIEW(nit), "elm,action,title,hide", "elm");
358      }
359    else
360      {
361         if (nit->title_enabled)
362           elm_object_signal_emit(VIEW(nit), "elm,state,title,show", "elm");
363         else
364           elm_object_signal_emit(VIEW(nit), "elm,state,title,hide", "elm");
365      }
366    edje_object_message_signal_process(elm_layout_edje_get(VIEW(nit)));
367 }
368 
369 EOLIAN static Eina_Error
_elm_naviframe_efl_ui_widget_theme_apply(Eo * obj,Elm_Naviframe_Data * sd)370 _elm_naviframe_efl_ui_widget_theme_apply(Eo *obj, Elm_Naviframe_Data *sd)
371 {
372    Elm_Naviframe_Item_Data *it;
373    const char *style = NULL, *sstyle = NULL;
374 
375    style = efl_ui_widget_style_get(obj);
376 
377    EINA_INLIST_FOREACH(sd->stack, it)
378      {
379         sstyle = efl_ui_widget_style_get(VIEW(it));
380         if ((style && sstyle) && strcmp(style, sstyle))
381           _item_style_set(it, elm_wdg_item_style_get(EO_OBJ(it)));
382         _item_signals_emit(it);
383         _item_title_enabled_update(it, EINA_FALSE);
384      }
385 
386    elm_layout_sizing_eval(obj);
387    return EFL_UI_THEME_APPLY_ERROR_NONE;
388 }
389 
390 static char *
_access_info_cb(void * data,Evas_Object * obj EINA_UNUSED)391 _access_info_cb(void *data, Evas_Object *obj EINA_UNUSED)
392 {
393    Elm_Naviframe_Item_Data *nit;
394    Evas_Object *layout;
395    Eina_Strbuf *buf;
396    const char *info;
397    char *ret;
398 
399    nit = data;
400    if (!nit->title_enabled) return NULL;
401 
402    layout = VIEW(nit);
403    info = elm_object_part_text_get(layout, TITLE_PART);
404    if (!info) return NULL;
405 
406    buf = eina_strbuf_new();
407    eina_strbuf_append(buf, info);
408    eina_strbuf_append_printf(buf, ", %s", N_("Title"));
409 
410    info = elm_object_part_text_get(layout, SUBTITLE_PART);
411    if (!info) goto end;
412    if (!strcmp(info, "")) goto end;
413 
414    eina_strbuf_append_printf(buf, ", %s", info);
415    eina_strbuf_append_printf(buf, ", %s", N_("Subtitle"));
416 
417 end:
418    ret = eina_strbuf_string_steal(buf);
419    eina_strbuf_free(buf);
420    return ret;
421 }
422 
423 static void
_access_obj_process(Elm_Naviframe_Item_Data * it,Eina_Bool is_access)424 _access_obj_process(Elm_Naviframe_Item_Data *it, Eina_Bool is_access)
425 {
426    Evas_Object *ao, *eo;
427 
428    if (is_access && (it->title_label || it->subtitle_label))
429      {
430         if (!_access_object_get(it, TITLE_ACCESS_PART))
431           {
432              eo = elm_layout_edje_get(VIEW(it));
433              ao =_elm_access_edje_object_part_object_register(WIDGET(it), eo,
434                                                             TITLE_ACCESS_PART);
435             _elm_access_text_set(_elm_access_info_get(ao),
436                                 ELM_ACCESS_TYPE, E_("Title"));
437             _elm_access_callback_set(_elm_access_info_get(ao),
438                                      ELM_ACCESS_INFO, _access_info_cb, it);
439             /* to access title access object, any idea? */
440             it->base->access_obj = ao;
441          }
442      }
443    else
444      {
445         /* to access title access object, any idea? */
446         ao = it->base->access_obj;
447         if (!ao) return;
448 
449         if (it->title_label || it->subtitle_label)
450           _elm_access_edje_object_part_object_unregister
451              (WIDGET(it), elm_layout_edje_get(VIEW(it)), TITLE_ACCESS_PART);
452         evas_object_del(ao);
453      }
454 }
455 
456 static void
_elm_naviframe_item_elm_widget_item_part_text_set(Eo * eo_it,Elm_Naviframe_Item_Data * it,const char * part,const char * label)457 _elm_naviframe_item_elm_widget_item_part_text_set(Eo *eo_it,
458                                                   Elm_Naviframe_Item_Data *it,
459                                                   const char *part,
460                                                   const char *label)
461 {
462    Elm_Naviframe_Item_Data *nit = it;
463    Elm_Naviframe_Text_Item_Pair *pair = NULL;
464    char buf[1024];
465 
466    if ((!part) || (!strcmp(part, "default")) ||
467        (!strcmp(part, TITLE_PART)))
468      {
469         eina_stringshare_replace(&nit->title_label, label);
470         if (label)
471           elm_object_signal_emit(VIEW(it), "elm,state,title_label,show", "elm");
472         else
473           elm_object_signal_emit(VIEW(it), "elm,state,title_label,hide", "elm");
474         elm_object_part_text_set(VIEW(it), TITLE_PART, label);
475      }
476    else if ((!strcmp(part, "subtitle")) || (!strcmp(part, SUBTITLE_PART)))
477      {
478         eina_stringshare_replace(&nit->subtitle_label, label);
479         if (label)
480           elm_object_signal_emit(VIEW(it), "elm,state,subtitle,show", "elm");
481         else
482           elm_object_signal_emit(VIEW(it), "elm,state,subtitle,hide", "elm");
483         elm_object_part_text_set(VIEW(it), SUBTITLE_PART, label);
484      }
485    else
486      {
487         EINA_INLIST_FOREACH(nit->text_list, pair)
488           if (!strcmp(part, pair->part)) break;
489 
490         if (!pair)
491           {
492              pair = ELM_NEW(Elm_Naviframe_Text_Item_Pair);
493              if (!pair)
494                {
495                   ERR("Failed to allocate new text part of the item! : naviframe=%p",
496                   WIDGET(it));
497                   return;
498                }
499              eina_stringshare_replace(&pair->part, part);
500              nit->text_list = eina_inlist_append(nit->text_list,
501                                                  EINA_INLIST_GET(pair));
502           }
503         if (label)
504           snprintf(buf, sizeof(buf), "elm,state,%s,show", part);
505         else
506           snprintf(buf, sizeof(buf), "elm,state,%s,hide", part);
507         elm_object_signal_emit(VIEW(it), buf, "elm");
508         elm_object_part_text_set(VIEW(it), part, label);
509      }
510 
511    /* access */
512    if (_elm_config->access_mode)
513      _access_obj_process(nit, EINA_TRUE);
514 
515    buf[0] = 0;
516    if (nit->title_label)
517      strncpy(buf, nit->title_label, sizeof(buf) - 1);
518    if (nit->subtitle_label)
519      {
520         if ((nit->title_label) && (strlen(buf) < (sizeof(buf) - 2)))
521           strcat(buf, " ");
522         strncat(buf, nit->subtitle_label, sizeof(buf) - strlen(buf) - 2);
523      }
524    efl_access_object_i18n_name_set(eo_it, buf);
525 
526    elm_layout_sizing_eval(WIDGET(nit));
527 }
528 
529 EOLIAN static const char *
_elm_naviframe_item_elm_widget_item_part_text_get(const Eo * nit EINA_UNUSED,Elm_Naviframe_Item_Data * it,const char * part)530 _elm_naviframe_item_elm_widget_item_part_text_get(const Eo *nit EINA_UNUSED,
531                                              Elm_Naviframe_Item_Data *it,
532                                              const char *part)
533 {
534    char buf[1024];
535 
536    if (!part || !strcmp(part, "default"))
537      snprintf(buf, sizeof(buf), TITLE_PART);
538    else if (!strcmp("subtitle", part))
539      snprintf(buf, sizeof(buf), SUBTITLE_PART);
540    else
541      snprintf(buf, sizeof(buf), "%s", part);
542 
543    return elm_object_part_text_get(VIEW(it), buf);
544 }
545 
546 EOLIAN static void
_elm_naviframe_item_efl_object_destructor(Eo * eo_item,Elm_Naviframe_Item_Data * it)547 _elm_naviframe_item_efl_object_destructor(Eo *eo_item, Elm_Naviframe_Item_Data *it)
548 {
549    Eina_List *l;
550    Elm_Naviframe_Op *nfo;
551    Elm_Naviframe_Item_Data *nit = it;
552 
553    ELM_NAVIFRAME_DATA_GET(WIDGET(nit), sd);
554 
555    nit->delete_me = EINA_TRUE;
556 
557    // This should not happen, but just in case and by security
558    // make sure there is no more reference to this item.
559    EINA_LIST_FOREACH(sd->ops, l, nfo)
560      {
561         /* If an item is newly pushed and then deleted by elm_object_item_del()
562          * before item push transition is not started, then the item push
563          * transitions for both new item and current item should be cancelled.
564          * Otherwise, the current item becomes invisible due to the item push
565          * transition. */
566         if ((nit->pushing) && (nfo->self == nit))
567           {
568              nfo->self = NULL;
569              nfo->related = NULL;
570           }
571         else
572           {
573              if (nfo->self == nit)
574                nfo->self = NULL;
575              if (nfo->related == nit)
576                nfo->related = NULL;
577           }
578      }
579 
580    _item_free(nit);
581 
582    efl_destructor(efl_super(eo_item, ELM_NAVIFRAME_ITEM_CLASS));
583 }
584 
585 static void
_item_content_set(Elm_Naviframe_Item_Data * it,Evas_Object * content)586 _item_content_set(Elm_Naviframe_Item_Data *it,
587                   Evas_Object *content)
588 {
589    if (it->content == content) return;
590 
591    evas_object_del(it->content);
592    it->content = content;
593 
594    if (!content) return;
595 
596    elm_object_part_content_set(VIEW(it), CONTENT_PART, content);
597    elm_object_signal_emit(VIEW(it), "elm,state,content,show", "elm");
598 
599    evas_object_event_callback_add
600      (content, EVAS_CALLBACK_DEL, _item_content_del_cb, it);
601 }
602 
603 static void
_item_title_prev_btn_set(Elm_Naviframe_Item_Data * it,Evas_Object * btn)604 _item_title_prev_btn_set(Elm_Naviframe_Item_Data *it,
605                          Evas_Object *btn)
606 {
607    if (it->title_prev_btn == btn) return;
608    evas_object_del(it->title_prev_btn);
609    it->title_prev_btn = btn;
610    if (it->auto_pushed_btn && (it->auto_pushed_btn != btn))
611      it->auto_pushed_btn = NULL;
612    if (!btn) return;
613 
614    elm_object_part_content_set(VIEW(it), PREV_BTN_PART, btn);
615    elm_object_signal_emit(VIEW(it), "elm,state,prev_btn,show", "elm");
616    evas_object_event_callback_add
617      (btn, EVAS_CALLBACK_DEL, _item_title_prev_btn_del_cb, it);
618 
619    //FIXME: set back button callback here after elm 2.0
620 }
621 
622 static void
_item_title_next_btn_set(Elm_Naviframe_Item_Data * it,Evas_Object * btn)623 _item_title_next_btn_set(Elm_Naviframe_Item_Data *it,
624                          Evas_Object *btn)
625 {
626    if (it->title_next_btn == btn) return;
627    evas_object_del(it->title_next_btn);
628    it->title_next_btn = btn;
629    if (!btn) return;
630 
631    elm_object_part_content_set(VIEW(it), NEXT_BTN_PART, btn);
632    elm_object_signal_emit(VIEW(it), "elm,state,next_btn,show", "elm");
633 
634    evas_object_event_callback_add
635      (btn, EVAS_CALLBACK_DEL, _item_title_next_btn_del_cb, it);
636 }
637 
638 static void
_item_title_icon_set(Elm_Naviframe_Item_Data * it,Evas_Object * icon)639 _item_title_icon_set(Elm_Naviframe_Item_Data *it,
640                      Evas_Object *icon)
641 {
642    if (it->title_icon == icon) return;
643    evas_object_del(it->title_icon);
644    it->title_icon = icon;
645    if (!icon) return;
646 
647    elm_object_part_content_set(VIEW(it), ICON_PART, icon);
648    elm_object_signal_emit(VIEW(it), "elm,state,icon,show", "elm");
649 
650    evas_object_event_callback_add
651      (icon, EVAS_CALLBACK_DEL, _item_title_icon_del_cb, it);
652 }
653 
654 static Evas_Object *
_item_content_unset(Elm_Naviframe_Item_Data * it)655 _item_content_unset(Elm_Naviframe_Item_Data *it)
656 {
657    Evas_Object *content = it->content;
658 
659    if (!content) return NULL;
660 
661    elm_object_part_content_unset(VIEW(it), CONTENT_PART);
662    elm_object_signal_emit(VIEW(it), "elm,state,content,hide", "elm");
663 
664    evas_object_event_callback_del
665      (content, EVAS_CALLBACK_DEL, _item_content_del_cb);
666 
667    it->content = NULL;
668    return content;
669 }
670 
671 static Evas_Object *
_item_title_prev_btn_unset(Elm_Naviframe_Item_Data * it)672 _item_title_prev_btn_unset(Elm_Naviframe_Item_Data *it)
673 {
674    Evas_Object *content = it->title_prev_btn;
675 
676    if (!content) return NULL;
677 
678    elm_object_part_content_unset(VIEW(it), PREV_BTN_PART);
679    elm_object_signal_emit(VIEW(it), "elm,state,prev_btn,hide", "elm");
680 
681    evas_object_event_callback_del
682      (content, EVAS_CALLBACK_DEL, _item_title_prev_btn_del_cb);
683    evas_object_smart_callback_del(content, "clicked", _on_item_back_btn_clicked);
684    it->title_prev_btn = NULL;
685    if (it->auto_pushed_btn) it->auto_pushed_btn = NULL;
686    return content;
687 }
688 
689 static Evas_Object *
_item_title_next_btn_unset(Elm_Naviframe_Item_Data * it)690 _item_title_next_btn_unset(Elm_Naviframe_Item_Data *it)
691 {
692    Evas_Object *content = it->title_next_btn;
693 
694    if (!content) return NULL;
695 
696    elm_object_part_content_unset(VIEW(it), NEXT_BTN_PART);
697    elm_object_signal_emit(VIEW(it), "elm,state,next_btn,hide", "elm");
698 
699    evas_object_event_callback_del
700      (content, EVAS_CALLBACK_DEL, _item_title_next_btn_del_cb);
701 
702    it->title_next_btn = NULL;
703    return content;
704 }
705 
706 static Evas_Object *
_item_title_icon_unset(Elm_Naviframe_Item_Data * it)707 _item_title_icon_unset(Elm_Naviframe_Item_Data *it)
708 {
709    Evas_Object *content = it->title_icon;
710 
711    if (!content) return NULL;
712 
713    elm_object_part_content_unset(VIEW(it), ICON_PART);
714    elm_object_signal_emit(VIEW(it), "elm,state,icon,hide", "elm");
715 
716    evas_object_event_callback_del
717      (content, EVAS_CALLBACK_DEL, _item_title_icon_del_cb);
718 
719    it->title_icon = NULL;
720    return content;
721 }
722 
723 /* since we have each item as layout, we can't reusing the layout's
724  * aliasing, so let's do it ourselves */
725 static void
_part_aliasing_eval(const char ** part)726 _part_aliasing_eval(const char **part)
727 {
728    if (!*part || !strcmp(*part, "default"))
729      *part = CONTENT_PART;
730    else if (!strcmp(*part, "prev_btn"))
731      *part = PREV_BTN_PART;
732    else if (!strcmp(*part, "next_btn"))
733      *part = NEXT_BTN_PART;
734    else if (!strcmp(*part, "icon"))
735      *part = ICON_PART;
736 }
737 
738 static void
_title_content_set(Elm_Naviframe_Item_Data * it,const char * part,Evas_Object * content)739 _title_content_set(Elm_Naviframe_Item_Data *it,
740                    const char *part,
741                    Evas_Object *content)
742 {
743    Elm_Naviframe_Content_Item_Pair *pair = NULL;
744    char buf[1024];
745 
746    EINA_INLIST_FOREACH(it->content_list, pair)
747      if (!strcmp(part, pair->part)) break;
748    if (pair)
749      {
750         if (pair->content == content) return;
751         if (pair->content)
752           evas_object_event_callback_del(pair->content,
753                                          EVAS_CALLBACK_DEL,
754                                          _title_content_del);
755         if (content) elm_object_part_content_set(VIEW(it), part, content);
756      }
757    else
758      {
759         if (!content) return;
760 
761         //Remove the pair if new content was swallowed into other part.
762         EINA_INLIST_FOREACH(it->content_list, pair)
763           {
764              if (pair->content == content)
765                {
766                   eina_stringshare_del(pair->part);
767                   it->content_list = eina_inlist_remove(it->content_list,
768                                                         EINA_INLIST_GET(pair));
769                   evas_object_event_callback_del(pair->content,
770                                                  EVAS_CALLBACK_DEL,
771                                                  _title_content_del);
772                   free(pair);
773                   break;
774                }
775           }
776 
777         //New pair
778         pair = ELM_NEW(Elm_Naviframe_Content_Item_Pair);
779         if (!pair)
780           {
781              ERR("Failed to allocate new content part of the item! : naviframe=%p",
782              WIDGET(it));
783              return;
784           }
785         pair->it = it;
786         eina_stringshare_replace(&pair->part, part);
787         it->content_list = eina_inlist_append(it->content_list,
788                                               EINA_INLIST_GET(pair));
789         elm_object_part_content_set(VIEW(it), part, content);
790         snprintf(buf, sizeof(buf), "elm,state,%s,show", part);
791         elm_object_signal_emit(VIEW(it), buf, "elm");
792      }
793    pair->content = content;
794    evas_object_event_callback_add(content,
795                                   EVAS_CALLBACK_DEL,
796                                   _title_content_del,
797                                   pair);
798 }
799 
800 EOLIAN static void
_elm_naviframe_item_elm_widget_item_part_content_set(Eo * eo_nit EINA_UNUSED,Elm_Naviframe_Item_Data * nit,const char * part,Evas_Object * content)801 _elm_naviframe_item_elm_widget_item_part_content_set(Eo *eo_nit EINA_UNUSED,
802                                                      Elm_Naviframe_Item_Data *nit,
803                                                      const char *part,
804                                                      Evas_Object *content)
805 {
806    _part_aliasing_eval(&part);
807 
808    //specified parts
809    if (!strcmp(part, CONTENT_PART))
810      _item_content_set(nit, content);
811    else if (!strcmp(part, PREV_BTN_PART))
812      _item_title_prev_btn_set(nit, content);
813    else if (!strcmp(part, NEXT_BTN_PART))
814      _item_title_next_btn_set(nit, content);
815    else if (!strcmp(part, ICON_PART))
816      _item_title_icon_set(nit, content);
817    else
818      _title_content_set(nit, part, content);
819 
820    elm_layout_sizing_eval(WIDGET(nit));
821 }
822 
823 EOLIAN static Evas_Object *
_elm_naviframe_item_elm_widget_item_part_content_get(const Eo * eo_nit EINA_UNUSED,Elm_Naviframe_Item_Data * nit,const char * part)824 _elm_naviframe_item_elm_widget_item_part_content_get(const Eo *eo_nit EINA_UNUSED,
825                                                      Elm_Naviframe_Item_Data *nit,
826                                                      const char *part)
827 {
828    _part_aliasing_eval(&part);
829 
830    //specified parts
831    if (!strcmp(part, CONTENT_PART))
832      return nit->content;
833    else if (!strcmp(part, PREV_BTN_PART))
834      return nit->title_prev_btn;
835    else if (!strcmp(part, NEXT_BTN_PART))
836      return nit->title_next_btn;
837    else if (!strcmp(part, ICON_PART))
838      return nit->title_icon;
839 
840    //common parts
841    return elm_object_part_content_get(VIEW(nit), part);
842 }
843 
844 static Evas_Object *
_title_content_unset(Elm_Naviframe_Item_Data * it,const char * part)845 _title_content_unset(Elm_Naviframe_Item_Data *it, const char *part)
846 {
847    Elm_Naviframe_Content_Item_Pair *pair = NULL;
848    char buf[1028];
849    Evas_Object *content = NULL;
850 
851    EINA_INLIST_FOREACH(it->content_list, pair)
852      {
853         if (!strcmp(part, pair->part))
854           {
855              content = pair->content;
856              eina_stringshare_del(pair->part);
857              it->content_list = eina_inlist_remove(it->content_list,
858                                                    EINA_INLIST_GET(pair));
859              free(pair);
860              break;
861           }
862      }
863 
864    if (!content) return NULL;
865 
866    elm_object_part_content_unset(VIEW(it), part);
867    snprintf(buf, sizeof(buf), "elm,state,%s,hide", part);
868    elm_object_signal_emit(VIEW(it), buf, "elm");
869    evas_object_event_callback_del(content,
870                                   EVAS_CALLBACK_DEL,
871                                   _title_content_del);
872    return content;
873 }
874 
875 EOLIAN static Evas_Object *
_elm_naviframe_item_elm_widget_item_part_content_unset(Eo * eo_nit EINA_UNUSED,Elm_Naviframe_Item_Data * nit,const char * part)876 _elm_naviframe_item_elm_widget_item_part_content_unset(Eo *eo_nit EINA_UNUSED,
877                                                   Elm_Naviframe_Item_Data *nit,
878                                                   const char *part)
879 {
880    Evas_Object *o = NULL;
881 
882    _part_aliasing_eval(&part);
883 
884    //specified parts
885    if (!strcmp(part, CONTENT_PART))
886      o = _item_content_unset(nit);
887    else if (!strcmp(part, PREV_BTN_PART))
888      o = _item_title_prev_btn_unset(nit);
889    else if (!strcmp(part, NEXT_BTN_PART))
890      o = _item_title_next_btn_unset(nit);
891    else if (!strcmp(part, ICON_PART))
892      o = _item_title_icon_unset(nit);
893    else
894      o = _title_content_unset(nit, part);
895 
896    elm_layout_sizing_eval(WIDGET(nit));
897 
898    return o;
899 }
900 
901 EOLIAN static void
_elm_naviframe_item_elm_widget_item_signal_emit(Eo * eo_it EINA_UNUSED,Elm_Naviframe_Item_Data * it,const char * emission,const char * source)902 _elm_naviframe_item_elm_widget_item_signal_emit(Eo *eo_it EINA_UNUSED,
903                                                 Elm_Naviframe_Item_Data *it,
904                                                 const char *emission,
905                                                 const char *source)
906 {
907    elm_object_signal_emit(VIEW(it), emission, source);
908 }
909 
910 EOLIAN static void
_elm_naviframe_efl_canvas_group_group_calculate(Eo * obj,Elm_Naviframe_Data * sd)911 _elm_naviframe_efl_canvas_group_group_calculate(Eo *obj, Elm_Naviframe_Data *sd)
912 {
913    Evas_Coord minw = 0, minh = 0;
914    Elm_Naviframe_Item_Data *it, *top;
915    Evas_Coord x, y, w, h;
916 
917    if (sd->on_deletion) return;
918    if (!sd->stack) return;
919 
920    top = (EINA_INLIST_CONTAINER_GET(sd->stack->last, Elm_Naviframe_Item_Data));
921    evas_object_geometry_get(obj, &x, &y, &w, &h);
922    EINA_INLIST_FOREACH(sd->stack, it)
923      {
924         evas_object_geometry_set(VIEW(it), x, y, w, h);
925 
926         if (it == top)
927           {
928              edje_object_size_min_calc(elm_layout_edje_get(VIEW(it)),
929                                        &it->minw, &it->minh);
930              minw = it->minw;
931              minh = it->minh;
932           }
933      }
934 
935    evas_object_size_hint_min_set(obj, minw, minh);
936    evas_object_size_hint_max_set(obj, -1, -1);
937 }
938 
939 static void
_on_item_back_btn_clicked(void * data,Evas_Object * obj,void * event_info EINA_UNUSED)940 _on_item_back_btn_clicked(void *data, Evas_Object *obj, void *event_info EINA_UNUSED)
941 {
942    /* Since edje has the event queue, clicked event could be happened
943       multiple times on some heavy environment. This callback del will
944       prevent those scenario and guarantee only one clicked for it's own
945       page. */
946    evas_object_smart_callback_del(obj, "clicked", _on_item_back_btn_clicked);
947    elm_naviframe_item_pop(data);
948 }
949 
950 static Evas_Object *
_back_btn_new(Evas_Object * obj,const char * title_label)951 _back_btn_new(Evas_Object *obj, const char *title_label)
952 {
953    Evas_Object *btn, *ed;
954    char buf[1024];
955 
956    btn = elm_button_add(obj);
957 
958    if (!btn) return NULL;
959    evas_object_smart_callback_add(btn, "clicked", _on_item_back_btn_clicked, obj);
960    snprintf
961      (buf, sizeof(buf), "naviframe/back_btn/%s", elm_widget_style_get(obj));
962    elm_object_style_set(btn, buf);
963    if (title_label)
964      elm_layout_text_set(btn, NULL, title_label);
965    else
966      elm_object_domain_translatable_text_set(btn, PACKAGE, N_("Back"));
967 
968    /* HACK NOTE: this explicit check only exists to avoid an ERR()
969     * message from elm_layout_content_set().
970     *
971     * The button was ALWAYS supposed to support an elm.swallow.content, but
972     * default naviframe/back_btn/default theme did not provide such, then
973     * old themes would emit such error message.
974     *
975     * Once we can break the theme API, remove this check and always
976     * set an icon.
977     */
978    ed = elm_layout_edje_get(btn);
979    if (edje_object_part_exists(ed, CONTENT_PART))
980      {
981         Evas_Object *ico = elm_icon_add(btn);
982         elm_icon_standard_set(ico, "go-previous");
983         elm_layout_content_set(btn, CONTENT_PART, ico);
984      }
985 
986    return btn;
987 }
988 
989 EOLIAN static void
_elm_naviframe_efl_layout_signal_signal_emit(Eo * obj,Elm_Naviframe_Data * sd EINA_UNUSED,const char * emission,const char * source)990 _elm_naviframe_efl_layout_signal_signal_emit(Eo *obj, Elm_Naviframe_Data *sd EINA_UNUSED, const char *emission, const char *source)
991 {
992    Elm_Object_Item *eo_top_it;
993 
994    eo_top_it = elm_naviframe_top_item_get(obj);
995    if (!eo_top_it) return;
996    ELM_NAVIFRAME_ITEM_DATA_GET(eo_top_it, top_it);
997 
998    efl_layout_signal_emit(VIEW(top_it), emission, source);
999 }
1000 
1001 /* content/text smart functions proxying things to the top item, which
1002  * is the resize object of the layout */
1003 static Eina_Bool
_elm_naviframe_text_set(Eo * obj,Elm_Naviframe_Data * sd EINA_UNUSED,const char * part,const char * label)1004 _elm_naviframe_text_set(Eo *obj, Elm_Naviframe_Data *sd EINA_UNUSED, const char *part, const char *label)
1005 {
1006    Elm_Object_Item *it;
1007    const char *text = NULL;
1008 
1009    it = elm_naviframe_top_item_get(obj);
1010    if (!it) return EINA_FALSE;
1011 
1012    elm_object_item_part_text_set(it, part, label);
1013    text = elm_object_item_part_text_get(it, part);
1014    if ((text) && !strcmp(text, label))
1015      return EINA_TRUE;
1016    return EINA_FALSE;
1017 }
1018 
1019 static const char *
_elm_naviframe_text_get(Eo * obj,Elm_Naviframe_Data * sd EINA_UNUSED,const char * part)1020 _elm_naviframe_text_get(Eo *obj, Elm_Naviframe_Data *sd EINA_UNUSED, const char *part)
1021 {
1022    Elm_Object_Item *it = elm_naviframe_top_item_get(obj);
1023    if (!it) return NULL;
1024 
1025    return elm_object_item_part_text_get(it, part);
1026 }
1027 
1028 /* we have to keep a "manual" set here because of the callbacks on the
1029  * children */
1030 static Eina_Bool
_elm_naviframe_content_set(Eo * obj,Elm_Naviframe_Data * sd EINA_UNUSED,const char * part,Evas_Object * content)1031 _elm_naviframe_content_set(Eo *obj, Elm_Naviframe_Data *sd EINA_UNUSED, const char *part, Evas_Object *content)
1032 {
1033    Elm_Object_Item *it;
1034 
1035    it = elm_naviframe_top_item_get(obj);
1036    if (!it) return EINA_FALSE;
1037 
1038    elm_object_item_part_content_set(it, part, content);
1039 
1040    if (content == elm_object_item_part_content_get(it, part))
1041      return EINA_TRUE;
1042 
1043    return EINA_FALSE;
1044 }
1045 
1046 static Evas_Object*
_elm_naviframe_content_get(Eo * obj,Elm_Naviframe_Data * sd EINA_UNUSED,const char * part)1047 _elm_naviframe_content_get(Eo *obj, Elm_Naviframe_Data *sd EINA_UNUSED, const char *part)
1048 {
1049    Elm_Object_Item *it = elm_naviframe_top_item_get(obj);
1050 
1051    if (!it) return NULL;
1052 
1053    return elm_object_item_part_content_get(it, part);
1054 }
1055 
1056 static Evas_Object*
_elm_naviframe_content_unset(Eo * obj,Elm_Naviframe_Data * sd EINA_UNUSED,const char * part)1057 _elm_naviframe_content_unset(Eo *obj, Elm_Naviframe_Data *sd EINA_UNUSED, const char *part)
1058 {
1059    Elm_Object_Item *it = elm_naviframe_top_item_get(obj);
1060 
1061    if (!it) return NULL;
1062 
1063    return elm_object_item_part_content_unset(it, part);
1064 }
1065 
1066 static void
_on_item_title_clicked(void * data,Evas_Object * obj EINA_UNUSED,const char * emission EINA_UNUSED,const char * source EINA_UNUSED)1067 _on_item_title_clicked(void *data,
1068                        Evas_Object *obj EINA_UNUSED,
1069                        const char *emission EINA_UNUSED,
1070                        const char *source EINA_UNUSED)
1071 {
1072    Elm_Naviframe_Item_Data *it = data;
1073 
1074    efl_event_callback_legacy_call(WIDGET(it), ELM_NAVIFRAME_EVENT_TITLE_CLICKED, EO_OBJ(it));
1075 }
1076 
1077 /* "elm,state,cur,pushed"
1078  */
1079 static void
_on_item_push_finished(void * data,Evas_Object * obj EINA_UNUSED,const char * emission EINA_UNUSED,const char * source EINA_UNUSED)1080 _on_item_push_finished(void *data,
1081                        Evas_Object *obj EINA_UNUSED,
1082                        const char *emission EINA_UNUSED,
1083                        const char *source EINA_UNUSED)
1084 {
1085    Elm_Naviframe_Item_Data *it = data;
1086 
1087    if (!it) return;
1088 
1089    ELM_NAVIFRAME_DATA_GET(WIDGET(it), sd);
1090 
1091    /* If pushed item becomes top item, then do not hide pushed item view.
1092     * If top item is deleted in "transition,finished" smart callback by user
1093     * before this function is called, then pushed item becomes top item.
1094     */
1095    if (EO_OBJ(it) == elm_naviframe_top_item_get(WIDGET(it)))
1096      return;
1097 
1098    evas_object_hide(VIEW(it));
1099 
1100    elm_object_signal_emit(VIEW(it), "elm,state,invisible", "elm");
1101 
1102    if (sd->freeze_events)
1103      evas_object_freeze_events_set(VIEW(it), EINA_FALSE);
1104 }
1105 
1106 /* "elm,state,cur,popped"
1107  */
1108 static void
_on_item_pop_finished(void * data,Evas_Object * obj EINA_UNUSED,const char * emission EINA_UNUSED,const char * source EINA_UNUSED)1109 _on_item_pop_finished(void *data,
1110                       Evas_Object *obj EINA_UNUSED,
1111                       const char *emission EINA_UNUSED,
1112                       const char *source EINA_UNUSED)
1113 {
1114    Elm_Naviframe_Item_Data *it = data;
1115    Elm_Object_Item *eo_prev_it = NULL;
1116 
1117    ELM_NAVIFRAME_DATA_GET(WIDGET(it), sd);
1118 
1119    eo_prev_it = elm_naviframe_top_item_get(WIDGET(it));
1120    if (eo_prev_it)
1121      {
1122         ELM_NAVIFRAME_ITEM_DATA_GET(eo_prev_it, prev_it);
1123 
1124         evas_object_raise(VIEW(prev_it));
1125      }
1126 
1127    if (sd->preserve)
1128      elm_widget_tree_unfocusable_set(VIEW(it), EINA_FALSE);
1129    sd->popping = eina_list_remove(sd->popping, it);
1130 
1131    efl_del(EO_OBJ(it));
1132 }
1133 
1134 /* "elm,state,new,pushed",
1135  * "elm,state,prev,popped
1136  */
1137 static void
_on_item_show_finished(void * data,Evas_Object * obj EINA_UNUSED,const char * emission EINA_UNUSED,const char * source EINA_UNUSED)1138 _on_item_show_finished(void *data,
1139                        Evas_Object *obj EINA_UNUSED,
1140                        const char *emission EINA_UNUSED,
1141                        const char *source EINA_UNUSED)
1142 {
1143    Elm_Naviframe_Item_Data *it = data;
1144 
1145    ELM_NAVIFRAME_DATA_GET(WIDGET(it), sd);
1146 
1147    elm_object_signal_emit(VIEW(it), "elm,state,visible", "elm");
1148 
1149    elm_widget_tree_unfocusable_set(VIEW(it), EINA_FALSE);
1150    _prev_page_focus_recover(it);
1151 
1152    if (sd->freeze_events)
1153      evas_object_freeze_events_set(VIEW(it), EINA_FALSE);
1154 
1155    it->pushing = EINA_FALSE;
1156 
1157    efl_event_callback_legacy_call(WIDGET(it), ELM_NAVIFRAME_EVENT_TRANSITION_FINISHED, EO_OBJ(it));
1158 
1159    if (EO_OBJ(it) == elm_naviframe_top_item_get(WIDGET(it)))
1160      efl_event_callback_legacy_call(WIDGET(it), ELM_NAVIFRAME_EVENT_ITEM_ACTIVATED, EO_OBJ(it));
1161 }
1162 
1163 static void
_on_item_size_hints_changed(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)1164 _on_item_size_hints_changed(void *data,
1165                             Evas *e EINA_UNUSED,
1166                             Evas_Object *obj EINA_UNUSED,
1167                             void *event_info EINA_UNUSED)
1168 {
1169    elm_layout_sizing_eval(data);
1170 }
1171 
1172 static void
_item_dispmode_set(Elm_Naviframe_Item_Data * it,Evas_Display_Mode dispmode)1173 _item_dispmode_set(Elm_Naviframe_Item_Data *it, Evas_Display_Mode dispmode)
1174 {
1175    if (it->dispmode == dispmode) return;
1176    switch (dispmode)
1177      {
1178       case EVAS_DISPLAY_MODE_COMPRESS:
1179          elm_object_signal_emit(VIEW(it), "elm,state,display,compress", "elm");
1180          break;
1181       default:
1182          elm_object_signal_emit(VIEW(it), "elm,state,display,default", "elm");
1183          break;
1184      }
1185    it->dispmode = dispmode;
1186 }
1187 
1188 static char *
_access_prev_btn_info_cb(void * data EINA_UNUSED,Evas_Object * obj EINA_UNUSED)1189 _access_prev_btn_info_cb(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED)
1190 {
1191    return strdup(E_("Back"));
1192 }
1193 
1194 EOLIAN static void
_elm_naviframe_item_efl_object_invalidate(Eo * eo_item,Elm_Naviframe_Item_Data * it)1195 _elm_naviframe_item_efl_object_invalidate(Eo *eo_item, Elm_Naviframe_Item_Data *it)
1196 {
1197    Elm_Naviframe_Item_Data *prev_it = NULL;
1198    Elm_Naviframe_Content_Item_Pair *content_pair;
1199    Eina_Inlist *l;
1200    Eina_Bool top;
1201 
1202    ELM_NAVIFRAME_DATA_GET(WIDGET(it), sd);
1203    if (it->title_prev_btn)
1204      evas_object_event_callback_del(it->title_prev_btn, EVAS_CALLBACK_DEL, _item_title_prev_btn_del_cb);
1205    if (it->title_next_btn)
1206      evas_object_event_callback_del(it->title_next_btn, EVAS_CALLBACK_DEL, _item_title_next_btn_del_cb);
1207    if (it->title_icon)
1208      evas_object_event_callback_del(it->title_icon, EVAS_CALLBACK_DEL, _item_title_icon_del_cb);
1209    EINA_INLIST_FOREACH_SAFE(it->content_list, l, content_pair)
1210      {
1211         if (content_pair->content)
1212           {
1213              /* content object will be destroyed naturally */
1214              evas_object_event_callback_del(content_pair->content,
1215                                             EVAS_CALLBACK_DEL,
1216                                             _title_content_del);
1217              evas_object_del(content_pair->content);
1218           }
1219         eina_stringshare_del(content_pair->part);
1220         free(content_pair);
1221      }
1222    if (it->content)
1223      {
1224         evas_object_event_callback_del(it->content, EVAS_CALLBACK_DEL, _item_content_del_cb);
1225         if ((sd->preserve) && (!sd->on_deletion))
1226           {
1227              /* so that elm does not delete the contents with the item's
1228               * view after the destructor */
1229              elm_object_part_content_unset(VIEW(it), CONTENT_PART);
1230              evas_object_hide(it->content);
1231           }
1232      }
1233    if (evas_object_data_get(VIEW(it), "out_of_list"))
1234      goto end;
1235 
1236    top = (eo_item == elm_naviframe_top_item_get(WIDGET(it)));
1237    sd->stack = eina_inlist_remove(sd->stack, EINA_INLIST_GET(it));
1238 
1239    if (top && !sd->on_deletion) /* must raise another one */
1240      {
1241         if (sd->stack && sd->stack->last)
1242           prev_it = EINA_INLIST_CONTAINER_GET(sd->stack->last,
1243                                               Elm_Naviframe_Item_Data);
1244         if (!prev_it)
1245           {
1246              elm_widget_tree_unfocusable_set(VIEW(it), EINA_TRUE);
1247              goto end;
1248           }
1249 
1250         elm_widget_tree_unfocusable_set(VIEW(prev_it), EINA_FALSE);
1251         elm_widget_tree_unfocusable_set(VIEW(it), EINA_TRUE);
1252 
1253         if (sd->freeze_events)
1254           evas_object_freeze_events_set(VIEW(prev_it), EINA_FALSE);
1255         _resize_object_reset(WIDGET(prev_it), prev_it);
1256         evas_object_show(VIEW(prev_it));
1257 
1258         _prev_page_focus_recover(prev_it);
1259 
1260         elm_object_signal_emit(VIEW(prev_it), "elm,state,visible", "elm");
1261 
1262         efl_event_callback_legacy_call(WIDGET(prev_it), ELM_NAVIFRAME_EVENT_ITEM_ACTIVATED, EO_OBJ(prev_it));
1263      }
1264 end:
1265    efl_invalidate(efl_super(eo_item, ELM_NAVIFRAME_ITEM_CLASS));
1266 }
1267 
1268 EOLIAN static Eo *
_elm_naviframe_item_efl_object_constructor(Eo * eo_item,Elm_Naviframe_Item_Data * it)1269 _elm_naviframe_item_efl_object_constructor(Eo *eo_item, Elm_Naviframe_Item_Data *it)
1270 {
1271    eo_item = efl_constructor(efl_super(eo_item, ELM_NAVIFRAME_ITEM_CLASS));
1272    it->base = efl_data_scope_get(eo_item, ELM_WIDGET_ITEM_CLASS);
1273 
1274    return eo_item;
1275 }
1276 
1277 static Elm_Object_Item *
_item_new(Evas_Object * obj,const Elm_Object_Item * eo_prev_it,const char * title_label,Evas_Object * prev_btn,Evas_Object * next_btn,Evas_Object * content,const char * item_style)1278 _item_new(Evas_Object *obj,
1279           const Elm_Object_Item *eo_prev_it,
1280           const char *title_label,
1281           Evas_Object *prev_btn,
1282           Evas_Object *next_btn,
1283           Evas_Object *content,
1284           const char *item_style)
1285 {
1286    Eo *eo_item;
1287 
1288    ELM_NAVIFRAME_DATA_GET(obj, sd);
1289 
1290    eo_item = efl_add(ELM_NAVIFRAME_ITEM_CLASS, obj);
1291 
1292    if (!eo_item)
1293      {
1294         ERR("Failed to allocate new item! : naviframe=%p", obj);
1295         return NULL;
1296      }
1297 
1298    ELM_NAVIFRAME_ITEM_DATA_GET(eo_item, it);
1299 
1300    //item base layout
1301    Eo *elem = elm_layout_add(obj);
1302    VIEW_SET(it, elem);
1303    evas_object_smart_member_add(VIEW(it), obj);
1304 
1305    efl_access_object_role_set(elem, EFL_ACCESS_ROLE_PAGE_TAB);
1306    efl_access_object_i18n_name_set(elem, (char*)title_label);
1307 
1308    if (!elm_widget_sub_object_add(obj, VIEW(it)))
1309      ERR("could not add %p as sub object of %p", VIEW(it), obj);
1310 
1311    evas_object_event_callback_add
1312      (VIEW(it), EVAS_CALLBACK_CHANGED_SIZE_HINTS,
1313      _on_item_size_hints_changed, obj);
1314 
1315    elm_object_signal_callback_add
1316      (VIEW(it), "elm,action,show,finished", "*", _on_item_show_finished, it);
1317    elm_object_signal_callback_add
1318      (VIEW(it), "elm,action,pushed,finished", "*", _on_item_push_finished, it);
1319    elm_object_signal_callback_add
1320      (VIEW(it), "elm,action,popped,finished", "*", _on_item_pop_finished, it);
1321    elm_object_signal_callback_add
1322      (VIEW(it), "elm,action,title,transition,finished", "*", _on_item_title_transition_finished, it);
1323    elm_object_signal_callback_add
1324      (VIEW(it), "elm,action,title,clicked", "*", _on_item_title_clicked, it);
1325 
1326    _item_style_set(it, item_style);
1327 
1328    if (title_label)
1329      elm_wdg_item_part_text_set(eo_item, TITLE_PART, title_label);
1330 
1331    //title buttons
1332    if ((!prev_btn) && sd->auto_pushed && eo_prev_it)
1333      {
1334         ELM_NAVIFRAME_ITEM_DATA_GET(eo_prev_it, prev_it);
1335         const char *prev_title = prev_it->title_label;
1336         prev_btn = _back_btn_new(obj, prev_title);
1337         it->auto_pushed_btn = prev_btn;
1338      }
1339 
1340    if (prev_btn)
1341      {
1342         elm_wdg_item_part_content_set(eo_item, PREV_BTN_PART, prev_btn);
1343         if (!elm_layout_text_get(prev_btn, NULL))
1344           {
1345              if (!_access_info_has(prev_btn, ELM_ACCESS_INFO))
1346                {
1347                   /* set access info */
1348                   _elm_access_callback_set
1349                      (_elm_access_info_get(prev_btn), ELM_ACCESS_INFO,
1350                       _access_prev_btn_info_cb, it);
1351                }
1352           }
1353      }
1354 
1355    if (next_btn)
1356      {
1357         elm_wdg_item_part_content_set(eo_item, NEXT_BTN_PART, next_btn);
1358 
1359         if (!elm_layout_text_get(next_btn, NULL))
1360           {
1361              if (!_access_info_has(next_btn, ELM_ACCESS_INFO))
1362                {
1363                   /* set access info */
1364                   _elm_access_text_set
1365                      (_elm_access_info_get(next_btn), ELM_ACCESS_INFO, E_("Next"));
1366                }
1367           }
1368      }
1369 
1370    _item_content_set(it, content);
1371    _item_dispmode_set(it, sd->dispmode);
1372 
1373    it->title_enabled = EINA_TRUE;
1374 
1375    return EO_OBJ(it);
1376 }
1377 
1378 static void
_on_obj_size_hints_changed(void * data EINA_UNUSED,Evas * e EINA_UNUSED,Evas_Object * obj,void * event_info EINA_UNUSED)1379 _on_obj_size_hints_changed(void *data EINA_UNUSED, Evas *e EINA_UNUSED,
1380                            Evas_Object *obj, void *event_info EINA_UNUSED)
1381 {
1382    Elm_Naviframe_Item_Data *it;
1383    Evas_Display_Mode dispmode;
1384 
1385    ELM_NAVIFRAME_DATA_GET(obj, sd);
1386 
1387    dispmode = evas_object_size_hint_display_mode_get(obj);
1388    if (sd->dispmode == dispmode) return;
1389 
1390    sd->dispmode = dispmode;
1391 
1392    EINA_INLIST_FOREACH(sd->stack, it)
1393      _item_dispmode_set(it, dispmode);
1394 }
1395 
1396 EOLIAN static void
_elm_naviframe_efl_canvas_group_group_add(Eo * obj,Elm_Naviframe_Data * priv)1397 _elm_naviframe_efl_canvas_group_group_add(Eo *obj, Elm_Naviframe_Data *priv)
1398 {
1399    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
1400 
1401    efl_canvas_group_add(efl_super(obj, MY_CLASS));
1402 
1403    priv->dummy_edje = wd->resize_obj;
1404    evas_object_smart_member_add(priv->dummy_edje, obj);
1405 
1406    priv->auto_pushed = _elm_config->naviframe_prev_btn_auto_pushed;
1407    priv->freeze_events = EINA_TRUE;
1408 
1409    evas_object_event_callback_add(obj, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
1410                                   _on_obj_size_hints_changed, obj);
1411    elm_widget_can_focus_set(obj, EINA_FALSE);
1412 }
1413 
1414 static void
_send_signal(Elm_Naviframe_Item_Data * it,const char * sig)1415 _send_signal(Elm_Naviframe_Item_Data *it, const char *sig)
1416 {
1417    if (!it) return ;
1418    elm_object_signal_emit(VIEW(it), sig, "elm");
1419    edje_object_message_signal_process(elm_layout_edje_get(VIEW(it)));
1420 }
1421 
1422 static void
_deferred(void * data,const Efl_Event * event EINA_UNUSED)1423 _deferred(void *data, const Efl_Event *event EINA_UNUSED)
1424 {
1425    Elm_Naviframe_Data *nfd = data;
1426    Elm_Naviframe_Op *nfo;
1427 
1428    EINA_LIST_FREE(nfd->ops, nfo)
1429      {
1430         const char *signals_cur[] = {
1431           "elm,state,cur,popped,deferred",
1432           "elm,state,cur,pushed,deferred"
1433         };
1434         const char *signals_prev = "elm,state,prev,popped,deferred";
1435         const char *signals_new = "elm,state,new,pushed,deferred";
1436         Elm_Naviframe_Item_Data *cur;
1437         Elm_Naviframe_Item_Data *other;
1438 
1439         cur = nfo->push ? nfo->related : nfo->self;
1440         other = nfo->push ? nfo->self : nfo->related;
1441 
1442         _send_signal(cur, signals_cur[nfo->push]);
1443         _send_signal(other, nfo->push ? signals_new : signals_prev);
1444 
1445         free(nfo);
1446      }
1447 
1448    efl_event_callback_del(nfd->obj, EFL_CANVAS_OBJECT_EVENT_ANIMATOR_TICK, _deferred, nfd);
1449 }
1450 
1451 EOLIAN static void
_elm_naviframe_efl_canvas_group_group_del(Eo * obj,Elm_Naviframe_Data * sd)1452 _elm_naviframe_efl_canvas_group_group_del(Eo *obj, Elm_Naviframe_Data *sd)
1453 {
1454    Elm_Naviframe_Item_Data *it;
1455    Elm_Naviframe_Op *nfo;
1456    Eina_Inlist *l = NULL;
1457 
1458    sd->on_deletion = EINA_TRUE;
1459    if (sd->stack) l = sd->stack->last;
1460 
1461    while (l)
1462      {
1463         it = EINA_INLIST_CONTAINER_GET(l, Elm_Naviframe_Item_Data);
1464         l = l->prev;
1465         efl_del(EO_OBJ(it));
1466      }
1467 
1468    // No need to cleanup animator as it is an event on myself
1469    EINA_LIST_FREE(sd->ops, nfo)
1470      free(nfo);
1471    EINA_LIST_FREE(sd->popping, it)
1472      efl_del(EO_OBJ(it));
1473 
1474    evas_object_del(sd->dummy_edje);
1475 
1476    efl_canvas_group_del(efl_super(obj, MY_CLASS));
1477 }
1478 
1479 //Show only the top item view
1480 EOLIAN static void
_elm_naviframe_efl_gfx_entity_visible_set(Eo * obj,Elm_Naviframe_Data * sd EINA_UNUSED,Eina_Bool vis)1481 _elm_naviframe_efl_gfx_entity_visible_set(Eo *obj, Elm_Naviframe_Data *sd EINA_UNUSED, Eina_Bool vis)
1482 {
1483    Elm_Object_Item *eo_top;
1484 
1485    if (_evas_object_intercept_call(obj, EVAS_OBJECT_INTERCEPT_CB_VISIBLE, 0, vis))
1486      return;
1487 
1488    efl_gfx_entity_visible_set(efl_super(obj, MY_CLASS), vis);
1489    if (!vis) return;
1490 
1491    eo_top = elm_naviframe_top_item_get(obj);
1492    ELM_NAVIFRAME_ITEM_DATA_GET(eo_top, top);
1493 
1494    if (top && !top->delete_me)
1495      evas_object_show(VIEW(top));
1496 }
1497 
1498 static Eina_Bool
_key_action_top_item_get(Evas_Object * obj,const char * params EINA_UNUSED)1499 _key_action_top_item_get(Evas_Object *obj, const char *params EINA_UNUSED)
1500 {
1501    Elm_Object_Item *eo_item = NULL;
1502    eo_item = elm_obj_naviframe_top_item_get(obj);
1503    if (!eo_item) return EINA_FALSE;
1504 
1505    //FIXME: Replace this below code to elm_naviframe_item_pop() at elm 2.0.
1506    ///Leave for compatibility.
1507    ELM_NAVIFRAME_ITEM_DATA_GET(eo_item, it);
1508    if (it->title_prev_btn)
1509      efl_event_callback_legacy_call(it->title_prev_btn, EFL_INPUT_EVENT_CLICKED, NULL);
1510 
1511    return EINA_TRUE;
1512 }
1513 
1514 static Eina_Bool
_key_action_item_pop(Evas_Object * obj,const char * params EINA_UNUSED)1515 _key_action_item_pop(Evas_Object *obj, const char *params EINA_UNUSED)
1516 {
1517    Elm_Object_Item *eo_item = NULL;
1518    eo_item = elm_naviframe_top_item_get(obj);
1519    if (!eo_item) return EINA_FALSE;
1520 
1521    ELM_NAVIFRAME_ITEM_DATA_GET(eo_item, it);
1522 
1523    if (it->pushing || it->popping) return EINA_FALSE;
1524 
1525    elm_naviframe_item_pop(obj);
1526 
1527    return EINA_TRUE;
1528 }
1529 
1530 EOLIAN static void
_elm_naviframe_efl_ui_widget_on_access_update(Eo * obj EINA_UNUSED,Elm_Naviframe_Data * sd,Eina_Bool is_access)1531 _elm_naviframe_efl_ui_widget_on_access_update(Eo *obj EINA_UNUSED, Elm_Naviframe_Data *sd, Eina_Bool is_access)
1532 {
1533    Elm_Naviframe_Item_Data *it;
1534 
1535    EINA_INLIST_FOREACH(sd->stack, it)
1536      _access_obj_process(it, is_access);
1537 }
1538 
1539 static void
_schedule_deferred(Elm_Naviframe_Op * nfo,Elm_Naviframe_Data * sd)1540 _schedule_deferred(Elm_Naviframe_Op *nfo, Elm_Naviframe_Data *sd)
1541 {
1542    if (!sd->ops)
1543      efl_event_callback_add(sd->obj, EFL_CANVAS_OBJECT_EVENT_ANIMATOR_TICK, _deferred, sd);
1544 
1545    sd->ops = eina_list_append(sd->ops, nfo);
1546 }
1547 
1548 static void
_item_push_helper(Elm_Naviframe_Item_Data * item)1549 _item_push_helper(Elm_Naviframe_Item_Data *item)
1550 {
1551    Elm_Object_Item *eo_top_item;
1552    Evas_Object *obj = WIDGET(item);
1553    ELM_NAVIFRAME_DATA_GET(obj, sd);
1554    eo_top_item = elm_naviframe_top_item_get(obj);
1555    evas_object_show(VIEW(item));
1556 
1557    ELM_NAVIFRAME_ITEM_DATA_GET(eo_top_item, top_item);
1558    _resize_object_reset(obj, item);
1559    if (top_item)
1560      {
1561         Elm_Naviframe_Op *nfo = calloc(1, sizeof (Elm_Naviframe_Op));
1562 
1563         elm_widget_tree_unfocusable_set(VIEW(item), EINA_TRUE);
1564         elm_widget_tree_unfocusable_set(VIEW(top_item), EINA_TRUE);
1565 
1566         if (sd->freeze_events)
1567           {
1568              evas_object_freeze_events_set(VIEW(item), EINA_TRUE);
1569              evas_object_freeze_events_set(VIEW(top_item), EINA_TRUE);
1570           }
1571         elm_object_signal_emit(VIEW(top_item), "elm,state,cur,pushed", "elm");
1572         elm_object_signal_emit(VIEW(item), "elm,state,new,pushed", "elm");
1573         edje_object_message_signal_process(elm_layout_edje_get(VIEW(top_item)));
1574         edje_object_message_signal_process(elm_layout_edje_get(VIEW(item)));
1575 
1576         nfo->self = item;
1577         nfo->related = top_item;
1578         nfo->push = EINA_TRUE;
1579 
1580         _schedule_deferred(nfo, sd);
1581 
1582         if (top_item) top_item->pushing = EINA_FALSE;
1583         item->pushing = EINA_TRUE;
1584      }
1585    else
1586      {
1587         if (elm_object_focus_allow_get(VIEW(item)))
1588           elm_object_focus_set(VIEW(item), EINA_TRUE);
1589         else
1590           elm_object_focus_set(WIDGET(item), EINA_TRUE);
1591      }
1592 
1593    sd->stack = eina_inlist_append(sd->stack, EINA_INLIST_GET(item));
1594 
1595    if (!top_item)
1596      elm_object_signal_emit(VIEW(item), "elm,state,visible", "elm");
1597 
1598    elm_layout_sizing_eval(obj);
1599 
1600    if (!top_item)
1601      efl_event_callback_legacy_call(obj, ELM_NAVIFRAME_EVENT_ITEM_ACTIVATED, EO_OBJ(item));
1602 }
1603 
1604 EAPI Evas_Object *
elm_naviframe_add(Evas_Object * parent)1605 elm_naviframe_add(Evas_Object *parent)
1606 {
1607    EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
1608    return elm_legacy_add(MY_CLASS, parent);
1609 }
1610 
1611 EOLIAN static Eo *
_elm_naviframe_efl_object_constructor(Eo * obj,Elm_Naviframe_Data * sd)1612 _elm_naviframe_efl_object_constructor(Eo *obj, Elm_Naviframe_Data *sd)
1613 {
1614    obj = efl_constructor(efl_super(obj, MY_CLASS));
1615    sd->obj = obj;
1616    legacy_child_focus_handle(obj);
1617    efl_canvas_object_type_set(obj, MY_CLASS_NAME_LEGACY);
1618    evas_object_smart_callbacks_descriptions_set(obj, _smart_callbacks);
1619    efl_access_object_role_set(obj, EFL_ACCESS_ROLE_PAGE_TAB_LIST);
1620 
1621    return obj;
1622 }
1623 
1624 EOLIAN static Elm_Object_Item*
_elm_naviframe_item_push(Eo * obj,Elm_Naviframe_Data * sd EINA_UNUSED,const char * title_label,Evas_Object * prev_btn,Evas_Object * next_btn,Evas_Object * content,const char * item_style)1625 _elm_naviframe_item_push(Eo *obj, Elm_Naviframe_Data *sd EINA_UNUSED, const char *title_label, Evas_Object *prev_btn, Evas_Object *next_btn, Evas_Object *content, const char *item_style)
1626 {
1627    Elm_Object_Item *top_item, *eo_item;
1628 
1629    top_item = elm_naviframe_top_item_get(obj);
1630    eo_item = _item_new(obj, top_item,
1631                   title_label, prev_btn, next_btn, content, item_style);
1632    ELM_NAVIFRAME_ITEM_DATA_GET(eo_item, item);
1633    if (!item) return NULL;
1634    _item_push_helper(item);
1635    return eo_item;
1636 }
1637 
1638 EOLIAN static Elm_Object_Item*
_elm_naviframe_item_insert_before(Eo * obj,Elm_Naviframe_Data * sd,Elm_Object_Item * eo_before,const char * title_label,Evas_Object * prev_btn,Evas_Object * next_btn,Evas_Object * content,const char * item_style)1639 _elm_naviframe_item_insert_before(Eo *obj, Elm_Naviframe_Data *sd, Elm_Object_Item *eo_before, const char *title_label, Evas_Object *prev_btn, Evas_Object *next_btn, Evas_Object *content, const char *item_style)
1640 {
1641    Elm_Object_Item *eo_it;
1642    Elm_Naviframe_Item_Data *prev_it = NULL;
1643 
1644    EINA_SAFETY_ON_NULL_RETURN_VAL(eo_before, NULL);
1645    ELM_NAVIFRAME_ITEM_DATA_GET(eo_before, before);
1646 
1647    ELM_NAVIFRAME_ITEM_CHECK_OR_RETURN(before, NULL);
1648 
1649    eo_it = eo_before;
1650    ELM_NAVIFRAME_ITEM_DATA_GET(eo_it, it);
1651    if (EINA_INLIST_GET(it)->prev)
1652      prev_it = EINA_INLIST_CONTAINER_GET(EINA_INLIST_GET(it)->prev,
1653                                          Elm_Naviframe_Item_Data);
1654    eo_it = _item_new(obj, EO_OBJ(prev_it),
1655                   title_label, prev_btn, next_btn, content, item_style);
1656    if (!eo_it) return NULL;
1657 
1658    it = efl_data_scope_get(eo_it, ELM_NAVIFRAME_ITEM_CLASS);
1659 
1660    sd->stack = eina_inlist_prepend_relative
1661        (sd->stack, EINA_INLIST_GET(it),
1662        EINA_INLIST_GET(before));
1663 
1664    elm_widget_tree_unfocusable_set(VIEW(it), EINA_TRUE);
1665    evas_object_hide(VIEW(it));
1666    elm_object_signal_emit(VIEW(it), "elm,state,invisible", "elm");
1667 
1668    elm_layout_sizing_eval(obj);
1669 
1670    return eo_it;
1671 }
1672 
1673 EOLIAN static Elm_Object_Item*
_elm_naviframe_item_insert_after(Eo * obj,Elm_Naviframe_Data * sd,Elm_Object_Item * eo_after,const char * title_label,Evas_Object * prev_btn,Evas_Object * next_btn,Evas_Object * content,const char * item_style)1674 _elm_naviframe_item_insert_after(Eo *obj, Elm_Naviframe_Data *sd, Elm_Object_Item *eo_after, const char *title_label, Evas_Object *prev_btn, Evas_Object *next_btn, Evas_Object *content, const char *item_style)
1675 {
1676    Elm_Object_Item *eo_item;
1677    Eina_Bool top_inserted = EINA_FALSE;
1678 
1679    EINA_SAFETY_ON_NULL_RETURN_VAL(eo_after, NULL);
1680    ELM_NAVIFRAME_ITEM_DATA_GET(eo_after, after);
1681 
1682    ELM_NAVIFRAME_ITEM_CHECK_OR_RETURN(after, NULL);
1683 
1684    eo_item = _item_new(obj, eo_after,
1685                   title_label, prev_btn, next_btn, content, item_style);
1686    if (!eo_item) return NULL;
1687 
1688    ELM_NAVIFRAME_ITEM_DATA_GET(eo_item, it);
1689 
1690    if (elm_naviframe_top_item_get(obj) == eo_after) top_inserted = EINA_TRUE;
1691 
1692    sd->stack = eina_inlist_append_relative
1693        (sd->stack, EINA_INLIST_GET(it),
1694        EINA_INLIST_GET(after));
1695 
1696 
1697    if (top_inserted)
1698      {
1699         elm_widget_tree_unfocusable_set(VIEW(after), EINA_TRUE);
1700         _resize_object_reset(obj, it);
1701         evas_object_show(VIEW(it));
1702         evas_object_hide(VIEW(after));
1703         if (elm_object_focus_allow_get(VIEW(it)))
1704           elm_object_focus_set(VIEW(it), EINA_TRUE);
1705         else
1706           elm_object_focus_set(WIDGET(it), EINA_TRUE);
1707         elm_object_signal_emit(VIEW(it), "elm,state,visible", "elm");
1708         elm_object_signal_emit(VIEW(after), "elm,state,invisible", "elm");
1709      }
1710    else
1711      elm_object_signal_emit(VIEW(it), "elm,state,invisible", "elm");
1712 
1713    elm_layout_sizing_eval(obj);
1714 
1715    if (top_inserted)
1716      efl_event_callback_legacy_call(obj, ELM_NAVIFRAME_EVENT_ITEM_ACTIVATED, eo_item);
1717 
1718    return eo_item;
1719 }
1720 
1721 EOLIAN static Evas_Object*
_elm_naviframe_item_pop(Eo * obj,Elm_Naviframe_Data * sd)1722 _elm_naviframe_item_pop(Eo *obj, Elm_Naviframe_Data *sd)
1723 {
1724    Elm_Object_Item *eo_item;
1725    Elm_Naviframe_Item_Data *prev_it = NULL;
1726    Evas_Object *content = NULL;
1727 
1728    eo_item = elm_naviframe_top_item_get(obj);
1729    if (!eo_item) return NULL;
1730 
1731    ELM_NAVIFRAME_ITEM_DATA_GET(eo_item, it);
1732 
1733    if (it->pushing || it->popping) return NULL;
1734    it->popping = EINA_TRUE;
1735 
1736    evas_object_ref(obj);
1737    if (it->pop_cb)
1738      {
1739         efl_ref(eo_item);
1740         if (!it->pop_cb(it->pop_data, eo_item))
1741           {
1742              efl_unref(eo_item);
1743              if (!it->delete_me)
1744                {
1745                   /* To avoid multiple item pops, the auto pushed button deletes
1746                      its clicked callback once it is called.
1747                      Since the item is not popped or deleted here, the deleted
1748                      callback of the auto pushed button should be restored. */
1749                   if (it->auto_pushed_btn)
1750                     evas_object_smart_callback_add(it->auto_pushed_btn, "clicked", _on_item_back_btn_clicked, obj);
1751                   it->popping = EINA_FALSE;
1752                }
1753              evas_object_unref(obj);
1754              return NULL;
1755           }
1756         efl_unref(eo_item);
1757      }
1758    evas_object_unref(obj);
1759 
1760    if (sd->preserve)
1761      content = it->content;
1762 
1763    evas_object_data_set(VIEW(it), "out_of_list", (void *)1);
1764 
1765    if (sd->stack->last->prev)
1766      prev_it = EINA_INLIST_CONTAINER_GET
1767          (sd->stack->last->prev, Elm_Naviframe_Item_Data);
1768 
1769    sd->stack = eina_inlist_remove(sd->stack, EINA_INLIST_GET(it));
1770 
1771    if (prev_it)
1772      {
1773         Elm_Naviframe_Op *nfo = calloc(1, sizeof (Elm_Naviframe_Op));
1774 
1775         elm_widget_tree_unfocusable_set(VIEW(it), EINA_TRUE);
1776 
1777         if (sd->freeze_events)
1778           {
1779              evas_object_freeze_events_set(VIEW(it), EINA_TRUE);
1780              evas_object_freeze_events_set(VIEW(prev_it), EINA_TRUE);
1781           }
1782 
1783         elm_widget_resize_object_set(obj, VIEW(prev_it));
1784 
1785         /* these 2 signals MUST take place simultaneously */
1786         elm_object_signal_emit(VIEW(it), "elm,state,cur,popped", "elm");
1787         elm_object_signal_emit(VIEW(prev_it), "elm,state,prev,popped", "elm");
1788         edje_object_message_signal_process(elm_layout_edje_get(VIEW(it)));
1789         edje_object_message_signal_process(elm_layout_edje_get(VIEW(prev_it)));
1790 
1791         //Show hidden previous view when pop transition begins.
1792         evas_object_show(VIEW(prev_it));
1793 
1794         if (!nfo) goto on_error;
1795 
1796         nfo->self = it;
1797         nfo->related = prev_it;
1798         nfo->push = EINA_FALSE;
1799 
1800         sd->popping = eina_list_append(sd->popping, it);
1801 
1802         _schedule_deferred(nfo, sd);
1803      }
1804    else
1805      efl_del(eo_item);
1806 
1807  on_error:
1808    return content;
1809 }
1810 
1811 EOLIAN static void
_elm_naviframe_item_pop_to(Eo * eo_it,Elm_Naviframe_Item_Data * it)1812 _elm_naviframe_item_pop_to(Eo *eo_it, Elm_Naviframe_Item_Data *it)
1813 {
1814    Eina_Inlist *l;
1815 
1816    ELM_NAVIFRAME_DATA_GET(WIDGET(it), sd);
1817 
1818    if (eo_it == elm_naviframe_top_item_get(WIDGET(it))) return;
1819 
1820    l = sd->stack->last->prev;
1821 
1822    sd->on_deletion = EINA_TRUE;
1823 
1824    while (l)
1825      {
1826         Elm_Naviframe_Item_Data *iit = EINA_INLIST_CONTAINER_GET
1827             (l, Elm_Naviframe_Item_Data);
1828 
1829         if (iit == it) break;
1830 
1831         l = l->prev;
1832 
1833         efl_del(EO_OBJ(iit));
1834      }
1835 
1836    sd->on_deletion = EINA_FALSE;
1837 
1838    elm_naviframe_item_pop(WIDGET(it));
1839 }
1840 
1841 EOLIAN static void
_elm_naviframe_item_promote(Eo * eo_it,Elm_Naviframe_Item_Data * it)1842 _elm_naviframe_item_promote(Eo *eo_it, Elm_Naviframe_Item_Data *it)
1843 {
1844    Elm_Object_Item *eo_prev_top;
1845    Elm_Naviframe_Item_Data *nit = it;
1846 
1847    ELM_NAVIFRAME_DATA_GET(WIDGET(nit), sd);
1848 
1849    eo_prev_top = elm_naviframe_top_item_get(WIDGET(nit));
1850    if (eo_it == eo_prev_top) return;
1851 
1852    sd->stack = eina_inlist_remove(sd->stack, EINA_INLIST_GET(nit));
1853    _item_push_helper(nit);
1854 }
1855 
1856 EOLIAN static void
_elm_naviframe_item_simple_promote(Eo * obj EINA_UNUSED,Elm_Naviframe_Data * sd,Evas_Object * content)1857 _elm_naviframe_item_simple_promote(Eo *obj EINA_UNUSED, Elm_Naviframe_Data *sd, Evas_Object *content)
1858 {
1859    Elm_Naviframe_Item_Data *itr;
1860 
1861    EINA_INLIST_FOREACH(sd->stack, itr)
1862      {
1863         if (elm_object_item_content_get(EO_OBJ(itr)) == content)
1864           {
1865              elm_naviframe_item_promote(EO_OBJ(itr));
1866              break;
1867           }
1868      }
1869 }
1870 
1871 EOLIAN static void
_elm_naviframe_content_preserve_on_pop_set(Eo * obj EINA_UNUSED,Elm_Naviframe_Data * sd,Eina_Bool preserve)1872 _elm_naviframe_content_preserve_on_pop_set(Eo *obj EINA_UNUSED, Elm_Naviframe_Data *sd, Eina_Bool preserve)
1873 {
1874    sd->preserve = !!preserve;
1875 }
1876 
1877 EOLIAN static Eina_Bool
_elm_naviframe_content_preserve_on_pop_get(const Eo * obj EINA_UNUSED,Elm_Naviframe_Data * sd)1878 _elm_naviframe_content_preserve_on_pop_get(const Eo *obj EINA_UNUSED, Elm_Naviframe_Data *sd)
1879 {
1880    return sd->preserve;
1881 }
1882 
1883 EOLIAN static Elm_Object_Item*
_elm_naviframe_top_item_get(const Eo * obj EINA_UNUSED,Elm_Naviframe_Data * sd)1884 _elm_naviframe_top_item_get(const Eo *obj EINA_UNUSED, Elm_Naviframe_Data *sd)
1885 {
1886    if (!sd->stack) return NULL;
1887    Elm_Naviframe_Item_Data *ret_it = EINA_INLIST_CONTAINER_GET
1888                                 (sd->stack->last, Elm_Naviframe_Item_Data);
1889    return EO_OBJ(ret_it);
1890 }
1891 
1892 EOLIAN static Elm_Object_Item*
_elm_naviframe_bottom_item_get(const Eo * obj EINA_UNUSED,Elm_Naviframe_Data * sd)1893 _elm_naviframe_bottom_item_get(const Eo *obj EINA_UNUSED, Elm_Naviframe_Data *sd)
1894 {
1895    if (!sd->stack) return NULL;
1896    Elm_Naviframe_Item_Data *ret_it = EINA_INLIST_CONTAINER_GET
1897                                 (sd->stack, Elm_Naviframe_Item_Data);
1898    return EO_OBJ(ret_it);
1899 }
1900 
1901 EOLIAN static void
_elm_naviframe_item_elm_widget_item_style_set(Eo * eo_item EINA_UNUSED,Elm_Naviframe_Item_Data * nit,const char * item_style)1902 _elm_naviframe_item_elm_widget_item_style_set(Eo *eo_item EINA_UNUSED,
1903                               Elm_Naviframe_Item_Data *nit,
1904                               const char *item_style)
1905 {
1906    if (item_style && eina_streq(item_style, elm_wdg_item_style_get(EO_OBJ(nit)))) return;
1907 
1908    if (!item_style)
1909      if (eina_streq("basic", elm_wdg_item_style_get(EO_OBJ(nit)))) return;
1910 
1911    _item_style_set(nit, item_style);
1912    _item_signals_emit(nit);
1913    _item_title_enabled_update(nit, EINA_FALSE);
1914 }
1915 
1916 EAPI void
elm_naviframe_item_style_set(Elm_Object_Item * obj,const char * style)1917 elm_naviframe_item_style_set(Elm_Object_Item *obj, const char *style)
1918 {
1919    elm_wdg_item_style_set(obj, style);
1920 }
1921 
1922 EAPI const char *
elm_naviframe_item_style_get(const Elm_Object_Item * obj)1923 elm_naviframe_item_style_get(const Elm_Object_Item *obj)
1924 {
1925    return elm_wdg_item_style_get(obj);
1926 }
1927 
1928 EINA_DEPRECATED EAPI void
elm_naviframe_item_title_visible_set(Elm_Object_Item * it,Eina_Bool visible)1929 elm_naviframe_item_title_visible_set(Elm_Object_Item *it,
1930                                      Eina_Bool visible)
1931 {
1932    elm_naviframe_item_title_enabled_set(it, visible, EINA_FALSE);
1933 }
1934 
1935 EINA_DEPRECATED EAPI Eina_Bool
elm_naviframe_item_title_visible_get(const Elm_Object_Item * it)1936 elm_naviframe_item_title_visible_get(const Elm_Object_Item *it)
1937 {
1938    return elm_naviframe_item_title_enabled_get(it);
1939 }
1940 
1941 EOLIAN static void
_elm_naviframe_item_title_enabled_set(Eo * eo_item EINA_UNUSED,Elm_Naviframe_Item_Data * nit,Eina_Bool enabled,Eina_Bool transition)1942 _elm_naviframe_item_title_enabled_set(Eo *eo_item EINA_UNUSED,
1943                                       Elm_Naviframe_Item_Data *nit,
1944                                       Eina_Bool enabled,
1945                                       Eina_Bool transition)
1946 {
1947    enabled = !!enabled;
1948    if (nit->title_enabled == enabled) return;
1949 
1950    nit->title_enabled = enabled;
1951 
1952    transition = !!transition;
1953    _item_title_enabled_update(nit, transition);
1954 }
1955 
1956 EOLIAN static Eina_Bool
_elm_naviframe_item_title_enabled_get(const Eo * eo_item EINA_UNUSED,Elm_Naviframe_Item_Data * nit)1957 _elm_naviframe_item_title_enabled_get(const Eo *eo_item EINA_UNUSED, Elm_Naviframe_Item_Data *nit)
1958 {
1959    return nit->title_enabled;
1960 }
1961 
1962 EOLIAN static void
_elm_naviframe_item_pop_cb_set(Eo * eo_item EINA_UNUSED,Elm_Naviframe_Item_Data * nit,Elm_Naviframe_Item_Pop_Cb func,void * data)1963 _elm_naviframe_item_pop_cb_set(Eo *eo_item EINA_UNUSED,
1964                                Elm_Naviframe_Item_Data *nit,
1965                                Elm_Naviframe_Item_Pop_Cb func,
1966                                void *data)
1967 {
1968    nit->pop_cb = func;
1969    nit->pop_data = data;
1970 }
1971 
1972 EOLIAN static Eina_List*
_elm_naviframe_item_efl_access_object_access_children_get(const Eo * eo_item EINA_UNUSED,Elm_Naviframe_Item_Data * nit)1973 _elm_naviframe_item_efl_access_object_access_children_get(const Eo *eo_item EINA_UNUSED, Elm_Naviframe_Item_Data *nit)
1974 {
1975    Eina_List *ret = NULL;
1976 
1977    ret = eina_list_append(ret, VIEW(nit));
1978    return ret;
1979 }
1980 
1981 EOLIAN static void
_elm_naviframe_prev_btn_auto_pushed_set(Eo * obj EINA_UNUSED,Elm_Naviframe_Data * sd,Eina_Bool auto_pushed)1982 _elm_naviframe_prev_btn_auto_pushed_set(Eo *obj EINA_UNUSED, Elm_Naviframe_Data *sd, Eina_Bool auto_pushed)
1983 {
1984    sd->auto_pushed = !!auto_pushed;
1985 }
1986 
1987 EOLIAN static Eina_Bool
_elm_naviframe_prev_btn_auto_pushed_get(const Eo * obj EINA_UNUSED,Elm_Naviframe_Data * sd)1988 _elm_naviframe_prev_btn_auto_pushed_get(const Eo *obj EINA_UNUSED, Elm_Naviframe_Data *sd)
1989 {
1990    return sd->auto_pushed;
1991 }
1992 
1993 EOLIAN static Eina_List*
_elm_naviframe_items_get(const Eo * obj EINA_UNUSED,Elm_Naviframe_Data * sd)1994 _elm_naviframe_items_get(const Eo *obj EINA_UNUSED, Elm_Naviframe_Data *sd)
1995 {
1996    Eina_List *ret = NULL;
1997    Elm_Naviframe_Item_Data *itr;
1998 
1999    EINA_INLIST_FOREACH(sd->stack, itr)
2000      ret = eina_list_append(ret, EO_OBJ(itr));
2001 
2002    return ret;
2003 }
2004 
2005 EOLIAN static void
_elm_naviframe_event_enabled_set(Eo * obj EINA_UNUSED,Elm_Naviframe_Data * sd,Eina_Bool enabled)2006 _elm_naviframe_event_enabled_set(Eo *obj EINA_UNUSED, Elm_Naviframe_Data *sd, Eina_Bool enabled)
2007 {
2008    enabled = !!enabled;
2009    if (sd->freeze_events == !enabled) return;
2010    sd->freeze_events = !enabled;
2011 }
2012 
2013 EOLIAN static Eina_Bool
_elm_naviframe_event_enabled_get(const Eo * obj EINA_UNUSED,Elm_Naviframe_Data * sd)2014 _elm_naviframe_event_enabled_get(const Eo *obj EINA_UNUSED, Elm_Naviframe_Data *sd)
2015 {
2016    return !sd->freeze_events;
2017 }
2018 
2019 static void
_elm_naviframe_class_constructor(Efl_Class * klass)2020 _elm_naviframe_class_constructor(Efl_Class *klass)
2021 {
2022    evas_smart_legacy_type_register(MY_CLASS_NAME_LEGACY, klass);
2023 }
2024 
2025 EOLIAN const Efl_Access_Action_Data *
_elm_naviframe_efl_access_widget_action_elm_actions_get(const Eo * obj EINA_UNUSED,Elm_Naviframe_Data * pd EINA_UNUSED)2026 _elm_naviframe_efl_access_widget_action_elm_actions_get(const Eo *obj EINA_UNUSED, Elm_Naviframe_Data *pd EINA_UNUSED)
2027 {
2028    static Efl_Access_Action_Data atspi_actions[] = {
2029           { "top_item_get", "top_item_get", NULL, _key_action_top_item_get },
2030           { "item_pop", "item_pop", NULL, _key_action_item_pop },
2031           { NULL, NULL, NULL, NULL }
2032    };
2033    return &atspi_actions[0];
2034 }
2035 
2036 /* Standard widget overrides */
2037 
2038 ELM_WIDGET_KEY_DOWN_DEFAULT_IMPLEMENT(elm_naviframe, Elm_Naviframe_Data)
2039 
2040 /* Efl.Part begin */
2041 
2042 ELM_PART_OVERRIDE(elm_naviframe, ELM_NAVIFRAME, Elm_Naviframe_Data)
2043 ELM_PART_OVERRIDE_CONTENT_SET(elm_naviframe, ELM_NAVIFRAME, Elm_Naviframe_Data)
2044 ELM_PART_OVERRIDE_CONTENT_GET(elm_naviframe, ELM_NAVIFRAME, Elm_Naviframe_Data)
2045 ELM_PART_OVERRIDE_CONTENT_UNSET(elm_naviframe, ELM_NAVIFRAME, Elm_Naviframe_Data)
2046 ELM_PART_OVERRIDE_TEXT_SET(elm_naviframe, ELM_NAVIFRAME, Elm_Naviframe_Data)
2047 ELM_PART_OVERRIDE_TEXT_GET(elm_naviframe, ELM_NAVIFRAME, Elm_Naviframe_Data)
2048 #include "elm_naviframe_part.eo.c"
2049 
2050 /* Efl.Part end */
2051 
2052 /* Internal EO APIs and hidden overrides */
2053 
2054 #define ELM_NAVIFRAME_EXTRA_OPS \
2055    EFL_CANVAS_GROUP_CALC_OPS(elm_naviframe), \
2056    EFL_CANVAS_GROUP_ADD_DEL_OPS(elm_naviframe)
2057 
2058 #include "elm_naviframe_item_eo.c"
2059 #include "elm_naviframe_eo.c"
2060