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    Evas_Coord         minw;
45    Evas_Coord         minh;
46    Eina_Bool          back_btn: 1;
47    Eina_Bool          title_visible: 1;
48 };
49
50 static const char *widtype = NULL;
51
52 static const char SIG_TRANSITION_FINISHED[] = "transition,finished";
53 static const char SIG_PUSH_FINISHED[] = "push,finished";
54 static const char SIG_POP_FINISHED[] = "pop,finished";
55 static const char SIG_TITLE_CLICKED[] = "title,clicked";
56
57 static const Evas_Smart_Cb_Description _signals[] = {
58        {SIG_TRANSITION_FINISHED, ""},
59        {SIG_TITLE_CLICKED, ""},
60        {NULL, NULL}
61 };
62
63 static void _del_hook(Evas_Object *obj);
64 static void _theme_hook(Evas_Object *obj);
65 static void _emit_hook(Evas_Object *obj,
66                        const char *emission,
67                        const char *source);
68 static void _disable_hook(Evas_Object *obj);
69 static void _mirrored_set(Evas_Object *obj, Eina_Bool rtl);
70 static void _item_text_set_hook(Elm_Object_Item *it,
71                                 const char *part,
72                                 const char *label);
73 static const char *_item_text_get_hook(const Elm_Object_Item *it,
74                                        const char *part);
75 static void _item_content_set_hook(Elm_Object_Item *it,
76                                    const char *part,
77                                    Evas_Object *content);
78 static Evas_Object *_item_content_get_hook(const Elm_Object_Item *it,
79                                            const char *part);
80 static Evas_Object *_item_content_unset_hook(Elm_Object_Item *it,
81                                              const char *part);
82 static void _item_signal_emit_hook(Elm_Object_Item *it,
83                                    const char *emission,
84                                    const char *source);
85 static void _item_title_visible_update(Elm_Naviframe_Item *navi_it);
86 static void _sizing_eval(Evas_Object *obj);
87 static void _move(void *data, Evas *e, Evas_Object *obj, void *event_info);
88 static void _resize(void *data,
89                     Evas *e,
90                     Evas_Object *obj,
91                     void *event_info);
92 static void _title_clicked(void *data, Evas_Object *obj,
93                            const char *emission,
94                            const char *source);
95 static void _back_btn_clicked(void *data,
96                               Evas_Object *obj,
97                               void *event_info);
98 static Evas_Object *_back_btn_new(Evas_Object *obj);
99 static void _item_content_del(void *data,
100                               Evas *e,
101                               Evas_Object *obj,
102                               void *event_info);
103 static void _title_content_del(void *data,
104                                Evas *e,
105                                Evas_Object *obj,
106                                void *event_info);
107 static void _title_prev_btn_del(void *data,
108                                 Evas *e,
109                                 Evas_Object *obj,
110                                 void *event_info);
111 static void _title_next_btn_del(void *data,
112                                 Evas *e,
113                                 Evas_Object *obj,
114                                 void *event_info);
115 static void _title_icon_del(void *data,
116                             Evas *e,
117                             Evas_Object *obj,
118                             void *event_info);
119 static void _title_content_set(Elm_Naviframe_Item *it,
120                                const char *part,
121                                Evas_Object *content);
122 static void _title_prev_btn_set(Elm_Naviframe_Item *it,
123                                 Evas_Object *btn,
124                                 Eina_Bool back_btn);
125 static void _title_next_btn_set(Elm_Naviframe_Item *it, Evas_Object *btn);
126 static void _title_icon_set(Elm_Naviframe_Item *it, Evas_Object *icon);
127 static Evas_Object * _item_content_unset(Elm_Naviframe_Item *it);
128 static Evas_Object * _title_prev_btn_unset(Elm_Naviframe_Item *it);
129 static Evas_Object * _title_next_btn_unset(Elm_Naviframe_Item *it);
130 static Evas_Object * _title_icon_unset(Elm_Naviframe_Item *it);
131 static Evas_Object * _title_content_unset(Elm_Naviframe_Item *it,
132                                           const char *part);
133 static void _item_del(Elm_Naviframe_Item *it);
134 static void _pushed_finished(void *data,
135                              Evas_Object *obj,
136                              const char *emission,
137                              const char *source);
138 static void _popped_finished(void *data,
139                              Evas_Object *obj,
140                              const char *emission,
141                              const char *source);
142 static void _show_finished(void *data,
143                            Evas_Object *obj,
144                            const char *emission,
145                            const char *source);
146 static void _changed_size_hints(void *data,
147                                 Evas *e,
148                                 Evas_Object *obj,
149                                 void *event_info);
150 static void _item_content_set(Elm_Naviframe_Item *navi_it,
151                               Evas_Object *content);
152 static void _item_style_set(Elm_Naviframe_Item *navi_it,
153                             const char *item_style);
154 static Elm_Naviframe_Item * _item_new(Evas_Object *obj,
155                                       const char *title_label,
156                                       Evas_Object *prev_btn,
157                                       Evas_Object *next_btn,
158                                       Evas_Object *content,
159                                       const char *item_style);
160
161 static void
162 _del_hook(Evas_Object *obj)
163 {
164    Widget_Data *wd;
165    Elm_Naviframe_Item *it;
166
167    wd = elm_widget_data_get(obj);
168    if (!wd) return;
169
170    if (wd->stack)
171      {
172         while (wd->stack->last)
173           {
174              it = EINA_INLIST_CONTAINER_GET(wd->stack->last,
175                                             Elm_Naviframe_Item);
176              wd->stack = eina_inlist_remove(wd->stack, wd->stack->last);
177              _item_del(it);
178              if (!wd->stack) break;
179           }
180      }
181    free(wd);
182 }
183
184 static void
185 _theme_hook(Evas_Object *obj)
186 {
187    Widget_Data *wd;
188    Elm_Naviframe_Item *it;
189
190    wd  = elm_widget_data_get(obj);
191    if (!wd) return;
192
193    _elm_theme_object_set(obj,
194                          wd->base,
195                          "naviframe",
196                          "base",
197                          elm_widget_style_get(obj));
198
199    EINA_INLIST_FOREACH(wd->stack, it)
200      {
201         _item_style_set(it, it->style);
202         _item_title_visible_update(it);
203      }
204
205    _elm_widget_mirrored_reload(obj);
206    _mirrored_set(obj, elm_widget_mirrored_get(obj));
207 }
208
209 static void _emit_hook(Evas_Object *obj,
210                        const char *emission,
211                        const char *source)
212 {
213    ELM_CHECK_WIDTYPE(obj, widtype);
214
215    Widget_Data *wd = elm_widget_data_get(obj);
216    if (!wd) return;
217
218    edje_object_signal_emit(wd->base, emission, source);
219 }
220
221 static void
222 _disable_hook(Evas_Object *obj __UNUSED__)
223 {
224    //FIXME:
225 }
226
227 static void
228 _mirrored_set(Evas_Object *obj, Eina_Bool rtl)
229 {
230    Widget_Data *wd;
231    Elm_Naviframe_Item *it;
232
233    wd  = elm_widget_data_get(obj);
234    if (!wd) return;
235
236    EINA_INLIST_FOREACH(wd->stack, it)
237      edje_object_mirrored_set(VIEW(it), rtl);
238    edje_object_mirrored_set(wd->base, rtl);
239 }
240
241 static void
242 _item_text_set_hook(Elm_Object_Item *it,
243                     const char *part,
244                     const char *label)
245 {
246    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
247
248    Elm_Naviframe_Text_Item_Pair *pair = NULL;
249    Elm_Naviframe_Item *navi_it = (Elm_Naviframe_Item *) it;
250    char buf[1024];
251
252    if (!part || !strcmp(part, "default"))
253      snprintf(buf, sizeof(buf), "elm.text.title");
254    else if(!strcmp("subtitle", part))
255      snprintf(buf, sizeof(buf), "elm.text.subtitle");
256    else
257      snprintf(buf, sizeof(buf), "%s", part);
258
259    EINA_INLIST_FOREACH(navi_it->text_list, pair)
260      if (!strcmp(buf, pair->part)) break;
261
262    if (!pair)
263      {
264         pair = ELM_NEW(Elm_Naviframe_Text_Item_Pair);
265         if (!pair)
266           {
267              ERR("Failed to allocate new text part of the item! : naviframe=%p",
268              WIDGET(navi_it));
269              return;
270           }
271         eina_stringshare_replace(&pair->part, buf);
272         navi_it->text_list = eina_inlist_append(navi_it->text_list,
273                                                 EINA_INLIST_GET(pair));
274      }
275
276    eina_stringshare_replace(&pair->text, label);
277    edje_object_part_text_set(VIEW(navi_it), buf, label);
278
279    if (label)
280      {
281         snprintf(buf, sizeof(buf), "elm,state,%s,show", buf);
282         edje_object_signal_emit(VIEW(navi_it), buf, "elm");
283      }
284    else
285      {
286         snprintf(buf, sizeof(buf), "elm,state,%s,hide", buf);
287         edje_object_signal_emit(VIEW(navi_it), buf, "elm");
288      }
289
290    _sizing_eval(WIDGET(navi_it));
291 }
292
293 static const char *
294 _item_text_get_hook(const Elm_Object_Item *it, const char *part)
295 {
296    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
297    Elm_Naviframe_Text_Item_Pair *pair = NULL;
298    Elm_Naviframe_Item *navi_it = (Elm_Naviframe_Item *) it;
299    char buf[1024];
300
301    if (!part || !strcmp(part, "default"))
302      snprintf(buf, sizeof(buf), "elm.text.title");
303    else if(!strcmp("subtitle", part))
304      snprintf(buf, sizeof(buf), "elm.text.subtitle");
305    else
306      snprintf(buf, sizeof(buf), "%s", part);
307
308    EINA_INLIST_FOREACH(navi_it->text_list, pair)
309      {
310         if (!strcmp(buf, pair->part))
311           return pair->text;
312      }
313    return NULL;
314 }
315
316 static void
317 _item_content_set_hook(Elm_Object_Item *it,
318                        const char *part,
319                        Evas_Object *content)
320 {
321    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
322
323    Elm_Naviframe_Item *navi_it = (Elm_Naviframe_Item *) it;
324
325    //specified parts
326    if ((!part) || (!strcmp(part, "elm.swallow.content")))
327      {
328         _item_content_set(navi_it, content);
329         return;
330      }
331    else if (!strcmp(part, "elm.swallow.prev_btn"))
332      {
333         _title_prev_btn_set(navi_it, content, EINA_FALSE);
334         return;
335      }
336    else if (!strcmp(part, "elm.swallow.next_btn"))
337      {
338         _title_next_btn_set(navi_it, content);
339         return;
340      }
341    else if (!strcmp(part, "icon"))
342      {
343         _title_icon_set(navi_it, content);
344         return;
345      }
346
347    //common part
348    _title_content_set(navi_it, part, content);
349 }
350
351 static Evas_Object *
352 _item_content_get_hook(const Elm_Object_Item *it, const char *part)
353 {
354    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
355    Elm_Naviframe_Content_Item_Pair *pair = NULL;
356    Elm_Naviframe_Item *navi_it = (Elm_Naviframe_Item *) it;
357
358    //specified parts
359    if ((!part) || (!strcmp(part, "elm.swallow.content")))
360      return navi_it->content;
361    else if (!strcmp(part, "elm.swallow.prev_btn"))
362      return navi_it->title_prev_btn;
363    else if (!strcmp(part, "elm.swallow.next_btn"))
364      return navi_it->title_next_btn;
365    else if (!strcmp(part, "icon"))
366      return navi_it->title_icon;
367
368    //common parts
369    EINA_INLIST_FOREACH(navi_it->content_list, pair)
370      {
371         if (!strcmp(part, pair->part))
372           return pair->content;
373      }
374    return NULL;
375 }
376
377 static Evas_Object *
378 _item_content_unset_hook(Elm_Object_Item *it, const char *part)
379 {
380    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
381    Elm_Naviframe_Item *navi_it = (Elm_Naviframe_Item *) it;
382
383    //specified parts
384    if (!part || !strcmp("elm.swallow.content", part))
385      return _item_content_unset(navi_it);
386    else if (!strcmp(part, "elm.swallow.prev_btn"))
387      return _title_prev_btn_unset(navi_it);
388    else if (!strcmp(part, "elm.swallow.next_btn"))
389      return _title_next_btn_unset(navi_it);
390    else if (!strcmp(part, "icon"))
391      return _title_icon_unset(navi_it);
392
393    return _title_content_unset(navi_it, part);
394 }
395
396 static void
397 _item_signal_emit_hook(Elm_Object_Item *it,
398                        const char *emission,
399                        const char *source)
400 {
401    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
402    Elm_Naviframe_Item *navi_it = (Elm_Naviframe_Item *) it;
403    edje_object_signal_emit(VIEW(navi_it), emission, source);
404 }
405
406 static void
407 _item_title_visible_update(Elm_Naviframe_Item *navi_it)
408 {
409    if (navi_it->title_visible)
410      edje_object_signal_emit(VIEW(navi_it), "elm,state,title,show", "elm");
411    else
412      edje_object_signal_emit(VIEW(navi_it), "elm,state,title,hide", "elm");
413 }
414
415 static void
416 _sizing_eval(Evas_Object *obj)
417 {
418    Widget_Data *wd;
419    Elm_Naviframe_Item *it;
420    Evas_Coord x, y, w, h;
421    Evas_Coord minw = -1, minh = -1;
422
423    wd = elm_widget_data_get(obj);
424    if (!wd) return;
425
426    evas_object_geometry_get(obj, &x, &y, &w, &h);
427
428    EINA_INLIST_FOREACH(wd->stack, it)
429      {
430         evas_object_move(VIEW(it), x, y);
431         evas_object_resize(VIEW(it), w, h);
432         edje_object_size_min_calc(VIEW(it), &it->minw, &it->minh);
433         if (it->minw > minw) minw = it->minw;
434         if (it->minh > minh) minh = it->minh;
435      }
436    evas_object_size_hint_min_set(obj, minw, minh);
437    evas_object_size_hint_max_set(obj, -1, -1);
438 }
439
440 static void
441 _move(void *data __UNUSED__,
442       Evas *e __UNUSED__,
443       Evas_Object *obj,
444       void *event_info __UNUSED__)
445 {
446    _sizing_eval(obj);
447 }
448
449 static void
450 _resize(void *data __UNUSED__,
451         Evas *e __UNUSED__,
452         Evas_Object *obj,
453         void *event_info __UNUSED__)
454 {
455    _sizing_eval(obj);
456 }
457
458 static void
459 _title_clicked(void *data,
460                Evas_Object *obj __UNUSED__,
461                const char *emission __UNUSED__,
462                const char *source __UNUSED__)
463 {
464    Elm_Naviframe_Item *it = data;
465    evas_object_smart_callback_call(WIDGET(it), SIG_TITLE_CLICKED, it);
466 }
467
468 static void
469 _back_btn_clicked(void *data,
470                   Evas_Object *obj,
471                   void *event_info __UNUSED__)
472 {
473 /* Since edje has the event queue, clicked event could be happend multiple times
474    on some heavy environment. This callback del will prevent those  scenario and
475    guarantee only one clicked for it's own page. */
476    evas_object_smart_callback_del(obj, "clicked", _back_btn_clicked);
477    elm_naviframe_item_pop(data);
478 }
479
480 static Evas_Object *
481 _back_btn_new(Evas_Object *obj)
482 {
483    Evas_Object *btn;
484    char buf[1024];
485    btn = elm_button_add(obj);
486    if (!btn) return NULL;
487    evas_object_smart_callback_add(btn, "clicked", _back_btn_clicked, obj);
488    snprintf(buf, sizeof(buf), "naviframe/back_btn/%s", elm_widget_style_get(obj));
489    elm_object_style_set(btn, buf);
490    return btn;
491 }
492
493 static void
494 _title_content_del(void *data,
495                    Evas *e __UNUSED__,
496                    Evas_Object *obj __UNUSED__,
497                    void *event_info __UNUSED__)
498 {
499    char buf[1024];
500    Elm_Naviframe_Content_Item_Pair *pair = data;
501    Elm_Naviframe_Item *it = pair->it;
502    snprintf(buf, sizeof(buf), "elm,state,%s,hide", pair->part);
503    edje_object_signal_emit(VIEW(it), buf, "elm");
504    it->content_list = eina_inlist_remove(it->content_list,
505                                          EINA_INLIST_GET(pair));
506    eina_stringshare_del(pair->part);
507    free(pair);
508 }
509
510 static void
511 _title_prev_btn_del(void *data,
512                     Evas *e __UNUSED__,
513                     Evas_Object *obj __UNUSED__,
514                     void *event_info __UNUSED__)
515 {
516    Elm_Naviframe_Item *it = data;
517    it->back_btn = EINA_FALSE;
518    it->title_prev_btn = NULL;
519    edje_object_signal_emit(VIEW(it), "elm,state,prev_btn,hide", "elm");
520 }
521
522 static void
523 _title_next_btn_del(void *data,
524                     Evas *e __UNUSED__,
525                     Evas_Object *obj __UNUSED__,
526                     void *event_info __UNUSED__)
527 {
528    Elm_Naviframe_Item *it = data;
529    it->title_next_btn = NULL;
530    edje_object_signal_emit(VIEW(it), "elm,state,next_btn,hide", "elm");
531 }
532
533 static void
534 _title_icon_del(void *data,
535                 Evas *e __UNUSED__,
536                 Evas_Object *obj __UNUSED__,
537                 void *event_info __UNUSED__)
538 {
539    Elm_Naviframe_Item *it = data;
540    it->title_icon = NULL;
541    edje_object_signal_emit(VIEW(it), "elm,state,icon,hide", "elm");
542 }
543
544 static void
545 _item_content_del(void *data,
546                   Evas *e __UNUSED__,
547                   Evas_Object *obj __UNUSED__,
548                   void *event_info __UNUSED__)
549 {
550    Elm_Naviframe_Item *it = data;
551    it->content = NULL;
552    edje_object_signal_emit(VIEW(it), "elm,state,content,hide", "elm");
553 }
554
555 static void
556 _title_content_set(Elm_Naviframe_Item *it,
557                    const char *part,
558                    Evas_Object *content)
559 {
560    char buf[1024];
561    Elm_Naviframe_Content_Item_Pair *pair = NULL;
562
563    EINA_INLIST_FOREACH(it->content_list, pair)
564      if (!strcmp(part, pair->part)) break;
565
566    if (pair)
567      {
568         if (pair->content != content)
569           {
570              if (content)
571                {
572                   evas_object_event_callback_del(pair->content,
573                                                  EVAS_CALLBACK_DEL,
574                                                  _title_content_del);
575                   evas_object_event_callback_del(pair->content,
576                                                  EVAS_CALLBACK_CHANGED_SIZE_HINTS,
577                                                  _changed_size_hints);
578                   snprintf(buf, sizeof(buf), "elm,state,%s,hide", part);
579                   edje_object_signal_emit(VIEW(it), buf, "elm");
580                }
581              evas_object_del(pair->content);
582              if (!content) return;
583           }
584      }
585    else
586      {
587         if (!content) return;
588         pair = ELM_NEW(Elm_Naviframe_Content_Item_Pair);
589         if (!pair)
590           {
591              ERR("Failed to allocate new content part of the item! : naviframe=%p", WIDGET(it));
592              return;
593           }
594         pair->it = it;
595         eina_stringshare_replace(&pair->part, part);
596         it->content_list = eina_inlist_append(it->content_list,
597                                               EINA_INLIST_GET(pair));
598      }
599    if (pair->content != content)
600      {
601         elm_widget_sub_object_add(WIDGET(it), content);
602         evas_object_event_callback_add(content,
603                                        EVAS_CALLBACK_DEL,
604                                        _title_content_del,
605                                        pair);
606         evas_object_event_callback_add(content,
607                                        EVAS_CALLBACK_CHANGED_SIZE_HINTS,
608                                        _changed_size_hints,
609                                        WIDGET(it));
610      }
611    edje_object_part_swallow(VIEW(it), part, content);
612    snprintf(buf, sizeof(buf), "elm,state,%s,show", part);
613    edje_object_signal_emit(VIEW(it), buf, "elm");
614    pair->content = content;
615
616    _sizing_eval(WIDGET(it));
617 }
618
619 static void
620 _title_prev_btn_set(Elm_Naviframe_Item *it,
621                     Evas_Object *btn,
622                     Eina_Bool back_btn)
623 {
624    if (it->title_prev_btn == btn) return;
625
626    if (it->title_prev_btn)
627      evas_object_del(it->title_prev_btn);
628
629    it->title_prev_btn = btn;
630    if (!btn) return;
631
632    elm_widget_sub_object_add(WIDGET(it), btn);
633    evas_object_event_callback_add(btn,
634                                   EVAS_CALLBACK_DEL,
635                                   _title_prev_btn_del,
636                                   it);
637    evas_object_event_callback_add(btn,
638                                   EVAS_CALLBACK_CHANGED_SIZE_HINTS,
639                                   _changed_size_hints,
640                                   WIDGET(it));
641    edje_object_part_swallow(VIEW(it), "elm.swallow.prev_btn", btn);
642    edje_object_signal_emit(VIEW(it), "elm,state,prev_btn,show", "elm");
643    it->back_btn = back_btn;
644
645    _sizing_eval(WIDGET(it));
646 }
647
648 static void
649 _title_next_btn_set(Elm_Naviframe_Item *it, Evas_Object *btn)
650 {
651    if (it->title_next_btn == btn) return;
652
653    if (it->title_next_btn)
654      evas_object_del(it->title_next_btn);
655
656    it->title_next_btn = btn;
657    if (!btn) return;
658
659    elm_widget_sub_object_add(WIDGET(it), btn);
660    evas_object_event_callback_add(btn,
661                                   EVAS_CALLBACK_DEL,
662                                   _title_next_btn_del,
663                                   it);
664    evas_object_event_callback_add(btn,
665                                   EVAS_CALLBACK_CHANGED_SIZE_HINTS,
666                                   _changed_size_hints,
667                                   WIDGET(it));
668    edje_object_part_swallow(VIEW(it), "elm.swallow.next_btn", btn);
669    edje_object_signal_emit(VIEW(it), "elm,state,next_btn,show", "elm");
670
671    _sizing_eval(WIDGET(it));
672 }
673
674 static void
675 _title_icon_set(Elm_Naviframe_Item *it, Evas_Object *icon)
676 {
677    if (it->title_icon == icon) return;
678
679    if (it->title_icon)
680      evas_object_del(it->title_icon);
681
682    it->title_icon = icon;
683    if (!icon) return;
684
685    elm_widget_sub_object_add(WIDGET(it), icon);
686    evas_object_event_callback_add(icon,
687                                   EVAS_CALLBACK_DEL,
688                                   _title_icon_del,
689                                   it);
690    evas_object_event_callback_add(icon,
691                                   EVAS_CALLBACK_CHANGED_SIZE_HINTS,
692                                   _changed_size_hints,
693                                   WIDGET(it));
694    edje_object_part_swallow(VIEW(it), "elm.swallow.icon", icon);
695    edje_object_signal_emit(VIEW(it), "elm,state,icon,show", "elm");
696
697    _sizing_eval(WIDGET(it));
698 }
699
700 static Evas_Object *
701 _item_content_unset(Elm_Naviframe_Item *it)
702 {
703    Evas_Object *content = it->content;
704    if (!content) return NULL;
705
706    elm_widget_sub_object_del(WIDGET(it), content);
707    edje_object_part_unswallow(VIEW(it), content);
708    edje_object_signal_emit(VIEW(it), "elm,state,content,hide", "elm");
709    evas_object_event_callback_del(content,
710                                   EVAS_CALLBACK_DEL,
711                                   _item_content_del);
712    evas_object_event_callback_del(content,
713                                   EVAS_CALLBACK_CHANGED_SIZE_HINTS,
714                                   _changed_size_hints);
715    _sizing_eval(WIDGET(it));
716
717    it->content = NULL;
718    return content;
719 }
720
721 static Evas_Object *
722 _title_prev_btn_unset(Elm_Naviframe_Item *it)
723 {
724    Evas_Object *content = it->title_prev_btn;
725    if (!content) return NULL;
726
727    elm_widget_sub_object_del(WIDGET(it), content);
728    edje_object_part_unswallow(VIEW(it), content);
729    edje_object_signal_emit(VIEW(it), "elm,state,prev_btn,hide", "elm");
730    evas_object_event_callback_del(content,
731                                   EVAS_CALLBACK_DEL,
732                                   _title_prev_btn_del);
733    evas_object_event_callback_del(content,
734                                   EVAS_CALLBACK_CHANGED_SIZE_HINTS,
735                                   _changed_size_hints);
736    _sizing_eval(WIDGET(it));
737
738    it->title_prev_btn = NULL;
739    return content;
740 }
741
742 static Evas_Object *
743 _title_next_btn_unset(Elm_Naviframe_Item *it)
744 {
745    Evas_Object *content = it->title_next_btn;
746    if (!content) return NULL;
747
748    elm_widget_sub_object_del(WIDGET(it), content);
749    edje_object_part_unswallow(VIEW(it), content);
750    edje_object_signal_emit(VIEW(it), "elm,state,next_btn,hide", "elm");
751    evas_object_event_callback_del(content,
752                                   EVAS_CALLBACK_DEL,
753                                   _title_next_btn_del);
754    evas_object_event_callback_del(content,
755                                   EVAS_CALLBACK_CHANGED_SIZE_HINTS,
756                                   _changed_size_hints);
757    _sizing_eval(WIDGET(it));
758
759    it->title_next_btn = NULL;
760    return content;
761 }
762
763 static Evas_Object *
764 _title_icon_unset(Elm_Naviframe_Item *it)
765 {
766    Evas_Object *content = it->title_icon;
767    if (!content) return NULL;
768
769    elm_widget_sub_object_del(WIDGET(it), content);
770    edje_object_part_unswallow(VIEW(it), content);
771    edje_object_signal_emit(VIEW(it), "elm,state,icon,hide", "elm");
772    evas_object_event_callback_del(content,
773                                   EVAS_CALLBACK_DEL,
774                                   _title_icon_del);
775    evas_object_event_callback_del(content,
776                                   EVAS_CALLBACK_CHANGED_SIZE_HINTS,
777                                   _changed_size_hints);
778    _sizing_eval(WIDGET(it));
779    it->title_icon = NULL;
780
781    return content;
782 }
783
784 static Evas_Object *
785 _title_content_unset(Elm_Naviframe_Item *it, const char *part)
786 {
787    Elm_Naviframe_Content_Item_Pair *pair = NULL;
788    char buf[1028];
789    Evas_Object *content = NULL;
790
791    EINA_INLIST_FOREACH(it->content_list, pair)
792      {
793         if (!strcmp(part, pair->part))
794           {
795              content = pair->content;
796              eina_stringshare_del(pair->part);
797              it->content_list = eina_inlist_remove(it->content_list,
798                                                    EINA_INLIST_GET(pair));
799              free(pair);
800              break;
801           }
802      }
803
804    if (!content) return NULL;
805
806    elm_widget_sub_object_del(WIDGET(it), content);
807    edje_object_part_unswallow(VIEW(it), content);
808    snprintf(buf, sizeof(buf), "elm,state,%s,hide", part);
809    edje_object_signal_emit(VIEW(it), buf, "elm");
810    evas_object_event_callback_del(content,
811                                   EVAS_CALLBACK_DEL,
812                                   _title_content_del);
813    evas_object_event_callback_del(content,
814                                   EVAS_CALLBACK_CHANGED_SIZE_HINTS,
815                                   _changed_size_hints);
816    _sizing_eval(WIDGET(it));
817
818    return content;
819 }
820
821 static void
822 _item_del(Elm_Naviframe_Item *it)
823 {
824    Widget_Data *wd;
825    Elm_Naviframe_Content_Item_Pair *content_pair;
826    Elm_Naviframe_Text_Item_Pair *text_pair;
827
828    if (!it) return;
829
830    wd = elm_widget_data_get(WIDGET(it));
831    if (!wd) return;
832
833    if (it->title_prev_btn)
834      evas_object_del(it->title_prev_btn);
835    if (it->title_next_btn)
836      evas_object_del(it->title_next_btn);
837    if (it->title_icon)
838      evas_object_del(it->title_icon);
839    if ((it->content) && (!wd->preserve))
840      evas_object_del(it->content);
841
842    while (it->content_list)
843      {
844         content_pair = EINA_INLIST_CONTAINER_GET(it->content_list,
845                                                  Elm_Naviframe_Content_Item_Pair);
846         evas_object_event_callback_del(content_pair->content,
847                                        EVAS_CALLBACK_DEL,
848                                        _title_content_del);
849         evas_object_event_callback_del(content_pair->content,
850                                        EVAS_CALLBACK_CHANGED_SIZE_HINTS,
851                                        _changed_size_hints);
852         evas_object_del(content_pair->content);
853         eina_stringshare_del(content_pair->part);
854         it->content_list = eina_inlist_remove(it->content_list,
855                                               it->content_list);
856         free(content_pair);
857      }
858
859    while (it->text_list)
860      {
861         text_pair = EINA_INLIST_CONTAINER_GET(it->text_list,
862                                               Elm_Naviframe_Text_Item_Pair);
863         eina_stringshare_del(text_pair->part);
864         eina_stringshare_del(text_pair->text);
865         it->text_list = eina_inlist_remove(it->text_list,
866                                            it->text_list);
867         free(text_pair);
868      }
869
870    eina_stringshare_del(it->style);
871
872    elm_widget_item_del(it);
873 }
874
875 static void
876 _pushed_finished(void *data,
877                  Evas_Object *obj __UNUSED__,
878                  const char *emission __UNUSED__,
879                  const char *source __UNUSED__)
880 {
881    Widget_Data *wd;
882    Elm_Naviframe_Item *it = data;
883    if (!it) return;
884
885    wd = elm_widget_data_get(WIDGET(it));
886    if (!wd) return;
887
888    evas_object_hide(VIEW(it));
889    evas_object_smart_callback_call(WIDGET(it),
890                                    SIG_PUSH_FINISHED,
891                                    data);
892    if (wd->freeze_events)
893      evas_object_freeze_events_set(VIEW(it), EINA_FALSE);
894 }
895
896 static void
897 _popped_finished(void *data,
898                  Evas_Object *obj __UNUSED__,
899                  const char *emission __UNUSED__,
900                  const char *source __UNUSED__)
901 {
902    Elm_Naviframe_Item *it = data;
903    if (!it) return;
904    evas_object_smart_callback_call(WIDGET(it),
905                                    SIG_POP_FINISHED,
906                                    data);
907    _item_del(data);
908 }
909
910 static void
911 _show_finished(void *data,
912                Evas_Object *obj __UNUSED__,
913                const char *emission __UNUSED__,
914                const char *source __UNUSED__)
915 {
916    Elm_Naviframe_Item *it;
917    Widget_Data *wd;
918
919    it = data;
920    if (!it) return;
921    wd =  elm_widget_data_get(WIDGET(it));
922    if (!wd) return;
923
924    evas_object_smart_callback_call(WIDGET(it),
925                                    SIG_TRANSITION_FINISHED,
926                                    data);
927    if (wd->freeze_events)
928      evas_object_freeze_events_set(VIEW(it), EINA_FALSE);
929 }
930
931 static void
932 _changed_size_hints(void *data,
933                     Evas *e __UNUSED__,
934                     Evas_Object *obj __UNUSED__,
935                     void *event_info __UNUSED__)
936 {
937    _sizing_eval(data);
938 }
939
940 static void
941 _item_content_set(Elm_Naviframe_Item *navi_it, Evas_Object *content)
942 {
943    if (navi_it->content == content) return;
944    if (navi_it->content) evas_object_del(navi_it->content);
945    elm_widget_sub_object_add(WIDGET(navi_it), content);
946    edje_object_part_swallow(VIEW(navi_it),
947                             "elm.swallow.content",
948                             content);
949    if (content)
950      edje_object_signal_emit(VIEW(navi_it),
951                              "elm,state,content,show",
952                              "elm");
953    else
954      edje_object_signal_emit(VIEW(navi_it),
955                              "elm,state,content,hide",
956                              "elm");
957    evas_object_event_callback_add(content,
958                                   EVAS_CALLBACK_DEL,
959                                   _item_content_del,
960                                   navi_it);
961    evas_object_event_callback_add(content,
962                                   EVAS_CALLBACK_CHANGED_SIZE_HINTS,
963                                   _changed_size_hints,
964                                   WIDGET(navi_it));
965    navi_it->content = content;
966    _sizing_eval(WIDGET(navi_it));
967 }
968
969 //FIXME: need to handle if this function is called while transition
970 static void
971 _item_style_set(Elm_Naviframe_Item *navi_it, const char *item_style)
972 {
973    Elm_Naviframe_Content_Item_Pair *content_pair;
974    Elm_Naviframe_Text_Item_Pair *text_pair;
975    Widget_Data *wd;
976
977    char buf[256];
978
979    if (!item_style)
980      {
981         strcpy(buf, "item/basic");
982         eina_stringshare_replace(&navi_it->style, "basic");
983      }
984    else
985      {
986         snprintf(buf, sizeof(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         //If the item is only one, the stack will be empty
1364         if (!wd->stack) return;
1365         navi_it = EINA_INLIST_CONTAINER_GET(wd->stack->last,
1366                                             Elm_Naviframe_Item);
1367         evas_object_show(VIEW(navi_it));
1368         evas_object_raise(VIEW(navi_it));
1369         edje_object_signal_emit(VIEW(navi_it), "elm,state,visible", "elm");
1370      }
1371    else
1372      {
1373         wd->stack = eina_inlist_remove(wd->stack, EINA_INLIST_GET(navi_it));
1374         _item_del(navi_it);
1375      }
1376 }
1377
1378 EAPI void
1379 elm_naviframe_content_preserve_on_pop_set(Evas_Object *obj, Eina_Bool preserve)
1380 {
1381    ELM_CHECK_WIDTYPE(obj, widtype);
1382    Widget_Data *wd = elm_widget_data_get(obj);
1383    if (!wd) return;
1384    wd->preserve = !!preserve;
1385 }
1386
1387 EAPI Eina_Bool
1388 elm_naviframe_content_preserve_on_pop_get(const Evas_Object *obj)
1389 {
1390    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1391    Widget_Data *wd = elm_widget_data_get(obj);
1392    if (!wd) return EINA_FALSE;
1393    return wd->preserve;
1394 }
1395
1396 EAPI Elm_Object_Item*
1397 elm_naviframe_top_item_get(const Evas_Object *obj)
1398 {
1399    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1400    Widget_Data *wd = elm_widget_data_get(obj);
1401    if ((!wd) || (!wd->stack)) return NULL;
1402    return (Elm_Object_Item *) (EINA_INLIST_CONTAINER_GET(wd->stack->last,
1403                                                          Elm_Naviframe_Item));
1404 }
1405
1406 EAPI Elm_Object_Item*
1407 elm_naviframe_bottom_item_get(const Evas_Object *obj)
1408 {
1409    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1410    Widget_Data *wd = elm_widget_data_get(obj);
1411    if ((!wd) || (!wd->stack)) return NULL;
1412    return (Elm_Object_Item *) (EINA_INLIST_CONTAINER_GET(wd->stack,
1413                                                          Elm_Naviframe_Item));
1414 }
1415
1416 EAPI void
1417 elm_naviframe_item_style_set(Elm_Object_Item *it, const char *item_style)
1418 {
1419    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1420    Elm_Naviframe_Item *navi_it = (Elm_Naviframe_Item *) it;
1421
1422    //Return if new style is exsiting one.
1423    if (item_style)
1424      if (!strcmp(item_style, navi_it->style)) return;
1425
1426    if (!item_style)
1427      if (!strcmp("basic", navi_it->style)) return;
1428
1429    _item_style_set(navi_it, item_style);
1430 }
1431
1432 EAPI const char *
1433 elm_naviframe_item_style_get(const Elm_Object_Item *it)
1434 {
1435    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
1436    Elm_Naviframe_Item *navi_it = (Elm_Naviframe_Item *) it;
1437    return navi_it->style;
1438 }
1439
1440 EAPI void
1441 elm_naviframe_item_title_visible_set(Elm_Object_Item *it, Eina_Bool visible)
1442 {
1443    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1444    Elm_Naviframe_Item *navi_it = (Elm_Naviframe_Item *) it;
1445
1446    visible = !!visible;
1447    if (navi_it->title_visible == visible) return;
1448
1449    navi_it->title_visible = visible;
1450    _item_title_visible_update(navi_it);
1451 }
1452
1453 EAPI Eina_Bool
1454 elm_naviframe_item_title_visible_get(const Elm_Object_Item *it)
1455 {
1456    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
1457    Elm_Naviframe_Item *navi_it = (Elm_Naviframe_Item *) it;
1458    return navi_it->title_visible;
1459 }
1460
1461 EAPI void
1462 elm_naviframe_prev_btn_auto_pushed_set(Evas_Object *obj, Eina_Bool auto_pushed)
1463 {
1464    ELM_CHECK_WIDTYPE(obj, widtype);
1465    Widget_Data *wd = elm_widget_data_get(obj);
1466    if (!wd) return;
1467    wd->auto_pushed = !!auto_pushed;
1468 }
1469
1470 EAPI Eina_Bool
1471 elm_naviframe_prev_btn_auto_pushed_get(const Evas_Object *obj)
1472 {
1473    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1474    Widget_Data *wd = elm_widget_data_get(obj);
1475    if (!wd) return EINA_FALSE;
1476    return wd->auto_pushed;
1477 }
1478
1479 EAPI Eina_Inlist *
1480 elm_naviframe_items_get(const Evas_Object *obj)
1481 {
1482    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1483    Widget_Data *wd = elm_widget_data_get(obj);
1484    if (!wd) return NULL;
1485    return wd->stack;
1486 }
1487
1488 EAPI void
1489 elm_naviframe_event_enabled_set(Evas_Object *obj, Eina_Bool enabled)
1490 {
1491    ELM_CHECK_WIDTYPE(obj, widtype);
1492    Widget_Data *wd = elm_widget_data_get(obj);
1493    if (!wd) return;
1494    enabled = !!enabled;
1495    if (wd->freeze_events == !enabled) return;
1496    wd->freeze_events = !enabled;
1497 }
1498
1499 EAPI Eina_Bool
1500 elm_naviframe_event_enabled_get(const Evas_Object *obj)
1501 {
1502    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1503    Widget_Data *wd = elm_widget_data_get(obj);
1504    if (!wd) return EINA_FALSE;
1505    return !wd->freeze_events;
1506 }