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