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