elementary/naviframe - removed FIXME
[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_List    *stack;
12    Evas_Object  *base;
13    Eina_Bool     preserve: 1;
14    Eina_Bool     pass_events: 1;
15 };
16
17 struct _Elm_Naviframe_Content_Item_Pair
18 {
19    const char *part;
20    Evas_Object *content;
21    Elm_Naviframe_Item *it;
22 };
23
24 struct _Elm_Naviframe_Text_Item_Pair
25 {
26    const char *part;
27    const char *text;
28 };
29
30 struct _Elm_Naviframe_Item
31 {
32    Elm_Widget_Item    base;
33    Evas_Object       *title;
34    Eina_List         *content_list;
35    Eina_List         *text_list;
36    Evas_Object       *content;
37    Evas_Object       *title_prev_btn;
38    Evas_Object       *title_next_btn;
39    const char        *style;
40    Eina_Bool          back_btn: 1;
41    Eina_Bool          title_visible: 1;
42 };
43
44 static const char *widtype = NULL;
45
46 static const char SIG_TRANSITION_FINISHED[] = "transition,finished";
47 static const char SIG_TITLE_CLICKED[] = "title,clicked";
48
49 static const Evas_Smart_Cb_Description _signals[] = {
50        {SIG_TRANSITION_FINISHED, ""},
51        {SIG_TITLE_CLICKED, ""},
52        {NULL, NULL}
53 };
54
55 static void _del_hook(Evas_Object *obj);
56 static void _theme_hook(Evas_Object *obj);
57 static void _disable_hook(Evas_Object *obj);
58 static void _text_set_hook(Elm_Object_Item *it,
59                            const char *part,
60                            const char *label);
61 static const char *_text_get_hook(const Elm_Object_Item *it,
62                                    const char *part);
63 static void _content_set_hook(Elm_Object_Item *it,
64                               const char *part,
65                               Evas_Object *content);
66 static Evas_Object *_content_get_hook(const Elm_Object_Item *it,
67                                       const char *part);
68 static Evas_Object *_content_unset_hook(Elm_Object_Item *it,
69                                         const char *part);
70 static void _sizing_eval(Evas_Object *obj);
71 static void _item_sizing_eval(Elm_Naviframe_Item *it);
72 static void _move(void *data, Evas *e, Evas_Object *obj, void *event_info);
73 static void _resize(void *data,
74                     Evas *e,
75                     Evas_Object *obj,
76                     void *event_info);
77 static void _title_clicked(void *data, Evas_Object *obj,
78                            const char *emission,
79                            const char *source);
80 static void _back_btn_clicked(void *data,
81                               Evas_Object *obj,
82                               void *event_info);
83 static Evas_Object *_back_btn_new(Evas_Object *obj);
84 static void _item_content_del(void *data,
85                               Evas *e,
86                               Evas_Object *obj,
87                               void *event_info);
88 static void _title_content_del(void *data,
89                                Evas *e,
90                                Evas_Object *obj,
91                                void *event_info);
92 static void _title_prev_btn_del(void *data,
93                                 Evas *e,
94                                 Evas_Object *obj,
95                                 void *event_info);
96 static void _title_next_btn_del(void *data,
97                                 Evas *e,
98                                 Evas_Object *obj,
99                                 void *event_info);
100 static void _title_content_set(Elm_Naviframe_Item *it,
101                                Elm_Naviframe_Content_Item_Pair *pair,
102                                const char *part,
103                                Evas_Object *content);
104 static void _title_prev_btn_set(Elm_Naviframe_Item *it,
105                                 Evas_Object *btn,
106                                 Eina_Bool back_btn);
107 static void _title_next_btn_set(Elm_Naviframe_Item *it, Evas_Object *btn);
108 static void _item_del(Elm_Naviframe_Item *it);
109 static void _pushed_finished(void *data,
110                              Evas_Object *obj,
111                              const char *emission,
112                              const char *source);
113 static void _popped_finished(void *data,
114                              Evas_Object *obj,
115                              const char *emission,
116                              const char *source);
117 static void _show_finished(void *data,
118                            Evas_Object *obj,
119                            const char *emission,
120                            const char *source);
121 static void _item_content_set(Elm_Naviframe_Item *navi_it,
122                               Evas_Object *content);
123
124 static void
125 _del_hook(Evas_Object *obj)
126 {
127    Widget_Data *wd;
128    Eina_List *list;
129    Elm_Naviframe_Item *it;
130
131    wd = elm_widget_data_get(obj);
132    if (!wd) return;
133
134    EINA_LIST_FOREACH(wd->stack, list, it)
135      _item_del(it);
136    eina_list_free(wd->stack);
137    free(wd);
138 }
139
140 static void
141 _theme_hook(Evas_Object *obj __UNUSED__)
142 {
143    //FIXME:
144 }
145
146 static void
147 _disable_hook(Evas_Object *obj __UNUSED__)
148 {
149    //FIXME:
150 }
151
152 static void
153 _text_set_hook(Elm_Object_Item *it, const char *part, const char *label)
154 {
155    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
156
157    Eina_List *l = NULL;
158    Elm_Naviframe_Text_Item_Pair *pair = NULL;
159    Elm_Naviframe_Item *navi_it = ELM_CAST(it);
160    char buf[1024];
161
162    if (!part) return;
163
164    EINA_LIST_FOREACH(navi_it->text_list, l, pair)
165      {
166         if (!strcmp(part, pair->part))
167           {
168              if (pair->text)
169                {
170                   if (!strcmp(pair->text, label))
171                     return;
172                }
173              break;
174           }
175      }
176
177    if (!pair)
178      {
179         pair = ELM_NEW(Elm_Naviframe_Text_Item_Pair);
180         if (!pair)
181           {
182              ERR("Failed to allocate new text part of the item! : naviframe=%p", navi_it->base.widget);
183              return;
184           }
185         eina_stringshare_replace(&pair->part, part);
186         navi_it->text_list = eina_list_append(navi_it->text_list, pair);
187      }
188
189    eina_stringshare_replace(&pair->text, label);
190    edje_object_part_text_set(navi_it->title, part, label);
191
192    snprintf(buf, sizeof(buf), "elm,state,%s,show", part);
193
194    if (label)
195      edje_object_signal_emit(navi_it->title, buf, "elm");
196    else
197      edje_object_signal_emit(navi_it->title, buf, "elm");
198
199    _item_sizing_eval(navi_it);
200 }
201
202 static const char *
203 _text_get_hook(const Elm_Object_Item *it, const char *part)
204 {
205    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
206    Eina_List *l = NULL;
207    Elm_Naviframe_Text_Item_Pair *pair = NULL;
208    Elm_Naviframe_Item *navi_it = ELM_CAST(it);
209
210    if (!part) return NULL;
211
212    EINA_LIST_FOREACH(navi_it->text_list, l, pair)
213      {
214         if (!strcmp(part, pair->part))
215           return pair->text;
216      }
217    return NULL;
218 }
219
220 static void
221 _content_set_hook(Elm_Object_Item *it,
222                   const char *part,
223                   Evas_Object *content)
224 {
225    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
226
227    Elm_Naviframe_Content_Item_Pair *pair = NULL;
228    Elm_Naviframe_Item *navi_it = ELM_CAST(it);
229
230    if (!part) return;
231
232    //specified parts
233    if (!strcmp(part, "elm.swallow.content"))
234      {
235        _item_content_set(navi_it, content);
236        return;
237      }
238    else if (!strcmp(part, "elm.swallow.prev_btn"))
239      {
240        _title_prev_btn_set(navi_it, content, EINA_FALSE);
241        return;
242      }
243    else if(!strcmp(part, "elm.swallow.next_btn"))
244      {
245        _title_next_btn_set(navi_it, content);
246        return;
247      }
248
249    //common part
250    _title_content_set(navi_it, pair, part, content);
251 }
252
253 /*
254    */
255 static Evas_Object *
256 _content_get_hook(const Elm_Object_Item *it,
257                   const char *part)
258 {
259    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
260    Eina_List *l = NULL;
261    Elm_Naviframe_Content_Item_Pair *pair = NULL;
262    Elm_Naviframe_Item *navi_it = ELM_CAST(it);
263
264    //specified parts 
265    if (!strcmp(part, "elm.swallow.content"))
266      return navi_it->content;
267    else if (!strcmp(part, "elm.swallow.prev_btn"))
268      return navi_it->title_prev_btn;
269    else if(!strcmp(part, "elm.swallow.next_btn"))
270      return navi_it->title_next_btn;
271
272    //common parts
273    EINA_LIST_FOREACH(navi_it->content_list, l, pair)
274      {
275         if (!strcmp(part, pair->part))
276           return pair->content;
277      }
278    return NULL;
279 }
280
281 static Evas_Object *
282 _content_unset_hook(Elm_Object_Item *it __UNUSED__,
283                     const char *part __UNUSED__)
284 {
285    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
286    Eina_List *l = NULL;
287    Elm_Naviframe_Content_Item_Pair *pair = NULL;
288    Elm_Naviframe_Item *navi_it = ELM_CAST(it);
289    Evas_Object *content = NULL;
290    char buf[1028];
291
292   if (!part) return NULL;
293
294   //specified parts
295   //FIXME: could be unset the below specified contents also. 
296    if (!strcmp(part, "elm.swallow.content") ||
297        !strcmp(part, "elm.swallow.prev_btn") ||
298        !strcmp(part, "elm.swallow.next_btn"))
299      {
300         WRN("You can not unset the content! : naviframe=%p",
301             navi_it->base.widget);
302         return NULL;
303      }
304
305   //common parts
306    EINA_LIST_FOREACH(navi_it->content_list, l, pair)
307      {
308         if (!strcmp(part, pair->part))
309           {
310              content = pair->content;
311              eina_stringshare_del(pair->part);
312              navi_it->content_list = eina_list_remove(navi_it->content_list,
313                                                       pair);
314              free(pair);
315              break;
316           }
317      }
318
319    if (!content) return NULL;
320
321    elm_widget_sub_object_del(navi_it->base.widget, content);
322    edje_object_part_unswallow(navi_it->title, content);
323    snprintf(buf, sizeof(buf), "elm,state,%s,hide", part);
324    edje_object_signal_emit(navi_it->title, buf, "elm");
325    evas_object_event_callback_del(content,
326                                   EVAS_CALLBACK_DEL,
327                                   _title_content_del);
328    _item_sizing_eval(navi_it);
329
330    return content;
331 }
332
333 static void
334 _sizing_eval(Evas_Object *obj)
335 {
336    Widget_Data *wd;
337    Eina_List *list;
338    Elm_Naviframe_Item *it;
339    wd  = elm_widget_data_get(obj);
340    if (!wd) return;
341
342    list = eina_list_last(wd->stack);
343    if (!list) return;
344
345    EINA_LIST_FOREACH(wd->stack, list, it)
346      _item_sizing_eval(it);
347 }
348
349 static void
350 _item_sizing_eval(Elm_Naviframe_Item *it)
351 {
352    Widget_Data *wd;
353    Evas_Coord x, y, w, h;
354    if (!it) return;
355
356    wd = elm_widget_data_get(it->base.widget);
357    if (!wd) return;
358
359    evas_object_geometry_get(it->base.widget, &x, &y, &w, &h);
360    evas_object_move(it->base.view, x, y);
361    evas_object_resize(it->base.view, w, h);
362 }
363
364 static void
365 _move(void *data __UNUSED__,
366       Evas *e __UNUSED__,
367       Evas_Object *obj,
368       void *event_info __UNUSED__)
369 {
370    _sizing_eval(obj);
371 }
372
373 static void
374 _resize(void *data __UNUSED__,
375         Evas *e __UNUSED__,
376         Evas_Object *obj,
377         void *event_info __UNUSED__)
378 {
379    _sizing_eval(obj);
380 }
381
382 static void
383 _title_clicked(void *data,
384                Evas_Object *obj __UNUSED__,
385                const char *emission __UNUSED__,
386                const char *source __UNUSED__)
387 {
388    Elm_Naviframe_Item *it = data;
389    evas_object_smart_callback_call(it->base.widget, SIG_TITLE_CLICKED, it);
390 }
391
392 static void
393 _back_btn_clicked(void *data,
394                   Evas_Object *obj __UNUSED__,
395                   void *event_info __UNUSED__)
396 {
397    elm_naviframe_item_pop(data);
398 }
399
400 static Evas_Object *
401 _back_btn_new(Evas_Object *obj)
402 {
403    Evas_Object *btn;
404    char buf[1024];
405    btn = elm_button_add(obj);
406    if (!btn) return NULL;
407    evas_object_smart_callback_add(btn, "clicked", _back_btn_clicked, obj);
408    snprintf(buf, sizeof(buf), "naviframe/back_btn/%s", elm_widget_style_get(obj));
409    elm_object_style_set(btn, buf);
410    return btn;
411 }
412
413 static void
414 _title_content_del(void *data,
415                    Evas *e __UNUSED__,
416                    Evas_Object *obj __UNUSED__,
417                    void *event_info __UNUSED__)
418 {
419    char buf[1024];
420    Elm_Naviframe_Content_Item_Pair *pair = data;
421    Elm_Naviframe_Item *it = pair->it;
422    snprintf(buf, sizeof(buf), "elm,state,%s,hide", pair->part);
423    edje_object_signal_emit(it->title, buf, "elm");
424    it->content_list = eina_list_remove(it->content_list, pair);
425    eina_stringshare_del(pair->part);
426    free(pair);
427 }
428
429 static void
430 _title_prev_btn_del(void *data,
431                     Evas *e __UNUSED__,
432                     Evas_Object *obj __UNUSED__,
433                     void *event_info __UNUSED__)
434 {
435    Elm_Naviframe_Item *it = data;
436    it->back_btn = EINA_FALSE;
437    it->title_prev_btn = NULL;
438 }
439
440 static void
441 _title_next_btn_del(void *data,
442                     Evas *e __UNUSED__,
443                     Evas_Object *obj __UNUSED__,
444                     void *event_info __UNUSED__)
445 {
446    Elm_Naviframe_Item *it = data;
447    it->title_next_btn = NULL;
448 }
449
450 static void
451 _item_content_del(void *data,
452                   Evas *e __UNUSED__,
453                   Evas_Object *obj __UNUSED__,
454                   void *event_info __UNUSED__)
455 {
456    Elm_Naviframe_Item *it = data;
457    it->content = NULL;
458    edje_object_signal_emit(it->base.view, "elm,state,content,hide", "elm");
459 }
460
461 static void
462 _title_content_set(Elm_Naviframe_Item *it,
463                    Elm_Naviframe_Content_Item_Pair *pair,
464                    const char *part,
465                    Evas_Object *content)
466 {
467    Eina_List *l = NULL;
468    char buf[1024];
469
470    EINA_LIST_FOREACH(it->content_list, l, pair)
471      {
472         if (!strcmp(part, pair->part))
473           {
474              if (pair->content == content) return;
475              break;
476           }
477      }
478
479    if (!pair)
480      {
481         pair = ELM_NEW(Elm_Naviframe_Content_Item_Pair);
482         if (!pair)
483           {
484              ERR("Failed to allocate new content part of the item! : naviframe=%p", it->base.widget);
485              return;
486           }
487         pair->it = it;
488         eina_stringshare_replace(&pair->part, part);
489         it->content_list = eina_list_append(it->content_list, pair);
490      }
491
492    if (pair->content) evas_object_del(pair->content);
493    pair->content = content;
494
495    if (!content)
496      {
497         snprintf(buf, sizeof(buf), "elm,state,%s,hide", part);
498         edje_object_signal_emit(it->title, buf, "elm");
499         return;
500      }
501
502    elm_widget_sub_object_add(it->base.widget, content);
503    edje_object_part_swallow(it->title, part, content);
504    snprintf(buf, sizeof(buf), "elm,state,%s,show", part);
505    edje_object_signal_emit(it->title, buf, "elm");
506    evas_object_event_callback_add(content,
507                                   EVAS_CALLBACK_DEL,
508                                   _title_content_del,
509                                   pair);
510    _item_sizing_eval(it);
511 }
512
513 static void
514 _title_prev_btn_set(Elm_Naviframe_Item *it, Evas_Object *btn, Eina_Bool back_btn)
515 {
516    char buf[1024];
517
518    if (it->title_prev_btn == btn) return;
519
520    if (it->title_prev_btn)
521      evas_object_del(it->title_prev_btn);
522
523    it->title_prev_btn = btn;
524
525    if (!btn) return;
526
527    if (!back_btn)
528      {
529         snprintf(buf,
530                  sizeof(buf),
531                  "naviframe/prev_btn/%s",
532                  elm_widget_style_get(it->base.widget));
533         elm_object_style_set(btn, buf);
534      }
535    elm_widget_sub_object_add(it->base.widget, btn);
536    evas_object_event_callback_add(btn,
537                                   EVAS_CALLBACK_DEL,
538                                   _title_prev_btn_del,
539                                   it);
540    edje_object_part_swallow(it->title, "elm.swallow.prev_btn", btn);
541    it->back_btn = back_btn;
542
543    _item_sizing_eval(it);
544 }
545
546 static void
547 _title_next_btn_set(Elm_Naviframe_Item *it, Evas_Object *btn)
548 {
549    char buf[1024];
550
551    if (it->title_next_btn == btn) return;
552
553    if (it->title_next_btn)
554      evas_object_del(it->title_next_btn);
555
556    it->title_next_btn = btn;
557
558    if (!btn) return;
559
560    snprintf(buf,
561             sizeof(buf),
562             "naviframe/next_btn/%s",
563             elm_widget_style_get(it->base.widget));
564    elm_object_style_set(btn, buf);
565    elm_widget_sub_object_add(it->base.widget, btn);
566    evas_object_event_callback_add(btn,
567                                   EVAS_CALLBACK_DEL,
568                                   _title_next_btn_del,
569                                   it);
570    edje_object_part_swallow(it->title, "elm.swallow.next_btn", btn);
571
572    _item_sizing_eval(it);
573 }
574
575 static void
576 _item_del(Elm_Naviframe_Item *it)
577 {
578    Widget_Data *wd;
579    Eina_List *l;
580    Elm_Naviframe_Content_Item_Pair *content_pair;
581    Elm_Naviframe_Text_Item_Pair *text_pair;
582
583    if (!it) return;
584
585    wd = elm_widget_data_get(it->base.widget);
586    if (!wd) return;
587
588    if (it->title_prev_btn)
589      evas_object_del(it->title_prev_btn);
590    if (it->title_next_btn)
591      evas_object_del(it->title_next_btn);
592       if ((it->content) && (!wd->preserve))
593      evas_object_del(it->content);
594
595    EINA_LIST_FOREACH(it->content_list, l, content_pair)
596      evas_object_del(content_pair->content);
597
598    EINA_LIST_FOREACH(it->text_list, l, text_pair)
599      {
600         eina_stringshare_del(text_pair->part);
601         eina_stringshare_del(text_pair->text);
602      }
603
604    eina_list_free(it->content_list);
605    eina_list_free(it->text_list);
606
607    evas_object_del(it->title);
608    evas_object_del(it->base.view);
609
610    wd->stack = eina_list_remove(wd->stack, it);
611
612    free(it);
613 }
614
615 static void
616 _pushed_finished(void *data,
617                  Evas_Object *obj __UNUSED__,
618                  const char *emission __UNUSED__,
619                  const char *source __UNUSED__)
620 {
621    Elm_Naviframe_Item *it = data;
622    if (!it) return;
623    evas_object_hide(it->base.view);
624 }
625
626 static void
627 _popped_finished(void *data,
628                  Evas_Object *obj __UNUSED__,
629                  const char *emission __UNUSED__,
630                  const char *source __UNUSED__)
631 {
632    _item_del(data);
633 }
634
635 static void
636 _show_finished(void *data,
637                Evas_Object *obj __UNUSED__,
638                const char *emission __UNUSED__,
639                const char *source __UNUSED__)
640 {
641    Elm_Naviframe_Item *it;
642    Widget_Data *wd;
643
644    it = data;
645    if (!it) return;
646    wd =  elm_widget_data_get(it->base.widget);
647    if (!wd) return;
648
649    evas_object_smart_callback_call(it->base.widget,
650                                    SIG_TRANSITION_FINISHED,
651                                    (void *) EINA_TRUE);
652    if (wd->pass_events)
653      evas_object_pass_events_set(wd->base, EINA_FALSE);
654 }
655
656 static void
657 _item_content_set(Elm_Naviframe_Item *navi_it, Evas_Object *content)
658 {
659    if (navi_it->content == content) return;
660    if (navi_it->content) evas_object_del(navi_it->content);
661    elm_widget_sub_object_add(navi_it->base.widget, content);
662    edje_object_part_swallow(navi_it->base.view, "elm.swallow.content", content);
663    if (content)
664      edje_object_signal_emit(navi_it->base.view,
665                              "elm,state,content,show",
666                              "elm");
667    else
668      edje_object_signal_emit(navi_it->base.view,
669                              "elm,state,content,hide",
670                              "elm");
671    evas_object_event_callback_add(content,
672                                   EVAS_CALLBACK_DEL,
673                                   _item_content_del,
674                                   navi_it);
675    navi_it->content = content;
676    _item_sizing_eval(navi_it);
677 }
678
679 EAPI Evas_Object *
680 elm_naviframe_add(Evas_Object *parent)
681 {
682    Evas_Object *obj;
683    Evas *e;
684    Widget_Data *wd;
685
686    ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
687    ELM_SET_WIDTYPE(widtype, "naviframe");
688    elm_widget_type_set(obj, "naviframe");
689    elm_widget_sub_object_add(parent, obj);
690    elm_widget_data_set(obj, wd);
691    elm_widget_del_hook_set(obj, _del_hook);
692    elm_widget_disable_hook_set(obj, _disable_hook);
693    elm_widget_theme_hook_set(obj, _theme_hook);
694
695    //base
696    wd->base = edje_object_add(e);
697    elm_widget_resize_object_set(obj, wd->base);
698    _elm_theme_object_set(obj, wd->base, "naviframe", "base", "default");
699
700    evas_object_event_callback_add(obj, EVAS_CALLBACK_MOVE, _move, obj);
701    evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE, _resize, obj);
702    evas_object_smart_callbacks_descriptions_set(obj, _signals);
703
704    wd->pass_events = EINA_TRUE;
705
706    return obj;
707 }
708
709 EAPI Elm_Object_Item *
710 elm_naviframe_item_push(Evas_Object *obj, const char *title_label, Evas_Object *prev_btn, Evas_Object *next_btn, Evas_Object *content, const char *item_style)
711 {
712    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
713    Widget_Data *wd;
714    Elm_Naviframe_Item *prev_it, *it;
715
716    wd = elm_widget_data_get(obj);
717    if (!wd) return NULL;
718
719    //create item
720    it = elm_widget_item_new(obj, Elm_Naviframe_Item);
721    if (!it)
722      {
723         ERR("Failed to allocate new item! : naviframe=%p", obj);
724         return NULL;
725      }
726
727    elm_widget_item_text_set_hook_set(it, _text_set_hook);
728    elm_widget_item_text_get_hook_set(it, _text_get_hook);
729    elm_widget_item_content_set_hook_set(it, _content_set_hook);
730    elm_widget_item_content_get_hook_set(it, _content_get_hook);
731    elm_widget_item_content_unset_hook_set(it, _content_unset_hook);
732
733    //item base layout
734    it->base.view = edje_object_add(evas_object_evas_get(obj));
735    evas_object_smart_member_add(it->base.view, wd->base);
736    elm_widget_sub_object_add(obj, it->base.view);
737    edje_object_signal_callback_add(it->base.view,
738                                    "elm,action,show,finished",
739                                    "",
740                                    _show_finished, it);
741    edje_object_signal_callback_add(it->base.view,
742                                    "elm,action,pushed,finished",
743                                    "",
744                                    _pushed_finished, it);
745    edje_object_signal_callback_add(it->base.view,
746                                    "elm,action,popped,finished",
747                                    "",
748                                    _popped_finished, it);
749    elm_naviframe_item_style_set(ELM_CAST(it), item_style);
750
751    //title
752    it->title = edje_object_add(evas_object_evas_get(obj));
753    elm_widget_sub_object_add(obj, it->title);
754    _elm_theme_object_set(obj,
755                          it->title, "naviframe",
756                          "title",
757                          elm_widget_style_get(obj));
758    edje_object_signal_callback_add(it->title,
759                                    "elm,action,clicked",
760                                    "elm",
761                                    _title_clicked, it);
762
763    _text_set_hook(ELM_CAST(it), "elm.text.title", title_label);
764
765    //title buttons
766    if ((!prev_btn) && (eina_list_count(wd->stack)))
767      {
768         prev_btn = _back_btn_new(obj);
769         _title_prev_btn_set(it, prev_btn, EINA_TRUE);
770      }
771    else
772      _title_prev_btn_set(it, prev_btn, EINA_FALSE);
773
774    _title_next_btn_set(it, next_btn);
775    edje_object_part_swallow(it->base.view, "elm.swallow.title", it->title);
776
777    _item_content_set(it, content);
778
779    _item_sizing_eval(it);
780    evas_object_show(it->base.view);
781
782    prev_it = ELM_CAST(elm_naviframe_top_item_get(obj));
783    if (prev_it)
784      {
785         if (wd->pass_events)
786           evas_object_pass_events_set(wd->base, EINA_TRUE);
787         edje_object_signal_emit(prev_it->base.view,
788                                 "elm,state,pushed",
789                                 "elm");
790         edje_object_signal_emit(it->base.view,
791                                 "elm,state,show",
792                                 "elm");
793      }
794    else
795      edje_object_signal_emit(it->base.view, "elm,state,visible", "elm");
796    it->title_visible = EINA_TRUE;
797    wd->stack = eina_list_append(wd->stack, it);
798    return ELM_CAST(it);
799 }
800
801 EAPI Evas_Object *
802 elm_naviframe_item_pop(Evas_Object *obj)
803 {
804    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
805    Elm_Naviframe_Item *it, *prev_it;
806    Widget_Data *wd;
807    Evas_Object *content = NULL;
808
809    wd = elm_widget_data_get(obj);
810    if (!wd) return NULL;
811
812    it = ELM_CAST(elm_naviframe_top_item_get(obj));
813    if (!it) return NULL;
814    wd->stack = eina_list_remove(wd->stack, it);
815
816    if (wd->preserve)
817      content = it->content;
818
819    prev_it = ELM_CAST(elm_naviframe_top_item_get(obj));
820    if (prev_it)
821      {
822         if (wd->pass_events)
823           evas_object_pass_events_set(wd->base, EINA_TRUE);
824         evas_object_show(prev_it->base.view);
825         evas_object_raise(prev_it->base.view);
826         edje_object_signal_emit(prev_it->base.view,
827                                 "elm,state,show",
828                                 "elm");
829         edje_object_signal_emit(it->base.view, "elm,state,popped", "elm");
830      }
831    else
832      _item_del(it);
833
834    return content;
835 }
836
837 EAPI void
838 elm_naviframe_content_preserve_on_pop_set(Evas_Object *obj, Eina_Bool preserve)
839 {
840    ELM_CHECK_WIDTYPE(obj, widtype);
841    Widget_Data *wd = elm_widget_data_get(obj);
842    if (!wd) return;
843    wd->preserve = !!preserve;
844 }
845
846 EAPI Eina_Bool
847 elm_naviframe_content_preserve_on_pop_get(const Evas_Object *obj)
848 {
849    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
850    Widget_Data *wd = elm_widget_data_get(obj);
851    if (!wd) return EINA_FALSE;
852    return wd->preserve;
853 }
854
855 EAPI Elm_Object_Item*
856 elm_naviframe_top_item_get(const Evas_Object *obj)
857 {
858    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
859    Widget_Data *wd = elm_widget_data_get(obj);
860    if ((!wd) || (!wd->stack)) return NULL;
861    return eina_list_last(wd->stack)->data;
862 }
863
864 EAPI Elm_Object_Item*
865 elm_naviframe_bottom_item_get(const Evas_Object *obj)
866 {
867    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
868    Widget_Data *wd = elm_widget_data_get(obj);
869    if (!wd) return NULL;
870    return NULL;
871 }
872
873 EAPI void
874 elm_naviframe_item_style_set(Elm_Object_Item *it, const char *item_style)
875 {
876    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
877    Elm_Naviframe_Item *navi_it = ELM_CAST(it);
878
879    char buf[256];
880
881    if (!item_style) sprintf(buf, "item/basic");
882    else
883      {
884         if (strlen(item_style) > sizeof(buf))
885           WRN("too much long style name! : naviframe=%p", navi_it->base.widget);
886         else
887           sprintf(buf, "item/%s", item_style);
888      }
889    _elm_theme_object_set(navi_it->base.widget,
890                          navi_it->base.view,
891                          "naviframe",
892                          buf,
893                          elm_widget_style_get(navi_it->base.widget));
894 }
895
896 EAPI const char *
897 elm_naviframe_item_style_get(const Elm_Object_Item *it)
898 {
899    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
900    Elm_Naviframe_Item *navi_it = ELM_CAST(it);
901    return navi_it->style;
902 }
903
904 EAPI void
905 elm_naviframe_item_title_visible_set(Elm_Object_Item *it, Eina_Bool visible)
906 {
907    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
908    Elm_Naviframe_Item *navi_it = ELM_CAST(it);
909
910    visible = !!visible;
911    if (navi_it->title_visible == visible) return;
912
913    if (visible)
914      edje_object_signal_emit(navi_it->base.view, "elm,state,title,show", "elm");
915    else
916      edje_object_signal_emit(navi_it->base.view, "elm,state,title,hide", "elm");
917
918    navi_it->title_visible = visible;
919 }
920
921 EAPI Eina_Bool
922 elm_naviframe_item_title_visible_get(const Elm_Object_Item *it)
923 {
924    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
925    Elm_Naviframe_Item *navi_it = ELM_CAST(it);
926    return navi_it->title_visible;
927 }
928