naviframe - merged with opensource
[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 (!content) return;
570         pair = ELM_NEW(Elm_Naviframe_Content_Item_Pair);
571         if (!pair)
572           {
573              ERR("Failed to allocate new content part of the item! : naviframe=%p", WIDGET(it));
574              return;
575           }
576         pair->it = it;
577         eina_stringshare_replace(&pair->part, part);
578         it->content_list = eina_inlist_append(it->content_list,
579                                               EINA_INLIST_GET(pair));
580      }
581    if (pair->content && (pair->content != content))
582      {
583         evas_object_event_callback_del(pair->content,
584                                        EVAS_CALLBACK_DEL,
585                                        _title_content_del);
586         evas_object_event_callback_del(pair->content,
587                                        EVAS_CALLBACK_CHANGED_SIZE_HINTS,
588                                        _changed_size_hints);
589         evas_object_del(pair->content);
590         snprintf(buf, sizeof(buf), "elm,state,%s,hide", part);
591         edje_object_signal_emit(VIEW(it), buf, "elm");
592      }
593    if (content)
594      {
595         if (pair->content != content)
596           {
597              elm_widget_sub_object_add(WIDGET(it), content);
598              evas_object_event_callback_add(content,
599                                             EVAS_CALLBACK_DEL,
600                                             _title_content_del,
601                                             pair);
602              evas_object_event_callback_add(content,
603                                             EVAS_CALLBACK_CHANGED_SIZE_HINTS,
604                                             _changed_size_hints,
605                                             WIDGET(it));
606              pair->content = content;
607           }
608         edje_object_part_swallow(VIEW(it), part, content);
609         snprintf(buf, sizeof(buf), "elm,state,%s,show", part);
610         edje_object_signal_emit(VIEW(it), buf, "elm");
611      }
612
613    _sizing_eval(WIDGET(it));
614 }
615
616 static void
617 _title_prev_btn_set(Elm_Naviframe_Item *it,
618                     Evas_Object *btn,
619                     Eina_Bool back_btn)
620 {
621    if (it->title_prev_btn == btn) return;
622
623    if (it->title_prev_btn)
624      evas_object_del(it->title_prev_btn);
625
626    it->title_prev_btn = btn;
627    if (!btn) return;
628
629    elm_widget_sub_object_add(WIDGET(it), btn);
630    evas_object_event_callback_add(btn,
631                                   EVAS_CALLBACK_DEL,
632                                   _title_prev_btn_del,
633                                   it);
634    evas_object_event_callback_add(btn,
635                                   EVAS_CALLBACK_CHANGED_SIZE_HINTS,
636                                   _changed_size_hints,
637                                   WIDGET(it));
638    edje_object_part_swallow(VIEW(it), "elm.swallow.prev_btn", btn);
639    edje_object_signal_emit(VIEW(it), "elm,state,prev_btn,show", "elm");
640    it->back_btn = back_btn;
641
642    _sizing_eval(WIDGET(it));
643 }
644
645 static void
646 _title_next_btn_set(Elm_Naviframe_Item *it, Evas_Object *btn)
647 {
648    if (it->title_next_btn == btn) return;
649
650    if (it->title_next_btn)
651      evas_object_del(it->title_next_btn);
652
653    it->title_next_btn = btn;
654    if (!btn) return;
655
656    elm_widget_sub_object_add(WIDGET(it), btn);
657    evas_object_event_callback_add(btn,
658                                   EVAS_CALLBACK_DEL,
659                                   _title_next_btn_del,
660                                   it);
661    evas_object_event_callback_add(btn,
662                                   EVAS_CALLBACK_CHANGED_SIZE_HINTS,
663                                   _changed_size_hints,
664                                   WIDGET(it));
665    edje_object_part_swallow(VIEW(it), "elm.swallow.next_btn", btn);
666    edje_object_signal_emit(VIEW(it), "elm,state,next_btn,show", "elm");
667
668    _sizing_eval(WIDGET(it));
669 }
670
671 static void
672 _title_icon_set(Elm_Naviframe_Item *it, Evas_Object *icon)
673 {
674    if (it->title_icon == icon) return;
675
676    if (it->title_icon)
677      evas_object_del(it->title_icon);
678
679    it->title_icon = icon;
680    if (!icon) return;
681
682    elm_widget_sub_object_add(WIDGET(it), icon);
683    evas_object_event_callback_add(icon,
684                                   EVAS_CALLBACK_DEL,
685                                   _title_icon_del,
686                                   it);
687    evas_object_event_callback_add(icon,
688                                   EVAS_CALLBACK_CHANGED_SIZE_HINTS,
689                                   _changed_size_hints,
690                                   WIDGET(it));
691    edje_object_part_swallow(VIEW(it), "elm.swallow.icon", icon);
692    edje_object_signal_emit(VIEW(it), "elm,state,icon,show", "elm");
693
694    _sizing_eval(WIDGET(it));
695 }
696
697 static Evas_Object *
698 _item_content_unset(Elm_Naviframe_Item *it)
699 {
700    Evas_Object *content = it->content;
701    if (!content) return NULL;
702
703    elm_widget_sub_object_del(WIDGET(it), content);
704    edje_object_part_unswallow(VIEW(it), content);
705    edje_object_signal_emit(VIEW(it), "elm,state,content,hide", "elm");
706    evas_object_event_callback_del(content,
707                                   EVAS_CALLBACK_DEL,
708                                   _item_content_del);
709    evas_object_event_callback_del(content,
710                                   EVAS_CALLBACK_CHANGED_SIZE_HINTS,
711                                   _changed_size_hints);
712    _sizing_eval(WIDGET(it));
713
714    it->content = NULL;
715    return content;
716 }
717
718 static Evas_Object *
719 _title_prev_btn_unset(Elm_Naviframe_Item *it)
720 {
721    Evas_Object *content = it->title_prev_btn;
722    if (!content) return NULL;
723
724    elm_widget_sub_object_del(WIDGET(it), content);
725    edje_object_part_unswallow(VIEW(it), content);
726    edje_object_signal_emit(VIEW(it), "elm,state,prev_btn,hide", "elm");
727    evas_object_event_callback_del(content,
728                                   EVAS_CALLBACK_DEL,
729                                   _title_prev_btn_del);
730    evas_object_event_callback_del(content,
731                                   EVAS_CALLBACK_CHANGED_SIZE_HINTS,
732                                   _changed_size_hints);
733    _sizing_eval(WIDGET(it));
734
735    it->title_prev_btn = NULL;
736    return content;
737 }
738
739 static Evas_Object *
740 _title_next_btn_unset(Elm_Naviframe_Item *it)
741 {
742    Evas_Object *content = it->title_next_btn;
743    if (!content) return NULL;
744
745    elm_widget_sub_object_del(WIDGET(it), content);
746    edje_object_part_unswallow(VIEW(it), content);
747    edje_object_signal_emit(VIEW(it), "elm,state,next_btn,hide", "elm");
748    evas_object_event_callback_del(content,
749                                   EVAS_CALLBACK_DEL,
750                                   _title_next_btn_del);
751    evas_object_event_callback_del(content,
752                                   EVAS_CALLBACK_CHANGED_SIZE_HINTS,
753                                   _changed_size_hints);
754    _sizing_eval(WIDGET(it));
755
756    it->title_next_btn = NULL;
757    return content;
758 }
759
760 static Evas_Object *
761 _title_icon_unset(Elm_Naviframe_Item *it)
762 {
763    Evas_Object *content = it->title_icon;
764    if (!content) return NULL;
765
766    elm_widget_sub_object_del(WIDGET(it), content);
767    edje_object_part_unswallow(VIEW(it), content);
768    edje_object_signal_emit(VIEW(it), "elm,state,icon,hide", "elm");
769    evas_object_event_callback_del(content,
770                                   EVAS_CALLBACK_DEL,
771                                   _title_icon_del);
772    evas_object_event_callback_del(content,
773                                   EVAS_CALLBACK_CHANGED_SIZE_HINTS,
774                                   _changed_size_hints);
775    _sizing_eval(WIDGET(it));
776    it->title_icon = NULL;
777
778    return content;
779 }
780
781 static Evas_Object *
782 _title_content_unset(Elm_Naviframe_Item *it, const char *part)
783 {
784    Elm_Naviframe_Content_Item_Pair *pair = NULL;
785    char buf[1028];
786    Evas_Object *content = NULL;
787
788    EINA_INLIST_FOREACH(it->content_list, pair)
789      {
790         if (!strcmp(part, pair->part))
791           {
792              content = pair->content;
793              eina_stringshare_del(pair->part);
794              it->content_list = eina_inlist_remove(it->content_list,
795                                                    EINA_INLIST_GET(pair));
796              free(pair);
797              break;
798           }
799      }
800
801    if (!content) return NULL;
802
803    elm_widget_sub_object_del(WIDGET(it), content);
804    edje_object_part_unswallow(VIEW(it), content);
805    snprintf(buf, sizeof(buf), "elm,state,%s,hide", part);
806    edje_object_signal_emit(VIEW(it), buf, "elm");
807    evas_object_event_callback_del(content,
808                                   EVAS_CALLBACK_DEL,
809                                   _title_content_del);
810    evas_object_event_callback_del(content,
811                                   EVAS_CALLBACK_CHANGED_SIZE_HINTS,
812                                   _changed_size_hints);
813    _sizing_eval(WIDGET(it));
814
815    return content;
816 }
817
818
819 static void
820 _item_del(Elm_Naviframe_Item *it)
821 {
822    Widget_Data *wd;
823    Elm_Naviframe_Content_Item_Pair *content_pair;
824    Elm_Naviframe_Text_Item_Pair *text_pair;
825
826    if (!it) return;
827
828    wd = elm_widget_data_get(WIDGET(it));
829    if (!wd) return;
830
831    if (it->title_prev_btn)
832      evas_object_del(it->title_prev_btn);
833    if (it->title_next_btn)
834      evas_object_del(it->title_next_btn);
835    if (it->title_icon)
836      evas_object_del(it->title_icon);
837    if ((it->content) && (!wd->preserve))
838      evas_object_del(it->content);
839
840    while (it->content_list)
841      {
842         content_pair = EINA_INLIST_CONTAINER_GET(it->content_list,
843                                                  Elm_Naviframe_Content_Item_Pair);
844         evas_object_event_callback_del(content_pair->content,
845                                        EVAS_CALLBACK_DEL,
846                                        _title_content_del);
847         evas_object_event_callback_del(content_pair->content,
848                                        EVAS_CALLBACK_CHANGED_SIZE_HINTS,
849                                        _changed_size_hints);
850         evas_object_del(content_pair->content);
851         eina_stringshare_del(content_pair->part);
852         it->content_list = eina_inlist_remove(it->content_list,
853                                               it->content_list);
854         free(content_pair);
855      }
856
857    while (it->text_list)
858      {
859         text_pair = EINA_INLIST_CONTAINER_GET(it->text_list,
860                                               Elm_Naviframe_Text_Item_Pair);
861         eina_stringshare_del(text_pair->part);
862         eina_stringshare_del(text_pair->text);
863         it->text_list = eina_inlist_remove(it->text_list,
864                                            it->text_list);
865         free(text_pair);
866      }
867
868    eina_stringshare_del(it->style);
869
870    elm_widget_item_del(it);
871 }
872
873 static void
874 _pushed_finished(void *data,
875                  Evas_Object *obj __UNUSED__,
876                  const char *emission __UNUSED__,
877                  const char *source __UNUSED__)
878 {
879    Widget_Data *wd;
880    Elm_Naviframe_Item *it = data;
881    if (!it) return;
882
883    wd = elm_widget_data_get(WIDGET(it));
884    if (!wd) return;
885
886    evas_object_hide(VIEW(it));
887    evas_object_smart_callback_call(WIDGET(it),
888                                    SIG_PUSH_FINISHED,
889                                    data);
890    if (wd->freeze_events)
891      evas_object_freeze_events_set(VIEW(it), EINA_FALSE);
892 }
893
894 static void
895 _popped_finished(void *data,
896                  Evas_Object *obj __UNUSED__,
897                  const char *emission __UNUSED__,
898                  const char *source __UNUSED__)
899 {
900    Elm_Naviframe_Item *it = data;
901    if (!it) return;
902    evas_object_smart_callback_call(WIDGET(it),
903                                    SIG_POP_FINISHED,
904                                    data);
905    _item_del(data);
906 }
907
908 static void
909 _show_finished(void *data,
910                Evas_Object *obj __UNUSED__,
911                const char *emission __UNUSED__,
912                const char *source __UNUSED__)
913 {
914    Elm_Naviframe_Item *it;
915    Widget_Data *wd;
916
917    it = data;
918    if (!it) return;
919    wd =  elm_widget_data_get(WIDGET(it));
920    if (!wd) return;
921
922    evas_object_smart_callback_call(WIDGET(it),
923                                    SIG_TRANSITION_FINISHED,
924                                    data);
925    if (wd->freeze_events)
926      evas_object_freeze_events_set(VIEW(it), EINA_FALSE);
927 }
928
929 static void
930 _changed_size_hints(void *data,
931                     Evas *e __UNUSED__,
932                     Evas_Object *obj __UNUSED__,
933                     void *event_info __UNUSED__)
934 {
935    _sizing_eval(data);
936 }
937
938 static void
939 _item_content_set(Elm_Naviframe_Item *navi_it, Evas_Object *content)
940 {
941    if (navi_it->content == content) return;
942    if (navi_it->content) evas_object_del(navi_it->content);
943    elm_widget_sub_object_add(WIDGET(navi_it), content);
944    edje_object_part_swallow(VIEW(navi_it),
945                             "elm.swallow.content",
946                             content);
947    if (content)
948      edje_object_signal_emit(VIEW(navi_it),
949                              "elm,state,content,show",
950                              "elm");
951    else
952      edje_object_signal_emit(VIEW(navi_it),
953                              "elm,state,content,hide",
954                              "elm");
955    evas_object_event_callback_add(content,
956                                   EVAS_CALLBACK_DEL,
957                                   _item_content_del,
958                                   navi_it);
959    evas_object_event_callback_add(content,
960                                   EVAS_CALLBACK_CHANGED_SIZE_HINTS,
961                                   _changed_size_hints,
962                                   WIDGET(navi_it));
963    navi_it->content = content;
964    _sizing_eval(WIDGET(navi_it));
965 }
966
967 //FIXME: need to handle if this function is called while transition
968 static void
969 _item_style_set(Elm_Naviframe_Item *navi_it, const char *item_style)
970 {
971    Elm_Naviframe_Content_Item_Pair *content_pair;
972    Elm_Naviframe_Text_Item_Pair *text_pair;
973    Widget_Data *wd;
974
975    char buf[256];
976
977    if (!item_style)
978      {
979         sprintf(buf, "item/basic");
980         eina_stringshare_replace(&navi_it->style, "basic");
981      }
982    else
983      {
984         if (strlen(item_style) > sizeof(buf))
985           WRN("too much long style name! : naviframe=%p", WIDGET(navi_it));
986         sprintf(buf, "item/%s", item_style);
987         eina_stringshare_replace(&navi_it->style, item_style);
988      }
989    _elm_theme_object_set(WIDGET(navi_it),
990                          VIEW(navi_it),
991                          "naviframe",
992                          buf,
993                          elm_widget_style_get(WIDGET(navi_it)));
994    //recover item
995    EINA_INLIST_FOREACH(navi_it->text_list, text_pair)
996       _item_text_set_hook((Elm_Object_Item *) navi_it,
997                           text_pair->part,
998                           text_pair->text);
999
1000    EINA_INLIST_FOREACH(navi_it->content_list, content_pair)
1001       _item_content_set_hook((Elm_Object_Item *) navi_it,
1002                              content_pair->part,
1003                              content_pair->content);
1004    //content
1005    if (navi_it->content)
1006      {
1007         edje_object_part_swallow(VIEW(navi_it),
1008                                  "elm.swallow.content",
1009                                  navi_it->content);
1010         edje_object_signal_emit(VIEW(navi_it),
1011                                 "elm,state,content,show",
1012                                 "elm");
1013      }
1014
1015    //prev button
1016    if (navi_it->title_prev_btn)
1017      {
1018         edje_object_part_swallow(VIEW(navi_it),
1019                                  "elm.swallow.prev_btn",
1020                                  navi_it->title_prev_btn);
1021         edje_object_signal_emit(VIEW(navi_it),
1022                                 "elm,state,prev_btn,show",
1023                                 "elm");
1024      }
1025
1026    //next button
1027    if (navi_it->title_next_btn)
1028      {
1029         edje_object_part_swallow(VIEW(navi_it),
1030                                  "elm.swallow.next_btn",
1031                                  navi_it->title_next_btn);
1032         edje_object_signal_emit(VIEW(navi_it),
1033                                 "elm,state,next_btn,show",
1034                                 "elm");
1035      }
1036
1037    navi_it->title_visible = EINA_TRUE;
1038    _sizing_eval(WIDGET(navi_it));
1039
1040    wd = elm_widget_data_get(WIDGET(navi_it));
1041    if (!wd) return;
1042
1043    if (wd->freeze_events)
1044      evas_object_freeze_events_set(VIEW(navi_it), EINA_FALSE);
1045 }
1046
1047 static Elm_Naviframe_Item *
1048 _item_new(Evas_Object *obj,
1049           const char *title_label,
1050           Evas_Object *prev_btn,
1051           Evas_Object *next_btn,
1052           Evas_Object *content,
1053           const char *item_style)
1054 {
1055    Widget_Data *wd = elm_widget_data_get(obj);
1056
1057    //create item
1058    Elm_Naviframe_Item *it = elm_widget_item_new(obj, Elm_Naviframe_Item);
1059    if (!it)
1060      {
1061         ERR("Failed to allocate new item! : naviframe=%p", obj);
1062         return NULL;
1063      }
1064
1065    elm_widget_item_text_set_hook_set(it, _item_text_set_hook);
1066    elm_widget_item_text_get_hook_set(it, _item_text_get_hook);
1067    elm_widget_item_content_set_hook_set(it, _item_content_set_hook);
1068    elm_widget_item_content_get_hook_set(it, _item_content_get_hook);
1069    elm_widget_item_content_unset_hook_set(it, _item_content_unset_hook);
1070    elm_widget_item_signal_emit_hook_set(it, _item_signal_emit_hook);
1071
1072    //item base layout
1073    VIEW(it) = edje_object_add(evas_object_evas_get(obj));
1074    edje_object_mirrored_set(VIEW(it), elm_widget_mirrored_get(obj));
1075    evas_object_smart_member_add(VIEW(it), wd->base);
1076    elm_widget_sub_object_add(obj, VIEW(it));
1077    edje_object_signal_callback_add(VIEW(it),
1078                                    "elm,action,show,finished",
1079                                    "",
1080                                    _show_finished, it);
1081    edje_object_signal_callback_add(VIEW(it),
1082                                    "elm,action,pushed,finished",
1083                                    "",
1084                                    _pushed_finished, it);
1085    edje_object_signal_callback_add(VIEW(it),
1086                                    "elm,action,popped,finished",
1087                                    "",
1088                                    _popped_finished, it);
1089    edje_object_signal_callback_add(VIEW(it),
1090                                    "elm,action,title,clicked",
1091                                    "",
1092                                    _title_clicked, it);
1093
1094    _item_style_set(it, item_style);
1095    _item_text_set_hook((Elm_Object_Item *) it, "elm.text.title", title_label);
1096
1097    //title buttons
1098    if ((!prev_btn) && wd->auto_pushed && eina_inlist_count(wd->stack))
1099      {
1100         prev_btn = _back_btn_new(obj);
1101         _title_prev_btn_set(it, prev_btn, EINA_TRUE);
1102      }
1103    else
1104      _title_prev_btn_set(it, prev_btn, EINA_FALSE);
1105
1106    _title_next_btn_set(it, next_btn);
1107    _item_content_set(it, content);
1108    it->title_visible = EINA_TRUE;
1109    return it;
1110 }
1111
1112 EAPI Evas_Object *
1113 elm_naviframe_add(Evas_Object *parent)
1114 {
1115    Evas_Object *obj;
1116    Evas *e;
1117    Widget_Data *wd;
1118
1119    ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
1120    ELM_SET_WIDTYPE(widtype, "naviframe");
1121    elm_widget_type_set(obj, "naviframe");
1122    elm_widget_sub_object_add(parent, obj);
1123    elm_widget_data_set(obj, wd);
1124    elm_widget_del_hook_set(obj, _del_hook);
1125    elm_widget_disable_hook_set(obj, _disable_hook);
1126    elm_widget_theme_hook_set(obj, _theme_hook);
1127    elm_widget_signal_emit_hook_set(obj, _emit_hook);
1128
1129    //base
1130    wd->base = edje_object_add(e);
1131    edje_object_mirrored_set(wd->base, elm_widget_mirrored_get(obj));
1132    elm_widget_resize_object_set(obj, wd->base);
1133    _elm_theme_object_set(obj, wd->base, "naviframe", "base", "default");
1134
1135    evas_object_event_callback_add(obj, EVAS_CALLBACK_MOVE, _move, obj);
1136    evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE, _resize, obj);
1137    evas_object_smart_callbacks_descriptions_set(obj, _signals);
1138
1139    wd->auto_pushed = EINA_TRUE;
1140    wd->freeze_events = EINA_TRUE;
1141
1142    return obj;
1143 }
1144
1145 EAPI Elm_Object_Item *
1146 elm_naviframe_item_push(Evas_Object *obj,
1147                         const char *title_label,
1148                         Evas_Object *prev_btn,
1149                         Evas_Object *next_btn,
1150                         Evas_Object *content,
1151                         const char *item_style)
1152 {
1153    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1154    Widget_Data *wd;
1155    Elm_Naviframe_Item *prev_it, *it;
1156
1157    wd = elm_widget_data_get(obj);
1158    if (!wd) return NULL;
1159
1160    it = _item_new(obj, title_label, prev_btn, next_btn, content, item_style);
1161    if (!it) return NULL;
1162
1163    evas_object_show(VIEW(it));
1164
1165    prev_it = (Elm_Naviframe_Item *) elm_naviframe_top_item_get(obj);
1166    if (prev_it)
1167      {
1168         if (wd->freeze_events)
1169           {
1170              evas_object_freeze_events_set(VIEW(it), EINA_TRUE);
1171              evas_object_freeze_events_set(VIEW(prev_it), EINA_TRUE);
1172           }
1173         edje_object_signal_emit(VIEW(prev_it),
1174                                 "elm,state,cur,pushed",
1175                                 "elm");
1176         edje_object_signal_emit(VIEW(it),
1177                                 "elm,state,new,pushed",
1178                                 "elm");
1179         edje_object_message_signal_process(VIEW(prev_it));
1180         edje_object_message_signal_process(VIEW(it));
1181      }
1182    wd->stack = eina_inlist_append(wd->stack, EINA_INLIST_GET(it));
1183    _sizing_eval(obj);
1184    return (Elm_Object_Item *) it;
1185 }
1186
1187 EAPI Elm_Object_Item *
1188 elm_naviframe_item_insert_before(Elm_Object_Item *before,
1189                                  const char *title_label,
1190                                  Evas_Object *prev_btn,
1191                                  Evas_Object *next_btn,
1192                                  Evas_Object *content,
1193                                  const char *item_style)
1194 {
1195    ELM_OBJ_ITEM_CHECK_OR_RETURN(before, NULL);
1196    Elm_Naviframe_Item *it;
1197    Widget_Data *wd;
1198
1199    wd = elm_widget_data_get(WIDGET(before));
1200    if (!wd) return NULL;
1201
1202    it = _item_new(WIDGET(before), title_label, prev_btn, next_btn, content,
1203                   item_style);
1204    if (!it) return NULL;
1205
1206    wd->stack =
1207       eina_inlist_prepend_relative(wd->stack, EINA_INLIST_GET(it),
1208                                    EINA_INLIST_GET(((Elm_Naviframe_Item *) before)));
1209    _sizing_eval(WIDGET(before));
1210    return (Elm_Object_Item *) it;
1211 }
1212
1213 EAPI Elm_Object_Item *
1214 elm_naviframe_item_insert_after(Elm_Object_Item *after,
1215                                 const char *title_label,
1216                                 Evas_Object *prev_btn,
1217                                 Evas_Object *next_btn,
1218                                 Evas_Object *content,
1219                                 const char *item_style)
1220 {
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(WIDGET(after));
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, EINA_INLIST_GET(it),
1239                                   EINA_INLIST_GET(((Elm_Naviframe_Item *) after)));
1240    _sizing_eval(WIDGET(after));
1241    return (Elm_Object_Item *) it;
1242 }
1243
1244 EAPI Evas_Object *
1245 elm_naviframe_item_pop(Evas_Object *obj)
1246 {
1247    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1248    Elm_Naviframe_Item *it, *prev_it = NULL;
1249    Widget_Data *wd;
1250    Evas_Object *content = NULL;
1251
1252    wd = elm_widget_data_get(obj);
1253    if (!wd) return NULL;
1254
1255    it = (Elm_Naviframe_Item *) elm_naviframe_top_item_get(obj);
1256    if (!it) return NULL;
1257    elm_widget_tree_unfocusable_set(it->content, EINA_TRUE);
1258    if (wd->preserve)
1259      content = it->content;
1260
1261    if (wd->stack->last->prev)
1262      prev_it = EINA_INLIST_CONTAINER_GET(wd->stack->last->prev,
1263                                          Elm_Naviframe_Item);
1264    wd->stack = eina_inlist_remove(wd->stack, EINA_INLIST_GET(it));
1265    if (prev_it)
1266      {
1267         if (wd->freeze_events)
1268           {
1269              evas_object_freeze_events_set(VIEW(it), EINA_TRUE);
1270              evas_object_freeze_events_set(VIEW(prev_it), EINA_TRUE);
1271           }
1272         edje_object_signal_emit(VIEW(it), "elm,state,cur,popped", "elm");
1273         evas_object_show(VIEW(prev_it));
1274         evas_object_raise(VIEW(prev_it));
1275         edje_object_signal_emit(VIEW(prev_it),
1276                                 "elm,state,prev,popped",
1277                                 "elm");
1278         edje_object_message_signal_process(VIEW(it));
1279         edje_object_message_signal_process(VIEW(prev_it));
1280      }
1281    else
1282      _item_del(it);
1283
1284    return content;
1285 }
1286
1287 EAPI void
1288 elm_naviframe_item_pop_to(Elm_Object_Item *it)
1289 {
1290    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1291    Elm_Naviframe_Item *navi_it;
1292    Widget_Data *wd;
1293    Eina_Inlist *l, *prev_l;
1294
1295    navi_it = (Elm_Naviframe_Item *) it;
1296    wd = elm_widget_data_get(WIDGET(navi_it));
1297    if (!wd) return;
1298
1299    if (it == elm_naviframe_top_item_get(WIDGET(navi_it))) return;
1300
1301    l = wd->stack->last->prev;
1302
1303    while(l)
1304      {
1305         if (EINA_INLIST_CONTAINER_GET(l, Elm_Naviframe_Item) ==
1306             ((Elm_Naviframe_Item *) it)) break;
1307         prev_l = l->prev;
1308         wd->stack = eina_inlist_remove(wd->stack, l);
1309         _item_del(EINA_INLIST_CONTAINER_GET(l, Elm_Naviframe_Item));
1310         l = prev_l;
1311      }
1312    elm_naviframe_item_pop(WIDGET(navi_it));
1313 }
1314
1315 EAPI void
1316 elm_naviframe_item_promote(Elm_Object_Item *it)
1317 {
1318    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1319    Elm_Naviframe_Item *navi_it;
1320    Elm_Naviframe_Item *prev_it;
1321    Widget_Data *wd;
1322
1323    navi_it = (Elm_Naviframe_Item *) it;
1324    wd = elm_widget_data_get(navi_it->base.widget);
1325    if (!wd) return;
1326
1327    if (it == elm_naviframe_top_item_get(navi_it->base.widget)) return;
1328    wd->stack = eina_inlist_demote(wd->stack, EINA_INLIST_GET(navi_it));
1329    prev_it = EINA_INLIST_CONTAINER_GET(wd->stack->last->prev,
1330                                          Elm_Naviframe_Item);
1331    if (wd->freeze_events)
1332      {
1333         evas_object_freeze_events_set(VIEW(it), EINA_TRUE);
1334         evas_object_freeze_events_set(VIEW(prev_it), EINA_TRUE);
1335      }
1336    edje_object_signal_emit(VIEW(prev_it),
1337                            "elm,state,cur,pushed",
1338                            "elm");
1339    evas_object_show(VIEW(navi_it));
1340    evas_object_raise(VIEW(navi_it));
1341    edje_object_signal_emit(VIEW(navi_it),
1342                            "elm,state,new,pushed",
1343                            "elm");
1344    edje_object_message_signal_process(VIEW(prev_it));
1345    edje_object_message_signal_process(VIEW(navi_it));
1346 }
1347
1348 EAPI void
1349 elm_naviframe_item_del(Elm_Object_Item *it)
1350 {
1351    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1352    Elm_Naviframe_Item *navi_it;
1353    Widget_Data *wd;
1354
1355    navi_it =(Elm_Naviframe_Item *) it;
1356    wd = elm_widget_data_get(WIDGET(navi_it));
1357    if (!wd) return;
1358
1359    if (it == elm_naviframe_top_item_get(WIDGET(navi_it)))
1360      {
1361         wd->stack = eina_inlist_remove(wd->stack, EINA_INLIST_GET(navi_it));
1362         _item_del(navi_it);
1363         navi_it = EINA_INLIST_CONTAINER_GET(wd->stack->last,
1364                                             Elm_Naviframe_Item);
1365         evas_object_show(VIEW(navi_it));
1366         evas_object_raise(VIEW(navi_it));
1367         edje_object_signal_emit(VIEW(navi_it), "elm,state,visible", "elm");
1368      }
1369    else
1370      {
1371         wd->stack = eina_inlist_remove(wd->stack, EINA_INLIST_GET(navi_it));
1372         _item_del(navi_it);
1373      }
1374 }
1375
1376 EAPI void
1377 elm_naviframe_content_preserve_on_pop_set(Evas_Object *obj, Eina_Bool preserve)
1378 {
1379    ELM_CHECK_WIDTYPE(obj, widtype);
1380    Widget_Data *wd = elm_widget_data_get(obj);
1381    if (!wd) return;
1382    wd->preserve = !!preserve;
1383 }
1384
1385 EAPI Eina_Bool
1386 elm_naviframe_content_preserve_on_pop_get(const Evas_Object *obj)
1387 {
1388    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1389    Widget_Data *wd = elm_widget_data_get(obj);
1390    if (!wd) return EINA_FALSE;
1391    return wd->preserve;
1392 }
1393
1394 EAPI Elm_Object_Item*
1395 elm_naviframe_top_item_get(const Evas_Object *obj)
1396 {
1397    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1398    Widget_Data *wd = elm_widget_data_get(obj);
1399    if ((!wd) || (!wd->stack)) return NULL;
1400    return (Elm_Object_Item *) (EINA_INLIST_CONTAINER_GET(wd->stack->last,
1401                                                          Elm_Naviframe_Item));
1402 }
1403
1404 EAPI Elm_Object_Item*
1405 elm_naviframe_bottom_item_get(const Evas_Object *obj)
1406 {
1407    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1408    Widget_Data *wd = elm_widget_data_get(obj);
1409    if ((!wd) || (!wd->stack)) return NULL;
1410    return (Elm_Object_Item *) (EINA_INLIST_CONTAINER_GET(wd->stack,
1411                                                          Elm_Naviframe_Item));
1412 }
1413
1414 EAPI void
1415 elm_naviframe_item_style_set(Elm_Object_Item *it, const char *item_style)
1416 {
1417    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1418    Elm_Naviframe_Item *navi_it = (Elm_Naviframe_Item *) it;
1419
1420    //Return if new style is exsiting one.
1421    if (item_style)
1422      if (!strcmp(item_style, navi_it->style)) return;
1423
1424    if (!item_style)
1425      if (!strcmp("basic", navi_it->style)) return;
1426
1427    _item_style_set(navi_it, item_style);
1428 }
1429
1430 EAPI const char *
1431 elm_naviframe_item_style_get(const Elm_Object_Item *it)
1432 {
1433    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
1434    Elm_Naviframe_Item *navi_it = (Elm_Naviframe_Item *) it;
1435    return navi_it->style;
1436 }
1437
1438 EAPI void
1439 elm_naviframe_item_title_visible_set(Elm_Object_Item *it, Eina_Bool visible)
1440 {
1441    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1442    Elm_Naviframe_Item *navi_it = (Elm_Naviframe_Item *) it;
1443
1444    visible = !!visible;
1445    if (navi_it->title_visible == visible) return;
1446
1447    navi_it->title_visible = visible;
1448    _item_title_visible_update(navi_it);
1449 }
1450
1451 EAPI Eina_Bool
1452 elm_naviframe_item_title_visible_get(const Elm_Object_Item *it)
1453 {
1454    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
1455    Elm_Naviframe_Item *navi_it = (Elm_Naviframe_Item *) it;
1456    return navi_it->title_visible;
1457 }
1458
1459 EAPI void
1460 elm_naviframe_prev_btn_auto_pushed_set(Evas_Object *obj, Eina_Bool auto_pushed)
1461 {
1462    ELM_CHECK_WIDTYPE(obj, widtype);
1463    Widget_Data *wd = elm_widget_data_get(obj);
1464    if (!wd) return;
1465    wd->auto_pushed = !!auto_pushed;
1466 }
1467
1468 EAPI Eina_Bool
1469 elm_naviframe_prev_btn_auto_pushed_get(const Evas_Object *obj)
1470 {
1471    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1472    Widget_Data *wd = elm_widget_data_get(obj);
1473    if (!wd) return EINA_FALSE;
1474    return wd->auto_pushed;
1475 }
1476
1477 EAPI Eina_Inlist *
1478 elm_naviframe_items_get(const Evas_Object *obj)
1479 {
1480    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1481    Widget_Data *wd = elm_widget_data_get(obj);
1482    if (!wd) return NULL;
1483    return wd->stack;
1484 }