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