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