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