elementary/naviframe - Bad Hermet... the flag should be flipped inside.
[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    Eina_Bool     preserve: 1;
14    Eina_Bool     auto_pushed: 1;
15    Eina_Bool     freeze_events: 1;
16 };
17
18 struct _Elm_Naviframe_Content_Item_Pair
19 {
20    EINA_INLIST;
21    const char *part;
22    Evas_Object *content;
23    Elm_Naviframe_Item *it;
24 };
25
26 struct _Elm_Naviframe_Text_Item_Pair
27 {
28    EINA_INLIST;
29    const char *part;
30    const char *text;
31 };
32
33 struct _Elm_Naviframe_Item
34 {
35    ELM_WIDGET_ITEM;
36    EINA_INLIST;
37    Eina_Inlist       *content_list;
38    Eina_Inlist       *text_list;
39    Evas_Object       *content;
40    Evas_Object       *title_prev_btn;
41    Evas_Object       *title_next_btn;
42    Evas_Object       *title_icon;
43    const char        *style;
44    Evas_Coord         minw;
45    Evas_Coord         minh;
46    Eina_Bool          back_btn: 1;
47    Eina_Bool          title_visible: 1;
48 };
49
50 static const char *widtype = NULL;
51
52 static const char SIG_TRANSITION_FINISHED[] = "transition,finished";
53 static const char SIG_PUSH_FINISHED[] = "push,finished";
54 static const char SIG_POP_FINISHED[] = "pop,finished";
55 static const char SIG_TITLE_CLICKED[] = "title,clicked";
56
57 static const Evas_Smart_Cb_Description _signals[] = {
58        {SIG_TRANSITION_FINISHED, ""},
59        {SIG_TITLE_CLICKED, ""},
60        {NULL, NULL}
61 };
62
63 static void _del_hook(Evas_Object *obj);
64 static void _theme_hook(Evas_Object *obj);
65 static void _emit_hook(Evas_Object *obj,
66                        const char *emission,
67                        const char *source);
68 static void _disable_hook(Evas_Object *obj);
69 static void _mirrored_set(Evas_Object *obj, Eina_Bool rtl);
70 static void _item_text_set_hook(Elm_Object_Item *it,
71                                 const char *part,
72                                 const char *label);
73 static const char *_item_text_get_hook(const Elm_Object_Item *it,
74                                        const char *part);
75 static void _item_content_set_hook(Elm_Object_Item *it,
76                                    const char *part,
77                                    Evas_Object *content);
78 static Evas_Object *_item_content_get_hook(const Elm_Object_Item *it,
79                                            const char *part);
80 static Evas_Object *_item_content_unset_hook(Elm_Object_Item *it,
81                                              const char *part);
82 static void _item_signal_emit_hook(Elm_Object_Item *it,
83                                    const char *emission,
84                                    const char *source);
85 static void _item_title_visible_update(Elm_Naviframe_Item *navi_it);
86 static void _sizing_eval(Evas_Object *obj);
87 static void _move(void *data, Evas *e, Evas_Object *obj, void *event_info);
88 static void _resize(void *data,
89                     Evas *e,
90                     Evas_Object *obj,
91                     void *event_info);
92 static void _title_clicked(void *data, Evas_Object *obj,
93                            const char *emission,
94                            const char *source);
95 static void _back_btn_clicked(void *data,
96                               Evas_Object *obj,
97                               void *event_info);
98 static Evas_Object *_back_btn_new(Evas_Object *obj);
99 static void _item_content_del(void *data,
100                               Evas *e,
101                               Evas_Object *obj,
102                               void *event_info);
103 static void _title_content_del(void *data,
104                                Evas *e,
105                                Evas_Object *obj,
106                                void *event_info);
107 static void _title_prev_btn_del(void *data,
108                                 Evas *e,
109                                 Evas_Object *obj,
110                                 void *event_info);
111 static void _title_next_btn_del(void *data,
112                                 Evas *e,
113                                 Evas_Object *obj,
114                                 void *event_info);
115 static void _title_icon_del(void *data,
116                             Evas *e,
117                             Evas_Object *obj,
118                             void *event_info);
119 static void _title_content_set(Elm_Naviframe_Item *it,
120                                const char *part,
121                                Evas_Object *content);
122 static void _title_prev_btn_set(Elm_Naviframe_Item *it,
123                                 Evas_Object *btn,
124                                 Eina_Bool back_btn);
125 static void _title_next_btn_set(Elm_Naviframe_Item *it, Evas_Object *btn);
126 static void _title_icon_set(Elm_Naviframe_Item *it, Evas_Object *icon);
127 static Evas_Object * _item_content_unset(Elm_Naviframe_Item *it);
128 static Evas_Object * _title_prev_btn_unset(Elm_Naviframe_Item *it);
129 static Evas_Object * _title_next_btn_unset(Elm_Naviframe_Item *it);
130 static Evas_Object * _title_icon_unset(Elm_Naviframe_Item *it);
131 static Evas_Object * _title_content_unset(Elm_Naviframe_Item *it,
132                                           const char *part);
133 static void _item_del(Elm_Naviframe_Item *it);
134 static void _pushed_finished(void *data,
135                              Evas_Object *obj,
136                              const char *emission,
137                              const char *source);
138 static void _popped_finished(void *data,
139                              Evas_Object *obj,
140                              const char *emission,
141                              const char *source);
142 static void _show_finished(void *data,
143                            Evas_Object *obj,
144                            const char *emission,
145                            const char *source);
146 static void _changed_size_hints(void *data,
147                                 Evas *e,
148                                 Evas_Object *obj,
149                                 void *event_info);
150 static void _item_content_set(Elm_Naviframe_Item *navi_it,
151                               Evas_Object *content);
152 static void _item_style_set(Elm_Naviframe_Item *navi_it,
153                             const char *item_style);
154 static Elm_Naviframe_Item * _item_new(Evas_Object *obj,
155                                       const char *title_label,
156                                       Evas_Object *prev_btn,
157                                       Evas_Object *next_btn,
158                                       Evas_Object *content,
159                                       const char *item_style);
160
161 static void
162 _del_hook(Evas_Object *obj)
163 {
164    Widget_Data *wd;
165    Elm_Naviframe_Item *it;
166
167    wd = elm_widget_data_get(obj);
168    if (!wd) return;
169
170    if (wd->stack)
171      {
172         while (wd->stack->last)
173           {
174              it = EINA_INLIST_CONTAINER_GET(wd->stack->last,
175                                             Elm_Naviframe_Item);
176              wd->stack = eina_inlist_remove(wd->stack, wd->stack->last);
177              _item_del(it);
178              if (!wd->stack) break;
179           }
180      }
181    free(wd);
182 }
183
184 static void
185 _theme_hook(Evas_Object *obj)
186 {
187    Widget_Data *wd;
188    Elm_Naviframe_Item *it;
189
190    wd  = elm_widget_data_get(obj);
191    if (!wd) return;
192
193    _elm_theme_object_set(obj,
194                          wd->base,
195                          "naviframe",
196                          "base",
197                          elm_widget_style_get(obj));
198
199    EINA_INLIST_FOREACH(wd->stack, it)
200      {
201         _item_style_set(it, it->style);
202         _item_title_visible_update(it);
203      }
204
205    _elm_widget_mirrored_reload(obj);
206    _mirrored_set(obj, elm_widget_mirrored_get(obj));
207 }
208
209 static void _emit_hook(Evas_Object *obj,
210                        const char *emission,
211                        const char *source)
212 {
213    ELM_CHECK_WIDTYPE(obj, widtype);
214
215    Widget_Data *wd = elm_widget_data_get(obj);
216    if (!wd) return;
217
218    edje_object_signal_emit(wd->base, emission, source);
219 }
220
221 static void
222 _disable_hook(Evas_Object *obj __UNUSED__)
223 {
224    //FIXME:
225 }
226
227 static void
228 _mirrored_set(Evas_Object *obj, Eina_Bool rtl)
229 {
230    Widget_Data *wd;
231    Elm_Naviframe_Item *it;
232
233    wd  = elm_widget_data_get(obj);
234    if (!wd) return;
235
236    EINA_INLIST_FOREACH(wd->stack, it)
237      edje_object_mirrored_set(VIEW(it), rtl);
238    edje_object_mirrored_set(wd->base, rtl);
239 }
240
241 static void
242 _item_text_set_hook(Elm_Object_Item *it,
243                     const char *part,
244                     const char *label)
245 {
246    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
247
248    Elm_Naviframe_Text_Item_Pair *pair = NULL;
249    Elm_Naviframe_Item *navi_it = (Elm_Naviframe_Item *) it;
250    char buf[1024];
251
252    if (!part || !strcmp(part, "default"))
253      snprintf(buf, sizeof(buf), "elm.text.title");
254    else if(!strcmp("subtitle", part))
255      snprintf(buf, sizeof(buf), "elm.text.subtitle");
256    else
257      snprintf(buf, sizeof(buf), "%s", part);
258
259    EINA_INLIST_FOREACH(navi_it->text_list, pair)
260      if (!strcmp(buf, pair->part)) break;
261
262    if (!pair)
263      {
264         pair = ELM_NEW(Elm_Naviframe_Text_Item_Pair);
265         if (!pair)
266           {
267              ERR("Failed to allocate new text part of the item! : naviframe=%p",
268              WIDGET(navi_it));
269              return;
270           }
271         eina_stringshare_replace(&pair->part, buf);
272         navi_it->text_list = eina_inlist_append(navi_it->text_list,
273                                                 EINA_INLIST_GET(pair));
274      }
275
276    eina_stringshare_replace(&pair->text, label);
277    edje_object_part_text_set(VIEW(navi_it), buf, label);
278
279    if (label)
280      {
281         snprintf(buf, sizeof(buf), "elm,state,%s,show", buf);
282         edje_object_signal_emit(VIEW(navi_it), buf, "elm");
283      }
284    else
285      {
286         snprintf(buf, sizeof(buf), "elm,state,%s,hide", buf);
287         edje_object_signal_emit(VIEW(navi_it), buf, "elm");
288      }
289
290    _sizing_eval(WIDGET(navi_it));
291 }
292
293 static const char *
294 _item_text_get_hook(const Elm_Object_Item *it, const char *part)
295 {
296    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
297    Elm_Naviframe_Text_Item_Pair *pair = NULL;
298    Elm_Naviframe_Item *navi_it = (Elm_Naviframe_Item *) it;
299    char buf[1024];
300
301    if (!part || !strcmp(part, "default"))
302      snprintf(buf, sizeof(buf), "elm.text.title");
303    else if(!strcmp("subtitle", part))
304      snprintf(buf, sizeof(buf), "elm.text.subtitle");
305    else
306      snprintf(buf, sizeof(buf), "%s", part);
307
308    EINA_INLIST_FOREACH(navi_it->text_list, pair)
309      {
310         if (!strcmp(buf, pair->part))
311           return pair->text;
312      }
313    return NULL;
314 }
315
316 static void
317 _item_content_set_hook(Elm_Object_Item *it,
318                        const char *part,
319                        Evas_Object *content)
320 {
321    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
322
323    Elm_Naviframe_Item *navi_it = (Elm_Naviframe_Item *) it;
324
325    //specified parts
326    if (!part || !strcmp("default", part))
327      {
328         _item_content_set(navi_it, content);
329         return;
330      }
331    else if (!strcmp(part, "prev_btn"))
332      {
333         _title_prev_btn_set(navi_it, content, EINA_FALSE);
334         return;
335      }
336    else if (!strcmp(part, "next_btn"))
337      {
338         _title_next_btn_set(navi_it, content);
339         return;
340      }
341    else if (!strcmp(part, "icon"))
342      {
343         _title_icon_set(navi_it, content);
344         return;
345      }
346
347    //common part
348    _title_content_set(navi_it, part, content);
349 }
350
351 static Evas_Object *
352 _item_content_get_hook(const Elm_Object_Item *it, const char *part)
353 {
354    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
355    Elm_Naviframe_Content_Item_Pair *pair = NULL;
356    Elm_Naviframe_Item *navi_it = (Elm_Naviframe_Item *) it;
357
358    //specified parts
359    if (!part || !strcmp("default", part))
360      return navi_it->content;
361    else if (!strcmp(part, "prev_btn"))
362      return navi_it->title_prev_btn;
363    else if (!strcmp(part, "next_btn"))
364      return navi_it->title_next_btn;
365    else if (!strcmp(part, "icon"))
366      return navi_it->title_icon;
367
368    //common parts
369    EINA_INLIST_FOREACH(navi_it->content_list, pair)
370      {
371         if (!strcmp(part, pair->part))
372           return pair->content;
373      }
374    return NULL;
375 }
376
377 static Evas_Object *
378 _item_content_unset_hook(Elm_Object_Item *it, const char *part)
379 {
380    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
381    Elm_Naviframe_Item *navi_it = (Elm_Naviframe_Item *) it;
382
383    //specified parts
384    if (!part || !strcmp("default", part))
385      return _item_content_unset(navi_it);
386    else if (!strcmp(part, "prev_btn"))
387      return _title_prev_btn_unset(navi_it);
388    else if (!strcmp(part, "next_btn"))
389      return _title_next_btn_unset(navi_it);
390    else if (!strcmp(part, "icon"))
391      return _title_icon_unset(navi_it);
392
393    return _title_content_unset(navi_it, part);
394 }
395
396 static void
397 _item_signal_emit_hook(Elm_Object_Item *it,
398                        const char *emission,
399                        const char *source)
400 {
401    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
402    Elm_Naviframe_Item *navi_it = (Elm_Naviframe_Item *) it;
403    edje_object_signal_emit(VIEW(navi_it), emission, source);
404 }
405
406 static void
407 _item_title_visible_update(Elm_Naviframe_Item *navi_it)
408 {
409    if (navi_it->title_visible)
410      edje_object_signal_emit(VIEW(navi_it), "elm,state,title,show", "elm");
411    else
412      edje_object_signal_emit(VIEW(navi_it), "elm,state,title,hide", "elm");
413 }
414
415 static void
416 _sizing_eval(Evas_Object *obj)
417 {
418    Widget_Data *wd;
419    Elm_Naviframe_Item *it;
420    Evas_Coord x, y, w, h;
421    Evas_Coord minw = -1, minh = -1;
422
423    wd = elm_widget_data_get(obj);
424    if (!wd) return;
425
426    EINA_INLIST_FOREACH(wd->stack, it)
427      {
428         evas_object_geometry_get(WIDGET(it), &x, &y, &w, &h);
429         evas_object_move(VIEW(it), x, y);
430         evas_object_resize(VIEW(it), w, h);
431         edje_object_size_min_calc(VIEW(it), &it->minw, &it->minh);
432         if (it->minw > minw) minw = it->minw;
433         if (it->minh > minh) minh = it->minh;
434      }
435    evas_object_size_hint_min_set(obj, minw, minh);
436    evas_object_size_hint_max_set(obj, -1, -1);
437 }
438
439 static void
440 _move(void *data __UNUSED__,
441       Evas *e __UNUSED__,
442       Evas_Object *obj,
443       void *event_info __UNUSED__)
444 {
445    _sizing_eval(obj);
446 }
447
448 static void
449 _resize(void *data __UNUSED__,
450         Evas *e __UNUSED__,
451         Evas_Object *obj,
452         void *event_info __UNUSED__)
453 {
454    _sizing_eval(obj);
455 }
456
457 static void
458 _title_clicked(void *data,
459                Evas_Object *obj __UNUSED__,
460                const char *emission __UNUSED__,
461                const char *source __UNUSED__)
462 {
463    Elm_Naviframe_Item *it = data;
464    evas_object_smart_callback_call(WIDGET(it), SIG_TITLE_CLICKED, it);
465 }
466
467 static void
468 _back_btn_clicked(void *data,
469                   Evas_Object *obj,
470                   void *event_info __UNUSED__)
471 {
472 /* Since edje has the event queue, clicked event could be happend multiple times
473    on some heavy environment. This callback del will prevent those  scenario and
474    guarantee only one clicked for it's own page. */
475    evas_object_smart_callback_del(obj, "clicked", _back_btn_clicked);
476    elm_naviframe_item_pop(data);
477 }
478
479 static Evas_Object *
480 _back_btn_new(Evas_Object *obj)
481 {
482    Evas_Object *btn;
483    char buf[1024];
484    btn = elm_button_add(obj);
485    if (!btn) return NULL;
486    evas_object_smart_callback_add(btn, "clicked", _back_btn_clicked, obj);
487    snprintf(buf, sizeof(buf), "naviframe/back_btn/%s", elm_widget_style_get(obj));
488    elm_object_style_set(btn, buf);
489    return btn;
490 }
491
492 static void
493 _title_content_del(void *data,
494                    Evas *e __UNUSED__,
495                    Evas_Object *obj __UNUSED__,
496                    void *event_info __UNUSED__)
497 {
498    char buf[1024];
499    Elm_Naviframe_Content_Item_Pair *pair = data;
500    Elm_Naviframe_Item *it = pair->it;
501    snprintf(buf, sizeof(buf), "elm,state,%s,hide", pair->part);
502    edje_object_signal_emit(VIEW(it), buf, "elm");
503    it->content_list = eina_inlist_remove(it->content_list,
504                                          EINA_INLIST_GET(pair));
505    eina_stringshare_del(pair->part);
506    free(pair);
507 }
508
509 static void
510 _title_prev_btn_del(void *data,
511                     Evas *e __UNUSED__,
512                     Evas_Object *obj __UNUSED__,
513                     void *event_info __UNUSED__)
514 {
515    Elm_Naviframe_Item *it = data;
516    it->back_btn = EINA_FALSE;
517    it->title_prev_btn = NULL;
518    edje_object_signal_emit(VIEW(it), "elm,state,prev_btn,hide", "elm");
519 }
520
521 static void
522 _title_next_btn_del(void *data,
523                     Evas *e __UNUSED__,
524                     Evas_Object *obj __UNUSED__,
525                     void *event_info __UNUSED__)
526 {
527    Elm_Naviframe_Item *it = data;
528    it->title_next_btn = NULL;
529    edje_object_signal_emit(VIEW(it), "elm,state,next_btn,hide", "elm");
530 }
531
532 static void
533 _title_icon_del(void *data,
534                 Evas *e __UNUSED__,
535                 Evas_Object *obj __UNUSED__,
536                 void *event_info __UNUSED__)
537 {
538    Elm_Naviframe_Item *it = data;
539    it->title_icon = NULL;
540    edje_object_signal_emit(VIEW(it), "elm,state,icon,hide", "elm");
541 }
542
543 static void
544 _item_content_del(void *data,
545                   Evas *e __UNUSED__,
546                   Evas_Object *obj __UNUSED__,
547                   void *event_info __UNUSED__)
548 {
549    Elm_Naviframe_Item *it = data;
550    it->content = NULL;
551    edje_object_signal_emit(VIEW(it), "elm,state,content,hide", "elm");
552 }
553
554 static void
555 _title_content_set(Elm_Naviframe_Item *it,
556                    const char *part,
557                    Evas_Object *content)
558 {
559    char buf[1024];
560    Elm_Naviframe_Content_Item_Pair *pair = NULL;
561
562    EINA_INLIST_FOREACH(it->content_list, pair)
563      if (!strcmp(part, pair->part)) break;
564
565    if (!pair)
566      {
567         if (!content) return;
568         pair = ELM_NEW(Elm_Naviframe_Content_Item_Pair);
569         if (!pair)
570           {
571              ERR("Failed to allocate new content part of the item! : naviframe=%p", WIDGET(it));
572              return;
573           }
574         pair->it = it;
575         eina_stringshare_replace(&pair->part, part);
576         it->content_list = eina_inlist_append(it->content_list,
577                                               EINA_INLIST_GET(pair));
578      }
579    if (pair->content && (pair->content != content))
580      {
581         evas_object_event_callback_del(pair->content,
582                                        EVAS_CALLBACK_DEL,
583                                        _title_content_del);
584         evas_object_event_callback_del(pair->content,
585                                        EVAS_CALLBACK_CHANGED_SIZE_HINTS,
586                                        _changed_size_hints);
587         evas_object_del(pair->content);
588         snprintf(buf, sizeof(buf), "elm,state,%s,hide", part);
589         edje_object_signal_emit(VIEW(it), buf, "elm");
590      }
591    if (content)
592      {
593         if (pair->content != content)
594           {
595              elm_widget_sub_object_add(WIDGET(it), content);
596              evas_object_event_callback_add(content,
597                                             EVAS_CALLBACK_DEL,
598                                             _title_content_del,
599                                             pair);
600              evas_object_event_callback_add(content,
601                                             EVAS_CALLBACK_CHANGED_SIZE_HINTS,
602                                             _changed_size_hints,
603                                             WIDGET(it));
604              pair->content = content;
605           }
606         edje_object_part_swallow(VIEW(it), part, content);
607         snprintf(buf, sizeof(buf), "elm,state,%s,show", part);
608         edje_object_signal_emit(VIEW(it), buf, "elm");
609      }
610
611    _sizing_eval(WIDGET(it));
612 }
613
614 static void
615 _title_prev_btn_set(Elm_Naviframe_Item *it,
616                     Evas_Object *btn,
617                     Eina_Bool back_btn)
618 {
619    if (it->title_prev_btn == btn) return;
620
621    if (it->title_prev_btn)
622      evas_object_del(it->title_prev_btn);
623
624    it->title_prev_btn = btn;
625    if (!btn) return;
626
627    elm_widget_sub_object_add(WIDGET(it), btn);
628    evas_object_event_callback_add(btn,
629                                   EVAS_CALLBACK_DEL,
630                                   _title_prev_btn_del,
631                                   it);
632    evas_object_event_callback_add(btn,
633                                   EVAS_CALLBACK_CHANGED_SIZE_HINTS,
634                                   _changed_size_hints,
635                                   WIDGET(it));
636    edje_object_part_swallow(VIEW(it), "elm.swallow.prev_btn", btn);
637    edje_object_signal_emit(VIEW(it), "elm,state,prev_btn,show", "elm");
638    it->back_btn = back_btn;
639
640    _sizing_eval(WIDGET(it));
641 }
642
643 static void
644 _title_next_btn_set(Elm_Naviframe_Item *it, Evas_Object *btn)
645 {
646    if (it->title_next_btn == btn) return;
647
648    if (it->title_next_btn)
649      evas_object_del(it->title_next_btn);
650
651    it->title_next_btn = btn;
652    if (!btn) return;
653
654    elm_widget_sub_object_add(WIDGET(it), btn);
655    evas_object_event_callback_add(btn,
656                                   EVAS_CALLBACK_DEL,
657                                   _title_next_btn_del,
658                                   it);
659    evas_object_event_callback_add(btn,
660                                   EVAS_CALLBACK_CHANGED_SIZE_HINTS,
661                                   _changed_size_hints,
662                                   WIDGET(it));
663    edje_object_part_swallow(VIEW(it), "elm.swallow.next_btn", btn);
664    edje_object_signal_emit(VIEW(it), "elm,state,next_btn,show", "elm");
665
666    _sizing_eval(WIDGET(it));
667 }
668
669 static void
670 _title_icon_set(Elm_Naviframe_Item *it, Evas_Object *icon)
671 {
672    if (it->title_icon == icon) return;
673
674    if (it->title_icon)
675      evas_object_del(it->title_icon);
676
677    it->title_icon = icon;
678    if (!icon) return;
679
680    elm_widget_sub_object_add(WIDGET(it), icon);
681    evas_object_event_callback_add(icon,
682                                   EVAS_CALLBACK_DEL,
683                                   _title_icon_del,
684                                   it);
685    evas_object_event_callback_add(icon,
686                                   EVAS_CALLBACK_CHANGED_SIZE_HINTS,
687                                   _changed_size_hints,
688                                   WIDGET(it));
689    edje_object_part_swallow(VIEW(it), "elm.swallow.icon", icon);
690    edje_object_signal_emit(VIEW(it), "elm,state,icon,show", "elm");
691
692    _sizing_eval(WIDGET(it));
693 }
694
695 static Evas_Object *
696 _item_content_unset(Elm_Naviframe_Item *it)
697 {
698    Evas_Object *content = it->content;
699    if (!content) return NULL;
700
701    elm_widget_sub_object_del(WIDGET(it), content);
702    edje_object_part_unswallow(VIEW(it), content);
703    edje_object_signal_emit(VIEW(it), "elm,state,content,hide", "elm");
704    evas_object_event_callback_del(content,
705                                   EVAS_CALLBACK_DEL,
706                                   _item_content_del);
707    evas_object_event_callback_del(content,
708                                   EVAS_CALLBACK_CHANGED_SIZE_HINTS,
709                                   _changed_size_hints);
710    _sizing_eval(WIDGET(it));
711
712    it->content = NULL;
713    return content;
714 }
715
716 static Evas_Object *
717 _title_prev_btn_unset(Elm_Naviframe_Item *it)
718 {
719    Evas_Object *content = it->title_prev_btn;
720    if (!content) return NULL;
721
722    elm_widget_sub_object_del(WIDGET(it), content);
723    edje_object_part_unswallow(VIEW(it), content);
724    edje_object_signal_emit(VIEW(it), "elm,state,prev_btn,hide", "elm");
725    evas_object_event_callback_del(content,
726                                   EVAS_CALLBACK_DEL,
727                                   _title_prev_btn_del);
728    evas_object_event_callback_del(content,
729                                   EVAS_CALLBACK_CHANGED_SIZE_HINTS,
730                                   _changed_size_hints);
731    _sizing_eval(WIDGET(it));
732
733    it->title_prev_btn = NULL;
734    return content;
735 }
736
737 static Evas_Object *
738 _title_next_btn_unset(Elm_Naviframe_Item *it)
739 {
740    Evas_Object *content = it->title_next_btn;
741    if (!content) return NULL;
742
743    elm_widget_sub_object_del(WIDGET(it), content);
744    edje_object_part_unswallow(VIEW(it), content);
745    edje_object_signal_emit(VIEW(it), "elm,state,next_btn,hide", "elm");
746    evas_object_event_callback_del(content,
747                                   EVAS_CALLBACK_DEL,
748                                   _title_next_btn_del);
749    evas_object_event_callback_del(content,
750                                   EVAS_CALLBACK_CHANGED_SIZE_HINTS,
751                                   _changed_size_hints);
752    _sizing_eval(WIDGET(it));
753
754    it->title_next_btn = NULL;
755    return content;
756 }
757
758 static Evas_Object *
759 _title_icon_unset(Elm_Naviframe_Item *it)
760 {
761    Evas_Object *content = it->title_icon;
762    if (!content) return NULL;
763
764    elm_widget_sub_object_del(WIDGET(it), content);
765    edje_object_part_unswallow(VIEW(it), content);
766    edje_object_signal_emit(VIEW(it), "elm,state,icon,hide", "elm");
767    evas_object_event_callback_del(content,
768                                   EVAS_CALLBACK_DEL,
769                                   _title_icon_del);
770    evas_object_event_callback_del(content,
771                                   EVAS_CALLBACK_CHANGED_SIZE_HINTS,
772                                   _changed_size_hints);
773    _sizing_eval(WIDGET(it));
774    it->title_icon = NULL;
775
776    return content;
777 }
778
779 static Evas_Object *
780 _title_content_unset(Elm_Naviframe_Item *it, const char *part)
781 {
782    Elm_Naviframe_Content_Item_Pair *pair = NULL;
783    char buf[1028];
784    Evas_Object *content = NULL;
785
786    EINA_INLIST_FOREACH(it->content_list, pair)
787      {
788         if (!strcmp(part, pair->part))
789           {
790              content = pair->content;
791              eina_stringshare_del(pair->part);
792              it->content_list = eina_inlist_remove(it->content_list,
793                                                    EINA_INLIST_GET(pair));
794              free(pair);
795              break;
796           }
797      }
798
799    if (!content) return NULL;
800
801    elm_widget_sub_object_del(WIDGET(it), content);
802    edje_object_part_unswallow(VIEW(it), content);
803    snprintf(buf, sizeof(buf), "elm,state,%s,hide", part);
804    edje_object_signal_emit(VIEW(it), buf, "elm");
805    evas_object_event_callback_del(content,
806                                   EVAS_CALLBACK_DEL,
807                                   _title_content_del);
808    evas_object_event_callback_del(content,
809                                   EVAS_CALLBACK_CHANGED_SIZE_HINTS,
810                                   _changed_size_hints);
811    _sizing_eval(WIDGET(it));
812
813    return content;
814 }
815
816
817 static void
818 _item_del(Elm_Naviframe_Item *it)
819 {
820    Widget_Data *wd;
821    Elm_Naviframe_Content_Item_Pair *content_pair;
822    Elm_Naviframe_Text_Item_Pair *text_pair;
823
824    if (!it) return;
825
826    wd = elm_widget_data_get(WIDGET(it));
827    if (!wd) return;
828
829    if (it->title_prev_btn)
830      evas_object_del(it->title_prev_btn);
831    if (it->title_next_btn)
832      evas_object_del(it->title_next_btn);
833    if (it->title_icon)
834      evas_object_del(it->title_icon);
835    if ((it->content) && (!wd->preserve))
836      evas_object_del(it->content);
837
838    while (it->content_list)
839      {
840         content_pair = EINA_INLIST_CONTAINER_GET(it->content_list,
841                                                  Elm_Naviframe_Content_Item_Pair);
842         evas_object_event_callback_del(content_pair->content,
843                                        EVAS_CALLBACK_DEL,
844                                        _title_content_del);
845         evas_object_event_callback_del(content_pair->content,
846                                        EVAS_CALLBACK_CHANGED_SIZE_HINTS,
847                                        _changed_size_hints);
848         evas_object_del(content_pair->content);
849         eina_stringshare_del(content_pair->part);
850         it->content_list = eina_inlist_remove(it->content_list,
851                                               it->content_list);
852         free(content_pair);
853      }
854
855    while (it->text_list)
856      {
857         text_pair = EINA_INLIST_CONTAINER_GET(it->text_list,
858                                               Elm_Naviframe_Text_Item_Pair);
859         eina_stringshare_del(text_pair->part);
860         eina_stringshare_del(text_pair->text);
861         it->text_list = eina_inlist_remove(it->text_list,
862                                            it->text_list);
863         free(text_pair);
864      }
865
866    eina_stringshare_del(it->style);
867
868    elm_widget_item_del(it);
869 }
870
871 static void
872 _pushed_finished(void *data,
873                  Evas_Object *obj __UNUSED__,
874                  const char *emission __UNUSED__,
875                  const char *source __UNUSED__)
876 {
877    Widget_Data *wd;
878    Elm_Naviframe_Item *it = data;
879    if (!it) return;
880
881    wd = elm_widget_data_get(WIDGET(it));
882    if (!wd) return;
883
884    evas_object_hide(VIEW(it));
885    evas_object_smart_callback_call(WIDGET(it),
886                                    SIG_PUSH_FINISHED,
887                                    data);
888    if (wd->freeze_events)
889      evas_object_freeze_events_set(VIEW(it), EINA_FALSE);
890 }
891
892 static void
893 _popped_finished(void *data,
894                  Evas_Object *obj __UNUSED__,
895                  const char *emission __UNUSED__,
896                  const char *source __UNUSED__)
897 {
898    Elm_Naviframe_Item *it = data;
899    if (!it) return;
900    evas_object_smart_callback_call(WIDGET(it),
901                                    SIG_POP_FINISHED,
902                                    data);
903    _item_del(data);
904 }
905
906 static void
907 _show_finished(void *data,
908                Evas_Object *obj __UNUSED__,
909                const char *emission __UNUSED__,
910                const char *source __UNUSED__)
911 {
912    Elm_Naviframe_Item *it;
913    Widget_Data *wd;
914
915    it = data;
916    if (!it) return;
917    wd =  elm_widget_data_get(WIDGET(it));
918    if (!wd) return;
919
920    evas_object_smart_callback_call(WIDGET(it),
921                                    SIG_TRANSITION_FINISHED,
922                                    data);
923    if (wd->freeze_events)
924      evas_object_freeze_events_set(VIEW(it), EINA_FALSE);
925 }
926
927 static void
928 _changed_size_hints(void *data,
929                     Evas *e __UNUSED__,
930                     Evas_Object *obj __UNUSED__,
931                     void *event_info __UNUSED__)
932 {
933    _sizing_eval(data);
934 }
935
936 static void
937 _item_content_set(Elm_Naviframe_Item *navi_it, Evas_Object *content)
938 {
939    if (navi_it->content == content) return;
940    if (navi_it->content) evas_object_del(navi_it->content);
941    elm_widget_sub_object_add(WIDGET(navi_it), content);
942    edje_object_part_swallow(VIEW(navi_it),
943                             "elm.swallow.content",
944                             content);
945    if (content)
946      edje_object_signal_emit(VIEW(navi_it),
947                              "elm,state,content,show",
948                              "elm");
949    else
950      edje_object_signal_emit(VIEW(navi_it),
951                              "elm,state,content,hide",
952                              "elm");
953    evas_object_event_callback_add(content,
954                                   EVAS_CALLBACK_DEL,
955                                   _item_content_del,
956                                   navi_it);
957    evas_object_event_callback_add(content,
958                                   EVAS_CALLBACK_CHANGED_SIZE_HINTS,
959                                   _changed_size_hints,
960                                   WIDGET(navi_it));
961    navi_it->content = content;
962    _sizing_eval(WIDGET(navi_it));
963 }
964
965 //FIXME: need to handle if this function is called while transition
966 static void
967 _item_style_set(Elm_Naviframe_Item *navi_it, const char *item_style)
968 {
969    Elm_Naviframe_Content_Item_Pair *content_pair;
970    Elm_Naviframe_Text_Item_Pair *text_pair;
971    Widget_Data *wd;
972
973    char buf[256];
974
975    if (!item_style)
976      {
977         sprintf(buf, "item/basic");
978         eina_stringshare_replace(&navi_it->style, "basic");
979      }
980    else
981      {
982         if (strlen(item_style) > sizeof(buf))
983           WRN("too much long style name! : naviframe=%p", WIDGET(navi_it));
984         sprintf(buf, "item/%s", item_style);
985         eina_stringshare_replace(&navi_it->style, item_style);
986      }
987    _elm_theme_object_set(WIDGET(navi_it),
988                          VIEW(navi_it),
989                          "naviframe",
990                          buf,
991                          elm_widget_style_get(WIDGET(navi_it)));
992    //recover item
993    EINA_INLIST_FOREACH(navi_it->text_list, text_pair)
994       _item_text_set_hook((Elm_Object_Item *) navi_it,
995                           text_pair->part,
996                           text_pair->text);
997
998    EINA_INLIST_FOREACH(navi_it->content_list, content_pair)
999       _item_content_set_hook((Elm_Object_Item *) navi_it,
1000                              content_pair->part,
1001                              content_pair->content);
1002    //content
1003    if (navi_it->content)
1004      {
1005         edje_object_part_swallow(VIEW(navi_it),
1006                                  "elm.swallow.content",
1007                                  navi_it->content);
1008         edje_object_signal_emit(VIEW(navi_it),
1009                                 "elm,state,content,show",
1010                                 "elm");
1011      }
1012
1013    //prev button
1014    if (navi_it->title_prev_btn)
1015      {
1016         edje_object_part_swallow(VIEW(navi_it),
1017                                  "elm.swallow.prev_btn",
1018                                  navi_it->title_prev_btn);
1019         edje_object_signal_emit(VIEW(navi_it),
1020                                 "elm,state,prev_btn,show",
1021                                 "elm");
1022      }
1023
1024    //next button
1025    if (navi_it->title_next_btn)
1026      {
1027         edje_object_part_swallow(VIEW(navi_it),
1028                                  "elm.swallow.next_btn",
1029                                  navi_it->title_next_btn);
1030         edje_object_signal_emit(VIEW(navi_it),
1031                                 "elm,state,next_btn,show",
1032                                 "elm");
1033      }
1034
1035    navi_it->title_visible = EINA_TRUE;
1036    _sizing_eval(WIDGET(navi_it));
1037
1038    wd = elm_widget_data_get(WIDGET(navi_it));
1039    if (!wd) return;
1040
1041    if (wd->freeze_events)
1042      evas_object_freeze_events_set(VIEW(navi_it), EINA_FALSE);
1043 }
1044
1045 static Elm_Naviframe_Item *
1046 _item_new(Evas_Object *obj,
1047           const char *title_label,
1048           Evas_Object *prev_btn,
1049           Evas_Object *next_btn,
1050           Evas_Object *content,
1051           const char *item_style)
1052 {
1053    Widget_Data *wd = elm_widget_data_get(obj);
1054
1055    //create item
1056    Elm_Naviframe_Item *it = elm_widget_item_new(obj, Elm_Naviframe_Item);
1057    if (!it)
1058      {
1059         ERR("Failed to allocate new item! : naviframe=%p", obj);
1060         return NULL;
1061      }
1062
1063    elm_widget_item_text_set_hook_set(it, _item_text_set_hook);
1064    elm_widget_item_text_get_hook_set(it, _item_text_get_hook);
1065    elm_widget_item_content_set_hook_set(it, _item_content_set_hook);
1066    elm_widget_item_content_get_hook_set(it, _item_content_get_hook);
1067    elm_widget_item_content_unset_hook_set(it, _item_content_unset_hook);
1068    elm_widget_item_signal_emit_hook_set(it, _item_signal_emit_hook);
1069
1070    //item base layout
1071    VIEW(it) = edje_object_add(evas_object_evas_get(obj));
1072    edje_object_mirrored_set(VIEW(it), elm_widget_mirrored_get(obj));
1073    evas_object_smart_member_add(VIEW(it), wd->base);
1074    elm_widget_sub_object_add(obj, VIEW(it));
1075    edje_object_signal_callback_add(VIEW(it),
1076                                    "elm,action,show,finished",
1077                                    "",
1078                                    _show_finished, it);
1079    edje_object_signal_callback_add(VIEW(it),
1080                                    "elm,action,pushed,finished",
1081                                    "",
1082                                    _pushed_finished, it);
1083    edje_object_signal_callback_add(VIEW(it),
1084                                    "elm,action,popped,finished",
1085                                    "",
1086                                    _popped_finished, it);
1087    edje_object_signal_callback_add(VIEW(it),
1088                                    "elm,action,title,clicked",
1089                                    "",
1090                                    _title_clicked, it);
1091
1092    _item_style_set(it, item_style);
1093    _item_text_set_hook((Elm_Object_Item *) it, "elm.text.title", title_label);
1094
1095    //title buttons
1096    if ((!prev_btn) && wd->auto_pushed && eina_inlist_count(wd->stack))
1097      {
1098         prev_btn = _back_btn_new(obj);
1099         _title_prev_btn_set(it, prev_btn, EINA_TRUE);
1100      }
1101    else
1102      _title_prev_btn_set(it, prev_btn, EINA_FALSE);
1103
1104    _title_next_btn_set(it, next_btn);
1105    _item_content_set(it, content);
1106    it->title_visible = EINA_TRUE;
1107    return it;
1108 }
1109
1110 EAPI Evas_Object *
1111 elm_naviframe_add(Evas_Object *parent)
1112 {
1113    Evas_Object *obj;
1114    Evas *e;
1115    Widget_Data *wd;
1116
1117    ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
1118    ELM_SET_WIDTYPE(widtype, "naviframe");
1119    elm_widget_type_set(obj, "naviframe");
1120    elm_widget_sub_object_add(parent, obj);
1121    elm_widget_data_set(obj, wd);
1122    elm_widget_del_hook_set(obj, _del_hook);
1123    elm_widget_disable_hook_set(obj, _disable_hook);
1124    elm_widget_theme_hook_set(obj, _theme_hook);
1125    elm_widget_signal_emit_hook_set(obj, _emit_hook);
1126
1127    //base
1128    wd->base = edje_object_add(e);
1129    edje_object_mirrored_set(wd->base, elm_widget_mirrored_get(obj));
1130    elm_widget_resize_object_set(obj, wd->base);
1131    _elm_theme_object_set(obj, wd->base, "naviframe", "base", "default");
1132
1133    evas_object_event_callback_add(obj, EVAS_CALLBACK_MOVE, _move, obj);
1134    evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE, _resize, obj);
1135    evas_object_smart_callbacks_descriptions_set(obj, _signals);
1136
1137    wd->auto_pushed = EINA_TRUE;
1138    wd->freeze_events = EINA_TRUE;
1139
1140    return obj;
1141 }
1142
1143 EAPI Elm_Object_Item *
1144 elm_naviframe_item_push(Evas_Object *obj,
1145                         const char *title_label,
1146                         Evas_Object *prev_btn,
1147                         Evas_Object *next_btn,
1148                         Evas_Object *content,
1149                         const char *item_style)
1150 {
1151    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1152    Widget_Data *wd;
1153    Elm_Naviframe_Item *prev_it, *it;
1154
1155    wd = elm_widget_data_get(obj);
1156    if (!wd) return NULL;
1157
1158    it = _item_new(obj, title_label, prev_btn, next_btn, content, item_style);
1159    if (!it) return NULL;
1160
1161    evas_object_show(VIEW(it));
1162
1163    prev_it = (Elm_Naviframe_Item *) elm_naviframe_top_item_get(obj);
1164    if (prev_it)
1165      {
1166         if (wd->freeze_events)
1167           {
1168              evas_object_freeze_events_set(VIEW(it), EINA_TRUE);
1169              evas_object_freeze_events_set(VIEW(prev_it), EINA_TRUE);
1170           }
1171         edje_object_signal_emit(VIEW(prev_it),
1172                                 "elm,state,cur,pushed",
1173                                 "elm");
1174         edje_object_signal_emit(VIEW(it),
1175                                 "elm,state,new,pushed",
1176                                 "elm");
1177         edje_object_message_signal_process(VIEW(prev_it));
1178         edje_object_message_signal_process(VIEW(it));
1179      }
1180    wd->stack = eina_inlist_append(wd->stack, EINA_INLIST_GET(it));
1181    _sizing_eval(obj);
1182    return (Elm_Object_Item *) it;
1183 }
1184
1185 EAPI Elm_Object_Item *
1186 elm_naviframe_item_insert_before(Elm_Object_Item *before,
1187                                  const char *title_label,
1188                                  Evas_Object *prev_btn,
1189                                  Evas_Object *next_btn,
1190                                  Evas_Object *content,
1191                                  const char *item_style)
1192 {
1193    ELM_OBJ_ITEM_CHECK_OR_RETURN(before, NULL);
1194    Elm_Naviframe_Item *it;
1195    Widget_Data *wd;
1196
1197    wd = elm_widget_data_get(WIDGET(before));
1198    if (!wd) return NULL;
1199
1200    it = _item_new(WIDGET(before), title_label, prev_btn, next_btn, content,
1201                   item_style);
1202    if (!it) return NULL;
1203
1204    wd->stack =
1205       eina_inlist_prepend_relative(wd->stack, EINA_INLIST_GET(it),
1206                                    EINA_INLIST_GET(((Elm_Naviframe_Item *) before)));
1207    _sizing_eval(WIDGET(before));
1208    return (Elm_Object_Item *) it;
1209 }
1210
1211 EAPI Elm_Object_Item *
1212 elm_naviframe_item_insert_after(Elm_Object_Item *after,
1213                                 const char *title_label,
1214                                 Evas_Object *prev_btn,
1215                                 Evas_Object *next_btn,
1216                                 Evas_Object *content,
1217                                 const char *item_style)
1218 {
1219    ELM_OBJ_ITEM_CHECK_OR_RETURN(after, NULL);
1220    Elm_Naviframe_Item *it;
1221    Widget_Data *wd;
1222
1223    wd = elm_widget_data_get(WIDGET(after));
1224    if (!wd) return NULL;
1225
1226    it = _item_new(WIDGET(after), title_label, prev_btn, next_btn, content,
1227                   item_style);
1228    if (!it) return NULL;
1229
1230    if (elm_naviframe_top_item_get(WIDGET(after)) == after)
1231      {
1232         evas_object_hide(VIEW(after));
1233         evas_object_show(VIEW(it));
1234      }
1235    wd->stack =
1236       eina_inlist_append_relative(wd->stack, EINA_INLIST_GET(it),
1237                                   EINA_INLIST_GET(((Elm_Naviframe_Item *) after)));
1238    _sizing_eval(WIDGET(after));
1239    return (Elm_Object_Item *) it;
1240 }
1241
1242 EAPI Evas_Object *
1243 elm_naviframe_item_pop(Evas_Object *obj)
1244 {
1245    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1246    Elm_Naviframe_Item *it, *prev_it = NULL;
1247    Widget_Data *wd;
1248    Evas_Object *content = NULL;
1249
1250    wd = elm_widget_data_get(obj);
1251    if (!wd) return NULL;
1252
1253    it = (Elm_Naviframe_Item *) elm_naviframe_top_item_get(obj);
1254    if (!it) return NULL;
1255    elm_widget_tree_unfocusable_set(it->content, EINA_TRUE);
1256    if (wd->preserve)
1257      content = it->content;
1258
1259    if (wd->stack->last->prev)
1260      prev_it = EINA_INLIST_CONTAINER_GET(wd->stack->last->prev,
1261                                          Elm_Naviframe_Item);
1262    wd->stack = eina_inlist_remove(wd->stack, EINA_INLIST_GET(it));
1263    if (prev_it)
1264      {
1265         if (wd->freeze_events)
1266           {
1267              evas_object_freeze_events_set(VIEW(it), EINA_TRUE);
1268              evas_object_freeze_events_set(VIEW(prev_it), EINA_TRUE);
1269           }
1270         edje_object_signal_emit(VIEW(it), "elm,state,cur,popped", "elm");
1271         evas_object_show(VIEW(prev_it));
1272         evas_object_raise(VIEW(prev_it));
1273         edje_object_signal_emit(VIEW(prev_it),
1274                                 "elm,state,prev,popped",
1275                                 "elm");
1276         edje_object_message_signal_process(VIEW(it));
1277         edje_object_message_signal_process(VIEW(prev_it));
1278      }
1279    else
1280      _item_del(it);
1281
1282    return content;
1283 }
1284
1285 EAPI void
1286 elm_naviframe_item_pop_to(Elm_Object_Item *it)
1287 {
1288    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1289    Elm_Naviframe_Item *navi_it;
1290    Widget_Data *wd;
1291    Eina_Inlist *l, *prev_l;
1292
1293    navi_it = (Elm_Naviframe_Item *) it;
1294    wd = elm_widget_data_get(WIDGET(navi_it));
1295    if (!wd) return;
1296
1297    if (it == elm_naviframe_top_item_get(WIDGET(navi_it))) return;
1298
1299    l = wd->stack->last->prev;
1300
1301    while(l)
1302      {
1303         if (EINA_INLIST_CONTAINER_GET(l, Elm_Naviframe_Item) ==
1304             ((Elm_Naviframe_Item *) it)) break;
1305         prev_l = l->prev;
1306         wd->stack = eina_inlist_remove(wd->stack, l);
1307         _item_del(EINA_INLIST_CONTAINER_GET(l, Elm_Naviframe_Item));
1308         l = prev_l;
1309      }
1310    elm_naviframe_item_pop(WIDGET(navi_it));
1311 }
1312
1313 EAPI void
1314 elm_naviframe_item_promote(Elm_Object_Item *it)
1315 {
1316    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1317    Elm_Naviframe_Item *navi_it;
1318    Elm_Naviframe_Item *prev_it;
1319    Widget_Data *wd;
1320
1321    navi_it = (Elm_Naviframe_Item *) it;
1322    wd = elm_widget_data_get(navi_it->base.widget);
1323    if (!wd) return;
1324
1325    if (it == elm_naviframe_top_item_get(navi_it->base.widget)) return;
1326    wd->stack = eina_inlist_demote(wd->stack, EINA_INLIST_GET(navi_it));
1327    prev_it = EINA_INLIST_CONTAINER_GET(wd->stack->last->prev,
1328                                          Elm_Naviframe_Item);
1329    if (wd->freeze_events)
1330      {
1331         evas_object_freeze_events_set(VIEW(it), EINA_TRUE);
1332         evas_object_freeze_events_set(VIEW(prev_it), EINA_TRUE);
1333      }
1334    edje_object_signal_emit(VIEW(prev_it),
1335                            "elm,state,cur,pushed",
1336                            "elm");
1337    evas_object_show(VIEW(navi_it));
1338    evas_object_raise(VIEW(navi_it));
1339    edje_object_signal_emit(VIEW(navi_it),
1340                            "elm,state,new,pushed",
1341                            "elm");
1342    edje_object_message_signal_process(VIEW(prev_it));
1343    edje_object_message_signal_process(VIEW(navi_it));
1344 }
1345
1346 EAPI void
1347 elm_naviframe_item_del(Elm_Object_Item *it)
1348 {
1349    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1350    Elm_Naviframe_Item *navi_it;
1351    Widget_Data *wd;
1352
1353    navi_it =(Elm_Naviframe_Item *) it;
1354    wd = elm_widget_data_get(WIDGET(navi_it));
1355    if (!wd) return;
1356
1357    if (it == elm_naviframe_top_item_get(WIDGET(navi_it)))
1358      {
1359         wd->stack = eina_inlist_remove(wd->stack, EINA_INLIST_GET(navi_it));
1360         _item_del(navi_it);
1361         navi_it = EINA_INLIST_CONTAINER_GET(wd->stack->last,
1362                                             Elm_Naviframe_Item);
1363         evas_object_show(VIEW(navi_it));
1364         evas_object_raise(VIEW(navi_it));
1365         edje_object_signal_emit(VIEW(navi_it), "elm,state,visible", "elm");
1366      }
1367    else
1368      {
1369         wd->stack = eina_inlist_remove(wd->stack, EINA_INLIST_GET(navi_it));
1370         _item_del(navi_it);
1371      }
1372 }
1373
1374 EAPI void
1375 elm_naviframe_content_preserve_on_pop_set(Evas_Object *obj, Eina_Bool preserve)
1376 {
1377    ELM_CHECK_WIDTYPE(obj, widtype);
1378    Widget_Data *wd = elm_widget_data_get(obj);
1379    if (!wd) return;
1380    wd->preserve = !!preserve;
1381 }
1382
1383 EAPI Eina_Bool
1384 elm_naviframe_content_preserve_on_pop_get(const Evas_Object *obj)
1385 {
1386    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1387    Widget_Data *wd = elm_widget_data_get(obj);
1388    if (!wd) return EINA_FALSE;
1389    return wd->preserve;
1390 }
1391
1392 EAPI Elm_Object_Item*
1393 elm_naviframe_top_item_get(const Evas_Object *obj)
1394 {
1395    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1396    Widget_Data *wd = elm_widget_data_get(obj);
1397    if ((!wd) || (!wd->stack)) return NULL;
1398    return (Elm_Object_Item *) (EINA_INLIST_CONTAINER_GET(wd->stack->last,
1399                                                          Elm_Naviframe_Item));
1400 }
1401
1402 EAPI Elm_Object_Item*
1403 elm_naviframe_bottom_item_get(const Evas_Object *obj)
1404 {
1405    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1406    Widget_Data *wd = elm_widget_data_get(obj);
1407    if ((!wd) || (!wd->stack)) return NULL;
1408    return (Elm_Object_Item *) (EINA_INLIST_CONTAINER_GET(wd->stack,
1409                                                          Elm_Naviframe_Item));
1410 }
1411
1412 EAPI void
1413 elm_naviframe_item_style_set(Elm_Object_Item *it, const char *item_style)
1414 {
1415    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1416    Elm_Naviframe_Item *navi_it = (Elm_Naviframe_Item *) it;
1417
1418    //Return if new style is exsiting one.
1419    if (item_style)
1420      if (!strcmp(item_style, navi_it->style)) return;
1421
1422    if (!item_style)
1423      if (!strcmp("basic", navi_it->style)) return;
1424
1425    _item_style_set(navi_it, item_style);
1426 }
1427
1428 EAPI const char *
1429 elm_naviframe_item_style_get(const Elm_Object_Item *it)
1430 {
1431    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
1432    Elm_Naviframe_Item *navi_it = (Elm_Naviframe_Item *) it;
1433    return navi_it->style;
1434 }
1435
1436 EAPI void
1437 elm_naviframe_item_title_visible_set(Elm_Object_Item *it, Eina_Bool visible)
1438 {
1439    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1440    Elm_Naviframe_Item *navi_it = (Elm_Naviframe_Item *) it;
1441
1442    visible = !!visible;
1443    if (navi_it->title_visible == visible) return;
1444
1445    navi_it->title_visible = visible;
1446    _item_title_visible_update(navi_it);
1447 }
1448
1449 EAPI Eina_Bool
1450 elm_naviframe_item_title_visible_get(const Elm_Object_Item *it)
1451 {
1452    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
1453    Elm_Naviframe_Item *navi_it = (Elm_Naviframe_Item *) it;
1454    return navi_it->title_visible;
1455 }
1456
1457 EAPI void
1458 elm_naviframe_prev_btn_auto_pushed_set(Evas_Object *obj, Eina_Bool auto_pushed)
1459 {
1460    ELM_CHECK_WIDTYPE(obj, widtype);
1461    Widget_Data *wd = elm_widget_data_get(obj);
1462    if (!wd) return;
1463    wd->auto_pushed = !!auto_pushed;
1464 }
1465
1466 EAPI Eina_Bool
1467 elm_naviframe_prev_btn_auto_pushed_get(const Evas_Object *obj)
1468 {
1469    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1470    Widget_Data *wd = elm_widget_data_get(obj);
1471    if (!wd) return EINA_FALSE;
1472    return wd->auto_pushed;
1473 }
1474
1475 EAPI Eina_Inlist *
1476 elm_naviframe_items_get(const Evas_Object *obj)
1477 {
1478    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1479    Widget_Data *wd = elm_widget_data_get(obj);
1480    if (!wd) return NULL;
1481    return wd->stack;
1482 }
1483
1484 EAPI void
1485 elm_naviframe_event_enabled_set(Evas_Object *obj, Eina_Bool enabled)
1486 {
1487    ELM_CHECK_WIDTYPE(obj, widtype);
1488    Widget_Data *wd = elm_widget_data_get(obj);
1489    if (!wd) return;
1490    enabled = !!enabled;
1491    if (wd->freeze_events == !enabled) return;
1492    wd->freeze_events = !enabled;
1493 }
1494
1495 EAPI Eina_Bool
1496 elm_naviframe_event_enabled_get(const Evas_Object *obj)
1497 {
1498    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1499    Widget_Data *wd = elm_widget_data_get(obj);
1500    if (!wd) return EINA_FALSE;
1501    return !wd->freeze_events;
1502 }