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