elementary/naviframe - elm_widget_item_free is called twice.
[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 }
940
941 static void
942 _show_finished(void *data,
943                Evas_Object *obj __UNUSED__,
944                const char *emission __UNUSED__,
945                const char *source __UNUSED__)
946 {
947    Elm_Naviframe_Item *it;
948    Widget_Data *wd;
949
950    it = data;
951    if (!it) return;
952    wd =  elm_widget_data_get(WIDGET(it));
953    if (!wd) return;
954
955    evas_object_smart_callback_call(WIDGET(it),
956                                    SIG_TRANSITION_FINISHED,
957                                    data);
958    if (wd->freeze_events)
959      evas_object_freeze_events_set(VIEW(it), EINA_FALSE);
960 }
961
962 static void
963 _changed_size_hints(void *data,
964                     Evas *e __UNUSED__,
965                     Evas_Object *obj __UNUSED__,
966                     void *event_info __UNUSED__)
967 {
968    _sizing_eval(data);
969 }
970
971 static void
972 _item_content_set(Elm_Naviframe_Item *navi_it, Evas_Object *content)
973 {
974    if (navi_it->content == content) return;
975    if (navi_it->content) evas_object_del(navi_it->content);
976    elm_widget_sub_object_add(WIDGET(navi_it), content);
977    edje_object_part_swallow(VIEW(navi_it),
978                             "elm.swallow.content",
979                             content);
980    if (content)
981      edje_object_signal_emit(VIEW(navi_it),
982                              "elm,state,content,show",
983                              "elm");
984    else
985      edje_object_signal_emit(VIEW(navi_it),
986                              "elm,state,content,hide",
987                              "elm");
988    evas_object_event_callback_add(content,
989                                   EVAS_CALLBACK_DEL,
990                                   _item_content_del,
991                                   navi_it);
992    evas_object_event_callback_add(content,
993                                   EVAS_CALLBACK_CHANGED_SIZE_HINTS,
994                                   _changed_size_hints,
995                                   WIDGET(navi_it));
996    navi_it->content = content;
997    _sizing_eval(WIDGET(navi_it));
998 }
999
1000 //FIXME: need to handle if this function is called while transition
1001 static void
1002 _item_style_set(Elm_Naviframe_Item *navi_it, const char *item_style)
1003 {
1004    Elm_Naviframe_Content_Item_Pair *content_pair;
1005    Elm_Naviframe_Text_Item_Pair *text_pair;
1006    Widget_Data *wd;
1007
1008    char buf[256];
1009
1010    if (!item_style)
1011      {
1012         strcpy(buf, "item/basic");
1013         eina_stringshare_replace(&navi_it->style, "basic");
1014      }
1015    else
1016      {
1017         snprintf(buf, sizeof(buf), "item/%s", item_style);
1018         eina_stringshare_replace(&navi_it->style, item_style);
1019      }
1020    _elm_theme_object_set(WIDGET(navi_it),
1021                          VIEW(navi_it),
1022                          "naviframe",
1023                          buf,
1024                          elm_widget_style_get(WIDGET(navi_it)));
1025    //recover item
1026    EINA_INLIST_FOREACH(navi_it->text_list, text_pair)
1027       _item_text_set_hook((Elm_Object_Item *) navi_it,
1028                           text_pair->part,
1029                           text_pair->text);
1030
1031    EINA_INLIST_FOREACH(navi_it->content_list, content_pair)
1032       _item_content_set_hook((Elm_Object_Item *) navi_it,
1033                              content_pair->part,
1034                              content_pair->content);
1035    //content
1036    if (navi_it->content)
1037      {
1038         edje_object_part_swallow(VIEW(navi_it),
1039                                  "elm.swallow.content",
1040                                  navi_it->content);
1041         edje_object_signal_emit(VIEW(navi_it),
1042                                 "elm,state,content,show",
1043                                 "elm");
1044      }
1045
1046    //prev button
1047    if (navi_it->title_prev_btn)
1048      {
1049         edje_object_part_swallow(VIEW(navi_it),
1050                                  "elm.swallow.prev_btn",
1051                                  navi_it->title_prev_btn);
1052         edje_object_signal_emit(VIEW(navi_it),
1053                                 "elm,state,prev_btn,show",
1054                                 "elm");
1055      }
1056
1057    //next button
1058    if (navi_it->title_next_btn)
1059      {
1060         edje_object_part_swallow(VIEW(navi_it),
1061                                  "elm.swallow.next_btn",
1062                                  navi_it->title_next_btn);
1063         edje_object_signal_emit(VIEW(navi_it),
1064                                 "elm,state,next_btn,show",
1065                                 "elm");
1066      }
1067
1068    navi_it->title_visible = EINA_TRUE;
1069    _sizing_eval(WIDGET(navi_it));
1070
1071    wd = elm_widget_data_get(WIDGET(navi_it));
1072    if (!wd) return;
1073
1074    if (wd->freeze_events)
1075      evas_object_freeze_events_set(VIEW(navi_it), EINA_FALSE);
1076 }
1077
1078 static Elm_Naviframe_Item *
1079 _item_new(Evas_Object *obj,
1080           const char *title_label,
1081           Evas_Object *prev_btn,
1082           Evas_Object *next_btn,
1083           Evas_Object *content,
1084           const char *item_style)
1085 {
1086    Widget_Data *wd = elm_widget_data_get(obj);
1087
1088    //create item
1089    Elm_Naviframe_Item *it = elm_widget_item_new(obj, Elm_Naviframe_Item);
1090    if (!it)
1091      {
1092         ERR("Failed to allocate new item! : naviframe=%p", obj);
1093         return NULL;
1094      }
1095
1096    elm_widget_item_text_set_hook_set(it, _item_text_set_hook);
1097    elm_widget_item_text_get_hook_set(it, _item_text_get_hook);
1098    elm_widget_item_content_set_hook_set(it, _item_content_set_hook);
1099    elm_widget_item_content_get_hook_set(it, _item_content_get_hook);
1100    elm_widget_item_content_unset_hook_set(it, _item_content_unset_hook);
1101    elm_widget_item_signal_emit_hook_set(it, _item_signal_emit_hook);
1102
1103    //item base layout
1104    VIEW(it) = edje_object_add(evas_object_evas_get(obj));
1105    edje_object_mirrored_set(VIEW(it), elm_widget_mirrored_get(obj));
1106    evas_object_smart_member_add(VIEW(it), wd->base);
1107    elm_widget_sub_object_add(obj, VIEW(it));
1108    edje_object_signal_callback_add(VIEW(it),
1109                                    "elm,action,show,finished",
1110                                    "",
1111                                    _show_finished, it);
1112    edje_object_signal_callback_add(VIEW(it),
1113                                    "elm,action,pushed,finished",
1114                                    "",
1115                                    _pushed_finished, it);
1116    edje_object_signal_callback_add(VIEW(it),
1117                                    "elm,action,popped,finished",
1118                                    "",
1119                                    _popped_finished, it);
1120    edje_object_signal_callback_add(VIEW(it),
1121                                    "elm,action,title,clicked",
1122                                    "",
1123                                    _title_clicked, it);
1124
1125    _item_style_set(it, item_style);
1126    _item_text_set_hook((Elm_Object_Item *) it, "elm.text.title", title_label);
1127
1128    //title buttons
1129    if ((!prev_btn) && wd->auto_pushed && eina_inlist_count(wd->stack))
1130      {
1131         prev_btn = _back_btn_new(obj);
1132         _title_prev_btn_set(it, prev_btn, EINA_TRUE);
1133      }
1134    else
1135      _title_prev_btn_set(it, prev_btn, EINA_FALSE);
1136
1137    _title_next_btn_set(it, next_btn);
1138    _item_content_set(it, content);
1139    it->title_visible = EINA_TRUE;
1140    return it;
1141 }
1142
1143 EAPI Evas_Object *
1144 elm_naviframe_add(Evas_Object *parent)
1145 {
1146    Evas_Object *obj;
1147    Evas *e;
1148    Widget_Data *wd;
1149
1150    ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
1151    ELM_SET_WIDTYPE(widtype, "naviframe");
1152    elm_widget_type_set(obj, "naviframe");
1153    elm_widget_sub_object_add(parent, obj);
1154    elm_widget_data_set(obj, wd);
1155    elm_widget_del_hook_set(obj, _del_hook);
1156    elm_widget_disable_hook_set(obj, _disable_hook);
1157    elm_widget_theme_hook_set(obj, _theme_hook);
1158    elm_widget_signal_emit_hook_set(obj, _emit_hook);
1159
1160    //base
1161    wd->base = edje_object_add(e);
1162    edje_object_mirrored_set(wd->base, elm_widget_mirrored_get(obj));
1163    elm_widget_resize_object_set(obj, wd->base);
1164    _elm_theme_object_set(obj, wd->base, "naviframe", "base", "default");
1165
1166    evas_object_event_callback_add(obj, EVAS_CALLBACK_MOVE, _move, obj);
1167    evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE, _resize, obj);
1168    evas_object_smart_callbacks_descriptions_set(obj, _signals);
1169
1170    wd->auto_pushed = EINA_TRUE;
1171    wd->freeze_events = EINA_TRUE;
1172
1173    return obj;
1174 }
1175
1176 EAPI Elm_Object_Item *
1177 elm_naviframe_item_push(Evas_Object *obj,
1178                         const char *title_label,
1179                         Evas_Object *prev_btn,
1180                         Evas_Object *next_btn,
1181                         Evas_Object *content,
1182                         const char *item_style)
1183 {
1184    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1185    Widget_Data *wd;
1186    Elm_Naviframe_Item *prev_it, *it;
1187
1188    wd = elm_widget_data_get(obj);
1189    if (!wd) return NULL;
1190
1191    it = _item_new(obj, title_label, prev_btn, next_btn, content, item_style);
1192    if (!it) return NULL;
1193
1194    evas_object_show(VIEW(it));
1195
1196    prev_it = (Elm_Naviframe_Item *) elm_naviframe_top_item_get(obj);
1197    if (prev_it)
1198      {
1199         if (wd->freeze_events)
1200           {
1201              evas_object_freeze_events_set(VIEW(it), EINA_TRUE);
1202              evas_object_freeze_events_set(VIEW(prev_it), EINA_TRUE);
1203           }
1204         edje_object_signal_emit(VIEW(prev_it),
1205                                 "elm,state,cur,pushed",
1206                                 "elm");
1207         edje_object_signal_emit(VIEW(it),
1208                                 "elm,state,new,pushed",
1209                                 "elm");
1210         edje_object_message_signal_process(VIEW(prev_it));
1211         edje_object_message_signal_process(VIEW(it));
1212      }
1213    wd->stack = eina_inlist_append(wd->stack, EINA_INLIST_GET(it));
1214    _sizing_eval(obj);
1215    return (Elm_Object_Item *) it;
1216 }
1217
1218 EAPI Elm_Object_Item *
1219 elm_naviframe_item_insert_before(Elm_Object_Item *before,
1220                                  const char *title_label,
1221                                  Evas_Object *prev_btn,
1222                                  Evas_Object *next_btn,
1223                                  Evas_Object *content,
1224                                  const char *item_style)
1225 {
1226    ELM_OBJ_ITEM_CHECK_OR_RETURN(before, NULL);
1227    Elm_Naviframe_Item *it;
1228    Widget_Data *wd;
1229
1230    wd = elm_widget_data_get(WIDGET(before));
1231    if (!wd) return NULL;
1232
1233    it = _item_new(WIDGET(before), title_label, prev_btn, next_btn, content,
1234                   item_style);
1235    if (!it) return NULL;
1236
1237    wd->stack =
1238       eina_inlist_prepend_relative(wd->stack, EINA_INLIST_GET(it),
1239                                    EINA_INLIST_GET(((Elm_Naviframe_Item *) before)));
1240    _sizing_eval(WIDGET(before));
1241    return (Elm_Object_Item *) it;
1242 }
1243
1244 EAPI Elm_Object_Item *
1245 elm_naviframe_item_insert_after(Elm_Object_Item *after,
1246                                 const char *title_label,
1247                                 Evas_Object *prev_btn,
1248                                 Evas_Object *next_btn,
1249                                 Evas_Object *content,
1250                                 const char *item_style)
1251 {
1252    ELM_OBJ_ITEM_CHECK_OR_RETURN(after, NULL);
1253    Elm_Naviframe_Item *it;
1254    Widget_Data *wd;
1255
1256    wd = elm_widget_data_get(WIDGET(after));
1257    if (!wd) return NULL;
1258
1259    it = _item_new(WIDGET(after), title_label, prev_btn, next_btn, content,
1260                   item_style);
1261    if (!it) return NULL;
1262
1263    if (elm_naviframe_top_item_get(WIDGET(after)) == after)
1264      {
1265         evas_object_hide(VIEW(after));
1266         evas_object_show(VIEW(it));
1267      }
1268    wd->stack =
1269       eina_inlist_append_relative(wd->stack, EINA_INLIST_GET(it),
1270                                   EINA_INLIST_GET(((Elm_Naviframe_Item *) after)));
1271    _sizing_eval(WIDGET(after));
1272    return (Elm_Object_Item *) it;
1273 }
1274
1275 EAPI Evas_Object *
1276 elm_naviframe_item_pop(Evas_Object *obj)
1277 {
1278    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1279    Elm_Naviframe_Item *it, *prev_it = NULL;
1280    Widget_Data *wd;
1281    Evas_Object *content = NULL;
1282
1283    wd = elm_widget_data_get(obj);
1284    if (!wd) return NULL;
1285
1286    it = (Elm_Naviframe_Item *) elm_naviframe_top_item_get(obj);
1287    if (!it) return NULL;
1288    elm_widget_tree_unfocusable_set(it->content, EINA_TRUE);
1289    if (wd->preserve)
1290      content = it->content;
1291
1292    if (wd->stack->last->prev)
1293      prev_it = EINA_INLIST_CONTAINER_GET(wd->stack->last->prev,
1294                                          Elm_Naviframe_Item);
1295    wd->stack = eina_inlist_remove(wd->stack, EINA_INLIST_GET(it));
1296    if (prev_it)
1297      {
1298         if (wd->freeze_events)
1299           {
1300              evas_object_freeze_events_set(VIEW(it), EINA_TRUE);
1301              evas_object_freeze_events_set(VIEW(prev_it), EINA_TRUE);
1302           }
1303         edje_object_signal_emit(VIEW(it), "elm,state,cur,popped", "elm");
1304         evas_object_show(VIEW(prev_it));
1305         evas_object_raise(VIEW(prev_it));
1306         edje_object_signal_emit(VIEW(prev_it),
1307                                 "elm,state,prev,popped",
1308                                 "elm");
1309         edje_object_message_signal_process(VIEW(it));
1310         edje_object_message_signal_process(VIEW(prev_it));
1311      }
1312    else
1313      _item_del(it);
1314
1315    return content;
1316 }
1317
1318 EAPI void
1319 elm_naviframe_item_pop_to(Elm_Object_Item *it)
1320 {
1321    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1322    Elm_Naviframe_Item *navi_it;
1323    Widget_Data *wd;
1324    Eina_Inlist *l, *prev_l;
1325
1326    navi_it = (Elm_Naviframe_Item *) it;
1327    wd = elm_widget_data_get(WIDGET(navi_it));
1328    if (!wd) return;
1329
1330    if (it == elm_naviframe_top_item_get(WIDGET(navi_it))) return;
1331
1332    l = wd->stack->last->prev;
1333
1334    while(l)
1335      {
1336         if (EINA_INLIST_CONTAINER_GET(l, Elm_Naviframe_Item) ==
1337             ((Elm_Naviframe_Item *) it)) break;
1338         prev_l = l->prev;
1339         wd->stack = eina_inlist_remove(wd->stack, l);
1340         _item_del(EINA_INLIST_CONTAINER_GET(l, Elm_Naviframe_Item));
1341         l = prev_l;
1342      }
1343    elm_naviframe_item_pop(WIDGET(navi_it));
1344 }
1345
1346 EAPI void
1347 elm_naviframe_item_promote(Elm_Object_Item *it)
1348 {
1349    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1350    Elm_Naviframe_Item *navi_it;
1351    Elm_Naviframe_Item *prev_it;
1352    Widget_Data *wd;
1353
1354    navi_it = (Elm_Naviframe_Item *) it;
1355    wd = elm_widget_data_get(navi_it->base.widget);
1356    if (!wd) return;
1357
1358    if (it == elm_naviframe_top_item_get(navi_it->base.widget)) return;
1359    wd->stack = eina_inlist_demote(wd->stack, EINA_INLIST_GET(navi_it));
1360    prev_it = EINA_INLIST_CONTAINER_GET(wd->stack->last->prev,
1361                                          Elm_Naviframe_Item);
1362    if (wd->freeze_events)
1363      {
1364         evas_object_freeze_events_set(VIEW(it), EINA_TRUE);
1365         evas_object_freeze_events_set(VIEW(prev_it), EINA_TRUE);
1366      }
1367    edje_object_signal_emit(VIEW(prev_it),
1368                            "elm,state,cur,pushed",
1369                            "elm");
1370    evas_object_show(VIEW(navi_it));
1371    evas_object_raise(VIEW(navi_it));
1372    edje_object_signal_emit(VIEW(navi_it),
1373                            "elm,state,new,pushed",
1374                            "elm");
1375    edje_object_message_signal_process(VIEW(prev_it));
1376    edje_object_message_signal_process(VIEW(navi_it));
1377 }
1378
1379 EAPI void
1380 elm_naviframe_item_del(Elm_Object_Item *it)
1381 {
1382    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1383    Elm_Naviframe_Item *navi_it;
1384    Widget_Data *wd;
1385
1386    navi_it =(Elm_Naviframe_Item *) it;
1387    wd = elm_widget_data_get(WIDGET(navi_it));
1388    if (!wd) return;
1389
1390    if (it == elm_naviframe_top_item_get(WIDGET(navi_it)))
1391      {
1392         wd->stack = eina_inlist_remove(wd->stack, EINA_INLIST_GET(navi_it));
1393         _item_del(navi_it);
1394         //If the item is only one, the stack will be empty
1395         if (!wd->stack) return;
1396         navi_it = EINA_INLIST_CONTAINER_GET(wd->stack->last,
1397                                             Elm_Naviframe_Item);
1398         evas_object_show(VIEW(navi_it));
1399         evas_object_raise(VIEW(navi_it));
1400         edje_object_signal_emit(VIEW(navi_it), "elm,state,visible", "elm");
1401      }
1402    else
1403      {
1404         wd->stack = eina_inlist_remove(wd->stack, EINA_INLIST_GET(navi_it));
1405         _item_del(navi_it);
1406      }
1407 }
1408
1409 EAPI void
1410 elm_naviframe_content_preserve_on_pop_set(Evas_Object *obj, Eina_Bool preserve)
1411 {
1412    ELM_CHECK_WIDTYPE(obj, widtype);
1413    Widget_Data *wd = elm_widget_data_get(obj);
1414    if (!wd) return;
1415    wd->preserve = !!preserve;
1416 }
1417
1418 EAPI Eina_Bool
1419 elm_naviframe_content_preserve_on_pop_get(const Evas_Object *obj)
1420 {
1421    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1422    Widget_Data *wd = elm_widget_data_get(obj);
1423    if (!wd) return EINA_FALSE;
1424    return wd->preserve;
1425 }
1426
1427 EAPI Elm_Object_Item*
1428 elm_naviframe_top_item_get(const Evas_Object *obj)
1429 {
1430    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1431    Widget_Data *wd = elm_widget_data_get(obj);
1432    if ((!wd) || (!wd->stack)) return NULL;
1433    return (Elm_Object_Item *) (EINA_INLIST_CONTAINER_GET(wd->stack->last,
1434                                                          Elm_Naviframe_Item));
1435 }
1436
1437 EAPI Elm_Object_Item*
1438 elm_naviframe_bottom_item_get(const Evas_Object *obj)
1439 {
1440    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1441    Widget_Data *wd = elm_widget_data_get(obj);
1442    if ((!wd) || (!wd->stack)) return NULL;
1443    return (Elm_Object_Item *) (EINA_INLIST_CONTAINER_GET(wd->stack,
1444                                                          Elm_Naviframe_Item));
1445 }
1446
1447 EAPI void
1448 elm_naviframe_item_style_set(Elm_Object_Item *it, const char *item_style)
1449 {
1450    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1451    Elm_Naviframe_Item *navi_it = (Elm_Naviframe_Item *) it;
1452
1453    //Return if new style is exsiting one.
1454    if (item_style)
1455      if (!strcmp(item_style, navi_it->style)) return;
1456
1457    if (!item_style)
1458      if (!strcmp("basic", navi_it->style)) return;
1459
1460    _item_style_set(navi_it, item_style);
1461 }
1462
1463 EAPI const char *
1464 elm_naviframe_item_style_get(const Elm_Object_Item *it)
1465 {
1466    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
1467    Elm_Naviframe_Item *navi_it = (Elm_Naviframe_Item *) it;
1468    return navi_it->style;
1469 }
1470
1471 EAPI void
1472 elm_naviframe_item_title_visible_set(Elm_Object_Item *it, Eina_Bool visible)
1473 {
1474    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1475    Elm_Naviframe_Item *navi_it = (Elm_Naviframe_Item *) it;
1476
1477    visible = !!visible;
1478    if (navi_it->title_visible == visible) return;
1479
1480    navi_it->title_visible = visible;
1481    _item_title_visible_update(navi_it);
1482 }
1483
1484 EAPI Eina_Bool
1485 elm_naviframe_item_title_visible_get(const Elm_Object_Item *it)
1486 {
1487    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
1488    Elm_Naviframe_Item *navi_it = (Elm_Naviframe_Item *) it;
1489    return navi_it->title_visible;
1490 }
1491
1492 EAPI void
1493 elm_naviframe_prev_btn_auto_pushed_set(Evas_Object *obj, Eina_Bool auto_pushed)
1494 {
1495    ELM_CHECK_WIDTYPE(obj, widtype);
1496    Widget_Data *wd = elm_widget_data_get(obj);
1497    if (!wd) return;
1498    wd->auto_pushed = !!auto_pushed;
1499 }
1500
1501 EAPI Eina_Bool
1502 elm_naviframe_prev_btn_auto_pushed_get(const Evas_Object *obj)
1503 {
1504    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1505    Widget_Data *wd = elm_widget_data_get(obj);
1506    if (!wd) return EINA_FALSE;
1507    return wd->auto_pushed;
1508 }
1509
1510 EAPI Eina_Inlist *
1511 elm_naviframe_items_get(const Evas_Object *obj)
1512 {
1513    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1514    Widget_Data *wd = elm_widget_data_get(obj);
1515    if (!wd) return NULL;
1516    return wd->stack;
1517 }
1518
1519 EAPI void
1520 elm_naviframe_event_enabled_set(Evas_Object *obj, Eina_Bool enabled)
1521 {
1522    ELM_CHECK_WIDTYPE(obj, widtype);
1523    Widget_Data *wd = elm_widget_data_get(obj);
1524    if (!wd) return;
1525    enabled = !!enabled;
1526    if (wd->freeze_events == !enabled) return;
1527    wd->freeze_events = !enabled;
1528 }
1529
1530 EAPI Eina_Bool
1531 elm_naviframe_event_enabled_get(const Evas_Object *obj)
1532 {
1533    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1534    Widget_Data *wd = elm_widget_data_get(obj);
1535    if (!wd) return EINA_FALSE;
1536    return !wd->freeze_events;
1537 }