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