1 #include <Elementary.h>
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;
13 Eina_Bool preserve: 1;
14 Eina_Bool pass_events: 1;
17 struct _Elm_Naviframe_Content_Item_Pair
21 Elm_Naviframe_Item *it;
24 struct _Elm_Naviframe_Text_Item_Pair
30 struct _Elm_Naviframe_Item
34 Eina_List *content_list;
37 Evas_Object *title_prev_btn;
38 Evas_Object *title_next_btn;
40 Eina_Bool back_btn: 1;
41 Eina_Bool title_visible: 1;
44 static const char *widtype = NULL;
46 static const char SIG_TRANSITION_FINISHED[] = "transition,finished";
47 static const char SIG_TITLE_CLICKED[] = "title,clicked";
49 static const Evas_Smart_Cb_Description _signals[] = {
50 {SIG_TRANSITION_FINISHED, ""},
51 {SIG_TITLE_CLICKED, ""},
55 static void _del_hook(Evas_Object *obj);
56 static void _theme_hook(Evas_Object *obj);
57 static void _disable_hook(Evas_Object *obj);
58 static void _text_set_hook(Elm_Object_Item *it,
61 static const char *_text_get_hook(const Elm_Object_Item *it,
63 static void _content_set_hook(Elm_Object_Item *it,
65 Evas_Object *content);
66 static Evas_Object *_content_get_hook(const Elm_Object_Item *it,
68 static Evas_Object *_content_unset_hook(Elm_Object_Item *it,
70 static void _sizing_eval(Evas_Object *obj);
71 static void _item_sizing_eval(Elm_Naviframe_Item *it);
72 static void _move(void *data, Evas *e, Evas_Object *obj, void *event_info);
73 static void _resize(void *data,
77 static void _title_clicked(void *data, Evas_Object *obj,
80 static void _back_btn_clicked(void *data,
83 static Evas_Object *_back_btn_new(Evas_Object *obj);
84 static void _item_content_del(void *data,
88 static void _title_content_del(void *data,
92 static void _title_prev_btn_del(void *data,
96 static void _title_next_btn_del(void *data,
100 static void _title_content_set(Elm_Naviframe_Item *it,
101 Elm_Naviframe_Content_Item_Pair *pair,
103 Evas_Object *content);
104 static void _title_prev_btn_set(Elm_Naviframe_Item *it,
107 static void _title_next_btn_set(Elm_Naviframe_Item *it, Evas_Object *btn);
108 static void _item_del(Elm_Naviframe_Item *it);
109 static void _pushed_finished(void *data,
111 const char *emission,
113 static void _popped_finished(void *data,
115 const char *emission,
117 static void _show_finished(void *data,
119 const char *emission,
121 static void _item_content_set(Elm_Naviframe_Item *navi_it,
122 Evas_Object *content);
125 _del_hook(Evas_Object *obj)
129 Elm_Naviframe_Item *it;
131 wd = elm_widget_data_get(obj);
134 EINA_LIST_FOREACH(wd->stack, list, it)
136 eina_list_free(wd->stack);
141 _theme_hook(Evas_Object *obj __UNUSED__)
147 _disable_hook(Evas_Object *obj __UNUSED__)
153 _text_set_hook(Elm_Object_Item *it, const char *part, const char *label)
155 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
158 Elm_Naviframe_Text_Item_Pair *pair = NULL;
159 Elm_Naviframe_Item *navi_it = ELM_CAST(it);
164 EINA_LIST_FOREACH(navi_it->text_list, l, pair)
166 if (!strcmp(part, pair->part))
170 if (!strcmp(pair->text, label))
179 pair = ELM_NEW(Elm_Naviframe_Text_Item_Pair);
182 ERR("Failed to allocate new text part of the item! : naviframe=%p", navi_it->base.widget);
185 eina_stringshare_replace(&pair->part, part);
186 navi_it->text_list = eina_list_append(navi_it->text_list, pair);
189 eina_stringshare_replace(&pair->text, label);
190 edje_object_part_text_set(navi_it->title, part, label);
192 snprintf(buf, sizeof(buf), "elm,state,%s,show", part);
195 edje_object_signal_emit(navi_it->title, buf, "elm");
197 edje_object_signal_emit(navi_it->title, buf, "elm");
199 _item_sizing_eval(navi_it);
203 _text_get_hook(const Elm_Object_Item *it, const char *part)
205 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
207 Elm_Naviframe_Text_Item_Pair *pair = NULL;
208 Elm_Naviframe_Item *navi_it = ELM_CAST(it);
210 if (!part) return NULL;
212 EINA_LIST_FOREACH(navi_it->text_list, l, pair)
214 if (!strcmp(part, pair->part))
221 _content_set_hook(Elm_Object_Item *it,
223 Evas_Object *content)
225 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
227 Elm_Naviframe_Content_Item_Pair *pair = NULL;
228 Elm_Naviframe_Item *navi_it = ELM_CAST(it);
233 if (!strcmp(part, "elm.swallow.content"))
235 _item_content_set(navi_it, content);
238 else if (!strcmp(part, "elm.swallow.prev_btn"))
240 _title_prev_btn_set(navi_it, content, EINA_FALSE);
243 else if(!strcmp(part, "elm.swallow.next_btn"))
245 _title_next_btn_set(navi_it, content);
250 _title_content_set(navi_it, pair, part, content);
256 _content_get_hook(const Elm_Object_Item *it,
259 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
261 Elm_Naviframe_Content_Item_Pair *pair = NULL;
262 Elm_Naviframe_Item *navi_it = ELM_CAST(it);
265 if (!strcmp(part, "elm.swallow.content"))
266 return navi_it->content;
267 else if (!strcmp(part, "elm.swallow.prev_btn"))
268 return navi_it->title_prev_btn;
269 else if(!strcmp(part, "elm.swallow.next_btn"))
270 return navi_it->title_next_btn;
273 EINA_LIST_FOREACH(navi_it->content_list, l, pair)
275 if (!strcmp(part, pair->part))
276 return pair->content;
282 _content_unset_hook(Elm_Object_Item *it __UNUSED__,
283 const char *part __UNUSED__)
285 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
287 Elm_Naviframe_Content_Item_Pair *pair = NULL;
288 Elm_Naviframe_Item *navi_it = ELM_CAST(it);
289 Evas_Object *content = NULL;
292 if (!part) return NULL;
295 //FIXME: could be unset the below specified contents also.
296 if (!strcmp(part, "elm.swallow.content") ||
297 !strcmp(part, "elm.swallow.prev_btn") ||
298 !strcmp(part, "elm.swallow.next_btn"))
300 WRN("You can not unset the content! : naviframe=%p",
301 navi_it->base.widget);
306 EINA_LIST_FOREACH(navi_it->content_list, l, pair)
308 if (!strcmp(part, pair->part))
310 content = pair->content;
311 eina_stringshare_del(pair->part);
312 navi_it->content_list = eina_list_remove(navi_it->content_list,
319 if (!content) return NULL;
321 elm_widget_sub_object_del(navi_it->base.widget, content);
322 edje_object_part_unswallow(navi_it->title, content);
323 snprintf(buf, sizeof(buf), "elm,state,%s,hide", part);
324 edje_object_signal_emit(navi_it->title, buf, "elm");
325 evas_object_event_callback_del(content,
328 _item_sizing_eval(navi_it);
334 _sizing_eval(Evas_Object *obj)
338 Elm_Naviframe_Item *it;
339 wd = elm_widget_data_get(obj);
342 list = eina_list_last(wd->stack);
345 EINA_LIST_FOREACH(wd->stack, list, it)
346 _item_sizing_eval(it);
350 _item_sizing_eval(Elm_Naviframe_Item *it)
353 Evas_Coord x, y, w, h;
356 wd = elm_widget_data_get(it->base.widget);
359 evas_object_geometry_get(it->base.widget, &x, &y, &w, &h);
360 evas_object_move(it->base.view, x, y);
361 evas_object_resize(it->base.view, w, h);
365 _move(void *data __UNUSED__,
368 void *event_info __UNUSED__)
374 _resize(void *data __UNUSED__,
377 void *event_info __UNUSED__)
383 _title_clicked(void *data,
384 Evas_Object *obj __UNUSED__,
385 const char *emission __UNUSED__,
386 const char *source __UNUSED__)
388 Elm_Naviframe_Item *it = data;
389 evas_object_smart_callback_call(it->base.widget, SIG_TITLE_CLICKED, it);
393 _back_btn_clicked(void *data,
394 Evas_Object *obj __UNUSED__,
395 void *event_info __UNUSED__)
397 elm_naviframe_item_pop(data);
401 _back_btn_new(Evas_Object *obj)
404 char buf[256]; //FIXME: How to guarantee the size of style name?
405 btn = elm_button_add(obj);
406 if (!btn) return NULL;
407 evas_object_smart_callback_add(btn, "clicked", _back_btn_clicked, obj);
408 snprintf(buf, sizeof(buf), "naviframe/back_btn/%s", elm_widget_style_get(obj));
409 elm_object_style_set(btn, buf);
414 _title_content_del(void *data,
416 Evas_Object *obj __UNUSED__,
417 void *event_info __UNUSED__)
420 Elm_Naviframe_Content_Item_Pair *pair = data;
421 Elm_Naviframe_Item *it = pair->it;
422 snprintf(buf, sizeof(buf), "elm,state,%s,hide", pair->part);
423 edje_object_signal_emit(it->title, buf, "elm");
424 it->content_list = eina_list_remove(it->content_list, pair);
425 eina_stringshare_del(pair->part);
430 _title_prev_btn_del(void *data,
432 Evas_Object *obj __UNUSED__,
433 void *event_info __UNUSED__)
435 Elm_Naviframe_Item *it = data;
436 it->back_btn = EINA_FALSE;
437 it->title_prev_btn = NULL;
441 _title_next_btn_del(void *data,
443 Evas_Object *obj __UNUSED__,
444 void *event_info __UNUSED__)
446 Elm_Naviframe_Item *it = data;
447 it->title_next_btn = NULL;
451 _item_content_del(void *data,
453 Evas_Object *obj __UNUSED__,
454 void *event_info __UNUSED__)
456 Elm_Naviframe_Item *it = data;
458 edje_object_signal_emit(it->base.view, "elm,state,content,hide", "elm");
462 _title_content_set(Elm_Naviframe_Item *it,
463 Elm_Naviframe_Content_Item_Pair *pair,
465 Evas_Object *content)
470 EINA_LIST_FOREACH(it->content_list, l, pair)
472 if (!strcmp(part, pair->part))
474 if (pair->content == content) return;
481 pair = ELM_NEW(Elm_Naviframe_Content_Item_Pair);
484 ERR("Failed to allocate new content part of the item! : naviframe=%p", it->base.widget);
488 eina_stringshare_replace(&pair->part, part);
489 it->content_list = eina_list_append(it->content_list, pair);
492 if (pair->content) evas_object_del(pair->content);
493 pair->content = content;
497 snprintf(buf, sizeof(buf), "elm,state,%s,hide", part);
498 edje_object_signal_emit(it->title, buf, "elm");
502 elm_widget_sub_object_add(it->base.widget, content);
503 edje_object_part_swallow(it->title, part, content);
504 snprintf(buf, sizeof(buf), "elm,state,%s,show", part);
505 edje_object_signal_emit(it->title, buf, "elm");
506 evas_object_event_callback_add(content,
510 _item_sizing_eval(it);
514 _title_prev_btn_set(Elm_Naviframe_Item *it, Evas_Object *btn, Eina_Bool back_btn)
516 char buf[256]; //FIXME: How to guarantee the size of style name?
518 if (it->title_prev_btn == btn) return;
520 if (it->title_prev_btn)
521 evas_object_del(it->title_prev_btn);
523 it->title_prev_btn = btn;
531 "naviframe/prev_btn/%s",
532 elm_widget_style_get(it->base.widget));
533 elm_object_style_set(btn, buf);
535 elm_widget_sub_object_add(it->base.widget, btn);
536 evas_object_event_callback_add(btn,
540 edje_object_part_swallow(it->title, "elm.swallow.prev_btn", btn);
541 it->back_btn = back_btn;
543 _item_sizing_eval(it);
547 _title_next_btn_set(Elm_Naviframe_Item *it, Evas_Object *btn)
549 char buf[256]; //FIXME: How to guarantee the size of style name?
551 if (it->title_next_btn == btn) return;
553 if (it->title_next_btn)
554 evas_object_del(it->title_next_btn);
556 it->title_next_btn = btn;
562 "naviframe/next_btn/%s",
563 elm_widget_style_get(it->base.widget));
564 elm_object_style_set(btn, buf);
565 elm_widget_sub_object_add(it->base.widget, btn);
566 evas_object_event_callback_add(btn,
570 edje_object_part_swallow(it->title, "elm.swallow.next_btn", btn);
572 _item_sizing_eval(it);
576 _item_del(Elm_Naviframe_Item *it)
580 Elm_Naviframe_Content_Item_Pair *content_pair;
581 Elm_Naviframe_Text_Item_Pair *text_pair;
585 wd = elm_widget_data_get(it->base.widget);
588 if (it->title_prev_btn)
589 evas_object_del(it->title_prev_btn);
590 if (it->title_next_btn)
591 evas_object_del(it->title_next_btn);
592 if ((it->content) && (!wd->preserve))
593 evas_object_del(it->content);
595 EINA_LIST_FOREACH(it->content_list, l, content_pair)
596 evas_object_del(content_pair->content);
598 EINA_LIST_FOREACH(it->text_list, l, text_pair)
600 eina_stringshare_del(text_pair->part);
601 eina_stringshare_del(text_pair->text);
604 eina_list_free(it->content_list);
605 eina_list_free(it->text_list);
607 evas_object_del(it->title);
608 evas_object_del(it->base.view);
610 wd->stack = eina_list_remove(wd->stack, it);
616 _pushed_finished(void *data,
617 Evas_Object *obj __UNUSED__,
618 const char *emission __UNUSED__,
619 const char *source __UNUSED__)
621 Elm_Naviframe_Item *it = data;
623 evas_object_hide(it->base.view);
627 _popped_finished(void *data,
628 Evas_Object *obj __UNUSED__,
629 const char *emission __UNUSED__,
630 const char *source __UNUSED__)
636 _show_finished(void *data,
637 Evas_Object *obj __UNUSED__,
638 const char *emission __UNUSED__,
639 const char *source __UNUSED__)
641 Elm_Naviframe_Item *it;
646 wd = elm_widget_data_get(it->base.widget);
649 evas_object_smart_callback_call(it->base.widget,
650 SIG_TRANSITION_FINISHED,
653 evas_object_pass_events_set(wd->base, EINA_FALSE);
657 _item_content_set(Elm_Naviframe_Item *navi_it, Evas_Object *content)
659 if (navi_it->content == content) return;
660 if (navi_it->content) evas_object_del(navi_it->content);
661 elm_widget_sub_object_add(navi_it->base.widget, content);
662 edje_object_part_swallow(navi_it->base.view, "elm.swallow.content", content);
664 edje_object_signal_emit(navi_it->base.view,
665 "elm,state,content,show",
668 edje_object_signal_emit(navi_it->base.view,
669 "elm,state,content,hide",
671 evas_object_event_callback_add(content,
675 navi_it->content = content;
676 _item_sizing_eval(navi_it);
680 elm_naviframe_add(Evas_Object *parent)
686 ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
687 ELM_SET_WIDTYPE(widtype, "naviframe");
688 elm_widget_type_set(obj, "naviframe");
689 elm_widget_sub_object_add(parent, obj);
690 elm_widget_data_set(obj, wd);
691 elm_widget_del_hook_set(obj, _del_hook);
692 elm_widget_disable_hook_set(obj, _disable_hook);
693 elm_widget_theme_hook_set(obj, _theme_hook);
696 wd->base = edje_object_add(e);
697 elm_widget_resize_object_set(obj, wd->base);
698 _elm_theme_object_set(obj, wd->base, "naviframe", "base", "default");
700 evas_object_event_callback_add(obj, EVAS_CALLBACK_MOVE, _move, obj);
701 evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE, _resize, obj);
702 evas_object_smart_callbacks_descriptions_set(obj, _signals);
704 wd->pass_events = EINA_TRUE;
709 EAPI Elm_Object_Item *
710 elm_naviframe_item_push(Evas_Object *obj, const char *title_label, Evas_Object *prev_btn, Evas_Object *next_btn, Evas_Object *content, const char *item_style)
712 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
714 Elm_Naviframe_Item *prev_it, *it;
716 wd = elm_widget_data_get(obj);
717 if (!wd) return NULL;
720 it = elm_widget_item_new(obj, Elm_Naviframe_Item);
723 ERR("Failed to allocate new item! : naviframe=%p", obj);
727 elm_widget_item_text_set_hook_set(it, _text_set_hook);
728 elm_widget_item_text_get_hook_set(it, _text_get_hook);
729 elm_widget_item_content_set_hook_set(it, _content_set_hook);
730 elm_widget_item_content_get_hook_set(it, _content_get_hook);
731 elm_widget_item_content_unset_hook_set(it, _content_unset_hook);
734 it->base.view = edje_object_add(evas_object_evas_get(obj));
735 evas_object_smart_member_add(it->base.view, wd->base);
736 elm_widget_sub_object_add(obj, it->base.view);
737 edje_object_signal_callback_add(it->base.view,
738 "elm,action,show,finished",
741 edje_object_signal_callback_add(it->base.view,
742 "elm,action,pushed,finished",
744 _pushed_finished, it);
745 edje_object_signal_callback_add(it->base.view,
746 "elm,action,popped,finished",
748 _popped_finished, it);
749 elm_naviframe_item_style_set(ELM_CAST(it), item_style);
752 it->title = edje_object_add(evas_object_evas_get(obj));
753 elm_widget_sub_object_add(obj, it->title);
754 _elm_theme_object_set(obj,
755 it->title, "naviframe",
757 elm_widget_style_get(obj));
758 edje_object_signal_callback_add(it->title,
759 "elm,action,clicked",
763 _text_set_hook(ELM_CAST(it), "elm.text.title", title_label);
766 if ((!prev_btn) && (eina_list_count(wd->stack)))
768 prev_btn = _back_btn_new(obj);
769 _title_prev_btn_set(it, prev_btn, EINA_TRUE);
772 _title_prev_btn_set(it, prev_btn, EINA_FALSE);
774 _title_next_btn_set(it, next_btn);
775 edje_object_part_swallow(it->base.view, "elm.swallow.title", it->title);
777 _item_content_set(it, content);
779 _item_sizing_eval(it);
780 evas_object_show(it->base.view);
782 prev_it = ELM_CAST(elm_naviframe_top_item_get(obj));
786 evas_object_pass_events_set(wd->base, EINA_TRUE);
787 edje_object_signal_emit(prev_it->base.view,
790 edje_object_signal_emit(it->base.view,
795 edje_object_signal_emit(it->base.view, "elm,state,visible", "elm");
796 it->title_visible = EINA_TRUE;
797 wd->stack = eina_list_append(wd->stack, it);
802 elm_naviframe_item_pop(Evas_Object *obj)
804 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
805 Elm_Naviframe_Item *it, *prev_it;
807 Evas_Object *content = NULL;
809 wd = elm_widget_data_get(obj);
810 if (!wd) return NULL;
812 it = ELM_CAST(elm_naviframe_top_item_get(obj));
813 if (!it) return NULL;
814 wd->stack = eina_list_remove(wd->stack, it);
817 content = it->content;
819 prev_it = ELM_CAST(elm_naviframe_top_item_get(obj));
823 evas_object_pass_events_set(wd->base, EINA_TRUE);
824 evas_object_show(prev_it->base.view);
825 evas_object_raise(prev_it->base.view);
826 edje_object_signal_emit(prev_it->base.view,
829 edje_object_signal_emit(it->base.view, "elm,state,popped", "elm");
838 elm_naviframe_content_preserve_on_pop_set(Evas_Object *obj, Eina_Bool preserve)
840 ELM_CHECK_WIDTYPE(obj, widtype);
841 Widget_Data *wd = elm_widget_data_get(obj);
843 wd->preserve = !!preserve;
847 elm_naviframe_content_preserve_on_pop_get(const Evas_Object *obj)
849 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
850 Widget_Data *wd = elm_widget_data_get(obj);
851 if (!wd) return EINA_FALSE;
855 EAPI Elm_Object_Item*
856 elm_naviframe_top_item_get(const Evas_Object *obj)
858 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
859 Widget_Data *wd = elm_widget_data_get(obj);
860 if ((!wd) || (!wd->stack)) return NULL;
861 return eina_list_last(wd->stack)->data;
864 EAPI Elm_Object_Item*
865 elm_naviframe_bottom_item_get(const Evas_Object *obj)
867 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
868 Widget_Data *wd = elm_widget_data_get(obj);
869 if (!wd) return NULL;
874 elm_naviframe_item_style_set(Elm_Object_Item *it, const char *item_style)
876 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
877 Elm_Naviframe_Item *navi_it = ELM_CAST(it);
881 if (!item_style) sprintf(buf, "item/basic");
884 if (strlen(item_style) > sizeof(buf))
885 WRN("too much long style name! : naviframe=%p", navi_it->base.widget);
887 sprintf(buf, "item/%s", item_style);
889 _elm_theme_object_set(navi_it->base.widget,
893 elm_widget_style_get(navi_it->base.widget));
897 elm_naviframe_item_style_get(const Elm_Object_Item *it)
899 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
900 Elm_Naviframe_Item *navi_it = ELM_CAST(it);
901 return navi_it->style;
905 elm_naviframe_item_title_visible_set(Elm_Object_Item *it, Eina_Bool visible)
907 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
908 Elm_Naviframe_Item *navi_it = ELM_CAST(it);
911 if (navi_it->title_visible == visible) return;
914 edje_object_signal_emit(navi_it->base.view, "elm,state,title,show", "elm");
916 edje_object_signal_emit(navi_it->base.view, "elm,state,title,hide", "elm");
918 navi_it->title_visible = visible;
922 elm_naviframe_item_title_visible_get(const Elm_Object_Item *it)
924 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
925 Elm_Naviframe_Item *navi_it = ELM_CAST(it);
926 return navi_it->title_visible;