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;
46 Eina_Bool content_unfocusable : 1;
49 static const char *widtype = NULL;
52 static const char SIG_TRANSITION_FINISHED[] = "transition,finished";
53 static const char SIG_TITLE_CLICKED[] = "title,clicked";
55 static const Evas_Smart_Cb_Description _signals[] = {
56 {SIG_TRANSITION_FINISHED, ""},
57 {SIG_TITLE_CLICKED, ""},
61 static void _text_set_hook(Evas_Object *obj,
64 static const char *_text_get_hook(const Evas_Object *obj, const char *part);
65 static void _content_set_hook(Evas_Object *obj,
67 Evas_Object *content);
68 static Evas_Object *_content_get_hook(const Evas_Object *obj, const char *part);
69 static Evas_Object *_content_unset_hook(Evas_Object *obj, const char *part);
70 static void _del_hook(Evas_Object *obj);
71 static void _theme_hook(Evas_Object *obj);
72 static void _emit_hook(Evas_Object *obj,
75 static void _disable_hook(Evas_Object *obj);
76 static void _item_text_set_hook(Elm_Object_Item *it,
79 static const char *_item_text_get_hook(const Elm_Object_Item *it,
81 static void _item_content_set_hook(Elm_Object_Item *it,
83 Evas_Object *content);
84 static Evas_Object *_item_content_get_hook(const Elm_Object_Item *it,
86 static Evas_Object *_item_content_unset_hook(Elm_Object_Item *it,
88 static void _item_signal_emit_hook(Elm_Object_Item *it,
91 static void _item_title_visible_update(Elm_Naviframe_Item *navi_it);
92 static void _sizing_eval(Evas_Object *obj);
93 static void _move(void *data, Evas *e, Evas_Object *obj, void *event_info);
94 static void _resize(void *data,
98 static void _title_clicked(void *data, Evas_Object *obj,
101 static void _back_btn_clicked(void *data,
104 static Evas_Object *_back_btn_new(Evas_Object *obj);
105 static void _item_content_del(void *data,
109 static void _title_content_del(void *data,
113 static void _title_prev_btn_del(void *data,
117 static void _title_next_btn_del(void *data,
121 static void _title_icon_del(void *data,
125 static void _title_content_set(Elm_Naviframe_Item *it,
127 Evas_Object *content);
128 static void _title_prev_btn_set(Elm_Naviframe_Item *it,
131 static void _title_next_btn_set(Elm_Naviframe_Item *it, Evas_Object *btn);
132 static void _title_icon_set(Elm_Naviframe_Item *it, Evas_Object *icon);
133 static Evas_Object * _item_content_unset(Elm_Naviframe_Item *it);
134 static Evas_Object * _title_prev_btn_unset(Elm_Naviframe_Item *it);
135 static Evas_Object * _title_next_btn_unset(Elm_Naviframe_Item *it);
136 static Evas_Object * _title_icon_unset(Elm_Naviframe_Item *it);
137 static Evas_Object * _title_content_unset(Elm_Naviframe_Item *it,
139 static void _item_del(Elm_Naviframe_Item *it);
140 static Eina_Bool _item_del_pre_hook(Elm_Object_Item *it);
141 static void _pushed_finished(void *data,
143 const char *emission,
145 static void _popped_finished(void *data,
147 const char *emission,
149 static void _show_finished(void *data,
151 const char *emission,
153 static void _changed_size_hints(void *data,
157 static void _item_content_set(Elm_Naviframe_Item *navi_it,
158 Evas_Object *content);
159 static void _item_style_set(Elm_Naviframe_Item *navi_it,
160 const char *item_style);
161 static Elm_Naviframe_Item * _item_new(Evas_Object *obj,
162 const char *title_label,
163 Evas_Object *prev_btn,
164 Evas_Object *next_btn,
165 Evas_Object *content,
166 const char *item_style);
167 static Eina_Bool _focus_next_hook(const Evas_Object *obj,
168 Elm_Focus_Direction dir,
172 _del_hook(Evas_Object *obj)
175 Elm_Naviframe_Item *it;
177 wd = elm_widget_data_get(obj);
182 while (wd->stack->last)
184 it = EINA_INLIST_CONTAINER_GET(wd->stack->last,
186 wd->stack = eina_inlist_remove(wd->stack, wd->stack->last);
188 elm_widget_item_free(it);
189 if (!wd->stack) break;
196 _theme_hook(Evas_Object *obj)
199 Elm_Naviframe_Item *it;
201 wd = elm_widget_data_get(obj);
204 _elm_theme_object_set(obj,
208 elm_widget_style_get(obj));
210 EINA_INLIST_FOREACH(wd->stack, it)
212 _item_style_set(it, it->style);
213 _item_title_visible_update(it);
217 static void _emit_hook(Evas_Object *obj,
218 const char *emission,
221 Elm_Object_Item *it = elm_naviframe_top_item_get(obj);
223 return elm_object_item_signal_emit(it, emission, source);
227 _disable_hook(Evas_Object *obj __UNUSED__)
233 _item_text_set_hook(Elm_Object_Item *it,
237 Elm_Naviframe_Text_Item_Pair *pair = NULL;
238 Elm_Naviframe_Item *navi_it = (Elm_Naviframe_Item *)it;
241 if (!part || !strcmp(part, "default"))
242 snprintf(buf, sizeof(buf), "elm.text.title");
243 else if(!strcmp("subtitle", part))
244 snprintf(buf, sizeof(buf), "elm.text.subtitle");
246 snprintf(buf, sizeof(buf), "%s", part);
248 EINA_INLIST_FOREACH(navi_it->text_list, pair)
249 if (!strcmp(buf, pair->part)) break;
253 pair = ELM_NEW(Elm_Naviframe_Text_Item_Pair);
256 ERR("Failed to allocate new text part of the item! : naviframe=%p",
260 eina_stringshare_replace(&pair->part, buf);
261 navi_it->text_list = eina_inlist_append(navi_it->text_list,
262 EINA_INLIST_GET(pair));
264 elm_object_part_text_set(VIEW(navi_it), buf, label);
268 snprintf(buf, sizeof(buf), "elm,state,%s,show", buf);
269 elm_object_signal_emit(VIEW(navi_it), buf, "elm");
273 snprintf(buf, sizeof(buf), "elm,state,%s,hide", buf);
274 elm_object_signal_emit(VIEW(navi_it), buf, "elm");
277 _sizing_eval(WIDGET(navi_it));
281 _item_text_get_hook(const Elm_Object_Item *it, const char *part)
285 if (!part || !strcmp(part, "default"))
286 snprintf(buf, sizeof(buf), "elm.text.title");
287 else if(!strcmp("subtitle", part))
288 snprintf(buf, sizeof(buf), "elm.text.subtitle");
290 snprintf(buf, sizeof(buf), "%s", part);
292 return elm_object_part_text_get(VIEW(it), buf);
296 _item_content_set_hook(Elm_Object_Item *it,
298 Evas_Object *content)
300 Elm_Naviframe_Item *navi_it = (Elm_Naviframe_Item *)it;
303 if (!part || !strcmp("default", part))
305 _item_content_set(navi_it, content);
308 else if (!strcmp(part, "prev_btn"))
310 _title_prev_btn_set(navi_it, content, EINA_FALSE);
313 else if (!strcmp(part, "next_btn"))
315 _title_next_btn_set(navi_it, content);
318 else if (!strcmp(part, "icon"))
320 _title_icon_set(navi_it, content);
325 _title_content_set(navi_it, part, content);
329 _item_content_get_hook(const Elm_Object_Item *it, const char *part)
331 Elm_Naviframe_Item *navi_it = (Elm_Naviframe_Item *)it;
334 if (!part || !strcmp("default", part))
335 return navi_it->content;
336 else if (!strcmp(part, "prev_btn"))
337 return navi_it->title_prev_btn;
338 else if (!strcmp(part, "next_btn"))
339 return navi_it->title_next_btn;
340 else if (!strcmp(part, "icon"))
341 return navi_it->title_icon;
344 return elm_object_part_content_get(VIEW(navi_it), part);
348 _item_content_unset_hook(Elm_Object_Item *it, const char *part)
350 Elm_Naviframe_Item *navi_it = (Elm_Naviframe_Item *)it;
353 if (!part || !strcmp("default", part))
354 return _item_content_unset(navi_it);
355 else if (!strcmp(part, "prev_btn"))
356 return _title_prev_btn_unset(navi_it);
357 else if (!strcmp(part, "next_btn"))
358 return _title_next_btn_unset(navi_it);
359 else if (!strcmp(part, "icon"))
360 return _title_icon_unset(navi_it);
362 return _title_content_unset(navi_it, part);
366 _item_signal_emit_hook(Elm_Object_Item *it,
367 const char *emission,
370 elm_object_signal_emit(VIEW(it), emission, source);
374 _item_title_visible_update(Elm_Naviframe_Item *navi_it)
376 if (navi_it->title_visible)
377 elm_object_signal_emit(VIEW(navi_it), "elm,state,title,show", "elm");
379 elm_object_signal_emit(VIEW(navi_it), "elm,state,title,hide", "elm");
383 _sizing_eval(Evas_Object *obj)
386 Elm_Naviframe_Item *it;
387 Evas_Coord x, y, w, h;
388 Evas_Coord minw = -1, minh = -1;
390 wd = elm_widget_data_get(obj);
393 evas_object_geometry_get(obj, &x, &y, &w, &h);
395 EINA_INLIST_FOREACH(wd->stack, it)
397 evas_object_move(VIEW(it), x, y);
398 evas_object_resize(VIEW(it), w, h);
399 edje_object_size_min_calc(elm_layout_edje_get(VIEW(it)),
402 if (it->minw > minw) minw = it->minw;
403 if (it->minh > minh) minh = it->minh;
405 evas_object_size_hint_min_set(obj, minw, minh);
406 evas_object_size_hint_max_set(obj, -1, -1);
410 _move(void *data __UNUSED__,
413 void *event_info __UNUSED__)
419 _resize(void *data __UNUSED__,
422 void *event_info __UNUSED__)
428 _title_clicked(void *data,
429 Evas_Object *obj __UNUSED__,
430 const char *emission __UNUSED__,
431 const char *source __UNUSED__)
433 Elm_Naviframe_Item *it = data;
434 evas_object_smart_callback_call(WIDGET(it), SIG_TITLE_CLICKED, it);
438 _back_btn_clicked(void *data,
440 void *event_info __UNUSED__)
442 /* Since edje has the event queue, clicked event could be happend multiple times
443 on some heavy environment. This callback del will prevent those scenario and
444 guarantee only one clicked for it's own page. */
445 evas_object_smart_callback_del(obj, "clicked", _back_btn_clicked);
446 elm_naviframe_item_pop(data);
450 _back_btn_new(Evas_Object *obj)
454 btn = elm_button_add(obj);
455 if (!btn) return NULL;
456 evas_object_smart_callback_add(btn, "clicked", _back_btn_clicked, obj);
457 snprintf(buf, sizeof(buf), "naviframe/back_btn/%s",
458 elm_widget_style_get(obj));
459 elm_object_style_set(btn, buf);
463 static void _text_set_hook(Evas_Object *obj,
467 Elm_Object_Item *it = elm_naviframe_top_item_get(obj);
469 elm_object_item_part_text_set(it, part, label);
472 static const char *_text_get_hook(const Evas_Object *obj, const char *part)
474 Elm_Object_Item *it = elm_naviframe_top_item_get(obj);
475 if (!it) return NULL;
476 return elm_object_item_part_text_get(it, part);
480 _content_set_hook(Evas_Object *obj, const char *part, Evas_Object *content)
482 Elm_Object_Item *it = elm_naviframe_top_item_get(obj);
484 elm_object_item_part_content_set(it, part, content);
488 _content_unset_hook(Evas_Object *obj, const char *part)
490 Elm_Object_Item *it = elm_naviframe_top_item_get(obj);
491 if (!it) return NULL;
492 return elm_object_item_part_content_unset(it, part);
496 _content_get_hook(const Evas_Object *obj, const char *part)
498 Elm_Object_Item *it = elm_naviframe_top_item_get(obj);
499 if (!it) return NULL;
500 return elm_object_item_part_content_get(it, part);
504 _title_content_del(void *data,
506 Evas_Object *obj __UNUSED__,
507 void *event_info __UNUSED__)
510 Elm_Naviframe_Content_Item_Pair *pair = data;
511 Elm_Naviframe_Item *it = pair->it;
512 snprintf(buf, sizeof(buf), "elm,state,%s,hide", pair->part);
513 elm_object_signal_emit(VIEW(it), buf, "elm");
514 it->content_list = eina_inlist_remove(it->content_list,
515 EINA_INLIST_GET(pair));
516 eina_stringshare_del(pair->part);
521 _title_prev_btn_del(void *data,
523 Evas_Object *obj __UNUSED__,
524 void *event_info __UNUSED__)
526 Elm_Naviframe_Item *it = data;
527 it->back_btn = EINA_FALSE;
528 it->title_prev_btn = NULL;
529 elm_object_signal_emit(VIEW(it), "elm,state,prev_btn,hide", "elm");
533 _title_next_btn_del(void *data,
535 Evas_Object *obj __UNUSED__,
536 void *event_info __UNUSED__)
538 Elm_Naviframe_Item *it = data;
539 it->title_next_btn = NULL;
540 elm_object_signal_emit(VIEW(it), "elm,state,next_btn,hide", "elm");
544 _title_icon_del(void *data,
546 Evas_Object *obj __UNUSED__,
547 void *event_info __UNUSED__)
549 Elm_Naviframe_Item *it = data;
550 it->title_icon = NULL;
551 elm_object_signal_emit(VIEW(it), "elm,state,icon,hide", "elm");
555 _item_content_del(void *data,
557 Evas_Object *obj __UNUSED__,
558 void *event_info __UNUSED__)
560 Elm_Naviframe_Item *it = data;
562 elm_object_signal_emit(VIEW(it), "elm,state,content,hide", "elm");
566 _title_content_set(Elm_Naviframe_Item *it,
568 Evas_Object *content)
571 Elm_Naviframe_Content_Item_Pair *pair = NULL;
572 Evas_Object *prev_content = NULL;
574 EINA_INLIST_FOREACH(it->content_list, pair)
575 if (!strcmp(part, pair->part)) break;
579 prev_content = elm_object_part_content_get(VIEW(it), part);
580 if (prev_content != content)
584 evas_object_event_callback_del(prev_content,
587 snprintf(buf, sizeof(buf), "elm,state,%s,hide", part);
588 elm_object_signal_emit(VIEW(it), buf, "elm");
590 evas_object_del(prev_content);
591 if (!content) return;
596 if (!content) return;
597 pair = ELM_NEW(Elm_Naviframe_Content_Item_Pair);
600 ERR("Failed to allocate new content part of the item! : naviframe=%p", WIDGET(it));
604 eina_stringshare_replace(&pair->part, part);
605 it->content_list = eina_inlist_append(it->content_list,
606 EINA_INLIST_GET(pair));
608 if (prev_content != content)
610 evas_object_event_callback_add(content,
615 elm_object_part_content_set(VIEW(it), part, content);
616 snprintf(buf, sizeof(buf), "elm,state,%s,show", part);
617 elm_object_signal_emit(VIEW(it), buf, "elm");
619 _sizing_eval(WIDGET(it));
623 _title_prev_btn_set(Elm_Naviframe_Item *it,
627 if (it->title_prev_btn == btn) return;
628 if (it->title_prev_btn) evas_object_del(it->title_prev_btn);
629 it->title_prev_btn = btn;
632 evas_object_event_callback_add(btn,
636 elm_object_part_content_set(VIEW(it), "elm.swallow.prev_btn", btn);
637 elm_object_signal_emit(VIEW(it), "elm,state,prev_btn,show", "elm");
638 it->back_btn = back_btn;
640 _sizing_eval(WIDGET(it));
644 _title_next_btn_set(Elm_Naviframe_Item *it, Evas_Object *btn)
646 if (it->title_next_btn == btn) return;
647 if (it->title_next_btn) evas_object_del(it->title_next_btn);
648 it->title_next_btn = btn;
651 evas_object_event_callback_add(btn,
655 elm_object_part_content_set(VIEW(it), "elm.swallow.next_btn", btn);
656 elm_object_signal_emit(VIEW(it), "elm,state,next_btn,show", "elm");
658 _sizing_eval(WIDGET(it));
662 _title_icon_set(Elm_Naviframe_Item *it, Evas_Object *icon)
664 if (it->title_icon == icon) return;
665 if (it->title_icon) evas_object_del(it->title_icon);
666 it->title_icon = icon;
669 evas_object_event_callback_add(icon,
673 elm_object_part_content_set(VIEW(it), "elm.swallow.icon", icon);
674 elm_object_signal_emit(VIEW(it), "elm,state,icon,show", "elm");
676 _sizing_eval(WIDGET(it));
680 _item_content_unset(Elm_Naviframe_Item *it)
682 Evas_Object *content = it->content;
683 if (!content) return NULL;
685 elm_object_part_content_unset(VIEW(it), "elm.swallow.content");
686 elm_object_signal_emit(VIEW(it), "elm,state,content,hide", "elm");
687 evas_object_event_callback_del(content,
690 _sizing_eval(WIDGET(it));
697 _title_prev_btn_unset(Elm_Naviframe_Item *it)
699 Evas_Object *content = it->title_prev_btn;
700 if (!content) return NULL;
702 elm_object_part_content_unset(VIEW(it), "elm.swallow.prev_btn");
703 elm_object_signal_emit(VIEW(it), "elm,state,prev_btn,hide", "elm");
704 evas_object_event_callback_del(content,
706 _title_prev_btn_del);
707 _sizing_eval(WIDGET(it));
709 it->title_prev_btn = NULL;
714 _title_next_btn_unset(Elm_Naviframe_Item *it)
716 Evas_Object *content = it->title_next_btn;
717 if (!content) return NULL;
719 elm_object_part_content_unset(VIEW(it), "elm.swallow.next_btn");
720 elm_object_signal_emit(VIEW(it), "elm,state,next_btn,hide", "elm");
721 evas_object_event_callback_del(content,
723 _title_next_btn_del);
724 _sizing_eval(WIDGET(it));
726 it->title_next_btn = NULL;
731 _title_icon_unset(Elm_Naviframe_Item *it)
733 Evas_Object *content = it->title_icon;
734 if (!content) return NULL;
736 elm_object_part_content_unset(VIEW(it), "elm.swallow.icon");
737 elm_object_signal_emit(VIEW(it), "elm,state,icon,hide", "elm");
738 evas_object_event_callback_del(content,
741 _sizing_eval(WIDGET(it));
742 it->title_icon = NULL;
748 _title_content_unset(Elm_Naviframe_Item *it, const char *part)
750 Elm_Naviframe_Content_Item_Pair *pair = NULL;
752 Evas_Object *content = NULL;
754 EINA_INLIST_FOREACH(it->content_list, pair)
756 if (!strcmp(part, pair->part))
758 content = elm_object_part_content_get(VIEW(it), part);
759 eina_stringshare_del(pair->part);
760 it->content_list = eina_inlist_remove(it->content_list,
761 EINA_INLIST_GET(pair));
767 if (!content) return NULL;
769 elm_object_part_content_unset(VIEW(it), part);
770 snprintf(buf, sizeof(buf), "elm,state,%s,hide", part);
771 elm_object_signal_emit(VIEW(it), buf, "elm");
772 evas_object_event_callback_del(content,
775 _sizing_eval(WIDGET(it));
781 _item_del(Elm_Naviframe_Item *it)
784 Elm_Naviframe_Content_Item_Pair *content_pair;
785 Elm_Naviframe_Text_Item_Pair *text_pair;
786 Evas_Object *content;
790 wd = elm_widget_data_get(WIDGET(it));
793 while (it->content_list)
796 EINA_INLIST_CONTAINER_GET(it->content_list,
797 Elm_Naviframe_Content_Item_Pair);
798 content = elm_object_part_content_get(VIEW(it), content_pair->part);
799 evas_object_event_callback_del(content,
802 eina_stringshare_del(content_pair->part);
803 it->content_list = eina_inlist_remove(it->content_list,
808 while (it->text_list)
810 text_pair = EINA_INLIST_CONTAINER_GET(it->text_list,
811 Elm_Naviframe_Text_Item_Pair);
812 eina_stringshare_del(text_pair->part);
813 it->text_list = eina_inlist_remove(it->text_list,
818 eina_stringshare_del(it->style);
820 if (wd->preserve && it->content)
822 elm_object_part_content_unset(VIEW(it), "elm.swallow.content");
823 evas_object_event_callback_del(it->content,
830 _item_del_pre_hook(Elm_Object_Item *it)
832 Elm_Naviframe_Item *navi_it;
835 navi_it =(Elm_Naviframe_Item *)it;
836 wd = elm_widget_data_get(WIDGET(navi_it));
837 if (!wd) return EINA_FALSE;
839 if (it == elm_naviframe_top_item_get(WIDGET(navi_it)))
841 wd->stack = eina_inlist_remove(wd->stack, EINA_INLIST_GET(navi_it));
843 //If the item is only one, the stack will be empty
844 if (!wd->stack) return EINA_TRUE;
845 navi_it = EINA_INLIST_CONTAINER_GET(wd->stack->last,
847 evas_object_show(VIEW(navi_it));
848 evas_object_raise(VIEW(navi_it));
849 elm_object_signal_emit(VIEW(navi_it), "elm,state,visible", "elm");
853 wd->stack = eina_inlist_remove(wd->stack, EINA_INLIST_GET(navi_it));
861 _pushed_finished(void *data,
862 Evas_Object *obj __UNUSED__,
863 const char *emission __UNUSED__,
864 const char *source __UNUSED__)
867 Elm_Naviframe_Item *it = data;
870 wd = elm_widget_data_get(WIDGET(it));
873 evas_object_hide(VIEW(it));
876 elm_widget_tree_unfocusable_set(it->content, it->content_unfocusable);
878 if (wd->freeze_events)
879 evas_object_freeze_events_set(VIEW(it), EINA_FALSE);
883 _popped_finished(void *data,
884 Evas_Object *obj __UNUSED__,
885 const char *emission __UNUSED__,
886 const char *source __UNUSED__)
889 Elm_Naviframe_Item *it = data;
892 wd = elm_widget_data_get(WIDGET(it));
895 if (wd->preserve && it->content)
896 elm_widget_tree_unfocusable_set(it->content, it->content_unfocusable);
900 elm_widget_item_free(data);
904 _show_finished(void *data,
905 Evas_Object *obj __UNUSED__,
906 const char *emission __UNUSED__,
907 const char *source __UNUSED__)
909 Elm_Naviframe_Item *it;
914 wd = elm_widget_data_get(WIDGET(it));
917 elm_widget_tree_unfocusable_set(it->content, it->content_unfocusable);
919 evas_object_smart_callback_call(WIDGET(it),
920 SIG_TRANSITION_FINISHED,
922 if (wd->freeze_events)
923 evas_object_freeze_events_set(VIEW(it), EINA_FALSE);
927 _changed_size_hints(void *data,
929 Evas_Object *obj __UNUSED__,
930 void *event_info __UNUSED__)
936 _item_content_set(Elm_Naviframe_Item *navi_it, Evas_Object *content)
938 if (navi_it->content == content) return;
939 if (navi_it->content) evas_object_del(navi_it->content);
940 elm_object_part_content_set(VIEW(navi_it), "elm.swallow.content", content);
943 elm_object_signal_emit(VIEW(navi_it), "elm,state,content,show", "elm");
945 elm_object_signal_emit(VIEW(navi_it), "elm,state,content,hide", "elm");
947 evas_object_event_callback_add(content,
951 navi_it->content = content;
952 _sizing_eval(WIDGET(navi_it));
955 //FIXME: need to handle if this function is called while transition
957 _item_style_set(Elm_Naviframe_Item *navi_it, const char *item_style)
959 Elm_Naviframe_Content_Item_Pair *content_pair;
960 Elm_Naviframe_Text_Item_Pair *text_pair;
967 strcpy(buf, "item/basic");
968 eina_stringshare_replace(&navi_it->style, "basic");
972 snprintf(buf, sizeof(buf), "item/%s", item_style);
973 eina_stringshare_replace(&navi_it->style, item_style);
975 elm_layout_theme_set(VIEW(navi_it),
978 elm_widget_style_get(WIDGET(navi_it)));
980 EINA_INLIST_FOREACH(navi_it->text_list, text_pair)
981 _item_text_set_hook((Elm_Object_Item *) navi_it,
983 elm_object_part_text_get(VIEW(navi_it),
986 EINA_INLIST_FOREACH(navi_it->content_list, content_pair)
987 _item_content_set_hook((Elm_Object_Item *) navi_it,
989 elm_object_part_content_get(VIEW(navi_it),
990 content_pair->part));
992 if (navi_it->content)
993 elm_object_signal_emit(VIEW(navi_it), "elm,state,content,show", "elm");
996 if (navi_it->title_prev_btn)
997 elm_object_signal_emit(VIEW(navi_it), "elm,state,prev_btn,show", "elm");
1000 if (navi_it->title_next_btn)
1001 elm_object_signal_emit(VIEW(navi_it), "elm,state,next_btn,show", "elm");
1003 // why does this forcibly enable title? isnt that separate to style?
1004 // navi_it->title_visible = EINA_TRUE;
1005 _sizing_eval(WIDGET(navi_it));
1007 wd = elm_widget_data_get(WIDGET(navi_it));
1010 if (wd->freeze_events)
1011 evas_object_freeze_events_set(VIEW(navi_it), EINA_FALSE);
1014 static Elm_Naviframe_Item *
1015 _item_new(Evas_Object *obj,
1016 const char *title_label,
1017 Evas_Object *prev_btn,
1018 Evas_Object *next_btn,
1019 Evas_Object *content,
1020 const char *item_style)
1022 Widget_Data *wd = elm_widget_data_get(obj);
1025 Elm_Naviframe_Item *it = elm_widget_item_new(obj, Elm_Naviframe_Item);
1028 ERR("Failed to allocate new item! : naviframe=%p", obj);
1032 elm_widget_item_del_pre_hook_set(it, _item_del_pre_hook);
1033 elm_widget_item_text_set_hook_set(it, _item_text_set_hook);
1034 elm_widget_item_text_get_hook_set(it, _item_text_get_hook);
1035 elm_widget_item_content_set_hook_set(it, _item_content_set_hook);
1036 elm_widget_item_content_get_hook_set(it, _item_content_get_hook);
1037 elm_widget_item_content_unset_hook_set(it, _item_content_unset_hook);
1038 elm_widget_item_signal_emit_hook_set(it, _item_signal_emit_hook);
1041 VIEW(it) = elm_layout_add(obj);
1042 evas_object_smart_member_add(VIEW(it), wd->base);
1044 evas_object_event_callback_add(VIEW(it),
1045 EVAS_CALLBACK_CHANGED_SIZE_HINTS,
1046 _changed_size_hints,
1048 elm_object_signal_callback_add(VIEW(it),
1049 "elm,action,show,finished",
1051 _show_finished, it);
1052 elm_object_signal_callback_add(VIEW(it),
1053 "elm,action,pushed,finished",
1055 _pushed_finished, it);
1056 elm_object_signal_callback_add(VIEW(it),
1057 "elm,action,popped,finished",
1059 _popped_finished, it);
1060 elm_object_signal_callback_add(VIEW(it),
1061 "elm,action,title,clicked",
1063 _title_clicked, it);
1065 _item_style_set(it, item_style);
1066 _item_text_set_hook((Elm_Object_Item *)it, "elm.text.title", title_label);
1069 if ((!prev_btn) && wd->auto_pushed && eina_inlist_count(wd->stack))
1071 prev_btn = _back_btn_new(obj);
1072 _title_prev_btn_set(it, prev_btn, EINA_TRUE);
1075 _title_prev_btn_set(it, prev_btn, EINA_FALSE);
1077 _title_next_btn_set(it, next_btn);
1078 _item_content_set(it, content);
1079 it->title_visible = EINA_TRUE;
1084 _focus_next_hook(const Evas_Object *obj, Elm_Focus_Direction dir, Evas_Object **next)
1087 Elm_Naviframe_Item *top_it;
1088 Eina_List *l = NULL;
1089 Widget_Data *wd = elm_widget_data_get(obj);
1090 void *(*list_data_get)(const Eina_List *list);
1091 if (!wd) return EINA_FALSE;
1093 top_it = (Elm_Naviframe_Item *)elm_naviframe_top_item_get(obj);
1094 if (!top_it) return EINA_FALSE;
1096 list_data_get = eina_list_data_get;
1098 //Forcus order: prev button, next button, contents
1099 if (top_it->title_prev_btn)
1100 l = eina_list_append(l, top_it->title_prev_btn);
1101 if (top_it->title_next_btn)
1102 l = eina_list_append(l, top_it->title_next_btn);
1103 l = eina_list_append(l, VIEW(top_it));
1105 ret = elm_widget_focus_list_next_get(obj, l, list_data_get, dir, next);
1111 elm_naviframe_add(Evas_Object *parent)
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_text_set_hook_set(obj, _text_set_hook);
1126 elm_widget_text_get_hook_set(obj, _text_get_hook);
1127 elm_widget_content_set_hook_set(obj, _content_set_hook);
1128 elm_widget_content_get_hook_set(obj, _content_get_hook);
1129 elm_widget_content_unset_hook_set(obj, _content_unset_hook);
1130 elm_widget_signal_emit_hook_set(obj, _emit_hook);
1131 elm_widget_can_focus_set(obj, EINA_FALSE);
1132 elm_widget_focus_next_hook_set(obj, _focus_next_hook);
1135 //FIXME: Is this base layout really needed?
1136 wd->base = elm_layout_add(parent);
1137 evas_object_event_callback_add(wd->base,
1138 EVAS_CALLBACK_CHANGED_SIZE_HINTS,
1139 _changed_size_hints,
1141 elm_widget_resize_object_set(obj, wd->base);
1142 elm_layout_theme_set(wd->base, "naviframe", "base", "default");
1144 evas_object_event_callback_add(obj, EVAS_CALLBACK_MOVE, _move, obj);
1145 evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE, _resize, obj);
1146 evas_object_smart_callbacks_descriptions_set(obj, _signals);
1148 wd->auto_pushed = EINA_TRUE;
1149 wd->freeze_events = EINA_TRUE;
1154 EAPI Elm_Object_Item *
1155 elm_naviframe_item_push(Evas_Object *obj,
1156 const char *title_label,
1157 Evas_Object *prev_btn,
1158 Evas_Object *next_btn,
1159 Evas_Object *content,
1160 const char *item_style)
1162 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1164 Elm_Naviframe_Item *prev_it, *it;
1166 wd = elm_widget_data_get(obj);
1167 if (!wd) return NULL;
1169 it = _item_new(obj, title_label, prev_btn, next_btn, content, item_style);
1170 if (!it) return NULL;
1172 evas_object_show(VIEW(it));
1174 prev_it = (Elm_Naviframe_Item *) elm_naviframe_top_item_get(obj);
1177 if (wd->freeze_events)
1179 evas_object_freeze_events_set(VIEW(it), EINA_TRUE);
1180 evas_object_freeze_events_set(VIEW(prev_it), EINA_TRUE);
1182 elm_object_signal_emit(VIEW(prev_it), "elm,state,cur,pushed", "elm");
1183 elm_object_signal_emit(VIEW(it), "elm,state,new,pushed", "elm");
1184 edje_object_message_signal_process(elm_layout_edje_get(VIEW(prev_it)));
1185 if (prev_it->content)
1187 prev_it->content_unfocusable = elm_widget_tree_unfocusable_get(prev_it->content);
1188 elm_widget_tree_unfocusable_set(prev_it->content, EINA_TRUE);
1190 edje_object_message_signal_process(elm_layout_edje_get(VIEW(it)));
1192 wd->stack = eina_inlist_append(wd->stack, EINA_INLIST_GET(it));
1194 return (Elm_Object_Item *)it;
1197 EAPI Elm_Object_Item *
1198 elm_naviframe_item_insert_before(Evas_Object *obj,
1199 Elm_Object_Item *before,
1200 const char *title_label,
1201 Evas_Object *prev_btn,
1202 Evas_Object *next_btn,
1203 Evas_Object *content,
1204 const char *item_style)
1206 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1207 ELM_OBJ_ITEM_CHECK_OR_RETURN(before, NULL);
1208 Elm_Naviframe_Item *it;
1211 wd = elm_widget_data_get(obj);
1212 if (!wd) return NULL;
1214 it = _item_new(obj, title_label, prev_btn, next_btn, content, item_style);
1215 if (!it) return NULL;
1218 eina_inlist_prepend_relative(wd->stack,
1219 EINA_INLIST_GET(it),
1220 EINA_INLIST_GET(((Elm_Naviframe_Item *) before)));
1222 return (Elm_Object_Item *)it;
1225 EAPI Elm_Object_Item *
1226 elm_naviframe_item_insert_after(Evas_Object *obj,
1227 Elm_Object_Item *after,
1228 const char *title_label,
1229 Evas_Object *prev_btn,
1230 Evas_Object *next_btn,
1231 Evas_Object *content,
1232 const char *item_style)
1234 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1235 ELM_OBJ_ITEM_CHECK_OR_RETURN(after, NULL);
1236 Elm_Naviframe_Item *it;
1239 wd = elm_widget_data_get(obj);
1240 if (!wd) return NULL;
1242 it = _item_new(obj, title_label, prev_btn, next_btn, content, item_style);
1243 if (!it) return NULL;
1245 if (elm_naviframe_top_item_get(obj) == after)
1247 evas_object_show(VIEW(it));
1248 evas_object_hide(VIEW(after));
1251 eina_inlist_append_relative(wd->stack,
1252 EINA_INLIST_GET(it),
1253 EINA_INLIST_GET(((Elm_Naviframe_Item *) after)));
1255 return (Elm_Object_Item *)it;
1259 elm_naviframe_item_pop(Evas_Object *obj)
1261 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1262 Elm_Naviframe_Item *it, *prev_it = NULL;
1264 Evas_Object *content = NULL;
1266 wd = elm_widget_data_get(obj);
1267 if (!wd) return NULL;
1269 it = (Elm_Naviframe_Item *) elm_naviframe_top_item_get(obj);
1270 if (!it) return NULL;
1272 content = it->content;
1276 it->content_unfocusable = elm_widget_tree_unfocusable_get(it->content);
1277 elm_widget_tree_unfocusable_set(it->content, EINA_TRUE);
1280 if (wd->stack->last->prev)
1281 prev_it = EINA_INLIST_CONTAINER_GET(wd->stack->last->prev,
1282 Elm_Naviframe_Item);
1283 wd->stack = eina_inlist_remove(wd->stack, EINA_INLIST_GET(it));
1286 if (wd->freeze_events)
1288 evas_object_freeze_events_set(VIEW(it), EINA_TRUE);
1289 evas_object_freeze_events_set(VIEW(prev_it), EINA_TRUE);
1291 elm_object_signal_emit(VIEW(it), "elm,state,cur,popped", "elm");
1292 evas_object_show(VIEW(prev_it));
1293 evas_object_raise(VIEW(prev_it));
1294 elm_object_signal_emit(VIEW(prev_it),
1295 "elm,state,prev,popped",
1297 edje_object_message_signal_process(elm_layout_edje_get(VIEW(it)));
1298 edje_object_message_signal_process(elm_layout_edje_get(VIEW(prev_it)));
1303 elm_widget_item_free(it);
1310 elm_naviframe_item_pop_to(Elm_Object_Item *it)
1312 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1313 Elm_Naviframe_Item *navi_it;
1315 Eina_Inlist *l, *prev_l;
1317 navi_it = (Elm_Naviframe_Item *)it;
1318 wd = elm_widget_data_get(WIDGET(navi_it));
1321 if (it == elm_naviframe_top_item_get(WIDGET(navi_it))) return;
1323 l = wd->stack->last->prev;
1327 if (EINA_INLIST_CONTAINER_GET(l, Elm_Naviframe_Item) ==
1328 ((Elm_Naviframe_Item *)it)) break;
1330 wd->stack = eina_inlist_remove(wd->stack, l);
1331 _item_del(EINA_INLIST_CONTAINER_GET(l, Elm_Naviframe_Item));
1332 elm_widget_item_free(EINA_INLIST_CONTAINER_GET(l,
1333 Elm_Naviframe_Item));
1336 elm_naviframe_item_pop(WIDGET(navi_it));
1340 elm_naviframe_item_promote(Elm_Object_Item *it)
1342 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1343 Elm_Naviframe_Item *navi_it;
1344 Elm_Naviframe_Item *prev_it;
1347 navi_it = (Elm_Naviframe_Item *)it;
1348 wd = elm_widget_data_get(navi_it->base.widget);
1351 if (it == elm_naviframe_top_item_get(navi_it->base.widget)) return;
1352 wd->stack = eina_inlist_demote(wd->stack, EINA_INLIST_GET(navi_it));
1353 prev_it = EINA_INLIST_CONTAINER_GET(wd->stack->last->prev,
1354 Elm_Naviframe_Item);
1355 if (prev_it->content)
1357 prev_it->content_unfocusable = elm_widget_tree_unfocusable_get(prev_it->content);
1358 elm_widget_tree_unfocusable_set(prev_it->content, EINA_TRUE);
1361 if (wd->freeze_events)
1363 evas_object_freeze_events_set(VIEW(it), EINA_TRUE);
1364 evas_object_freeze_events_set(VIEW(prev_it), EINA_TRUE);
1366 elm_object_signal_emit(VIEW(prev_it),
1367 "elm,state,cur,pushed",
1369 evas_object_show(VIEW(navi_it));
1370 evas_object_raise(VIEW(navi_it));
1371 elm_object_signal_emit(VIEW(navi_it),
1372 "elm,state,new,pushed",
1374 edje_object_message_signal_process(elm_layout_edje_get(VIEW(prev_it)));
1375 edje_object_message_signal_process(elm_layout_edje_get(VIEW(navi_it)));
1379 elm_naviframe_item_simple_promote(Evas_Object *obj, Evas_Object *content)
1381 ELM_CHECK_WIDTYPE(obj, widtype);
1382 Widget_Data *wd = elm_widget_data_get(obj);
1384 Elm_Naviframe_Item *itr;
1385 EINA_INLIST_FOREACH(wd->stack, itr)
1387 if (elm_object_item_content_get((Elm_Object_Item *)itr) == content)
1389 elm_naviframe_item_promote((Elm_Object_Item *)itr);
1397 elm_naviframe_content_preserve_on_pop_set(Evas_Object *obj, Eina_Bool preserve)
1399 ELM_CHECK_WIDTYPE(obj, widtype);
1400 Widget_Data *wd = elm_widget_data_get(obj);
1402 wd->preserve = !!preserve;
1406 elm_naviframe_content_preserve_on_pop_get(const Evas_Object *obj)
1408 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1409 Widget_Data *wd = elm_widget_data_get(obj);
1410 if (!wd) return EINA_FALSE;
1411 return wd->preserve;
1414 EAPI Elm_Object_Item*
1415 elm_naviframe_top_item_get(const Evas_Object *obj)
1417 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1418 Widget_Data *wd = elm_widget_data_get(obj);
1419 if ((!wd) || (!wd->stack)) return NULL;
1420 return (Elm_Object_Item *) (EINA_INLIST_CONTAINER_GET(wd->stack->last,
1421 Elm_Naviframe_Item));
1424 EAPI Elm_Object_Item*
1425 elm_naviframe_bottom_item_get(const Evas_Object *obj)
1427 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1428 Widget_Data *wd = elm_widget_data_get(obj);
1429 if ((!wd) || (!wd->stack)) return NULL;
1430 return (Elm_Object_Item *) (EINA_INLIST_CONTAINER_GET(wd->stack,
1431 Elm_Naviframe_Item));
1435 elm_naviframe_item_style_set(Elm_Object_Item *it, const char *item_style)
1437 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1438 Elm_Naviframe_Item *navi_it = (Elm_Naviframe_Item *)it;
1441 if (!strcmp(item_style, navi_it->style)) return;
1444 if (!strcmp("basic", navi_it->style)) return;
1446 _item_style_set(navi_it, item_style);
1450 elm_naviframe_item_style_get(const Elm_Object_Item *it)
1452 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
1453 Elm_Naviframe_Item *navi_it = (Elm_Naviframe_Item *)it;
1454 return navi_it->style;
1458 elm_naviframe_item_title_visible_set(Elm_Object_Item *it, Eina_Bool visible)
1460 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1461 Elm_Naviframe_Item *navi_it = (Elm_Naviframe_Item *)it;
1463 visible = !!visible;
1464 if (navi_it->title_visible == visible) return;
1466 navi_it->title_visible = visible;
1467 _item_title_visible_update(navi_it);
1471 elm_naviframe_item_title_visible_get(const Elm_Object_Item *it)
1473 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
1474 Elm_Naviframe_Item *navi_it = (Elm_Naviframe_Item *)it;
1475 return navi_it->title_visible;
1479 elm_naviframe_prev_btn_auto_pushed_set(Evas_Object *obj, Eina_Bool auto_pushed)
1481 ELM_CHECK_WIDTYPE(obj, widtype);
1482 Widget_Data *wd = elm_widget_data_get(obj);
1484 wd->auto_pushed = !!auto_pushed;
1488 elm_naviframe_prev_btn_auto_pushed_get(const Evas_Object *obj)
1490 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1491 Widget_Data *wd = elm_widget_data_get(obj);
1492 if (!wd) return EINA_FALSE;
1493 return wd->auto_pushed;
1497 elm_naviframe_items_get(const Evas_Object *obj)
1499 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1500 Widget_Data *wd = elm_widget_data_get(obj);
1501 if (!wd) return NULL;
1502 Eina_List *ret = NULL;
1503 Elm_Naviframe_Item *itr;
1504 EINA_INLIST_FOREACH(wd->stack, itr)
1505 ret = eina_list_append(ret, itr);
1510 elm_naviframe_event_enabled_set(Evas_Object *obj, Eina_Bool enabled)
1512 ELM_CHECK_WIDTYPE(obj, widtype);
1513 Widget_Data *wd = elm_widget_data_get(obj);
1515 enabled = !!enabled;
1516 if (wd->freeze_events == !enabled) return;
1517 wd->freeze_events = !enabled;
1521 elm_naviframe_event_enabled_get(const Evas_Object *obj)
1523 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1524 Widget_Data *wd = elm_widget_data_get(obj);
1525 if (!wd) return EINA_FALSE;
1526 return !wd->freeze_events;