elementary/naviframe - more clean tree
[framework/uifw/elementary.git] / src / lib / elc_naviframe.c
1 #include <Elementary.h>
2 #include "elm_priv.h"
3
4 typedef struct _Widget_Data Widget_Data;
5 typedef struct _Elm_Naviframe_Item Elm_Naviframe_Item;
6 typedef struct _Elm_Naviframe_Content_Item_Pair Elm_Naviframe_Content_Item_Pair;
7 typedef struct _Elm_Naviframe_Text_Item_Pair Elm_Naviframe_Text_Item_Pair;
8
9 struct _Widget_Data
10 {
11    Eina_Inlist  *stack;
12    Evas_Object  *base;
13    Eina_Bool     preserve: 1;
14    Eina_Bool     auto_pushed: 1;
15    Eina_Bool     freeze_events: 1;
16 };
17
18 struct _Elm_Naviframe_Content_Item_Pair
19 {
20    EINA_INLIST;
21    const char *part;
22    Elm_Naviframe_Item *it;
23 };
24
25 struct _Elm_Naviframe_Text_Item_Pair
26 {
27    EINA_INLIST;
28    const char *part;
29 };
30
31 struct _Elm_Naviframe_Item
32 {
33    ELM_WIDGET_ITEM;
34    EINA_INLIST;
35    Eina_Inlist       *content_list;
36    Eina_Inlist       *text_list;
37    Evas_Object       *content;
38    Evas_Object       *title_prev_btn;
39    Evas_Object       *title_next_btn;
40    Evas_Object       *title_icon;
41    const char        *style;
42    Evas_Coord         minw;
43    Evas_Coord         minh;
44    Eina_Bool          back_btn: 1;
45    Eina_Bool          title_visible: 1;
46 };
47
48 static const char *widtype = NULL;
49
50 //widget signals
51 static const char SIG_TRANSITION_FINISHED[] = "transition,finished";
52 static const char SIG_TITLE_CLICKED[] = "title,clicked";
53
54 static const Evas_Smart_Cb_Description _signals[] = {
55        {SIG_TRANSITION_FINISHED, ""},
56        {SIG_TITLE_CLICKED, ""},
57        {NULL, NULL}
58 };
59
60 static void _text_set_hook(Evas_Object *obj,
61                            const char *part,
62                            const char *label);
63 static const char *_text_get_hook(const Evas_Object *obj, const char *part);
64 static void _content_set_hook(Evas_Object *obj,
65                               const char *part,
66                               Evas_Object *content);
67 static Evas_Object *_content_get_hook(const Evas_Object *obj, const char *part);
68 static Evas_Object *_content_unset_hook(Evas_Object *obj, const char *part);
69 static void _del_hook(Evas_Object *obj);
70 static void _theme_hook(Evas_Object *obj);
71 static void _emit_hook(Evas_Object *obj,
72                        const char *emission,
73                        const char *source);
74 static void _disable_hook(Evas_Object *obj);
75 static void _item_text_set_hook(Elm_Object_Item *it,
76                                 const char *part,
77                                 const char *label);
78 static const char *_item_text_get_hook(const Elm_Object_Item *it,
79                                        const char *part);
80 static void _item_content_set_hook(Elm_Object_Item *it,
81                                    const char *part,
82                                    Evas_Object *content);
83 static Evas_Object *_item_content_get_hook(const Elm_Object_Item *it,
84                                            const char *part);
85 static Evas_Object *_item_content_unset_hook(Elm_Object_Item *it,
86                                              const char *part);
87 static void _item_signal_emit_hook(Elm_Object_Item *it,
88                                    const char *emission,
89                                    const char *source);
90 static void _item_title_visible_update(Elm_Naviframe_Item *navi_it);
91 static void _sizing_eval(Evas_Object *obj);
92 static void _move(void *data, Evas *e, Evas_Object *obj, void *event_info);
93 static void _resize(void *data,
94                     Evas *e,
95                     Evas_Object *obj,
96                     void *event_info);
97 static void _title_clicked(void *data, Evas_Object *obj,
98                            const char *emission,
99                            const char *source);
100 static void _back_btn_clicked(void *data,
101                               Evas_Object *obj,
102                               void *event_info);
103 static Evas_Object *_back_btn_new(Evas_Object *obj);
104 static void _item_content_del(void *data,
105                               Evas *e,
106                               Evas_Object *obj,
107                               void *event_info);
108 static void _title_content_del(void *data,
109                                Evas *e,
110                                Evas_Object *obj,
111                                void *event_info);
112 static void _title_prev_btn_del(void *data,
113                                 Evas *e,
114                                 Evas_Object *obj,
115                                 void *event_info);
116 static void _title_next_btn_del(void *data,
117                                 Evas *e,
118                                 Evas_Object *obj,
119                                 void *event_info);
120 static void _title_icon_del(void *data,
121                             Evas *e,
122                             Evas_Object *obj,
123                             void *event_info);
124 static void _title_content_set(Elm_Naviframe_Item *it,
125                                const char *part,
126                                Evas_Object *content);
127 static void _title_prev_btn_set(Elm_Naviframe_Item *it,
128                                 Evas_Object *btn,
129                                 Eina_Bool back_btn);
130 static void _title_next_btn_set(Elm_Naviframe_Item *it, Evas_Object *btn);
131 static void _title_icon_set(Elm_Naviframe_Item *it, Evas_Object *icon);
132 static Evas_Object * _item_content_unset(Elm_Naviframe_Item *it);
133 static Evas_Object * _title_prev_btn_unset(Elm_Naviframe_Item *it);
134 static Evas_Object * _title_next_btn_unset(Elm_Naviframe_Item *it);
135 static Evas_Object * _title_icon_unset(Elm_Naviframe_Item *it);
136 static Evas_Object * _title_content_unset(Elm_Naviframe_Item *it,
137                                           const char *part);
138 static void _item_del(Elm_Naviframe_Item *it);
139 static Eina_Bool _item_del_pre_hook(Elm_Object_Item *it);
140 static void _pushed_finished(void *data,
141                              Evas_Object *obj,
142                              const char *emission,
143                              const char *source);
144 static void _popped_finished(void *data,
145                              Evas_Object *obj,
146                              const char *emission,
147                              const char *source);
148 static void _show_finished(void *data,
149                            Evas_Object *obj,
150                            const char *emission,
151                            const char *source);
152 static void _changed_size_hints(void *data,
153                                 Evas *e,
154                                 Evas_Object *obj,
155                                 void *event_info);
156 static void _item_content_set(Elm_Naviframe_Item *navi_it,
157                               Evas_Object *content);
158 static void _item_style_set(Elm_Naviframe_Item *navi_it,
159                             const char *item_style);
160 static Elm_Naviframe_Item * _item_new(Evas_Object *obj,
161                                       const char *title_label,
162                                       Evas_Object *prev_btn,
163                                       Evas_Object *next_btn,
164                                       Evas_Object *content,
165                                       const char *item_style);
166 static Eina_Bool _focus_next_hook(const Evas_Object *obj,
167                                   Elm_Focus_Direction dir,
168                                   Evas_Object **next);
169
170 static void
171 _del_hook(Evas_Object *obj)
172 {
173    Widget_Data *wd;
174    Elm_Naviframe_Item *it;
175
176    wd = elm_widget_data_get(obj);
177    if (!wd) return;
178
179    if (wd->stack)
180      {
181         while (wd->stack->last)
182           {
183              it = EINA_INLIST_CONTAINER_GET(wd->stack->last,
184                                             Elm_Naviframe_Item);
185              wd->stack = eina_inlist_remove(wd->stack, wd->stack->last);
186              _item_del(it);
187              elm_widget_item_free(it);
188              if (!wd->stack) break;
189           }
190      }
191    free(wd);
192 }
193
194 static void
195 _theme_hook(Evas_Object *obj)
196 {
197    Widget_Data *wd;
198    Elm_Naviframe_Item *it;
199
200    wd  = elm_widget_data_get(obj);
201    if (!wd) return;
202
203    _elm_theme_object_set(obj,
204                          wd->base,
205                          "naviframe",
206                          "base",
207                          elm_widget_style_get(obj));
208
209    EINA_INLIST_FOREACH(wd->stack, it)
210      {
211         _item_style_set(it, it->style);
212         _item_title_visible_update(it);
213      }
214 }
215
216 static void _emit_hook(Evas_Object *obj,
217                        const char *emission,
218                        const char *source)
219 {
220    Elm_Object_Item *it = elm_naviframe_top_item_get(obj);
221    if (!it) return;
222    return elm_object_item_signal_emit(it, emission, source);
223 }
224
225 static void
226 _disable_hook(Evas_Object *obj __UNUSED__)
227 {
228    //FIXME:
229 }
230
231 static void
232 _item_text_set_hook(Elm_Object_Item *it,
233                     const char *part,
234                     const char *label)
235 {
236    Elm_Naviframe_Text_Item_Pair *pair = NULL;
237    Elm_Naviframe_Item *navi_it = (Elm_Naviframe_Item *)it;
238    char buf[1024];
239
240    if (!part || !strcmp(part, "default"))
241      snprintf(buf, sizeof(buf), "elm.text.title");
242    else if(!strcmp("subtitle", part))
243      snprintf(buf, sizeof(buf), "elm.text.subtitle");
244    else
245      snprintf(buf, sizeof(buf), "%s", part);
246
247    EINA_INLIST_FOREACH(navi_it->text_list, pair)
248      if (!strcmp(buf, pair->part)) break;
249
250    if (!pair)
251      {
252         pair = ELM_NEW(Elm_Naviframe_Text_Item_Pair);
253         if (!pair)
254           {
255              ERR("Failed to allocate new text part of the item! : naviframe=%p",
256              WIDGET(navi_it));
257              return;
258           }
259         eina_stringshare_replace(&pair->part, buf);
260         navi_it->text_list = eina_inlist_append(navi_it->text_list,
261                                                 EINA_INLIST_GET(pair));
262      }
263    elm_object_part_text_set(VIEW(navi_it), buf, label);
264
265    if (label)
266      {
267         snprintf(buf, sizeof(buf), "elm,state,%s,show", buf);
268         elm_object_signal_emit(VIEW(navi_it), buf, "elm");
269      }
270    else
271      {
272         snprintf(buf, sizeof(buf), "elm,state,%s,hide", buf);
273         elm_object_signal_emit(VIEW(navi_it), buf, "elm");
274      }
275
276    _sizing_eval(WIDGET(navi_it));
277 }
278
279 static const char *
280 _item_text_get_hook(const Elm_Object_Item *it, const char *part)
281 {
282    char buf[1024];
283
284    if (!part || !strcmp(part, "default"))
285      snprintf(buf, sizeof(buf), "elm.text.title");
286    else if(!strcmp("subtitle", part))
287      snprintf(buf, sizeof(buf), "elm.text.subtitle");
288    else
289      snprintf(buf, sizeof(buf), "%s", part);
290
291    return elm_object_part_text_get(VIEW(it), buf);
292 }
293
294 static void
295 _item_content_set_hook(Elm_Object_Item *it,
296                        const char *part,
297                        Evas_Object *content)
298 {
299    Elm_Naviframe_Item *navi_it = (Elm_Naviframe_Item *)it;
300
301    //specified parts
302    if (!part || !strcmp("default", part))
303      {
304         _item_content_set(navi_it, content);
305         return;
306      }
307    else if (!strcmp(part, "prev_btn"))
308      {
309         _title_prev_btn_set(navi_it, content, EINA_FALSE);
310         return;
311      }
312    else if (!strcmp(part, "next_btn"))
313      {
314         _title_next_btn_set(navi_it, content);
315         return;
316      }
317    else if (!strcmp(part, "icon"))
318      {
319         _title_icon_set(navi_it, content);
320         return;
321      }
322
323    //common part
324    _title_content_set(navi_it, part, content);
325 }
326
327 static Evas_Object *
328 _item_content_get_hook(const Elm_Object_Item *it, const char *part)
329 {
330    Elm_Naviframe_Item *navi_it = (Elm_Naviframe_Item *)it;
331
332    //specified parts
333    if (!part || !strcmp("default", part))
334      return navi_it->content;
335    else if (!strcmp(part, "prev_btn"))
336      return navi_it->title_prev_btn;
337    else if (!strcmp(part, "next_btn"))
338      return navi_it->title_next_btn;
339    else if (!strcmp(part, "icon"))
340      return navi_it->title_icon;
341
342    //common parts
343    return elm_object_part_content_get(VIEW(navi_it), part);
344 }
345
346 static Evas_Object *
347 _item_content_unset_hook(Elm_Object_Item *it, const char *part)
348 {
349    Elm_Naviframe_Item *navi_it = (Elm_Naviframe_Item *)it;
350
351    //specified parts
352    if (!part || !strcmp("default", part))
353      return _item_content_unset(navi_it);
354    else if (!strcmp(part, "prev_btn"))
355      return _title_prev_btn_unset(navi_it);
356    else if (!strcmp(part, "next_btn"))
357      return _title_next_btn_unset(navi_it);
358    else if (!strcmp(part, "icon"))
359      return _title_icon_unset(navi_it);
360
361    return _title_content_unset(navi_it, part);
362 }
363
364 static void
365 _item_signal_emit_hook(Elm_Object_Item *it,
366                        const char *emission,
367                        const char *source)
368 {
369    elm_object_signal_emit(VIEW(it), emission, source);
370 }
371
372 static void
373 _item_title_visible_update(Elm_Naviframe_Item *navi_it)
374 {
375    if (navi_it->title_visible)
376      elm_object_signal_emit(VIEW(navi_it), "elm,state,title,show", "elm");
377    else
378      elm_object_signal_emit(VIEW(navi_it), "elm,state,title,hide", "elm");
379 }
380
381 static void
382 _sizing_eval(Evas_Object *obj)
383 {
384    Widget_Data *wd;
385    Elm_Naviframe_Item *it;
386    Evas_Coord x, y, w, h;
387    Evas_Coord minw = -1, minh = -1;
388
389    wd = elm_widget_data_get(obj);
390    if (!wd) return;
391
392    evas_object_geometry_get(obj, &x, &y, &w, &h);
393
394    EINA_INLIST_FOREACH(wd->stack, it)
395      {
396         evas_object_move(VIEW(it), x, y);
397         evas_object_resize(VIEW(it), w, h);
398         edje_object_size_min_calc(elm_layout_edje_get(VIEW(it)),
399                                   &it->minw,
400                                   &it->minh);
401         if (it->minw > minw) minw = it->minw;
402         if (it->minh > minh) minh = it->minh;
403      }
404    evas_object_size_hint_min_set(obj, minw, minh);
405    evas_object_size_hint_max_set(obj, -1, -1);
406 }
407
408 static void
409 _move(void *data __UNUSED__,
410       Evas *e __UNUSED__,
411       Evas_Object *obj,
412       void *event_info __UNUSED__)
413 {
414    _sizing_eval(obj);
415 }
416
417 static void
418 _resize(void *data __UNUSED__,
419         Evas *e __UNUSED__,
420         Evas_Object *obj,
421         void *event_info __UNUSED__)
422 {
423    _sizing_eval(obj);
424 }
425
426 static void
427 _title_clicked(void *data,
428                Evas_Object *obj __UNUSED__,
429                const char *emission __UNUSED__,
430                const char *source __UNUSED__)
431 {
432    Elm_Naviframe_Item *it = data;
433    evas_object_smart_callback_call(WIDGET(it), SIG_TITLE_CLICKED, it);
434 }
435
436 static void
437 _back_btn_clicked(void *data,
438                   Evas_Object *obj,
439                   void *event_info __UNUSED__)
440 {
441 /* Since edje has the event queue, clicked event could be happend multiple times
442    on some heavy environment. This callback del will prevent those  scenario and
443    guarantee only one clicked for it's own page. */
444    evas_object_smart_callback_del(obj, "clicked", _back_btn_clicked);
445    elm_naviframe_item_pop(data);
446 }
447
448 static Evas_Object *
449 _back_btn_new(Evas_Object *obj)
450 {
451    Evas_Object *btn;
452    char buf[1024];
453    btn = elm_button_add(obj);
454    if (!btn) return NULL;
455    evas_object_smart_callback_add(btn, "clicked", _back_btn_clicked, obj);
456    snprintf(buf, sizeof(buf), "naviframe/back_btn/%s",
457             elm_widget_style_get(obj));
458    elm_object_style_set(btn, buf);
459    return btn;
460 }
461
462 static void _text_set_hook(Evas_Object *obj,
463                            const char *part,
464                            const char *label)
465 {
466    Elm_Object_Item *it = elm_naviframe_top_item_get(obj);
467    if (!it) return;
468    elm_object_item_part_text_set(it, part, label);
469 }
470
471 static const char *_text_get_hook(const Evas_Object *obj, const char *part)
472 {
473    Elm_Object_Item *it = elm_naviframe_top_item_get(obj);
474    if (!it) return NULL;
475    return elm_object_item_part_text_get(it, part);
476 }
477
478 static void
479 _content_set_hook(Evas_Object *obj, const char *part, Evas_Object *content)
480 {
481    Elm_Object_Item *it = elm_naviframe_top_item_get(obj);
482    if (!it) return;
483    elm_object_item_part_content_set(it, part, content);
484 }
485
486 static Evas_Object *
487 _content_unset_hook(Evas_Object *obj, const char *part)
488 {
489    Elm_Object_Item *it = elm_naviframe_top_item_get(obj);
490    if (!it) return NULL;
491    return elm_object_item_part_content_unset(it, part);
492 }
493
494 static Evas_Object *
495 _content_get_hook(const Evas_Object *obj, const char *part)
496 {
497    Elm_Object_Item *it = elm_naviframe_top_item_get(obj);
498    if (!it) return NULL;
499    return elm_object_item_part_content_get(it, part);
500 }
501
502 static void
503 _title_content_del(void *data,
504                    Evas *e __UNUSED__,
505                    Evas_Object *obj __UNUSED__,
506                    void *event_info __UNUSED__)
507 {
508    char buf[1024];
509    Elm_Naviframe_Content_Item_Pair *pair = data;
510    Elm_Naviframe_Item *it = pair->it;
511    snprintf(buf, sizeof(buf), "elm,state,%s,hide", pair->part);
512    elm_object_signal_emit(VIEW(it), buf, "elm");
513    it->content_list = eina_inlist_remove(it->content_list,
514                                          EINA_INLIST_GET(pair));
515    eina_stringshare_del(pair->part);
516    free(pair);
517 }
518
519 static void
520 _title_prev_btn_del(void *data,
521                     Evas *e __UNUSED__,
522                     Evas_Object *obj __UNUSED__,
523                     void *event_info __UNUSED__)
524 {
525    Elm_Naviframe_Item *it = data;
526    it->back_btn = EINA_FALSE;
527    it->title_prev_btn = NULL;
528    elm_object_signal_emit(VIEW(it), "elm,state,prev_btn,hide", "elm");
529 }
530
531 static void
532 _title_next_btn_del(void *data,
533                     Evas *e __UNUSED__,
534                     Evas_Object *obj __UNUSED__,
535                     void *event_info __UNUSED__)
536 {
537    Elm_Naviframe_Item *it = data;
538    it->title_next_btn = NULL;
539    elm_object_signal_emit(VIEW(it), "elm,state,next_btn,hide", "elm");
540 }
541
542 static void
543 _title_icon_del(void *data,
544                 Evas *e __UNUSED__,
545                 Evas_Object *obj __UNUSED__,
546                 void *event_info __UNUSED__)
547 {
548    Elm_Naviframe_Item *it = data;
549    it->title_icon = NULL;
550    elm_object_signal_emit(VIEW(it), "elm,state,icon,hide", "elm");
551 }
552
553 static void
554 _item_content_del(void *data,
555                   Evas *e __UNUSED__,
556                   Evas_Object *obj __UNUSED__,
557                   void *event_info __UNUSED__)
558 {
559    Elm_Naviframe_Item *it = data;
560    it->content = NULL;
561    elm_object_signal_emit(VIEW(it), "elm,state,content,hide", "elm");
562 }
563
564 static void
565 _title_content_set(Elm_Naviframe_Item *it,
566                    const char *part,
567                    Evas_Object *content)
568 {
569    char buf[1024];
570    Elm_Naviframe_Content_Item_Pair *pair = NULL;
571    Evas_Object *prev_content = NULL;
572
573    EINA_INLIST_FOREACH(it->content_list, pair)
574      if (!strcmp(part, pair->part)) break;
575
576    if (pair)
577      {
578         prev_content = elm_object_part_content_get(VIEW(it), part);
579         if (prev_content != content)
580           {
581              if (content)
582                {
583                   evas_object_event_callback_del(prev_content,
584                                                  EVAS_CALLBACK_DEL,
585                                                  _title_content_del);
586                   snprintf(buf, sizeof(buf), "elm,state,%s,hide", part);
587                   elm_object_signal_emit(VIEW(it), buf, "elm");
588                }
589              evas_object_del(prev_content);
590              if (!content) return;
591           }
592      }
593    else
594      {
595         if (!content) return;
596         pair = ELM_NEW(Elm_Naviframe_Content_Item_Pair);
597         if (!pair)
598           {
599              ERR("Failed to allocate new content part of the item! : naviframe=%p", WIDGET(it));
600              return;
601           }
602         pair->it = it;
603         eina_stringshare_replace(&pair->part, part);
604         it->content_list = eina_inlist_append(it->content_list,
605                                               EINA_INLIST_GET(pair));
606      }
607    if (prev_content != content)
608      {
609         evas_object_event_callback_add(content,
610                                        EVAS_CALLBACK_DEL,
611                                        _title_content_del,
612                                        pair);
613      }
614    elm_object_part_content_set(VIEW(it), part, content);
615    snprintf(buf, sizeof(buf), "elm,state,%s,show", part);
616    elm_object_signal_emit(VIEW(it), buf, "elm");
617
618    _sizing_eval(WIDGET(it));
619 }
620
621 static void
622 _title_prev_btn_set(Elm_Naviframe_Item *it,
623                     Evas_Object *btn,
624                     Eina_Bool back_btn)
625 {
626    if (it->title_prev_btn == btn) return;
627    if (it->title_prev_btn) evas_object_del(it->title_prev_btn);
628    it->title_prev_btn = btn;
629    if (!btn) return;
630
631    evas_object_event_callback_add(btn,
632                                   EVAS_CALLBACK_DEL,
633                                   _title_prev_btn_del,
634                                   it);
635    elm_object_part_content_set(VIEW(it), "elm.swallow.prev_btn", btn);
636    elm_object_signal_emit(VIEW(it), "elm,state,prev_btn,show", "elm");
637    it->back_btn = back_btn;
638
639    _sizing_eval(WIDGET(it));
640 }
641
642 static void
643 _title_next_btn_set(Elm_Naviframe_Item *it, Evas_Object *btn)
644 {
645    if (it->title_next_btn == btn) return;
646    if (it->title_next_btn) evas_object_del(it->title_next_btn);
647    it->title_next_btn = btn;
648    if (!btn) return;
649
650    evas_object_event_callback_add(btn,
651                                   EVAS_CALLBACK_DEL,
652                                   _title_next_btn_del,
653                                   it);
654    elm_object_part_content_set(VIEW(it), "elm.swallow.next_btn", btn);
655    elm_object_signal_emit(VIEW(it), "elm,state,next_btn,show", "elm");
656
657    _sizing_eval(WIDGET(it));
658 }
659
660 static void
661 _title_icon_set(Elm_Naviframe_Item *it, Evas_Object *icon)
662 {
663    if (it->title_icon == icon) return;
664    if (it->title_icon) evas_object_del(it->title_icon);
665    it->title_icon = icon;
666    if (!icon) return;
667
668    evas_object_event_callback_add(icon,
669                                   EVAS_CALLBACK_DEL,
670                                   _title_icon_del,
671                                   it);
672    elm_object_part_content_set(VIEW(it), "elm.swallow.icon", icon);
673    elm_object_signal_emit(VIEW(it), "elm,state,icon,show", "elm");
674
675    _sizing_eval(WIDGET(it));
676 }
677
678 static Evas_Object *
679 _item_content_unset(Elm_Naviframe_Item *it)
680 {
681    Evas_Object *content = it->content;
682    if (!content) return NULL;
683
684    elm_object_part_content_unset(VIEW(it), "elm.swallow.content");
685    elm_object_signal_emit(VIEW(it), "elm,state,content,hide", "elm");
686    evas_object_event_callback_del(content,
687                                   EVAS_CALLBACK_DEL,
688                                   _item_content_del);
689    _sizing_eval(WIDGET(it));
690
691    it->content = NULL;
692    return content;
693 }
694
695 static Evas_Object *
696 _title_prev_btn_unset(Elm_Naviframe_Item *it)
697 {
698    Evas_Object *content = it->title_prev_btn;
699    if (!content) return NULL;
700
701    elm_object_part_content_unset(VIEW(it), "elm.swallow.prev_btn");
702    elm_object_signal_emit(VIEW(it), "elm,state,prev_btn,hide", "elm");
703    evas_object_event_callback_del(content,
704                                   EVAS_CALLBACK_DEL,
705                                   _title_prev_btn_del);
706    _sizing_eval(WIDGET(it));
707
708    it->title_prev_btn = NULL;
709    return content;
710 }
711
712 static Evas_Object *
713 _title_next_btn_unset(Elm_Naviframe_Item *it)
714 {
715    Evas_Object *content = it->title_next_btn;
716    if (!content) return NULL;
717
718    elm_object_part_content_unset(VIEW(it), "elm.swallow.next_btn");
719    elm_object_signal_emit(VIEW(it), "elm,state,next_btn,hide", "elm");
720    evas_object_event_callback_del(content,
721                                   EVAS_CALLBACK_DEL,
722                                   _title_next_btn_del);
723    _sizing_eval(WIDGET(it));
724
725    it->title_next_btn = NULL;
726    return content;
727 }
728
729 static Evas_Object *
730 _title_icon_unset(Elm_Naviframe_Item *it)
731 {
732    Evas_Object *content = it->title_icon;
733    if (!content) return NULL;
734
735    elm_object_part_content_unset(VIEW(it), "elm.swallow.icon");
736    elm_object_signal_emit(VIEW(it), "elm,state,icon,hide", "elm");
737    evas_object_event_callback_del(content,
738                                   EVAS_CALLBACK_DEL,
739                                   _title_icon_del);
740    _sizing_eval(WIDGET(it));
741    it->title_icon = NULL;
742
743    return content;
744 }
745
746 static Evas_Object *
747 _title_content_unset(Elm_Naviframe_Item *it, const char *part)
748 {
749    Elm_Naviframe_Content_Item_Pair *pair = NULL;
750    char buf[1028];
751    Evas_Object *content = NULL;
752
753    EINA_INLIST_FOREACH(it->content_list, pair)
754      {
755         if (!strcmp(part, pair->part))
756           {
757              content = elm_object_part_content_get(VIEW(it), part);
758              eina_stringshare_del(pair->part);
759              it->content_list = eina_inlist_remove(it->content_list,
760                                                    EINA_INLIST_GET(pair));
761              free(pair);
762              break;
763           }
764      }
765
766    if (!content) return NULL;
767
768    elm_object_part_content_unset(VIEW(it), part);
769    snprintf(buf, sizeof(buf), "elm,state,%s,hide", part);
770    elm_object_signal_emit(VIEW(it), buf, "elm");
771    evas_object_event_callback_del(content,
772                                   EVAS_CALLBACK_DEL,
773                                   _title_content_del);
774    _sizing_eval(WIDGET(it));
775
776    return content;
777 }
778
779 static void
780 _item_del(Elm_Naviframe_Item *it)
781 {
782    Widget_Data *wd;
783    Elm_Naviframe_Content_Item_Pair *content_pair;
784    Elm_Naviframe_Text_Item_Pair *text_pair;
785    Evas_Object *content;
786
787    if (!it) return;
788
789    wd = elm_widget_data_get(WIDGET(it));
790    if (!wd) return;
791
792    while (it->content_list)
793      {
794         content_pair =
795            EINA_INLIST_CONTAINER_GET(it->content_list,
796                                      Elm_Naviframe_Content_Item_Pair);
797         content = elm_object_part_content_get(VIEW(it), content_pair->part);
798         evas_object_event_callback_del(content,
799                                        EVAS_CALLBACK_DEL,
800                                        _title_content_del);
801         eina_stringshare_del(content_pair->part);
802         it->content_list = eina_inlist_remove(it->content_list,
803                                               it->content_list);
804         free(content_pair);
805      }
806
807    while (it->text_list)
808      {
809         text_pair = EINA_INLIST_CONTAINER_GET(it->text_list,
810                                               Elm_Naviframe_Text_Item_Pair);
811         eina_stringshare_del(text_pair->part);
812         it->text_list = eina_inlist_remove(it->text_list,
813                                            it->text_list);
814         free(text_pair);
815      }
816
817    eina_stringshare_del(it->style);
818
819    if (wd->preserve && it->content)
820      {
821         elm_object_part_content_unset(VIEW(it), "elm.swallow.content");
822         evas_object_event_callback_del(it->content,
823                                        EVAS_CALLBACK_DEL,
824                                        _item_content_del);
825      }
826 }
827
828 static Eina_Bool
829 _item_del_pre_hook(Elm_Object_Item *it)
830 {
831    Elm_Naviframe_Item *navi_it;
832    Widget_Data *wd;
833
834    navi_it =(Elm_Naviframe_Item *)it;
835    wd = elm_widget_data_get(WIDGET(navi_it));
836    if (!wd) return EINA_FALSE;
837
838    if (it == elm_naviframe_top_item_get(WIDGET(navi_it)))
839      {
840         wd->stack = eina_inlist_remove(wd->stack, EINA_INLIST_GET(navi_it));
841         _item_del(navi_it);
842         //If the item is only one, the stack will be empty
843         if (!wd->stack) return EINA_TRUE;
844         navi_it = EINA_INLIST_CONTAINER_GET(wd->stack->last,
845                                             Elm_Naviframe_Item);
846         evas_object_show(VIEW(navi_it));
847         evas_object_raise(VIEW(navi_it));
848         elm_object_signal_emit(VIEW(navi_it), "elm,state,visible", "elm");
849      }
850    else
851      {
852         wd->stack = eina_inlist_remove(wd->stack, EINA_INLIST_GET(navi_it));
853         _item_del(navi_it);
854      }
855
856    return EINA_TRUE;
857 }
858
859 static void
860 _pushed_finished(void *data,
861                  Evas_Object *obj __UNUSED__,
862                  const char *emission __UNUSED__,
863                  const char *source __UNUSED__)
864 {
865    Widget_Data *wd;
866    Elm_Naviframe_Item *it = data;
867    if (!it) return;
868
869    wd = elm_widget_data_get(WIDGET(it));
870    if (!wd) return;
871
872    evas_object_hide(VIEW(it));
873    if (wd->freeze_events)
874      evas_object_freeze_events_set(VIEW(it), EINA_FALSE);
875 }
876
877 static void
878 _popped_finished(void *data,
879                  Evas_Object *obj __UNUSED__,
880                  const char *emission __UNUSED__,
881                  const char *source __UNUSED__)
882 {
883    Elm_Naviframe_Item *it = data;
884    if (!it) return;
885    _item_del(data);
886    elm_widget_item_free(data);
887 }
888
889 static void
890 _show_finished(void *data,
891                Evas_Object *obj __UNUSED__,
892                const char *emission __UNUSED__,
893                const char *source __UNUSED__)
894 {
895    Elm_Naviframe_Item *it;
896    Widget_Data *wd;
897
898    it = data;
899    if (!it) return;
900    wd =  elm_widget_data_get(WIDGET(it));
901    if (!wd) return;
902
903    // FIXME : If current top's content is unfocusable, it should be restored as focusable.
904    // Similar cases are should be checked and should call following function.
905    if (elm_widget_tree_unfocusable_get(it->content))
906      elm_widget_tree_unfocusable_set(it->content, EINA_FALSE);
907
908    evas_object_smart_callback_call(WIDGET(it),
909                                    SIG_TRANSITION_FINISHED,
910                                    data);
911    if (wd->freeze_events)
912      evas_object_freeze_events_set(VIEW(it), EINA_FALSE);
913 }
914
915 static void
916 _changed_size_hints(void *data,
917                     Evas *e __UNUSED__,
918                     Evas_Object *obj __UNUSED__,
919                     void *event_info __UNUSED__)
920 {
921    _sizing_eval(data);
922 }
923
924 static void
925 _item_content_set(Elm_Naviframe_Item *navi_it, Evas_Object *content)
926 {
927    if (navi_it->content == content) return;
928    if (navi_it->content) evas_object_del(navi_it->content);
929    elm_object_part_content_set(VIEW(navi_it), "elm.swallow.content", content);
930
931    if (content)
932      elm_object_signal_emit(VIEW(navi_it), "elm,state,content,show", "elm");
933    else
934      elm_object_signal_emit(VIEW(navi_it), "elm,state,content,hide", "elm");
935
936    evas_object_event_callback_add(content,
937                                   EVAS_CALLBACK_DEL,
938                                   _item_content_del,
939                                   navi_it);
940    navi_it->content = content;
941    _sizing_eval(WIDGET(navi_it));
942 }
943
944 //FIXME: need to handle if this function is called while transition
945 static void
946 _item_style_set(Elm_Naviframe_Item *navi_it, const char *item_style)
947 {
948    Elm_Naviframe_Content_Item_Pair *content_pair;
949    Elm_Naviframe_Text_Item_Pair *text_pair;
950    Widget_Data *wd;
951
952    char buf[256];
953
954    if (!item_style)
955      {
956         strcpy(buf, "item/basic");
957         eina_stringshare_replace(&navi_it->style, "basic");
958      }
959    else
960      {
961         snprintf(buf, sizeof(buf), "item/%s", item_style);
962         eina_stringshare_replace(&navi_it->style, item_style);
963      }
964    elm_layout_theme_set(VIEW(navi_it),
965                         "naviframe",
966                         buf,
967                         elm_widget_style_get(WIDGET(navi_it)));
968    //recover item
969    EINA_INLIST_FOREACH(navi_it->text_list, text_pair)
970      _item_text_set_hook((Elm_Object_Item *) navi_it,
971                          text_pair->part,
972                          elm_object_part_text_get(VIEW(navi_it),
973                                                   text_pair->part));
974
975    EINA_INLIST_FOREACH(navi_it->content_list, content_pair)
976      _item_content_set_hook((Elm_Object_Item *) navi_it,
977                             content_pair->part,
978                             elm_object_part_content_get(VIEW(navi_it),
979                                                         content_pair->part));
980    //content
981    if (navi_it->content)
982      elm_object_signal_emit(VIEW(navi_it), "elm,state,content,show", "elm");
983
984    //prev button
985    if (navi_it->title_prev_btn)
986      elm_object_signal_emit(VIEW(navi_it), "elm,state,prev_btn,show", "elm");
987
988    //next button
989    if (navi_it->title_next_btn)
990      elm_object_signal_emit(VIEW(navi_it), "elm,state,next_btn,show", "elm");
991
992 // why does this forcibly enable title? isnt that separate to style?   
993 //   navi_it->title_visible = EINA_TRUE;
994    _sizing_eval(WIDGET(navi_it));
995
996    wd = elm_widget_data_get(WIDGET(navi_it));
997    if (!wd) return;
998
999    if (wd->freeze_events)
1000      evas_object_freeze_events_set(VIEW(navi_it), EINA_FALSE);
1001 }
1002
1003 static Elm_Naviframe_Item *
1004 _item_new(Evas_Object *obj,
1005           const char *title_label,
1006           Evas_Object *prev_btn,
1007           Evas_Object *next_btn,
1008           Evas_Object *content,
1009           const char *item_style)
1010 {
1011    Widget_Data *wd = elm_widget_data_get(obj);
1012
1013    //create item
1014    Elm_Naviframe_Item *it = elm_widget_item_new(obj, Elm_Naviframe_Item);
1015    if (!it)
1016      {
1017         ERR("Failed to allocate new item! : naviframe=%p", obj);
1018         return NULL;
1019      }
1020
1021    elm_widget_item_del_pre_hook_set(it, _item_del_pre_hook);
1022    elm_widget_item_text_set_hook_set(it, _item_text_set_hook);
1023    elm_widget_item_text_get_hook_set(it, _item_text_get_hook);
1024    elm_widget_item_content_set_hook_set(it, _item_content_set_hook);
1025    elm_widget_item_content_get_hook_set(it, _item_content_get_hook);
1026    elm_widget_item_content_unset_hook_set(it, _item_content_unset_hook);
1027    elm_widget_item_signal_emit_hook_set(it, _item_signal_emit_hook);
1028
1029    //item base layout
1030    VIEW(it) = elm_layout_add(obj);
1031    evas_object_smart_member_add(VIEW(it), obj);
1032
1033    evas_object_event_callback_add(VIEW(it),
1034                                   EVAS_CALLBACK_CHANGED_SIZE_HINTS,
1035                                   _changed_size_hints,
1036                                   obj);
1037    elm_object_signal_callback_add(VIEW(it),
1038                                    "elm,action,show,finished",
1039                                    "",
1040                                    _show_finished, it);
1041    elm_object_signal_callback_add(VIEW(it),
1042                                    "elm,action,pushed,finished",
1043                                    "",
1044                                    _pushed_finished, it);
1045    elm_object_signal_callback_add(VIEW(it),
1046                                    "elm,action,popped,finished",
1047                                    "",
1048                                    _popped_finished, it);
1049    elm_object_signal_callback_add(VIEW(it),
1050                                    "elm,action,title,clicked",
1051                                    "",
1052                                    _title_clicked, it);
1053
1054    _item_style_set(it, item_style);
1055    _item_text_set_hook((Elm_Object_Item *)it, "elm.text.title", title_label);
1056
1057    //title buttons
1058    if ((!prev_btn) && wd->auto_pushed && eina_inlist_count(wd->stack))
1059      {
1060         prev_btn = _back_btn_new(obj);
1061         _title_prev_btn_set(it, prev_btn, EINA_TRUE);
1062      }
1063    else
1064      _title_prev_btn_set(it, prev_btn, EINA_FALSE);
1065
1066    _title_next_btn_set(it, next_btn);
1067    _item_content_set(it, content);
1068    it->title_visible = EINA_TRUE;
1069    return it;
1070 }
1071
1072 static Eina_Bool
1073 _focus_next_hook(const Evas_Object *obj, Elm_Focus_Direction dir, Evas_Object **next)
1074 {
1075    Eina_Bool ret;
1076    Elm_Naviframe_Item *top_it;
1077    Eina_List *l = NULL;
1078    Widget_Data *wd = elm_widget_data_get(obj);
1079    void *(*list_data_get)(const Eina_List *list);
1080    if (!wd) return EINA_FALSE;
1081
1082    top_it = (Elm_Naviframe_Item *)elm_naviframe_top_item_get(obj);
1083    if (!top_it) return EINA_FALSE;
1084
1085    list_data_get = eina_list_data_get;
1086
1087    //Forcus order: prev button, next button, contents
1088    if (top_it->title_prev_btn)
1089      l = eina_list_append(l, top_it->title_prev_btn);
1090    if (top_it->title_next_btn)
1091      l = eina_list_append(l, top_it->title_next_btn);
1092    l = eina_list_append(l, VIEW(top_it));
1093
1094    ret = elm_widget_focus_list_next_get(obj, l, list_data_get, dir, next);
1095    eina_list_free(l);
1096    return ret;
1097 }
1098
1099 EAPI Evas_Object *
1100 elm_naviframe_add(Evas_Object *parent)
1101 {
1102    Evas_Object *obj;
1103    Evas *e;
1104    Widget_Data *wd;
1105
1106    ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
1107    ELM_SET_WIDTYPE(widtype, "naviframe");
1108    elm_widget_type_set(obj, "naviframe");
1109    elm_widget_sub_object_add(parent, obj);
1110    elm_widget_data_set(obj, wd);
1111    elm_widget_del_hook_set(obj, _del_hook);
1112    elm_widget_disable_hook_set(obj, _disable_hook);
1113    elm_widget_theme_hook_set(obj, _theme_hook);
1114    elm_widget_text_set_hook_set(obj, _text_set_hook);
1115    elm_widget_text_get_hook_set(obj, _text_get_hook);
1116    elm_widget_content_set_hook_set(obj, _content_set_hook);
1117    elm_widget_content_get_hook_set(obj, _content_get_hook);
1118    elm_widget_content_unset_hook_set(obj, _content_unset_hook);
1119    elm_widget_signal_emit_hook_set(obj, _emit_hook);
1120    elm_widget_can_focus_set(obj, EINA_FALSE);
1121    elm_widget_focus_next_hook_set(obj, _focus_next_hook);
1122
1123    //base
1124    //FIXME: Is this base layout really needed?
1125    wd->base = elm_layout_add(obj);
1126    evas_object_event_callback_add(wd->base,
1127                                   EVAS_CALLBACK_CHANGED_SIZE_HINTS,
1128                                   _changed_size_hints,
1129                                   obj);
1130    elm_widget_resize_object_set(obj, wd->base);
1131    elm_layout_theme_set(wd->base, "naviframe", "base", "default");
1132
1133    evas_object_event_callback_add(obj, EVAS_CALLBACK_MOVE, _move, obj);
1134    evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE, _resize, obj);
1135    evas_object_smart_callbacks_descriptions_set(obj, _signals);
1136
1137    wd->auto_pushed = EINA_TRUE;
1138    wd->freeze_events = EINA_TRUE;
1139
1140    return obj;
1141 }
1142
1143 EAPI Elm_Object_Item *
1144 elm_naviframe_item_push(Evas_Object *obj,
1145                         const char *title_label,
1146                         Evas_Object *prev_btn,
1147                         Evas_Object *next_btn,
1148                         Evas_Object *content,
1149                         const char *item_style)
1150 {
1151    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1152    Widget_Data *wd;
1153    Elm_Naviframe_Item *prev_it, *it;
1154
1155    wd = elm_widget_data_get(obj);
1156    if (!wd) return NULL;
1157
1158    it = _item_new(obj, title_label, prev_btn, next_btn, content, item_style);
1159    if (!it) return NULL;
1160
1161    evas_object_show(VIEW(it));
1162
1163    prev_it = (Elm_Naviframe_Item *) elm_naviframe_top_item_get(obj);
1164    if (prev_it)
1165      {
1166         if (wd->freeze_events)
1167           {
1168              evas_object_freeze_events_set(VIEW(it), EINA_TRUE);
1169              evas_object_freeze_events_set(VIEW(prev_it), EINA_TRUE);
1170           }
1171         elm_object_signal_emit(VIEW(prev_it), "elm,state,cur,pushed", "elm");
1172         elm_object_signal_emit(VIEW(it), "elm,state,new,pushed", "elm");
1173         edje_object_message_signal_process(elm_layout_edje_get(VIEW(prev_it)));
1174         elm_widget_tree_unfocusable_set(prev_it->content, EINA_TRUE);
1175         edje_object_message_signal_process(elm_layout_edje_get(VIEW(it)));
1176      }
1177    wd->stack = eina_inlist_append(wd->stack, EINA_INLIST_GET(it));
1178    _sizing_eval(obj);
1179    return (Elm_Object_Item *)it;
1180 }
1181
1182 EAPI Elm_Object_Item *
1183 elm_naviframe_item_insert_before(Evas_Object *obj,
1184                                  Elm_Object_Item *before,
1185                                  const char *title_label,
1186                                  Evas_Object *prev_btn,
1187                                  Evas_Object *next_btn,
1188                                  Evas_Object *content,
1189                                  const char *item_style)
1190 {
1191    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1192    ELM_OBJ_ITEM_CHECK_OR_RETURN(before, NULL);
1193    Elm_Naviframe_Item *it;
1194    Widget_Data *wd;
1195
1196    wd = elm_widget_data_get(obj);
1197    if (!wd) return NULL;
1198
1199    it = _item_new(WIDGET(before), title_label, prev_btn, next_btn, content,
1200                   item_style);
1201    if (!it) return NULL;
1202
1203    wd->stack =
1204       eina_inlist_prepend_relative(wd->stack,
1205                                    EINA_INLIST_GET(it),
1206                                    EINA_INLIST_GET(((Elm_Naviframe_Item *) before)));
1207    _sizing_eval(WIDGET(before));
1208    return (Elm_Object_Item *)it;
1209 }
1210
1211 EAPI Elm_Object_Item *
1212 elm_naviframe_item_insert_after(Evas_Object *obj,
1213                                 Elm_Object_Item *after,
1214                                 const char *title_label,
1215                                 Evas_Object *prev_btn,
1216                                 Evas_Object *next_btn,
1217                                 Evas_Object *content,
1218                                 const char *item_style)
1219 {
1220    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1221    ELM_OBJ_ITEM_CHECK_OR_RETURN(after, NULL);
1222    Elm_Naviframe_Item *it;
1223    Widget_Data *wd;
1224
1225    wd = elm_widget_data_get(obj);
1226    if (!wd) return NULL;
1227
1228    it = _item_new(WIDGET(after), title_label, prev_btn, next_btn, content,
1229                   item_style);
1230    if (!it) return NULL;
1231
1232    if (elm_naviframe_top_item_get(WIDGET(after)) == after)
1233      {
1234         evas_object_hide(VIEW(after));
1235         evas_object_show(VIEW(it));
1236      }
1237    wd->stack =
1238       eina_inlist_append_relative(wd->stack,
1239                                   EINA_INLIST_GET(it),
1240                                   EINA_INLIST_GET(((Elm_Naviframe_Item *) after)));
1241    _sizing_eval(WIDGET(after));
1242    return (Elm_Object_Item *)it;
1243 }
1244
1245 EAPI Evas_Object *
1246 elm_naviframe_item_pop(Evas_Object *obj)
1247 {
1248    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1249    Elm_Naviframe_Item *it, *prev_it = NULL;
1250    Widget_Data *wd;
1251    Evas_Object *content = NULL;
1252
1253    wd = elm_widget_data_get(obj);
1254    if (!wd) return NULL;
1255
1256    it = (Elm_Naviframe_Item *) elm_naviframe_top_item_get(obj);
1257    if (!it) return NULL;
1258    if (wd->preserve)
1259      content = it->content;
1260    else
1261      elm_widget_tree_unfocusable_set(it->content, EINA_TRUE);
1262
1263    if (wd->stack->last->prev)
1264      prev_it = EINA_INLIST_CONTAINER_GET(wd->stack->last->prev,
1265                                          Elm_Naviframe_Item);
1266    wd->stack = eina_inlist_remove(wd->stack, EINA_INLIST_GET(it));
1267    if (prev_it)
1268      {
1269         if (wd->freeze_events)
1270           {
1271              evas_object_freeze_events_set(VIEW(it), EINA_TRUE);
1272              evas_object_freeze_events_set(VIEW(prev_it), EINA_TRUE);
1273           }
1274         elm_object_signal_emit(VIEW(it), "elm,state,cur,popped", "elm");
1275         evas_object_show(VIEW(prev_it));
1276         evas_object_raise(VIEW(prev_it));
1277         elm_object_signal_emit(VIEW(prev_it),
1278                                "elm,state,prev,popped",
1279                                "elm");
1280         edje_object_message_signal_process(elm_layout_edje_get(VIEW(it)));
1281         edje_object_message_signal_process(elm_layout_edje_get(VIEW(prev_it)));
1282      }
1283    else
1284      {
1285         _item_del(it);
1286         elm_widget_item_free(it);
1287      }
1288
1289    return content;
1290 }
1291
1292 EAPI void
1293 elm_naviframe_item_pop_to(Elm_Object_Item *it)
1294 {
1295    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1296    Elm_Naviframe_Item *navi_it;
1297    Widget_Data *wd;
1298    Eina_Inlist *l, *prev_l;
1299
1300    navi_it = (Elm_Naviframe_Item *)it;
1301    wd = elm_widget_data_get(WIDGET(navi_it));
1302    if (!wd) return;
1303
1304    if (it == elm_naviframe_top_item_get(WIDGET(navi_it))) return;
1305
1306    l = wd->stack->last->prev;
1307
1308    while(l)
1309      {
1310         if (EINA_INLIST_CONTAINER_GET(l, Elm_Naviframe_Item) ==
1311             ((Elm_Naviframe_Item *)it)) break;
1312         prev_l = l->prev;
1313         wd->stack = eina_inlist_remove(wd->stack, l);
1314         _item_del(EINA_INLIST_CONTAINER_GET(l, Elm_Naviframe_Item));
1315         elm_widget_item_free(EINA_INLIST_CONTAINER_GET(l,
1316                                                        Elm_Naviframe_Item));
1317         l = prev_l;
1318      }
1319    elm_naviframe_item_pop(WIDGET(navi_it));
1320 }
1321
1322 EAPI void
1323 elm_naviframe_item_promote(Elm_Object_Item *it)
1324 {
1325    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1326    Elm_Naviframe_Item *navi_it;
1327    Elm_Naviframe_Item *prev_it;
1328    Widget_Data *wd;
1329
1330    navi_it = (Elm_Naviframe_Item *)it;
1331    wd = elm_widget_data_get(navi_it->base.widget);
1332    if (!wd) return;
1333
1334    if (it == elm_naviframe_top_item_get(navi_it->base.widget)) return;
1335    elm_widget_tree_unfocusable_set(navi_it->content, EINA_FALSE);
1336    wd->stack = eina_inlist_demote(wd->stack, EINA_INLIST_GET(navi_it));
1337    prev_it = EINA_INLIST_CONTAINER_GET(wd->stack->last->prev,
1338                                          Elm_Naviframe_Item);
1339    elm_widget_tree_unfocusable_set(prev_it->content, EINA_FALSE);
1340    if (wd->freeze_events)
1341      {
1342         evas_object_freeze_events_set(VIEW(it), EINA_TRUE);
1343         evas_object_freeze_events_set(VIEW(prev_it), EINA_TRUE);
1344      }
1345    elm_object_signal_emit(VIEW(prev_it),
1346                           "elm,state,cur,pushed",
1347                           "elm");
1348    evas_object_show(VIEW(navi_it));
1349    evas_object_raise(VIEW(navi_it));
1350    elm_object_signal_emit(VIEW(navi_it),
1351                           "elm,state,new,pushed",
1352                           "elm");
1353    edje_object_message_signal_process(elm_layout_edje_get(VIEW(prev_it)));
1354    edje_object_message_signal_process(elm_layout_edje_get(VIEW(navi_it)));
1355 }
1356
1357 EAPI void
1358 elm_naviframe_item_simple_promote(Evas_Object *obj, Evas_Object *content)
1359 {
1360    ELM_CHECK_WIDTYPE(obj, widtype);
1361    Widget_Data *wd = elm_widget_data_get(obj);
1362    if (!wd) return;
1363    Elm_Naviframe_Item *itr;
1364    EINA_INLIST_FOREACH(wd->stack, itr)
1365      {
1366         if (elm_object_item_content_get((Elm_Object_Item *)itr) == content)
1367           {
1368              elm_naviframe_item_promote((Elm_Object_Item *)itr);
1369              break;
1370           }
1371      }
1372 }
1373
1374
1375 EAPI void
1376 elm_naviframe_content_preserve_on_pop_set(Evas_Object *obj, Eina_Bool preserve)
1377 {
1378    ELM_CHECK_WIDTYPE(obj, widtype);
1379    Widget_Data *wd = elm_widget_data_get(obj);
1380    if (!wd) return;
1381    wd->preserve = !!preserve;
1382 }
1383
1384 EAPI Eina_Bool
1385 elm_naviframe_content_preserve_on_pop_get(const Evas_Object *obj)
1386 {
1387    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1388    Widget_Data *wd = elm_widget_data_get(obj);
1389    if (!wd) return EINA_FALSE;
1390    return wd->preserve;
1391 }
1392
1393 EAPI Elm_Object_Item*
1394 elm_naviframe_top_item_get(const Evas_Object *obj)
1395 {
1396    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1397    Widget_Data *wd = elm_widget_data_get(obj);
1398    if ((!wd) || (!wd->stack)) return NULL;
1399    return (Elm_Object_Item *) (EINA_INLIST_CONTAINER_GET(wd->stack->last,
1400                                                          Elm_Naviframe_Item));
1401 }
1402
1403 EAPI Elm_Object_Item*
1404 elm_naviframe_bottom_item_get(const Evas_Object *obj)
1405 {
1406    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1407    Widget_Data *wd = elm_widget_data_get(obj);
1408    if ((!wd) || (!wd->stack)) return NULL;
1409    return (Elm_Object_Item *) (EINA_INLIST_CONTAINER_GET(wd->stack,
1410                                                          Elm_Naviframe_Item));
1411 }
1412
1413 EAPI void
1414 elm_naviframe_item_style_set(Elm_Object_Item *it, const char *item_style)
1415 {
1416    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1417    Elm_Naviframe_Item *navi_it = (Elm_Naviframe_Item *)it;
1418
1419    if (item_style)
1420      if (!strcmp(item_style, navi_it->style)) return;
1421
1422    if (!item_style)
1423      if (!strcmp("basic", navi_it->style)) return;
1424
1425    _item_style_set(navi_it, item_style);
1426 }
1427
1428 EAPI const char *
1429 elm_naviframe_item_style_get(const Elm_Object_Item *it)
1430 {
1431    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
1432    Elm_Naviframe_Item *navi_it = (Elm_Naviframe_Item *)it;
1433    return navi_it->style;
1434 }
1435
1436 EAPI void
1437 elm_naviframe_item_title_visible_set(Elm_Object_Item *it, Eina_Bool visible)
1438 {
1439    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1440    Elm_Naviframe_Item *navi_it = (Elm_Naviframe_Item *)it;
1441
1442    visible = !!visible;
1443    if (navi_it->title_visible == visible) return;
1444
1445    navi_it->title_visible = visible;
1446    _item_title_visible_update(navi_it);
1447 }
1448
1449 EAPI Eina_Bool
1450 elm_naviframe_item_title_visible_get(const Elm_Object_Item *it)
1451 {
1452    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
1453    Elm_Naviframe_Item *navi_it = (Elm_Naviframe_Item *)it;
1454    return navi_it->title_visible;
1455 }
1456
1457 EAPI void
1458 elm_naviframe_prev_btn_auto_pushed_set(Evas_Object *obj, Eina_Bool auto_pushed)
1459 {
1460    ELM_CHECK_WIDTYPE(obj, widtype);
1461    Widget_Data *wd = elm_widget_data_get(obj);
1462    if (!wd) return;
1463    wd->auto_pushed = !!auto_pushed;
1464 }
1465
1466 EAPI Eina_Bool
1467 elm_naviframe_prev_btn_auto_pushed_get(const Evas_Object *obj)
1468 {
1469    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1470    Widget_Data *wd = elm_widget_data_get(obj);
1471    if (!wd) return EINA_FALSE;
1472    return wd->auto_pushed;
1473 }
1474
1475 EAPI Eina_List *
1476 elm_naviframe_items_get(const Evas_Object *obj)
1477 {
1478    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1479    Widget_Data *wd = elm_widget_data_get(obj);
1480    if (!wd) return NULL;
1481    Eina_List *ret = NULL;
1482    Elm_Naviframe_Item *itr;
1483    EINA_INLIST_FOREACH(wd->stack, itr)
1484      ret = eina_list_append(ret, itr);
1485    return ret;
1486 }
1487
1488 EAPI void
1489 elm_naviframe_event_enabled_set(Evas_Object *obj, Eina_Bool enabled)
1490 {
1491    ELM_CHECK_WIDTYPE(obj, widtype);
1492    Widget_Data *wd = elm_widget_data_get(obj);
1493    if (!wd) return;
1494    enabled = !!enabled;
1495    if (wd->freeze_events == !enabled) return;
1496    wd->freeze_events = !enabled;
1497 }
1498
1499 EAPI Eina_Bool
1500 elm_naviframe_event_enabled_get(const Evas_Object *obj)
1501 {
1502    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1503    Widget_Data *wd = elm_widget_data_get(obj);
1504    if (!wd) return EINA_FALSE;
1505    return !wd->freeze_events;
1506 }