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