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