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