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