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