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