elementary - modified item_del_pre_hook function prototype.
[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         elm_widget_item_free(navi_it);
890         //If the item is only one, the stack will be empty
891         if (!wd->stack) return EINA_TRUE;
892         navi_it = EINA_INLIST_CONTAINER_GET(wd->stack->last,
893                                             Elm_Naviframe_Item);
894         evas_object_show(VIEW(navi_it));
895         evas_object_raise(VIEW(navi_it));
896         elm_object_signal_emit(VIEW(navi_it), "elm,state,visible", "elm");
897      }
898    else
899      {
900         wd->stack = eina_inlist_remove(wd->stack, EINA_INLIST_GET(navi_it));
901         _item_del(navi_it);
902         elm_widget_item_free(navi_it);
903      }
904
905    return EINA_TRUE;
906 }
907
908 static void
909 _pushed_finished(void *data,
910                  Evas_Object *obj __UNUSED__,
911                  const char *emission __UNUSED__,
912                  const char *source __UNUSED__)
913 {
914    Widget_Data *wd;
915    Elm_Naviframe_Item *it = data;
916    if (!it) return;
917
918    wd = elm_widget_data_get(WIDGET(it));
919    if (!wd) return;
920
921    evas_object_hide(VIEW(it));
922    evas_object_smart_callback_call(WIDGET(it),
923                                    SIG_PUSH_FINISHED,
924                                    data);
925    if (wd->freeze_events)
926      evas_object_freeze_events_set(VIEW(it), EINA_FALSE);
927 }
928
929 static void
930 _popped_finished(void *data,
931                  Evas_Object *obj __UNUSED__,
932                  const char *emission __UNUSED__,
933                  const char *source __UNUSED__)
934 {
935    Elm_Naviframe_Item *it = data;
936    if (!it) return;
937    evas_object_smart_callback_call(WIDGET(it),
938                                    SIG_POP_FINISHED,
939                                    data);
940    _item_del(data);
941 }
942
943 static void
944 _show_finished(void *data,
945                Evas_Object *obj __UNUSED__,
946                const char *emission __UNUSED__,
947                const char *source __UNUSED__)
948 {
949    Elm_Naviframe_Item *it;
950    Widget_Data *wd;
951
952    it = data;
953    if (!it) return;
954    wd =  elm_widget_data_get(WIDGET(it));
955    if (!wd) return;
956
957    evas_object_smart_callback_call(WIDGET(it),
958                                    SIG_TRANSITION_FINISHED,
959                                    data);
960    if (wd->freeze_events)
961      evas_object_freeze_events_set(VIEW(it), EINA_FALSE);
962 }
963
964 static void
965 _changed_size_hints(void *data,
966                     Evas *e __UNUSED__,
967                     Evas_Object *obj __UNUSED__,
968                     void *event_info __UNUSED__)
969 {
970    _sizing_eval(data);
971 }
972
973 static void
974 _item_content_set(Elm_Naviframe_Item *navi_it, Evas_Object *content)
975 {
976    if (navi_it->content == content) return;
977    if (navi_it->content) evas_object_del(navi_it->content);
978    elm_widget_sub_object_add(WIDGET(navi_it), content);
979    edje_object_part_swallow(VIEW(navi_it),
980                             "elm.swallow.content",
981                             content);
982    if (content)
983      edje_object_signal_emit(VIEW(navi_it),
984                              "elm,state,content,show",
985                              "elm");
986    else
987      edje_object_signal_emit(VIEW(navi_it),
988                              "elm,state,content,hide",
989                              "elm");
990    evas_object_event_callback_add(content,
991                                   EVAS_CALLBACK_DEL,
992                                   _item_content_del,
993                                   navi_it);
994    evas_object_event_callback_add(content,
995                                   EVAS_CALLBACK_CHANGED_SIZE_HINTS,
996                                   _changed_size_hints,
997                                   WIDGET(navi_it));
998    navi_it->content = content;
999    _sizing_eval(WIDGET(navi_it));
1000 }
1001
1002 //FIXME: need to handle if this function is called while transition
1003 static void
1004 _item_style_set(Elm_Naviframe_Item *navi_it, const char *item_style)
1005 {
1006    Elm_Naviframe_Content_Item_Pair *content_pair;
1007    Elm_Naviframe_Text_Item_Pair *text_pair;
1008    Widget_Data *wd;
1009
1010    char buf[256];
1011
1012    if (!item_style)
1013      {
1014         strcpy(buf, "item/basic");
1015         eina_stringshare_replace(&navi_it->style, "basic");
1016      }
1017    else
1018      {
1019         snprintf(buf, sizeof(buf), "item/%s", item_style);
1020         eina_stringshare_replace(&navi_it->style, item_style);
1021      }
1022    _elm_theme_object_set(WIDGET(navi_it),
1023                          VIEW(navi_it),
1024                          "naviframe",
1025                          buf,
1026                          elm_widget_style_get(WIDGET(navi_it)));
1027    //recover item
1028    EINA_INLIST_FOREACH(navi_it->text_list, text_pair)
1029       _item_text_set_hook((Elm_Object_Item *) navi_it,
1030                           text_pair->part,
1031                           text_pair->text);
1032
1033    EINA_INLIST_FOREACH(navi_it->content_list, content_pair)
1034       _item_content_set_hook((Elm_Object_Item *) navi_it,
1035                              content_pair->part,
1036                              content_pair->content);
1037    //content
1038    if (navi_it->content)
1039      {
1040         edje_object_part_swallow(VIEW(navi_it),
1041                                  "elm.swallow.content",
1042                                  navi_it->content);
1043         edje_object_signal_emit(VIEW(navi_it),
1044                                 "elm,state,content,show",
1045                                 "elm");
1046      }
1047
1048    //prev button
1049    if (navi_it->title_prev_btn)
1050      {
1051         edje_object_part_swallow(VIEW(navi_it),
1052                                  "elm.swallow.prev_btn",
1053                                  navi_it->title_prev_btn);
1054         edje_object_signal_emit(VIEW(navi_it),
1055                                 "elm,state,prev_btn,show",
1056                                 "elm");
1057      }
1058
1059    //next button
1060    if (navi_it->title_next_btn)
1061      {
1062         edje_object_part_swallow(VIEW(navi_it),
1063                                  "elm.swallow.next_btn",
1064                                  navi_it->title_next_btn);
1065         edje_object_signal_emit(VIEW(navi_it),
1066                                 "elm,state,next_btn,show",
1067                                 "elm");
1068      }
1069
1070    navi_it->title_visible = EINA_TRUE;
1071    _sizing_eval(WIDGET(navi_it));
1072
1073    wd = elm_widget_data_get(WIDGET(navi_it));
1074    if (!wd) return;
1075
1076    if (wd->freeze_events)
1077      evas_object_freeze_events_set(VIEW(navi_it), EINA_FALSE);
1078 }
1079
1080 static Elm_Naviframe_Item *
1081 _item_new(Evas_Object *obj,
1082           const char *title_label,
1083           Evas_Object *prev_btn,
1084           Evas_Object *next_btn,
1085           Evas_Object *content,
1086           const char *item_style)
1087 {
1088    Widget_Data *wd = elm_widget_data_get(obj);
1089
1090    //create item
1091    Elm_Naviframe_Item *it = elm_widget_item_new(obj, Elm_Naviframe_Item);
1092    if (!it)
1093      {
1094         ERR("Failed to allocate new item! : naviframe=%p", obj);
1095         return NULL;
1096      }
1097
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      _item_del(it);
1316
1317    return content;
1318 }
1319
1320 EAPI void
1321 elm_naviframe_item_pop_to(Elm_Object_Item *it)
1322 {
1323    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1324    Elm_Naviframe_Item *navi_it;
1325    Widget_Data *wd;
1326    Eina_Inlist *l, *prev_l;
1327
1328    navi_it = (Elm_Naviframe_Item *) it;
1329    wd = elm_widget_data_get(WIDGET(navi_it));
1330    if (!wd) return;
1331
1332    if (it == elm_naviframe_top_item_get(WIDGET(navi_it))) return;
1333
1334    l = wd->stack->last->prev;
1335
1336    while(l)
1337      {
1338         if (EINA_INLIST_CONTAINER_GET(l, Elm_Naviframe_Item) ==
1339             ((Elm_Naviframe_Item *) it)) break;
1340         prev_l = l->prev;
1341         wd->stack = eina_inlist_remove(wd->stack, l);
1342         _item_del(EINA_INLIST_CONTAINER_GET(l, Elm_Naviframe_Item));
1343         l = prev_l;
1344      }
1345    elm_naviframe_item_pop(WIDGET(navi_it));
1346 }
1347
1348 EAPI void
1349 elm_naviframe_item_promote(Elm_Object_Item *it)
1350 {
1351    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1352    Elm_Naviframe_Item *navi_it;
1353    Elm_Naviframe_Item *prev_it;
1354    Widget_Data *wd;
1355
1356    navi_it = (Elm_Naviframe_Item *) it;
1357    wd = elm_widget_data_get(navi_it->base.widget);
1358    if (!wd) return;
1359
1360    if (it == elm_naviframe_top_item_get(navi_it->base.widget)) return;
1361    wd->stack = eina_inlist_demote(wd->stack, EINA_INLIST_GET(navi_it));
1362    prev_it = EINA_INLIST_CONTAINER_GET(wd->stack->last->prev,
1363                                          Elm_Naviframe_Item);
1364    if (wd->freeze_events)
1365      {
1366         evas_object_freeze_events_set(VIEW(it), EINA_TRUE);
1367         evas_object_freeze_events_set(VIEW(prev_it), EINA_TRUE);
1368      }
1369    edje_object_signal_emit(VIEW(prev_it),
1370                            "elm,state,cur,pushed",
1371                            "elm");
1372    evas_object_show(VIEW(navi_it));
1373    evas_object_raise(VIEW(navi_it));
1374    edje_object_signal_emit(VIEW(navi_it),
1375                            "elm,state,new,pushed",
1376                            "elm");
1377    edje_object_message_signal_process(VIEW(prev_it));
1378    edje_object_message_signal_process(VIEW(navi_it));
1379 }
1380
1381 EAPI void
1382 elm_naviframe_item_del(Elm_Object_Item *it)
1383 {
1384    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1385    Elm_Naviframe_Item *navi_it;
1386    Widget_Data *wd;
1387
1388    navi_it =(Elm_Naviframe_Item *) it;
1389    wd = elm_widget_data_get(WIDGET(navi_it));
1390    if (!wd) return;
1391
1392    if (it == elm_naviframe_top_item_get(WIDGET(navi_it)))
1393      {
1394         wd->stack = eina_inlist_remove(wd->stack, EINA_INLIST_GET(navi_it));
1395         _item_del(navi_it);
1396         //If the item is only one, the stack will be empty
1397         if (!wd->stack) return;
1398         navi_it = EINA_INLIST_CONTAINER_GET(wd->stack->last,
1399                                             Elm_Naviframe_Item);
1400         evas_object_show(VIEW(navi_it));
1401         evas_object_raise(VIEW(navi_it));
1402         edje_object_signal_emit(VIEW(navi_it), "elm,state,visible", "elm");
1403      }
1404    else
1405      {
1406         wd->stack = eina_inlist_remove(wd->stack, EINA_INLIST_GET(navi_it));
1407         _item_del(navi_it);
1408      }
1409 }
1410
1411 EAPI void
1412 elm_naviframe_content_preserve_on_pop_set(Evas_Object *obj, Eina_Bool preserve)
1413 {
1414    ELM_CHECK_WIDTYPE(obj, widtype);
1415    Widget_Data *wd = elm_widget_data_get(obj);
1416    if (!wd) return;
1417    wd->preserve = !!preserve;
1418 }
1419
1420 EAPI Eina_Bool
1421 elm_naviframe_content_preserve_on_pop_get(const Evas_Object *obj)
1422 {
1423    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1424    Widget_Data *wd = elm_widget_data_get(obj);
1425    if (!wd) return EINA_FALSE;
1426    return wd->preserve;
1427 }
1428
1429 EAPI Elm_Object_Item*
1430 elm_naviframe_top_item_get(const Evas_Object *obj)
1431 {
1432    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1433    Widget_Data *wd = elm_widget_data_get(obj);
1434    if ((!wd) || (!wd->stack)) return NULL;
1435    return (Elm_Object_Item *) (EINA_INLIST_CONTAINER_GET(wd->stack->last,
1436                                                          Elm_Naviframe_Item));
1437 }
1438
1439 EAPI Elm_Object_Item*
1440 elm_naviframe_bottom_item_get(const Evas_Object *obj)
1441 {
1442    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1443    Widget_Data *wd = elm_widget_data_get(obj);
1444    if ((!wd) || (!wd->stack)) return NULL;
1445    return (Elm_Object_Item *) (EINA_INLIST_CONTAINER_GET(wd->stack,
1446                                                          Elm_Naviframe_Item));
1447 }
1448
1449 EAPI void
1450 elm_naviframe_item_style_set(Elm_Object_Item *it, const char *item_style)
1451 {
1452    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1453    Elm_Naviframe_Item *navi_it = (Elm_Naviframe_Item *) it;
1454
1455    //Return if new style is exsiting one.
1456    if (item_style)
1457      if (!strcmp(item_style, navi_it->style)) return;
1458
1459    if (!item_style)
1460      if (!strcmp("basic", navi_it->style)) return;
1461
1462    _item_style_set(navi_it, item_style);
1463 }
1464
1465 EAPI const char *
1466 elm_naviframe_item_style_get(const Elm_Object_Item *it)
1467 {
1468    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
1469    Elm_Naviframe_Item *navi_it = (Elm_Naviframe_Item *) it;
1470    return navi_it->style;
1471 }
1472
1473 EAPI void
1474 elm_naviframe_item_title_visible_set(Elm_Object_Item *it, Eina_Bool visible)
1475 {
1476    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1477    Elm_Naviframe_Item *navi_it = (Elm_Naviframe_Item *) it;
1478
1479    visible = !!visible;
1480    if (navi_it->title_visible == visible) return;
1481
1482    navi_it->title_visible = visible;
1483    _item_title_visible_update(navi_it);
1484 }
1485
1486 EAPI Eina_Bool
1487 elm_naviframe_item_title_visible_get(const Elm_Object_Item *it)
1488 {
1489    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
1490    Elm_Naviframe_Item *navi_it = (Elm_Naviframe_Item *) it;
1491    return navi_it->title_visible;
1492 }
1493
1494 EAPI void
1495 elm_naviframe_prev_btn_auto_pushed_set(Evas_Object *obj, Eina_Bool auto_pushed)
1496 {
1497    ELM_CHECK_WIDTYPE(obj, widtype);
1498    Widget_Data *wd = elm_widget_data_get(obj);
1499    if (!wd) return;
1500    wd->auto_pushed = !!auto_pushed;
1501 }
1502
1503 EAPI Eina_Bool
1504 elm_naviframe_prev_btn_auto_pushed_get(const Evas_Object *obj)
1505 {
1506    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1507    Widget_Data *wd = elm_widget_data_get(obj);
1508    if (!wd) return EINA_FALSE;
1509    return wd->auto_pushed;
1510 }
1511
1512 EAPI Eina_Inlist *
1513 elm_naviframe_items_get(const Evas_Object *obj)
1514 {
1515    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1516    Widget_Data *wd = elm_widget_data_get(obj);
1517    if (!wd) return NULL;
1518    return wd->stack;
1519 }
1520
1521 EAPI void
1522 elm_naviframe_event_enabled_set(Evas_Object *obj, Eina_Bool enabled)
1523 {
1524    ELM_CHECK_WIDTYPE(obj, widtype);
1525    Widget_Data *wd = elm_widget_data_get(obj);
1526    if (!wd) return;
1527    enabled = !!enabled;
1528    if (wd->freeze_events == !enabled) return;
1529    wd->freeze_events = !enabled;
1530 }
1531
1532 EAPI Eina_Bool
1533 elm_naviframe_event_enabled_get(const Evas_Object *obj)
1534 {
1535    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1536    Widget_Data *wd = elm_widget_data_get(obj);
1537    if (!wd) return EINA_FALSE;
1538    return !wd->freeze_events;
1539 }