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