elementary/naviframe - removed items in reverse since the items are stacked.
[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 /*
278    */
279 static Evas_Object *
280 _item_content_get_hook(const Elm_Object_Item *it, const char *part)
281 {
282    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
283    Eina_List *l = NULL;
284    Elm_Naviframe_Content_Item_Pair *pair = NULL;
285    Elm_Naviframe_Item *navi_it = ELM_CAST(it);
286
287    //specified parts
288    if ((!part) || (!strcmp(part, "elm.swallow.content")))
289      return navi_it->content;
290    else if (!strcmp(part, "elm.swallow.prev_btn"))
291      return navi_it->title_prev_btn;
292    else if(!strcmp(part, "elm.swallow.next_btn"))
293      return navi_it->title_next_btn;
294
295    //common parts
296    EINA_LIST_FOREACH(navi_it->content_list, l, pair)
297      {
298         if (!strcmp(part, pair->part))
299           return pair->content;
300      }
301    return NULL;
302 }
303
304 static Evas_Object *
305 _item_content_unset_hook(Elm_Object_Item *it, const char *part)
306 {
307    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
308    Eina_List *l = NULL;
309    Elm_Naviframe_Content_Item_Pair *pair = NULL;
310    Elm_Naviframe_Item *navi_it = ELM_CAST(it);
311    Evas_Object *content = NULL;
312    char buf[1028];
313
314    //specified parts
315    //FIXME: could be unset the below specified contents also.
316    if (!part ||
317        !strcmp(part, "elm.swallow.content") ||
318        !strcmp(part, "elm.swallow.prev_btn") ||
319        !strcmp(part, "elm.swallow.next_btn"))
320      {
321         WRN("You can not unset the content! : naviframe=%p",
322             navi_it->base.widget);
323         return NULL;
324      }
325
326    //common parts
327    EINA_LIST_FOREACH(navi_it->content_list, l, pair)
328      {
329         if (!strcmp(part, pair->part))
330           {
331              content = pair->content;
332              eina_stringshare_del(pair->part);
333              navi_it->content_list = eina_list_remove(navi_it->content_list,
334                                                       pair);
335              free(pair);
336              break;
337           }
338      }
339
340    if (!content) return NULL;
341
342    elm_widget_sub_object_del(navi_it->base.widget, content);
343    edje_object_part_unswallow(navi_it->base.view, content);
344    snprintf(buf, sizeof(buf), "elm,state,%s,hide", part);
345    edje_object_signal_emit(navi_it->base.view, buf, "elm");
346    evas_object_event_callback_del(content,
347                                   EVAS_CALLBACK_DEL,
348                                   _title_content_del);
349    _item_sizing_eval(navi_it);
350
351    return content;
352 }
353
354 static void
355 _item_signal_emit_hook(Elm_Object_Item *it,
356                        const char *emission,
357                        const char *source)
358 {
359    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
360    Elm_Naviframe_Item *navi_it = ELM_CAST(it);
361    edje_object_signal_emit(navi_it->base.view, emission, source);
362 }
363
364 static void
365 _sizing_eval(Evas_Object *obj)
366 {
367    Widget_Data *wd;
368    Eina_List *list;
369    Elm_Naviframe_Item *it;
370    wd  = elm_widget_data_get(obj);
371    if (!wd) return;
372
373    list = eina_list_last(wd->stack);
374    if (!list) return;
375
376    EINA_LIST_FOREACH(wd->stack, list, it)
377      _item_sizing_eval(it);
378 }
379
380 static void
381 _item_sizing_eval(Elm_Naviframe_Item *it)
382 {
383    Widget_Data *wd;
384    Evas_Coord x, y, w, h;
385    if (!it) return;
386
387    wd = elm_widget_data_get(it->base.widget);
388    if (!wd) return;
389
390    evas_object_geometry_get(it->base.widget, &x, &y, &w, &h);
391    evas_object_move(it->base.view, x, y);
392    evas_object_resize(it->base.view, w, h);
393 }
394
395 static void
396 _move(void *data __UNUSED__,
397       Evas *e __UNUSED__,
398       Evas_Object *obj,
399       void *event_info __UNUSED__)
400 {
401    _sizing_eval(obj);
402 }
403
404 static void
405 _resize(void *data __UNUSED__,
406         Evas *e __UNUSED__,
407         Evas_Object *obj,
408         void *event_info __UNUSED__)
409 {
410    _sizing_eval(obj);
411 }
412
413 static void
414 _title_clicked(void *data,
415                Evas_Object *obj __UNUSED__,
416                const char *emission __UNUSED__,
417                const char *source __UNUSED__)
418 {
419    Elm_Naviframe_Item *it = data;
420    evas_object_smart_callback_call(it->base.widget, SIG_TITLE_CLICKED, it);
421 }
422
423 static void
424 _back_btn_clicked(void *data,
425                   Evas_Object *obj __UNUSED__,
426                   void *event_info __UNUSED__)
427 {
428    elm_naviframe_item_pop(data);
429 }
430
431 static Evas_Object *
432 _back_btn_new(Evas_Object *obj)
433 {
434    Evas_Object *btn;
435    char buf[1024];
436    btn = elm_button_add(obj);
437    if (!btn) return NULL;
438    evas_object_smart_callback_add(btn, "clicked", _back_btn_clicked, obj);
439    snprintf(buf, sizeof(buf), "naviframe/back_btn/%s", elm_widget_style_get(obj));
440    elm_object_style_set(btn, buf);
441    return btn;
442 }
443
444 static void
445 _title_content_del(void *data,
446                    Evas *e __UNUSED__,
447                    Evas_Object *obj __UNUSED__,
448                    void *event_info __UNUSED__)
449 {
450    char buf[1024];
451    Elm_Naviframe_Content_Item_Pair *pair = data;
452    Elm_Naviframe_Item *it = pair->it;
453    snprintf(buf, sizeof(buf), "elm,state,%s,hide", pair->part);
454    edje_object_signal_emit(it->base.view, buf, "elm");
455    it->content_list = eina_list_remove(it->content_list, pair);
456    eina_stringshare_del(pair->part);
457    free(pair);
458 }
459
460 static void
461 _title_prev_btn_del(void *data,
462                     Evas *e __UNUSED__,
463                     Evas_Object *obj __UNUSED__,
464                     void *event_info __UNUSED__)
465 {
466    Elm_Naviframe_Item *it = data;
467    it->back_btn = EINA_FALSE;
468    it->title_prev_btn = NULL;
469 }
470
471 static void
472 _title_next_btn_del(void *data,
473                     Evas *e __UNUSED__,
474                     Evas_Object *obj __UNUSED__,
475                     void *event_info __UNUSED__)
476 {
477    Elm_Naviframe_Item *it = data;
478    it->title_next_btn = NULL;
479 }
480
481 static void
482 _item_content_del(void *data,
483                   Evas *e __UNUSED__,
484                   Evas_Object *obj __UNUSED__,
485                   void *event_info __UNUSED__)
486 {
487    Elm_Naviframe_Item *it = data;
488    it->content = NULL;
489    edje_object_signal_emit(it->base.view, "elm,state,content,hide", "elm");
490 }
491
492 static void
493 _title_content_set(Elm_Naviframe_Item *it,
494                    Elm_Naviframe_Content_Item_Pair *pair,
495                    const char *part,
496                    Evas_Object *content)
497 {
498    Eina_List *l = NULL;
499    char buf[1024];
500
501    EINA_LIST_FOREACH(it->content_list, l, pair)
502      {
503         if (!strcmp(part, pair->part))
504           {
505              if (pair->content == content) return;
506              break;
507           }
508      }
509
510    if (!pair)
511      {
512         pair = ELM_NEW(Elm_Naviframe_Content_Item_Pair);
513         if (!pair)
514           {
515              ERR("Failed to allocate new content part of the item! : naviframe=%p", it->base.widget);
516              return;
517           }
518         pair->it = it;
519         eina_stringshare_replace(&pair->part, part);
520         it->content_list = eina_list_append(it->content_list, pair);
521      }
522
523    if (pair->content) evas_object_del(pair->content);
524    pair->content = content;
525
526    if (!content)
527      {
528         snprintf(buf, sizeof(buf), "elm,state,%s,hide", part);
529         edje_object_signal_emit(it->base.view, buf, "elm");
530         return;
531      }
532
533    elm_widget_sub_object_add(it->base.widget, content);
534    edje_object_part_swallow(it->base.view, part, content);
535    snprintf(buf, sizeof(buf), "elm,state,%s,show", part);
536    edje_object_signal_emit(it->base.view, buf, "elm");
537    evas_object_event_callback_add(content,
538                                   EVAS_CALLBACK_DEL,
539                                   _title_content_del,
540                                   pair);
541    _item_sizing_eval(it);
542 }
543
544 static void
545 _title_prev_btn_set(Elm_Naviframe_Item *it, Evas_Object *btn, 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    evas_object_del(it->base.view);
622
623    wd->stack = eina_list_remove(wd->stack, it);
624
625    free(it);
626 }
627
628 static void
629 _pushed_finished(void *data,
630                  Evas_Object *obj __UNUSED__,
631                  const char *emission __UNUSED__,
632                  const char *source __UNUSED__)
633 {
634    Elm_Naviframe_Item *it = data;
635    if (!it) return;
636    evas_object_hide(it->base.view);
637 }
638
639 static void
640 _popped_finished(void *data,
641                  Evas_Object *obj __UNUSED__,
642                  const char *emission __UNUSED__,
643                  const char *source __UNUSED__)
644 {
645    _item_del(data);
646 }
647
648 static void
649 _show_finished(void *data,
650                Evas_Object *obj __UNUSED__,
651                const char *emission __UNUSED__,
652                const char *source __UNUSED__)
653 {
654    Elm_Naviframe_Item *it;
655    Widget_Data *wd;
656
657    it = data;
658    if (!it) return;
659    wd =  elm_widget_data_get(it->base.widget);
660    if (!wd) return;
661
662    evas_object_smart_callback_call(it->base.widget,
663                                    SIG_TRANSITION_FINISHED,
664                                    (void *) EINA_TRUE);
665    if (wd->pass_events)
666      evas_object_pass_events_set(wd->base, EINA_FALSE);
667 }
668
669 static void
670 _item_content_set(Elm_Naviframe_Item *navi_it, Evas_Object *content)
671 {
672    if (navi_it->content == content) return;
673    if (navi_it->content) evas_object_del(navi_it->content);
674    elm_widget_sub_object_add(navi_it->base.widget, content);
675    edje_object_part_swallow(navi_it->base.view, "elm.swallow.content", 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, const char *title_label, Evas_Object *prev_btn, Evas_Object *next_btn, Evas_Object *content, const char *item_style)
725 {
726    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
727    Widget_Data *wd;
728    Elm_Naviframe_Item *prev_it, *it;
729
730    wd = elm_widget_data_get(obj);
731    if (!wd) return NULL;
732
733    //create item
734    it = elm_widget_item_new(obj, Elm_Naviframe_Item);
735    if (!it)
736      {
737         ERR("Failed to allocate new item! : naviframe=%p", obj);
738         return NULL;
739      }
740
741    elm_widget_item_text_set_hook_set(it, _item_text_set_hook);
742    elm_widget_item_text_get_hook_set(it, _item_text_get_hook);
743    elm_widget_item_content_set_hook_set(it, _item_content_set_hook);
744    elm_widget_item_content_get_hook_set(it, _item_content_get_hook);
745    elm_widget_item_content_unset_hook_set(it, _item_content_unset_hook);
746    elm_widget_item_signal_emit_hook_set(it, _item_signal_emit_hook);
747
748    //item base layout
749    it->base.view = edje_object_add(evas_object_evas_get(obj));
750    evas_object_smart_member_add(it->base.view, wd->base);
751    elm_widget_sub_object_add(obj, it->base.view);
752    edje_object_signal_callback_add(it->base.view,
753                                    "elm,action,show,finished",
754                                    "",
755                                    _show_finished, it);
756    edje_object_signal_callback_add(it->base.view,
757                                    "elm,action,pushed,finished",
758                                    "",
759                                    _pushed_finished, it);
760    edje_object_signal_callback_add(it->base.view,
761                                    "elm,action,popped,finished",
762                                    "",
763                                    _popped_finished, it);
764    edje_object_signal_callback_add(it->base.view,
765                                    "elm,action,title,clicked",
766                                    "",
767                                    _title_clicked, it);
768
769    elm_naviframe_item_style_set(ELM_CAST(it), item_style);
770
771    _item_text_set_hook(ELM_CAST(it), "elm.text.title", title_label);
772
773    //title buttons
774    if ((!prev_btn) && (eina_list_count(wd->stack)))
775      {
776         prev_btn = _back_btn_new(obj);
777         _title_prev_btn_set(it, prev_btn, EINA_TRUE);
778      }
779    else
780      _title_prev_btn_set(it, prev_btn, EINA_FALSE);
781
782    _title_next_btn_set(it, next_btn);
783
784    _item_content_set(it, content);
785
786    _item_sizing_eval(it);
787    evas_object_show(it->base.view);
788
789    prev_it = ELM_CAST(elm_naviframe_top_item_get(obj));
790    if (prev_it)
791      {
792         if (wd->pass_events)
793           evas_object_pass_events_set(wd->base, EINA_TRUE);
794         edje_object_signal_emit(prev_it->base.view,
795                                 "elm,state,pushed",
796                                 "elm");
797         edje_object_signal_emit(it->base.view,
798                                 "elm,state,show",
799                                 "elm");
800      }
801    else
802      edje_object_signal_emit(it->base.view, "elm,state,visible", "elm");
803    it->title_visible = EINA_TRUE;
804    wd->stack = eina_list_append(wd->stack, it);
805    return ELM_CAST(it);
806 }
807
808 EAPI Evas_Object *
809 elm_naviframe_item_pop(Evas_Object *obj)
810 {
811    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
812    Elm_Naviframe_Item *it, *prev_it;
813    Widget_Data *wd;
814    Evas_Object *content = NULL;
815
816    wd = elm_widget_data_get(obj);
817    if (!wd) return NULL;
818
819    it = ELM_CAST(elm_naviframe_top_item_get(obj));
820    if (!it) return NULL;
821    wd->stack = eina_list_remove(wd->stack, it);
822
823    if (wd->preserve)
824      content = it->content;
825
826    prev_it = ELM_CAST(elm_naviframe_top_item_get(obj));
827    if (prev_it)
828      {
829         if (wd->pass_events)
830           evas_object_pass_events_set(wd->base, EINA_TRUE);
831         evas_object_show(prev_it->base.view);
832         evas_object_raise(prev_it->base.view);
833         edje_object_signal_emit(prev_it->base.view,
834                                 "elm,state,show",
835                                 "elm");
836         edje_object_signal_emit(it->base.view, "elm,state,popped", "elm");
837      }
838    else
839      _item_del(it);
840
841    return content;
842 }
843
844 EAPI void
845 elm_naviframe_content_preserve_on_pop_set(Evas_Object *obj, Eina_Bool preserve)
846 {
847    ELM_CHECK_WIDTYPE(obj, widtype);
848    Widget_Data *wd = elm_widget_data_get(obj);
849    if (!wd) return;
850    wd->preserve = !!preserve;
851 }
852
853 EAPI Eina_Bool
854 elm_naviframe_content_preserve_on_pop_get(const Evas_Object *obj)
855 {
856    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
857    Widget_Data *wd = elm_widget_data_get(obj);
858    if (!wd) return EINA_FALSE;
859    return wd->preserve;
860 }
861
862 EAPI Elm_Object_Item*
863 elm_naviframe_top_item_get(const Evas_Object *obj)
864 {
865    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
866    Widget_Data *wd = elm_widget_data_get(obj);
867    if ((!wd) || (!wd->stack)) return NULL;
868    return eina_list_last(wd->stack)->data;
869 }
870
871 EAPI Elm_Object_Item*
872 elm_naviframe_bottom_item_get(const Evas_Object *obj)
873 {
874    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
875    Widget_Data *wd = elm_widget_data_get(obj);
876    if (!wd) return NULL;
877    return NULL;
878 }
879
880 EAPI void
881 elm_naviframe_item_style_set(Elm_Object_Item *it, const char *item_style)
882 {
883    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
884    Elm_Naviframe_Item *navi_it = ELM_CAST(it);
885
886    char buf[256];
887
888    if (!item_style) sprintf(buf, "item/basic");
889    else
890      {
891         if (strlen(item_style) > sizeof(buf))
892           WRN("too much long style name! : naviframe=%p", navi_it->base.widget);
893         else
894           sprintf(buf, "item/%s", item_style);
895      }
896    _elm_theme_object_set(navi_it->base.widget,
897                          navi_it->base.view,
898                          "naviframe",
899                          buf,
900                          elm_widget_style_get(navi_it->base.widget));
901 }
902
903 EAPI const char *
904 elm_naviframe_item_style_get(const Elm_Object_Item *it)
905 {
906    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
907    Elm_Naviframe_Item *navi_it = ELM_CAST(it);
908    return navi_it->style;
909 }
910
911 EAPI void
912 elm_naviframe_item_title_visible_set(Elm_Object_Item *it, Eina_Bool visible)
913 {
914    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
915    Elm_Naviframe_Item *navi_it = ELM_CAST(it);
916
917    visible = !!visible;
918    if (navi_it->title_visible == visible) return;
919
920    if (visible)
921      edje_object_signal_emit(navi_it->base.view, "elm,state,title,show", "elm");
922    else
923      edje_object_signal_emit(navi_it->base.view, "elm,state,title,hide", "elm");
924
925    navi_it->title_visible = visible;
926 }
927
928 EAPI Eina_Bool
929 elm_naviframe_item_title_visible_get(const Elm_Object_Item *it)
930 {
931    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
932    Elm_Naviframe_Item *navi_it = ELM_CAST(it);
933    return navi_it->title_visible;
934 }
935