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 auto_pushed: 1;
15 Eina_Bool freeze_events: 1;
18 struct _Elm_Naviframe_Content_Item_Pair
22 Elm_Naviframe_Item *it;
25 struct _Elm_Naviframe_Text_Item_Pair
31 struct _Elm_Naviframe_Item
35 Eina_Inlist *content_list;
36 Eina_Inlist *text_list;
38 Evas_Object *title_prev_btn;
39 Evas_Object *title_next_btn;
40 Evas_Object *title_icon;
44 Eina_Bool back_btn: 1;
45 Eina_Bool title_visible: 1;
48 static const char *widtype = NULL;
51 static const char SIG_TRANSITION_FINISHED[] = "transition,finished";
52 static const char SIG_TITLE_CLICKED[] = "title,clicked";
54 static const Evas_Smart_Cb_Description _signals[] = {
55 {SIG_TRANSITION_FINISHED, ""},
56 {SIG_TITLE_CLICKED, ""},
60 static void _text_set_hook(Evas_Object *obj,
63 static const char *_text_get_hook(const Evas_Object *obj, const char *part);
64 static void _content_set_hook(Evas_Object *obj,
66 Evas_Object *content);
67 static Evas_Object *_content_get_hook(const Evas_Object *obj, const char *part);
68 static Evas_Object *_content_unset_hook(Evas_Object *obj, const char *part);
69 static void _del_hook(Evas_Object *obj);
70 static void _theme_hook(Evas_Object *obj);
71 static void _emit_hook(Evas_Object *obj,
74 static void _disable_hook(Evas_Object *obj);
75 static void _item_text_set_hook(Elm_Object_Item *it,
78 static const char *_item_text_get_hook(const Elm_Object_Item *it,
80 static void _item_content_set_hook(Elm_Object_Item *it,
82 Evas_Object *content);
83 static Evas_Object *_item_content_get_hook(const Elm_Object_Item *it,
85 static Evas_Object *_item_content_unset_hook(Elm_Object_Item *it,
87 static void _item_signal_emit_hook(Elm_Object_Item *it,
90 static void _item_title_visible_update(Elm_Naviframe_Item *navi_it);
91 static void _sizing_eval(Evas_Object *obj);
92 static void _move(void *data, Evas *e, Evas_Object *obj, void *event_info);
93 static void _resize(void *data,
97 static void _title_clicked(void *data, Evas_Object *obj,
100 static void _back_btn_clicked(void *data,
103 static Evas_Object *_back_btn_new(Evas_Object *obj);
104 static void _item_content_del(void *data,
108 static void _title_content_del(void *data,
112 static void _title_prev_btn_del(void *data,
116 static void _title_next_btn_del(void *data,
120 static void _title_icon_del(void *data,
124 static void _title_content_set(Elm_Naviframe_Item *it,
126 Evas_Object *content);
127 static void _title_prev_btn_set(Elm_Naviframe_Item *it,
130 static void _title_next_btn_set(Elm_Naviframe_Item *it, Evas_Object *btn);
131 static void _title_icon_set(Elm_Naviframe_Item *it, Evas_Object *icon);
132 static Evas_Object * _item_content_unset(Elm_Naviframe_Item *it);
133 static Evas_Object * _title_prev_btn_unset(Elm_Naviframe_Item *it);
134 static Evas_Object * _title_next_btn_unset(Elm_Naviframe_Item *it);
135 static Evas_Object * _title_icon_unset(Elm_Naviframe_Item *it);
136 static Evas_Object * _title_content_unset(Elm_Naviframe_Item *it,
138 static void _item_del(Elm_Naviframe_Item *it);
139 static Eina_Bool _item_del_pre_hook(Elm_Object_Item *it);
140 static void _pushed_finished(void *data,
142 const char *emission,
144 static void _popped_finished(void *data,
146 const char *emission,
148 static void _show_finished(void *data,
150 const char *emission,
152 static void _changed_size_hints(void *data,
156 static void _item_content_set(Elm_Naviframe_Item *navi_it,
157 Evas_Object *content);
158 static void _item_style_set(Elm_Naviframe_Item *navi_it,
159 const char *item_style);
160 static Elm_Naviframe_Item * _item_new(Evas_Object *obj,
161 const char *title_label,
162 Evas_Object *prev_btn,
163 Evas_Object *next_btn,
164 Evas_Object *content,
165 const char *item_style);
166 static Eina_Bool _focus_next_hook(const Evas_Object *obj,
167 Elm_Focus_Direction dir,
171 _del_hook(Evas_Object *obj)
174 Elm_Naviframe_Item *it;
176 wd = elm_widget_data_get(obj);
181 while (wd->stack->last)
183 it = EINA_INLIST_CONTAINER_GET(wd->stack->last,
185 wd->stack = eina_inlist_remove(wd->stack, wd->stack->last);
187 elm_widget_item_free(it);
188 if (!wd->stack) break;
195 _theme_hook(Evas_Object *obj)
198 Elm_Naviframe_Item *it;
200 wd = elm_widget_data_get(obj);
203 _elm_theme_object_set(obj,
207 elm_widget_style_get(obj));
209 EINA_INLIST_FOREACH(wd->stack, it)
211 _item_style_set(it, it->style);
212 _item_title_visible_update(it);
216 static void _emit_hook(Evas_Object *obj,
217 const char *emission,
220 Elm_Object_Item *it = elm_naviframe_top_item_get(obj);
222 return elm_object_item_signal_emit(it, emission, source);
226 _disable_hook(Evas_Object *obj __UNUSED__)
232 _item_text_set_hook(Elm_Object_Item *it,
236 Elm_Naviframe_Text_Item_Pair *pair = NULL;
237 Elm_Naviframe_Item *navi_it = (Elm_Naviframe_Item *)it;
240 if (!part || !strcmp(part, "default"))
241 snprintf(buf, sizeof(buf), "elm.text.title");
242 else if(!strcmp("subtitle", part))
243 snprintf(buf, sizeof(buf), "elm.text.subtitle");
245 snprintf(buf, sizeof(buf), "%s", part);
247 EINA_INLIST_FOREACH(navi_it->text_list, pair)
248 if (!strcmp(buf, pair->part)) break;
252 pair = ELM_NEW(Elm_Naviframe_Text_Item_Pair);
255 ERR("Failed to allocate new text part of the item! : naviframe=%p",
259 eina_stringshare_replace(&pair->part, buf);
260 navi_it->text_list = eina_inlist_append(navi_it->text_list,
261 EINA_INLIST_GET(pair));
263 elm_object_part_text_set(VIEW(navi_it), buf, label);
267 snprintf(buf, sizeof(buf), "elm,state,%s,show", buf);
268 elm_object_signal_emit(VIEW(navi_it), buf, "elm");
272 snprintf(buf, sizeof(buf), "elm,state,%s,hide", buf);
273 elm_object_signal_emit(VIEW(navi_it), buf, "elm");
276 _sizing_eval(WIDGET(navi_it));
280 _item_text_get_hook(const Elm_Object_Item *it, const char *part)
284 if (!part || !strcmp(part, "default"))
285 snprintf(buf, sizeof(buf), "elm.text.title");
286 else if(!strcmp("subtitle", part))
287 snprintf(buf, sizeof(buf), "elm.text.subtitle");
289 snprintf(buf, sizeof(buf), "%s", part);
291 return elm_object_part_text_get(VIEW(it), buf);
295 _item_content_set_hook(Elm_Object_Item *it,
297 Evas_Object *content)
299 Elm_Naviframe_Item *navi_it = (Elm_Naviframe_Item *)it;
302 if (!part || !strcmp("default", part))
304 _item_content_set(navi_it, content);
307 else if (!strcmp(part, "prev_btn"))
309 _title_prev_btn_set(navi_it, content, EINA_FALSE);
312 else if (!strcmp(part, "next_btn"))
314 _title_next_btn_set(navi_it, content);
317 else if (!strcmp(part, "icon"))
319 _title_icon_set(navi_it, content);
324 _title_content_set(navi_it, part, content);
328 _item_content_get_hook(const Elm_Object_Item *it, const char *part)
330 Elm_Naviframe_Item *navi_it = (Elm_Naviframe_Item *)it;
333 if (!part || !strcmp("default", part))
334 return navi_it->content;
335 else if (!strcmp(part, "prev_btn"))
336 return navi_it->title_prev_btn;
337 else if (!strcmp(part, "next_btn"))
338 return navi_it->title_next_btn;
339 else if (!strcmp(part, "icon"))
340 return navi_it->title_icon;
343 return elm_object_part_content_get(VIEW(navi_it), part);
347 _item_content_unset_hook(Elm_Object_Item *it, const char *part)
349 Elm_Naviframe_Item *navi_it = (Elm_Naviframe_Item *)it;
352 if (!part || !strcmp("default", part))
353 return _item_content_unset(navi_it);
354 else if (!strcmp(part, "prev_btn"))
355 return _title_prev_btn_unset(navi_it);
356 else if (!strcmp(part, "next_btn"))
357 return _title_next_btn_unset(navi_it);
358 else if (!strcmp(part, "icon"))
359 return _title_icon_unset(navi_it);
361 return _title_content_unset(navi_it, part);
365 _item_signal_emit_hook(Elm_Object_Item *it,
366 const char *emission,
369 elm_object_signal_emit(VIEW(it), emission, source);
373 _item_title_visible_update(Elm_Naviframe_Item *navi_it)
375 if (navi_it->title_visible)
376 elm_object_signal_emit(VIEW(navi_it), "elm,state,title,show", "elm");
378 elm_object_signal_emit(VIEW(navi_it), "elm,state,title,hide", "elm");
382 _sizing_eval(Evas_Object *obj)
385 Elm_Naviframe_Item *it;
386 Evas_Coord x, y, w, h;
387 Evas_Coord minw = -1, minh = -1;
389 wd = elm_widget_data_get(obj);
392 evas_object_geometry_get(obj, &x, &y, &w, &h);
394 EINA_INLIST_FOREACH(wd->stack, it)
396 evas_object_move(VIEW(it), x, y);
397 evas_object_resize(VIEW(it), w, h);
398 edje_object_size_min_calc(elm_layout_edje_get(VIEW(it)),
401 if (it->minw > minw) minw = it->minw;
402 if (it->minh > minh) minh = it->minh;
404 evas_object_size_hint_min_set(obj, minw, minh);
405 evas_object_size_hint_max_set(obj, -1, -1);
409 _move(void *data __UNUSED__,
412 void *event_info __UNUSED__)
418 _resize(void *data __UNUSED__,
421 void *event_info __UNUSED__)
427 _title_clicked(void *data,
428 Evas_Object *obj __UNUSED__,
429 const char *emission __UNUSED__,
430 const char *source __UNUSED__)
432 Elm_Naviframe_Item *it = data;
433 evas_object_smart_callback_call(WIDGET(it), SIG_TITLE_CLICKED, it);
437 _back_btn_clicked(void *data,
439 void *event_info __UNUSED__)
441 /* Since edje has the event queue, clicked event could be happend multiple times
442 on some heavy environment. This callback del will prevent those scenario and
443 guarantee only one clicked for it's own page. */
444 evas_object_smart_callback_del(obj, "clicked", _back_btn_clicked);
445 elm_naviframe_item_pop(data);
449 _back_btn_new(Evas_Object *obj)
453 btn = elm_button_add(obj);
454 if (!btn) return NULL;
455 evas_object_smart_callback_add(btn, "clicked", _back_btn_clicked, obj);
456 snprintf(buf, sizeof(buf), "naviframe/back_btn/%s",
457 elm_widget_style_get(obj));
458 elm_object_style_set(btn, buf);
462 static void _text_set_hook(Evas_Object *obj,
466 Elm_Object_Item *it = elm_naviframe_top_item_get(obj);
468 elm_object_item_part_text_set(it, part, label);
471 static const char *_text_get_hook(const Evas_Object *obj, const char *part)
473 Elm_Object_Item *it = elm_naviframe_top_item_get(obj);
474 if (!it) return NULL;
475 return elm_object_item_part_text_get(it, part);
479 _content_set_hook(Evas_Object *obj, const char *part, Evas_Object *content)
481 Elm_Object_Item *it = elm_naviframe_top_item_get(obj);
483 elm_object_item_part_content_set(it, part, content);
487 _content_unset_hook(Evas_Object *obj, const char *part)
489 Elm_Object_Item *it = elm_naviframe_top_item_get(obj);
490 if (!it) return NULL;
491 return elm_object_item_part_content_unset(it, part);
495 _content_get_hook(const Evas_Object *obj, const char *part)
497 Elm_Object_Item *it = elm_naviframe_top_item_get(obj);
498 if (!it) return NULL;
499 return elm_object_item_part_content_get(it, part);
503 _title_content_del(void *data,
505 Evas_Object *obj __UNUSED__,
506 void *event_info __UNUSED__)
509 Elm_Naviframe_Content_Item_Pair *pair = data;
510 Elm_Naviframe_Item *it = pair->it;
511 snprintf(buf, sizeof(buf), "elm,state,%s,hide", pair->part);
512 elm_object_signal_emit(VIEW(it), buf, "elm");
513 it->content_list = eina_inlist_remove(it->content_list,
514 EINA_INLIST_GET(pair));
515 eina_stringshare_del(pair->part);
520 _title_prev_btn_del(void *data,
522 Evas_Object *obj __UNUSED__,
523 void *event_info __UNUSED__)
525 Elm_Naviframe_Item *it = data;
526 it->back_btn = EINA_FALSE;
527 it->title_prev_btn = NULL;
528 elm_object_signal_emit(VIEW(it), "elm,state,prev_btn,hide", "elm");
532 _title_next_btn_del(void *data,
534 Evas_Object *obj __UNUSED__,
535 void *event_info __UNUSED__)
537 Elm_Naviframe_Item *it = data;
538 it->title_next_btn = NULL;
539 elm_object_signal_emit(VIEW(it), "elm,state,next_btn,hide", "elm");
543 _title_icon_del(void *data,
545 Evas_Object *obj __UNUSED__,
546 void *event_info __UNUSED__)
548 Elm_Naviframe_Item *it = data;
549 it->title_icon = NULL;
550 elm_object_signal_emit(VIEW(it), "elm,state,icon,hide", "elm");
554 _item_content_del(void *data,
556 Evas_Object *obj __UNUSED__,
557 void *event_info __UNUSED__)
559 Elm_Naviframe_Item *it = data;
561 elm_object_signal_emit(VIEW(it), "elm,state,content,hide", "elm");
565 _title_content_set(Elm_Naviframe_Item *it,
567 Evas_Object *content)
570 Elm_Naviframe_Content_Item_Pair *pair = NULL;
571 Evas_Object *prev_content = NULL;
573 EINA_INLIST_FOREACH(it->content_list, pair)
574 if (!strcmp(part, pair->part)) break;
578 prev_content = elm_object_part_content_get(VIEW(it), part);
579 if (prev_content != content)
583 evas_object_event_callback_del(prev_content,
586 snprintf(buf, sizeof(buf), "elm,state,%s,hide", part);
587 elm_object_signal_emit(VIEW(it), buf, "elm");
589 evas_object_del(prev_content);
590 if (!content) return;
595 if (!content) return;
596 pair = ELM_NEW(Elm_Naviframe_Content_Item_Pair);
599 ERR("Failed to allocate new content part of the item! : naviframe=%p", WIDGET(it));
603 eina_stringshare_replace(&pair->part, part);
604 it->content_list = eina_inlist_append(it->content_list,
605 EINA_INLIST_GET(pair));
607 if (prev_content != content)
609 evas_object_event_callback_add(content,
614 elm_object_part_content_set(VIEW(it), part, content);
615 snprintf(buf, sizeof(buf), "elm,state,%s,show", part);
616 elm_object_signal_emit(VIEW(it), buf, "elm");
618 _sizing_eval(WIDGET(it));
622 _title_prev_btn_set(Elm_Naviframe_Item *it,
626 if (it->title_prev_btn == btn) return;
627 if (it->title_prev_btn) evas_object_del(it->title_prev_btn);
628 it->title_prev_btn = btn;
631 evas_object_event_callback_add(btn,
635 elm_object_part_content_set(VIEW(it), "elm.swallow.prev_btn", btn);
636 elm_object_signal_emit(VIEW(it), "elm,state,prev_btn,show", "elm");
637 it->back_btn = back_btn;
639 _sizing_eval(WIDGET(it));
643 _title_next_btn_set(Elm_Naviframe_Item *it, Evas_Object *btn)
645 if (it->title_next_btn == btn) return;
646 if (it->title_next_btn) evas_object_del(it->title_next_btn);
647 it->title_next_btn = btn;
650 evas_object_event_callback_add(btn,
654 elm_object_part_content_set(VIEW(it), "elm.swallow.next_btn", btn);
655 elm_object_signal_emit(VIEW(it), "elm,state,next_btn,show", "elm");
657 _sizing_eval(WIDGET(it));
661 _title_icon_set(Elm_Naviframe_Item *it, Evas_Object *icon)
663 if (it->title_icon == icon) return;
664 if (it->title_icon) evas_object_del(it->title_icon);
665 it->title_icon = icon;
668 evas_object_event_callback_add(icon,
672 elm_object_part_content_set(VIEW(it), "elm.swallow.icon", icon);
673 elm_object_signal_emit(VIEW(it), "elm,state,icon,show", "elm");
675 _sizing_eval(WIDGET(it));
679 _item_content_unset(Elm_Naviframe_Item *it)
681 Evas_Object *content = it->content;
682 if (!content) return NULL;
684 elm_object_part_content_unset(VIEW(it), "elm.swallow.content");
685 elm_object_signal_emit(VIEW(it), "elm,state,content,hide", "elm");
686 evas_object_event_callback_del(content,
689 _sizing_eval(WIDGET(it));
696 _title_prev_btn_unset(Elm_Naviframe_Item *it)
698 Evas_Object *content = it->title_prev_btn;
699 if (!content) return NULL;
701 elm_object_part_content_unset(VIEW(it), "elm.swallow.prev_btn");
702 elm_object_signal_emit(VIEW(it), "elm,state,prev_btn,hide", "elm");
703 evas_object_event_callback_del(content,
705 _title_prev_btn_del);
706 _sizing_eval(WIDGET(it));
708 it->title_prev_btn = NULL;
713 _title_next_btn_unset(Elm_Naviframe_Item *it)
715 Evas_Object *content = it->title_next_btn;
716 if (!content) return NULL;
718 elm_object_part_content_unset(VIEW(it), "elm.swallow.next_btn");
719 elm_object_signal_emit(VIEW(it), "elm,state,next_btn,hide", "elm");
720 evas_object_event_callback_del(content,
722 _title_next_btn_del);
723 _sizing_eval(WIDGET(it));
725 it->title_next_btn = NULL;
730 _title_icon_unset(Elm_Naviframe_Item *it)
732 Evas_Object *content = it->title_icon;
733 if (!content) return NULL;
735 elm_object_part_content_unset(VIEW(it), "elm.swallow.icon");
736 elm_object_signal_emit(VIEW(it), "elm,state,icon,hide", "elm");
737 evas_object_event_callback_del(content,
740 _sizing_eval(WIDGET(it));
741 it->title_icon = NULL;
747 _title_content_unset(Elm_Naviframe_Item *it, const char *part)
749 Elm_Naviframe_Content_Item_Pair *pair = NULL;
751 Evas_Object *content = NULL;
753 EINA_INLIST_FOREACH(it->content_list, pair)
755 if (!strcmp(part, pair->part))
757 content = elm_object_part_content_get(VIEW(it), part);
758 eina_stringshare_del(pair->part);
759 it->content_list = eina_inlist_remove(it->content_list,
760 EINA_INLIST_GET(pair));
766 if (!content) return NULL;
768 elm_object_part_content_unset(VIEW(it), part);
769 snprintf(buf, sizeof(buf), "elm,state,%s,hide", part);
770 elm_object_signal_emit(VIEW(it), buf, "elm");
771 evas_object_event_callback_del(content,
774 _sizing_eval(WIDGET(it));
780 _item_del(Elm_Naviframe_Item *it)
783 Elm_Naviframe_Content_Item_Pair *content_pair;
784 Elm_Naviframe_Text_Item_Pair *text_pair;
785 Evas_Object *content;
789 wd = elm_widget_data_get(WIDGET(it));
792 while (it->content_list)
795 EINA_INLIST_CONTAINER_GET(it->content_list,
796 Elm_Naviframe_Content_Item_Pair);
797 content = elm_object_part_content_get(VIEW(it), content_pair->part);
798 evas_object_event_callback_del(content,
801 eina_stringshare_del(content_pair->part);
802 it->content_list = eina_inlist_remove(it->content_list,
807 while (it->text_list)
809 text_pair = EINA_INLIST_CONTAINER_GET(it->text_list,
810 Elm_Naviframe_Text_Item_Pair);
811 eina_stringshare_del(text_pair->part);
812 it->text_list = eina_inlist_remove(it->text_list,
817 eina_stringshare_del(it->style);
821 _item_del_pre_hook(Elm_Object_Item *it)
823 Elm_Naviframe_Item *navi_it;
826 navi_it =(Elm_Naviframe_Item *)it;
827 wd = elm_widget_data_get(WIDGET(navi_it));
828 if (!wd) return EINA_FALSE;
830 if (it == elm_naviframe_top_item_get(WIDGET(navi_it)))
832 wd->stack = eina_inlist_remove(wd->stack, EINA_INLIST_GET(navi_it));
834 //If the item is only one, the stack will be empty
835 if (!wd->stack) return EINA_TRUE;
836 navi_it = EINA_INLIST_CONTAINER_GET(wd->stack->last,
838 evas_object_show(VIEW(navi_it));
839 evas_object_raise(VIEW(navi_it));
840 elm_object_signal_emit(VIEW(navi_it), "elm,state,visible", "elm");
844 wd->stack = eina_inlist_remove(wd->stack, EINA_INLIST_GET(navi_it));
852 _pushed_finished(void *data,
853 Evas_Object *obj __UNUSED__,
854 const char *emission __UNUSED__,
855 const char *source __UNUSED__)
858 Elm_Naviframe_Item *it = data;
861 wd = elm_widget_data_get(WIDGET(it));
864 evas_object_hide(VIEW(it));
865 if (wd->freeze_events)
866 evas_object_freeze_events_set(VIEW(it), EINA_FALSE);
870 _popped_finished(void *data,
871 Evas_Object *obj __UNUSED__,
872 const char *emission __UNUSED__,
873 const char *source __UNUSED__)
875 Elm_Naviframe_Item *it = data;
878 elm_widget_item_free(data);
882 _show_finished(void *data,
883 Evas_Object *obj __UNUSED__,
884 const char *emission __UNUSED__,
885 const char *source __UNUSED__)
887 Elm_Naviframe_Item *it;
892 wd = elm_widget_data_get(WIDGET(it));
895 // FIXME : If current top's content is unfocusable, it should be restored as focusable.
896 // Similar cases are should be checked and should call following function.
897 if (elm_widget_tree_unfocusable_get(it->content))
898 elm_widget_tree_unfocusable_set(it->content, EINA_FALSE);
900 evas_object_smart_callback_call(WIDGET(it),
901 SIG_TRANSITION_FINISHED,
903 if (wd->freeze_events)
904 evas_object_freeze_events_set(VIEW(it), EINA_FALSE);
908 _changed_size_hints(void *data,
910 Evas_Object *obj __UNUSED__,
911 void *event_info __UNUSED__)
917 _item_content_set(Elm_Naviframe_Item *navi_it, Evas_Object *content)
919 if (navi_it->content == content) return;
920 if (navi_it->content) evas_object_del(navi_it->content);
921 elm_object_part_content_set(VIEW(navi_it), "elm.swallow.content", content);
924 elm_object_signal_emit(VIEW(navi_it), "elm,state,content,show", "elm");
926 elm_object_signal_emit(VIEW(navi_it), "elm,state,content,hide", "elm");
928 evas_object_event_callback_add(content,
932 navi_it->content = content;
933 _sizing_eval(WIDGET(navi_it));
936 //FIXME: need to handle if this function is called while transition
938 _item_style_set(Elm_Naviframe_Item *navi_it, const char *item_style)
940 Elm_Naviframe_Content_Item_Pair *content_pair;
941 Elm_Naviframe_Text_Item_Pair *text_pair;
948 strcpy(buf, "item/basic");
949 eina_stringshare_replace(&navi_it->style, "basic");
953 snprintf(buf, sizeof(buf), "item/%s", item_style);
954 eina_stringshare_replace(&navi_it->style, item_style);
956 elm_layout_theme_set(VIEW(navi_it),
959 elm_widget_style_get(WIDGET(navi_it)));
961 EINA_INLIST_FOREACH(navi_it->text_list, text_pair)
962 _item_text_set_hook((Elm_Object_Item *) navi_it,
964 elm_object_part_text_get(VIEW(navi_it),
967 EINA_INLIST_FOREACH(navi_it->content_list, content_pair)
968 _item_content_set_hook((Elm_Object_Item *) navi_it,
970 elm_object_part_content_get(VIEW(navi_it),
971 content_pair->part));
973 if (navi_it->content)
974 elm_object_signal_emit(VIEW(navi_it), "elm,state,content,show", "elm");
977 if (navi_it->title_prev_btn)
978 elm_object_signal_emit(VIEW(navi_it), "elm,state,prev_btn,show", "elm");
981 if (navi_it->title_next_btn)
982 elm_object_signal_emit(VIEW(navi_it), "elm,state,next_btn,show", "elm");
984 // why does this forcibly enable title? isnt that separate to style?
985 // navi_it->title_visible = EINA_TRUE;
986 _sizing_eval(WIDGET(navi_it));
988 wd = elm_widget_data_get(WIDGET(navi_it));
991 if (wd->freeze_events)
992 evas_object_freeze_events_set(VIEW(navi_it), EINA_FALSE);
995 static Elm_Naviframe_Item *
996 _item_new(Evas_Object *obj,
997 const char *title_label,
998 Evas_Object *prev_btn,
999 Evas_Object *next_btn,
1000 Evas_Object *content,
1001 const char *item_style)
1003 Widget_Data *wd = elm_widget_data_get(obj);
1006 Elm_Naviframe_Item *it = elm_widget_item_new(obj, Elm_Naviframe_Item);
1009 ERR("Failed to allocate new item! : naviframe=%p", obj);
1013 elm_widget_item_del_pre_hook_set(it, _item_del_pre_hook);
1014 elm_widget_item_text_set_hook_set(it, _item_text_set_hook);
1015 elm_widget_item_text_get_hook_set(it, _item_text_get_hook);
1016 elm_widget_item_content_set_hook_set(it, _item_content_set_hook);
1017 elm_widget_item_content_get_hook_set(it, _item_content_get_hook);
1018 elm_widget_item_content_unset_hook_set(it, _item_content_unset_hook);
1019 elm_widget_item_signal_emit_hook_set(it, _item_signal_emit_hook);
1022 VIEW(it) = elm_layout_add(obj);
1023 evas_object_smart_member_add(VIEW(it), wd->base);
1025 evas_object_event_callback_add(VIEW(it),
1026 EVAS_CALLBACK_CHANGED_SIZE_HINTS,
1027 _changed_size_hints,
1029 elm_object_signal_callback_add(VIEW(it),
1030 "elm,action,show,finished",
1032 _show_finished, it);
1033 elm_object_signal_callback_add(VIEW(it),
1034 "elm,action,pushed,finished",
1036 _pushed_finished, it);
1037 elm_object_signal_callback_add(VIEW(it),
1038 "elm,action,popped,finished",
1040 _popped_finished, it);
1041 elm_object_signal_callback_add(VIEW(it),
1042 "elm,action,title,clicked",
1044 _title_clicked, it);
1046 _item_style_set(it, item_style);
1047 _item_text_set_hook((Elm_Object_Item *)it, "elm.text.title", title_label);
1050 if ((!prev_btn) && wd->auto_pushed && eina_inlist_count(wd->stack))
1052 prev_btn = _back_btn_new(obj);
1053 _title_prev_btn_set(it, prev_btn, EINA_TRUE);
1056 _title_prev_btn_set(it, prev_btn, EINA_FALSE);
1058 _title_next_btn_set(it, next_btn);
1059 _item_content_set(it, content);
1060 it->title_visible = EINA_TRUE;
1065 _focus_next_hook(const Evas_Object *obj, Elm_Focus_Direction dir, Evas_Object **next)
1067 Widget_Data *wd = elm_widget_data_get(obj);
1068 if (!wd || !wd->stack) return EINA_FALSE;
1069 return elm_widget_focus_next_get(VIEW(elm_naviframe_top_item_get(obj)),
1075 elm_naviframe_add(Evas_Object *parent)
1081 ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
1082 ELM_SET_WIDTYPE(widtype, "naviframe");
1083 elm_widget_type_set(obj, "naviframe");
1084 elm_widget_sub_object_add(parent, obj);
1085 elm_widget_data_set(obj, wd);
1086 elm_widget_del_hook_set(obj, _del_hook);
1087 elm_widget_disable_hook_set(obj, _disable_hook);
1088 elm_widget_theme_hook_set(obj, _theme_hook);
1089 elm_widget_text_set_hook_set(obj, _text_set_hook);
1090 elm_widget_text_get_hook_set(obj, _text_get_hook);
1091 elm_widget_content_set_hook_set(obj, _content_set_hook);
1092 elm_widget_content_get_hook_set(obj, _content_get_hook);
1093 elm_widget_content_unset_hook_set(obj, _content_unset_hook);
1094 elm_widget_signal_emit_hook_set(obj, _emit_hook);
1095 elm_widget_can_focus_set(obj, EINA_FALSE);
1096 elm_widget_focus_next_hook_set(obj, _focus_next_hook);
1099 //FIXME: Is this base layout really needed?
1100 wd->base = elm_layout_add(parent);
1101 evas_object_event_callback_add(wd->base,
1102 EVAS_CALLBACK_CHANGED_SIZE_HINTS,
1103 _changed_size_hints,
1105 elm_widget_resize_object_set(obj, wd->base);
1106 elm_layout_theme_set(wd->base, "naviframe", "base", "default");
1108 evas_object_event_callback_add(obj, EVAS_CALLBACK_MOVE, _move, obj);
1109 evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE, _resize, obj);
1110 evas_object_smart_callbacks_descriptions_set(obj, _signals);
1112 wd->auto_pushed = EINA_TRUE;
1113 wd->freeze_events = EINA_TRUE;
1118 EAPI Elm_Object_Item *
1119 elm_naviframe_item_push(Evas_Object *obj,
1120 const char *title_label,
1121 Evas_Object *prev_btn,
1122 Evas_Object *next_btn,
1123 Evas_Object *content,
1124 const char *item_style)
1126 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1128 Elm_Naviframe_Item *prev_it, *it;
1130 wd = elm_widget_data_get(obj);
1131 if (!wd) return NULL;
1133 it = _item_new(obj, title_label, prev_btn, next_btn, content, item_style);
1134 if (!it) return NULL;
1136 evas_object_show(VIEW(it));
1138 prev_it = (Elm_Naviframe_Item *) elm_naviframe_top_item_get(obj);
1141 if (wd->freeze_events)
1143 evas_object_freeze_events_set(VIEW(it), EINA_TRUE);
1144 evas_object_freeze_events_set(VIEW(prev_it), EINA_TRUE);
1146 elm_object_signal_emit(VIEW(prev_it), "elm,state,cur,pushed", "elm");
1147 elm_object_signal_emit(VIEW(it), "elm,state,new,pushed", "elm");
1148 edje_object_message_signal_process(elm_layout_edje_get(VIEW(prev_it)));
1149 elm_widget_tree_unfocusable_set(prev_it->content, EINA_TRUE);
1150 edje_object_message_signal_process(elm_layout_edje_get(VIEW(it)));
1152 wd->stack = eina_inlist_append(wd->stack, EINA_INLIST_GET(it));
1154 return (Elm_Object_Item *)it;
1157 EAPI Elm_Object_Item *
1158 elm_naviframe_item_insert_before(Evas_Object *obj,
1159 Elm_Object_Item *before,
1160 const char *title_label,
1161 Evas_Object *prev_btn,
1162 Evas_Object *next_btn,
1163 Evas_Object *content,
1164 const char *item_style)
1166 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1167 ELM_OBJ_ITEM_CHECK_OR_RETURN(before, NULL);
1168 Elm_Naviframe_Item *it;
1171 wd = elm_widget_data_get(obj);
1172 if (!wd) return NULL;
1174 it = _item_new(WIDGET(before), title_label, prev_btn, next_btn, content,
1176 if (!it) return NULL;
1179 eina_inlist_prepend_relative(wd->stack,
1180 EINA_INLIST_GET(it),
1181 EINA_INLIST_GET(((Elm_Naviframe_Item *) before)));
1182 _sizing_eval(WIDGET(before));
1183 return (Elm_Object_Item *)it;
1186 EAPI Elm_Object_Item *
1187 elm_naviframe_item_insert_after(Evas_Object *obj,
1188 Elm_Object_Item *after,
1189 const char *title_label,
1190 Evas_Object *prev_btn,
1191 Evas_Object *next_btn,
1192 Evas_Object *content,
1193 const char *item_style)
1195 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1196 ELM_OBJ_ITEM_CHECK_OR_RETURN(after, NULL);
1197 Elm_Naviframe_Item *it;
1200 wd = elm_widget_data_get(obj);
1201 if (!wd) return NULL;
1203 it = _item_new(WIDGET(after), title_label, prev_btn, next_btn, content,
1205 if (!it) return NULL;
1207 if (elm_naviframe_top_item_get(WIDGET(after)) == after)
1209 evas_object_hide(VIEW(after));
1210 evas_object_show(VIEW(it));
1213 eina_inlist_append_relative(wd->stack,
1214 EINA_INLIST_GET(it),
1215 EINA_INLIST_GET(((Elm_Naviframe_Item *) after)));
1216 _sizing_eval(WIDGET(after));
1217 return (Elm_Object_Item *)it;
1221 elm_naviframe_item_pop(Evas_Object *obj)
1223 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1224 Elm_Naviframe_Item *it, *prev_it = NULL;
1226 Evas_Object *content = NULL;
1228 wd = elm_widget_data_get(obj);
1229 if (!wd) return NULL;
1231 it = (Elm_Naviframe_Item *) elm_naviframe_top_item_get(obj);
1232 if (!it) return NULL;
1234 content = it->content;
1236 elm_widget_tree_unfocusable_set(it->content, EINA_TRUE);
1238 if (wd->stack->last->prev)
1239 prev_it = EINA_INLIST_CONTAINER_GET(wd->stack->last->prev,
1240 Elm_Naviframe_Item);
1241 wd->stack = eina_inlist_remove(wd->stack, EINA_INLIST_GET(it));
1244 if (wd->freeze_events)
1246 evas_object_freeze_events_set(VIEW(it), EINA_TRUE);
1247 evas_object_freeze_events_set(VIEW(prev_it), EINA_TRUE);
1249 elm_object_signal_emit(VIEW(it), "elm,state,cur,popped", "elm");
1250 evas_object_show(VIEW(prev_it));
1251 evas_object_raise(VIEW(prev_it));
1252 elm_object_signal_emit(VIEW(prev_it),
1253 "elm,state,prev,popped",
1255 edje_object_message_signal_process(elm_layout_edje_get(VIEW(it)));
1256 edje_object_message_signal_process(elm_layout_edje_get(VIEW(prev_it)));
1261 elm_widget_item_free(it);
1268 elm_naviframe_item_pop_to(Elm_Object_Item *it)
1270 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1271 Elm_Naviframe_Item *navi_it;
1273 Eina_Inlist *l, *prev_l;
1275 navi_it = (Elm_Naviframe_Item *)it;
1276 wd = elm_widget_data_get(WIDGET(navi_it));
1279 if (it == elm_naviframe_top_item_get(WIDGET(navi_it))) return;
1281 l = wd->stack->last->prev;
1285 if (EINA_INLIST_CONTAINER_GET(l, Elm_Naviframe_Item) ==
1286 ((Elm_Naviframe_Item *)it)) break;
1288 wd->stack = eina_inlist_remove(wd->stack, l);
1289 _item_del(EINA_INLIST_CONTAINER_GET(l, Elm_Naviframe_Item));
1290 elm_widget_item_free(EINA_INLIST_CONTAINER_GET(l,
1291 Elm_Naviframe_Item));
1294 elm_naviframe_item_pop(WIDGET(navi_it));
1298 elm_naviframe_item_promote(Elm_Object_Item *it)
1300 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1301 Elm_Naviframe_Item *navi_it;
1302 Elm_Naviframe_Item *prev_it;
1305 navi_it = (Elm_Naviframe_Item *)it;
1306 wd = elm_widget_data_get(navi_it->base.widget);
1309 if (it == elm_naviframe_top_item_get(navi_it->base.widget)) return;
1310 elm_widget_tree_unfocusable_set(navi_it->content, EINA_FALSE);
1311 wd->stack = eina_inlist_demote(wd->stack, EINA_INLIST_GET(navi_it));
1312 prev_it = EINA_INLIST_CONTAINER_GET(wd->stack->last->prev,
1313 Elm_Naviframe_Item);
1314 elm_widget_tree_unfocusable_set(prev_it->content, EINA_FALSE);
1315 if (wd->freeze_events)
1317 evas_object_freeze_events_set(VIEW(it), EINA_TRUE);
1318 evas_object_freeze_events_set(VIEW(prev_it), EINA_TRUE);
1320 elm_object_signal_emit(VIEW(prev_it),
1321 "elm,state,cur,pushed",
1323 evas_object_show(VIEW(navi_it));
1324 evas_object_raise(VIEW(navi_it));
1325 elm_object_signal_emit(VIEW(navi_it),
1326 "elm,state,new,pushed",
1328 edje_object_message_signal_process(elm_layout_edje_get(VIEW(prev_it)));
1329 edje_object_message_signal_process(elm_layout_edje_get(VIEW(navi_it)));
1333 elm_naviframe_item_simple_promote(Evas_Object *obj, Evas_Object *content)
1335 ELM_CHECK_WIDTYPE(obj, widtype);
1336 Widget_Data *wd = elm_widget_data_get(obj);
1338 Elm_Naviframe_Item *itr;
1339 EINA_INLIST_FOREACH(wd->stack, itr)
1341 if (elm_object_item_content_get((Elm_Object_Item *)itr) == content)
1343 elm_naviframe_item_promote((Elm_Object_Item *)itr);
1351 elm_naviframe_item_del(Elm_Object_Item *it)
1353 elm_object_item_del(it);
1357 elm_naviframe_content_preserve_on_pop_set(Evas_Object *obj, Eina_Bool preserve)
1359 ELM_CHECK_WIDTYPE(obj, widtype);
1360 Widget_Data *wd = elm_widget_data_get(obj);
1362 wd->preserve = !!preserve;
1366 elm_naviframe_content_preserve_on_pop_get(const Evas_Object *obj)
1368 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1369 Widget_Data *wd = elm_widget_data_get(obj);
1370 if (!wd) return EINA_FALSE;
1371 return wd->preserve;
1374 EAPI Elm_Object_Item*
1375 elm_naviframe_top_item_get(const Evas_Object *obj)
1377 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1378 Widget_Data *wd = elm_widget_data_get(obj);
1379 if ((!wd) || (!wd->stack)) return NULL;
1380 return (Elm_Object_Item *) (EINA_INLIST_CONTAINER_GET(wd->stack->last,
1381 Elm_Naviframe_Item));
1384 EAPI Elm_Object_Item*
1385 elm_naviframe_bottom_item_get(const Evas_Object *obj)
1387 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1388 Widget_Data *wd = elm_widget_data_get(obj);
1389 if ((!wd) || (!wd->stack)) return NULL;
1390 return (Elm_Object_Item *) (EINA_INLIST_CONTAINER_GET(wd->stack,
1391 Elm_Naviframe_Item));
1395 elm_naviframe_item_style_set(Elm_Object_Item *it, const char *item_style)
1397 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1398 Elm_Naviframe_Item *navi_it = (Elm_Naviframe_Item *)it;
1401 if (!strcmp(item_style, navi_it->style)) return;
1404 if (!strcmp("basic", navi_it->style)) return;
1406 _item_style_set(navi_it, item_style);
1410 elm_naviframe_item_style_get(const Elm_Object_Item *it)
1412 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
1413 Elm_Naviframe_Item *navi_it = (Elm_Naviframe_Item *)it;
1414 return navi_it->style;
1418 elm_naviframe_item_title_visible_set(Elm_Object_Item *it, Eina_Bool visible)
1420 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1421 Elm_Naviframe_Item *navi_it = (Elm_Naviframe_Item *)it;
1423 visible = !!visible;
1424 if (navi_it->title_visible == visible) return;
1426 navi_it->title_visible = visible;
1427 _item_title_visible_update(navi_it);
1431 elm_naviframe_item_title_visible_get(const Elm_Object_Item *it)
1433 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
1434 Elm_Naviframe_Item *navi_it = (Elm_Naviframe_Item *)it;
1435 return navi_it->title_visible;
1439 elm_naviframe_prev_btn_auto_pushed_set(Evas_Object *obj, Eina_Bool auto_pushed)
1441 ELM_CHECK_WIDTYPE(obj, widtype);
1442 Widget_Data *wd = elm_widget_data_get(obj);
1444 wd->auto_pushed = !!auto_pushed;
1448 elm_naviframe_prev_btn_auto_pushed_get(const Evas_Object *obj)
1450 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1451 Widget_Data *wd = elm_widget_data_get(obj);
1452 if (!wd) return EINA_FALSE;
1453 return wd->auto_pushed;
1457 elm_naviframe_items_get(const Evas_Object *obj)
1459 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1460 Widget_Data *wd = elm_widget_data_get(obj);
1461 if (!wd) return NULL;
1462 Eina_List *ret = NULL;
1463 Elm_Naviframe_Item *itr;
1464 EINA_INLIST_FOREACH(wd->stack, itr)
1465 ret = eina_list_append(ret, itr);
1470 elm_naviframe_event_enabled_set(Evas_Object *obj, Eina_Bool enabled)
1472 ELM_CHECK_WIDTYPE(obj, widtype);
1473 Widget_Data *wd = elm_widget_data_get(obj);
1475 enabled = !!enabled;
1476 if (wd->freeze_events == !enabled) return;
1477 wd->freeze_events = !enabled;
1481 elm_naviframe_event_enabled_get(const Evas_Object *obj)
1483 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1484 Widget_Data *wd = elm_widget_data_get(obj);
1485 if (!wd) return EINA_FALSE;
1486 return !wd->freeze_events;