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