1 #include <Elementary.h>
5 * @defgroup NavigationBar NavigationBar
8 * The Navigationbar is an object that allows flipping (with animation) between 1 or
9 * more of objects, much like a stack of windows within the window. It also displays title
10 * area above all the pages consisting of title,function buttons.
12 * Objects can be pushed or popped from the stack.
13 * Pushes and pops will animate (and a pop will delete the object once the
14 * animation is finished). Objects are pushed to the top with
15 * elm_navigationbar_push() and when the top item is no longer
16 * wanted, simply pop it with elm_navigationbar_pop() and it will also be
17 * deleted. You can query which objects are the top and bottom with
18 * elm_navigationbar_content_bottom_get() and elm_navigationbar_content_top_get().
21 #define _ELM_NAVIBAR_PREV_BTN_DEFAULT_LABEL "Previous"
23 typedef struct _Widget_Data Widget_Data;
24 typedef struct _Elm_Navigationbar_Item Elm_Navigationbar_Item;
25 typedef struct _Transit_Cb_Data Transit_Cb_Data;
27 static const char _navigationbar_key[] = "_elm_navigationbar";
32 ELM_NAVIGATIONBAR_PREV_BUTTON = ELM_NAVIGATIONBAR_FUNCTION_BUTTON1,
33 ELM_NAVIGATIONBAR_NEXT_BUTTON = ELM_NAVIGATIONBAR_FUNCTION_BUTTON2,
34 ELM_NAVIGATIONBAR_TITLE_BTN_CNT = 2
35 } Elm_Navigationbar_Button_Type;
42 Eina_Bool title_visible : 1;
46 struct _Elm_Navigationbar_Item
51 Eina_List *title_obj_list; //TODO: Remove!
52 Evas_Object *title_obj;
53 Evas_Object *title_btns[ELM_NAVIGATIONBAR_TITLE_BTN_CNT];
56 Eina_Bool titleobj_visible :1;
57 Eina_Bool back_btn :1;
61 struct _Transit_Cb_Data
63 Elm_Navigationbar_Item* prev_it;
64 Elm_Navigationbar_Item* it;
67 Eina_Bool first_page : 1;
70 static const char *widtype = NULL;
72 static void _del_hook(Evas_Object *obj);
73 static void _theme_hook(Evas_Object *obj);
74 static void _sizing_eval(Evas_Object *obj);
75 static void _resize(void *data, Evas *e, Evas_Object *obj, void *event_info);
76 static void _item_sizing_eval(Elm_Navigationbar_Item *it);
77 static void _item_del(Elm_Navigationbar_Item *it);
78 static void _back_button_clicked(void *data, Evas_Object *obj, void *event_info);
79 static void _button_size_set(Evas_Object *obj);
80 static Eina_Bool _button_set(Evas_Object *obj, Evas_Object *prev_btn, Evas_Object *new_btn, Eina_Bool back_btn);
81 static void _transition_complete_cb(void *data);
82 static void _elm_navigationbar_prev_btn_set(Evas_Object *obj,
85 Elm_Navigationbar_Item *it);
86 static void _elm_navigationbar_next_btn_set(Evas_Object *obj,
89 Elm_Navigationbar_Item *it);
90 static void _title_clicked(void *data, Evas_Object *obj, const char *emission, const char *source);
91 static void _titleobj_switching(Evas_Object *obj, Elm_Navigationbar_Item *it);
92 static void _emit_hook(Evas_Object *obj, const char *emission, const char *source);
94 static const char SIG_HIDE_FINISHED[] = "hide,finished";
95 static const char SIG_TITLE_OBJ_VISIBLE_CHANGED[] = "titleobj,visible,changed";
96 static const char SIG_TITLE_CLICKED[] = "title,clicked";
98 static const Evas_Smart_Cb_Description _signals[] = {
99 {SIG_HIDE_FINISHED, ""},
100 {SIG_TITLE_OBJ_VISIBLE_CHANGED, ""},
101 {SIG_TITLE_CLICKED, ""},
106 _content_del(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
108 Elm_Navigationbar_Item *it = data;
109 evas_object_data_del(obj, _navigationbar_key);
111 //TODO: it will be better remove this page?
115 _title_obj_del(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
117 Elm_Navigationbar_Item *it = data;
119 elm_navigationbar_title_object_list_unset(it->base.widget, it->content, &l);
121 evas_object_del(eina_list_data_get(l));
126 _title_icon_del(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
128 Elm_Navigationbar_Item *it = data;
133 _title_btn_del(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
135 Elm_Navigationbar_Item *it = data;
137 if (it->title_btns[ELM_NAVIGATIONBAR_PREV_BUTTON] == obj)
138 it->title_btns[ELM_NAVIGATIONBAR_PREV_BUTTON] = NULL;
139 else if (it->title_btns[ELM_NAVIGATIONBAR_NEXT_BUTTON] == obj)
140 it->title_btns[ELM_NAVIGATIONBAR_NEXT_BUTTON] = NULL;
144 _title_btn_set(Elm_Navigationbar_Item *it, Evas_Object *btn, int title_btn_idx, Eina_Bool back_btn)
148 if(it->title_btns[title_btn_idx] == btn) return EINA_FALSE;
150 changed = _button_set(it->base.widget, it->title_btns[title_btn_idx], btn, back_btn);
151 it->title_btns[title_btn_idx] = btn;
153 if ((!changed) || (!btn)) return EINA_FALSE;
155 it->back_btn = back_btn;
157 evas_object_event_callback_add(btn, EVAS_CALLBACK_DEL, _title_btn_del, it);
163 _create_back_btn(Evas_Object *parent, const char *title, void *data)
165 Evas_Object *btn = elm_button_add(parent);
166 if (!btn) return NULL;
167 elm_object_text_set(btn, title);
168 evas_object_smart_callback_add(btn, "clicked", _back_button_clicked, data);
173 _del_hook(Evas_Object *obj)
175 Widget_Data *wd = elm_widget_data_get(obj);
177 Elm_Navigationbar_Item *it;
179 EINA_LIST_FOREACH(wd->stack, list, it)
181 eina_list_free(wd->stack);
186 _emit_hook(Evas_Object *obj, const char *emission, const char *source)
188 ELM_CHECK_WIDTYPE(obj, widtype);
192 Elm_Navigationbar_Item *it;
194 wd = elm_widget_data_get(obj);
197 last = eina_list_last(wd->stack);
200 it = eina_list_data_get(last);
201 if ((!it) || (!it->title_obj)) return;
203 //FIXME: I know this is really bullshit.
204 //We don't need to keep the titleobj_visible but return the status in edc.
205 if (!strcmp(source, "elm"))
207 if (!strcmp(emission, "elm,state,hide,noanimate,title"))
208 it->titleobj_visible = EINA_FALSE;
209 else if (!strcmp(emission, "elm,state,show,noanimate,title"))
210 it->titleobj_visible = EINA_TRUE;
213 edje_object_signal_emit(wd->base, emission, source);
217 _theme_hook(Evas_Object *obj)
219 Widget_Data *wd = elm_widget_data_get(obj);
220 Eina_List *list = NULL;
221 Elm_Navigationbar_Item *it = NULL;
224 _elm_theme_object_set(obj, wd->base, "navigationbar", "base", elm_widget_style_get(obj));
226 list = eina_list_last(wd->stack);
229 it = eina_list_data_get(list);
233 if (it->title_btns[ELM_NAVIGATIONBAR_PREV_BUTTON])
234 edje_object_part_swallow(wd->base, "elm.swallow.prev_btn", it->title_btns[ELM_NAVIGATIONBAR_PREV_BUTTON]);
235 if (it->title_btns[ELM_NAVIGATIONBAR_NEXT_BUTTON])
236 edje_object_part_swallow(wd->base, "elm.swallow.next_btn", it->title_btns[ELM_NAVIGATIONBAR_NEXT_BUTTON]);
241 edje_object_part_swallow(wd->base, "elm.swallow.icon", it->icon);
242 edje_object_signal_emit(wd->base, "elm,state,icon,visible", "elm");
247 edje_object_part_text_set(wd->base, "elm.text", it->title);
252 edje_object_part_swallow(wd->base, "elm.swallow.title", it->title_obj);
254 if (it->titleobj_visible)
255 edje_object_signal_emit(wd->base, "elm,state,show,noanimate,title", "elm");
257 edje_object_signal_emit(wd->base, "elm,state,hide,noanimate,title", "elm"); //elm,state,title,hide
260 edje_object_signal_emit(wd->base, "elm,state,show,extended", "elm");
265 if (!wd->title_visible)
266 edje_object_signal_emit(wd->base, "elm,state,item,moveup", "elm");
268 edje_object_message_signal_process(wd->base);
273 _item_del(Elm_Navigationbar_Item *it)
275 //TODO: So hard to manage.
276 //TODO: Just prepare one layout for title objects.
277 //TODO: then remove the layout only.
283 wd = elm_widget_data_get(it->base.widget);
286 //Remove Function Buttons
287 for (idx = 0; idx < ELM_NAVIGATIONBAR_TITLE_BTN_CNT; idx++)
289 if (!it->title_btns[idx]) continue;
290 if (!it->back_btn) elm_object_unfocus(it->title_btns[idx]);
291 evas_object_event_callback_del(it->title_btns[idx], EVAS_CALLBACK_DEL, _title_btn_del);
292 evas_object_del(it->title_btns[idx]);
296 evas_object_event_callback_del(it->icon, EVAS_CALLBACK_DEL, _title_icon_del);
297 evas_object_del(it->icon);
301 evas_object_event_callback_del(it->title_obj, EVAS_CALLBACK_DEL, _title_obj_del);
302 evas_object_del(it->title_obj);
303 eina_list_free(it->title_obj_list);
305 if (it->title) eina_stringshare_del(it->title);
306 if (it->subtitle) eina_stringshare_del(it->subtitle);
310 evas_object_data_del(it->content, _navigationbar_key);
311 evas_object_event_callback_del(it->content, EVAS_CALLBACK_DEL, _content_del);
318 _sizing_eval(Evas_Object *obj)
323 wd = elm_widget_data_get(obj);
326 list = eina_list_last(wd->stack);
329 _item_sizing_eval(list->data);
333 _item_sizing_eval(Elm_Navigationbar_Item *it)
336 Widget_Data *wd = elm_widget_data_get(it->base.widget);
341 edje_object_size_min_calc(wd->base, &minw, NULL);
343 //TODO: Even the below code for size calculation is redundant and should be removed.
344 //TODO: Item_sizing_eval function has to be totally refactored/removed.
345 _button_size_set(it->title_btns[ELM_NAVIGATIONBAR_PREV_BUTTON]);
346 _button_size_set(it->title_btns[ELM_NAVIGATIONBAR_NEXT_BUTTON]);
350 _resize(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
356 _titleobj_switching(Evas_Object *obj, Elm_Navigationbar_Item *it)
358 Widget_Data *wd = elm_widget_data_get(obj);
361 if (!it->title_obj) return;
363 if (elm_navigationbar_content_top_get(it->base.widget) != it->content)
366 if (it->titleobj_visible)
367 edje_object_signal_emit(wd->base, "elm,state,show,title", "elm"); //elm,state,title,show
369 edje_object_signal_emit(wd->base, "elm,state,hide,title", "elm"); //elm,state,title,hide
371 _item_sizing_eval(it);
375 _title_clicked(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
377 Evas_Object *navibar = data;
380 Elm_Navigationbar_Item *it;
382 wd = elm_widget_data_get(navibar);
385 last = eina_list_last(wd->stack);
388 it = eina_list_data_get(last);
389 if ((!it) || (!it->title_obj)) return;
391 if (!it->titleobj_visible)
393 it->titleobj_visible = EINA_TRUE;
394 evas_object_smart_callback_call(it->base.widget, SIG_TITLE_OBJ_VISIBLE_CHANGED, (void *) EINA_TRUE);
398 it->titleobj_visible = EINA_FALSE;
399 evas_object_smart_callback_call(it->base.widget, SIG_TITLE_OBJ_VISIBLE_CHANGED, (void *) EINA_FALSE);
402 evas_object_smart_callback_call(navibar, SIG_TITLE_CLICKED, NULL);
404 _titleobj_switching(navibar, it);
407 //TODO: should be renamed.
409 _transition_complete_cb(void *data)
411 Evas_Object *navi_bar;
413 Elm_Navigationbar_Item *prev_it;
414 Elm_Navigationbar_Item *it;
417 Transit_Cb_Data *cb = data;
420 navi_bar = cb->navibar;
421 if (!navi_bar) return;
423 wd = elm_widget_data_get(navi_bar);
426 prev_it = cb->prev_it;
429 if (cb->pop && prev_it)
431 ll = eina_list_last(wd->stack);
432 if (ll->data == prev_it)
435 wd->stack = eina_list_remove_list(wd->stack, ll);
440 if (prev_it->title_btns[ELM_NAVIGATIONBAR_PREV_BUTTON])
441 evas_object_hide(prev_it->title_btns[ELM_NAVIGATIONBAR_PREV_BUTTON]);
442 if (prev_it->title_btns[ELM_NAVIGATIONBAR_NEXT_BUTTON])
443 evas_object_hide(prev_it->title_btns[ELM_NAVIGATIONBAR_NEXT_BUTTON]);
444 if (prev_it->title_obj)
445 evas_object_hide(prev_it->title_obj);
447 evas_object_hide(prev_it->icon);
449 if ((it) && (wd->title_visible))
451 edje_object_part_text_set(wd->base, "elm.text", it->title);
456 edje_object_signal_emit(wd->base, "elm,action,pop", "elm");
458 edje_object_signal_emit(wd->base, "elm,action,push", "elm");
459 evas_object_pass_events_set(wd->base, EINA_TRUE);
463 edje_object_part_swallow(wd->base, "elm.swallow.title", it->title_obj);
466 edje_object_part_text_set(wd->base, "elm.text.sub", it->subtitle);
468 edje_object_part_text_set(wd->base, "elm.text.sub", NULL);
470 if (it->title_btns[ELM_NAVIGATIONBAR_PREV_BUTTON])
471 edje_object_part_swallow(wd->base, "elm.swallow.prev_btn", it->title_btns[ELM_NAVIGATIONBAR_PREV_BUTTON]);
472 if (it->title_btns[ELM_NAVIGATIONBAR_NEXT_BUTTON])
473 edje_object_part_swallow(wd->base, "elm.swallow.next_btn", it->title_btns[ELM_NAVIGATIONBAR_NEXT_BUTTON]);
477 edje_object_part_swallow(wd->base, "elm.swallow.icon", it->icon);
478 edje_object_signal_emit(wd->base, "elm,state,icon,visible", "elm");
481 edje_object_signal_emit(wd->base, "elm,state,icon,hidden", "elm");
483 if ((it->title_obj) && (it->title))
485 edje_object_signal_emit(wd->base, "elm,state,show,extended", "elm");
486 if(it->titleobj_visible)
488 //TODO: remove the dependency on these signals as related to nbeat, try to make it totally theme dependent
489 edje_object_signal_emit(wd->base, "elm,state,show,noanimate,title", "elm");
492 //TODO: remove the dependency on these signals as related to nbeat, try to make it totally theme dependent
493 edje_object_signal_emit(wd->base, "elm,state,hide,noanimate,title", "elm");
497 edje_object_signal_emit(wd->base, "elm,state,hide,extended", "elm");
498 //TODO: remove the dependency on these signals as related to nbeat, try to make it totally theme dependent
499 edje_object_signal_emit(wd->base, "elm,state,hide,noanimate,title", "elm");
500 it->titleobj_visible = EINA_FALSE;
506 _back_button_clicked(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
508 Elm_Navigationbar_Item *it = data;
509 elm_navigationbar_pop(it->base.widget);
513 _hide_finished(void *data, Evas_Object *obj __UNUSED__, void *event_info)
515 Evas_Object *navi_bar = data;
516 Widget_Data *wd = elm_widget_data_get(navi_bar);
517 wd->popping = EINA_FALSE;
518 evas_object_smart_callback_call(navi_bar, SIG_HIDE_FINISHED, event_info);
519 evas_object_pass_events_set(wd->base, EINA_FALSE);
523 _button_size_set(Evas_Object *obj)
526 Evas_Coord minw = -1, minh = -1, maxw= -1, maxh = -1;
527 Evas_Coord w = 0, h = 0;
529 evas_object_size_hint_min_get(obj, &minw, &minh);
530 evas_object_size_hint_max_get(obj, &maxw, &maxh);
531 evas_object_geometry_get(obj, NULL, NULL, &w, &h);
532 if (w < minw) w = minw;
533 if (h < minh) h = minh;
534 if ((maxw >= 0) && (w > maxw)) w = maxw;
535 if ((maxh >= 0) && (h > maxh)) h = maxh;
536 evas_object_resize(obj, w, h);
540 _elm_navigationbar_prev_btn_set(Evas_Object *obj, Evas_Object *content, Evas_Object *new_btn, Elm_Navigationbar_Item *it)
543 Evas_Object *prev_btn;
545 wd = elm_widget_data_get(obj);
548 if (!_title_btn_set(it, new_btn, ELM_NAVIGATIONBAR_PREV_BUTTON, EINA_FALSE))
551 //update if the content is the top item
552 if (elm_navigationbar_content_top_get(obj) != content)
555 prev_btn = edje_object_part_swallow_get(wd->base, "elm.swallow.prev_btn");
556 if (prev_btn) evas_object_del(prev_btn);
557 edje_object_part_swallow(wd->base, "elm.swallow.prev_btn", new_btn);
560 //TODO: looks make this _elm_navigationbar_function_button1_set same.
562 _elm_navigationbar_next_btn_set(Evas_Object *obj, Evas_Object *content, Evas_Object *new_btn, Elm_Navigationbar_Item *it)
565 Evas_Object *prev_btn;
567 wd = elm_widget_data_get(obj);
570 if (!_title_btn_set(it, new_btn, ELM_NAVIGATIONBAR_NEXT_BUTTON, EINA_FALSE))
573 //update if the content is the top item
574 if (elm_navigationbar_content_top_get(obj) != content)
577 prev_btn = edje_object_part_swallow_get(wd->base, "elm.swallow.next_btn");
578 if (prev_btn) evas_object_del(prev_btn);
579 edje_object_part_swallow(wd->base, "elm.swallow.next_btn", new_btn);
583 _button_set(Evas_Object *obj, Evas_Object *prev_btn, Evas_Object *new_btn, Eina_Bool back_btn)
585 char buf[4096]; //TODO: How to guarantee this buffer size?
586 Eina_Bool changed = EINA_FALSE;
591 evas_object_del(prev_btn);
593 if (!new_btn) return changed;
597 snprintf(buf, sizeof(buf), "navigationbar_prev_btn/%s", elm_widget_style_get(obj));
598 elm_object_style_set(new_btn, buf);
602 if (!strcmp("default", elm_object_style_get(new_btn)))
604 snprintf(buf, sizeof(buf), "navigationbar_next_btn/%s", elm_widget_style_get(obj));
605 elm_object_style_set(new_btn, buf);
609 elm_widget_sub_object_add(obj, new_btn);
616 * Add a new navigationbar to the parent
618 * @param[in] parent The parent object
619 * @return The new object or NULL if it cannot be created
621 * @ingroup NavigationBar
624 elm_navigationbar_add(Evas_Object *parent)
630 EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
632 wd = ELM_NEW(Widget_Data);
633 e = evas_object_evas_get(parent);
634 obj = elm_widget_add(e);
635 ELM_SET_WIDTYPE(widtype, "navigationbar");
636 elm_widget_type_set(obj, "navigationbar");
637 elm_widget_sub_object_add(parent, obj);
638 elm_widget_data_set(obj, wd);
639 elm_widget_del_hook_set(obj, _del_hook);
640 elm_widget_theme_hook_set(obj, _theme_hook);
641 elm_widget_signal_emit_hook_set(obj, _emit_hook);
643 wd->base = edje_object_add(e);
644 _elm_theme_object_set(obj, wd->base, "navigationbar", "base", "default");
645 elm_widget_resize_object_set(obj, wd->base);
646 //TODO: elm,action,title,clicked
647 edje_object_signal_callback_add(wd->base, "elm,action,clicked", "elm",
648 _title_clicked, obj);
650 //TODO: How about making the pager as a base?
651 //TODO: Swallow title and content as one content into the pager.
652 wd->pager = elm_pager_add(obj);
653 elm_object_style_set(wd->pager, "navigationbar");
654 elm_widget_sub_object_add(obj, wd->pager);
655 edje_object_part_swallow(wd->base, "elm.swallow.content", wd->pager);
656 evas_object_smart_callback_add(wd->pager, "hide,finished", _hide_finished, obj);
657 evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE, _resize, NULL);
659 wd->title_visible = EINA_TRUE;
661 evas_object_smart_callbacks_descriptions_set(obj, _signals);
663 //TODO: apply elm_object_disabled_set
669 * Push an object to the top of the NavigationBar stack (and show it)
670 * The object pushed becomes a child of the navigationbar and will be controlled
671 * it is deleted when the navigationbar is deleted or when the content is popped.
673 * @param[in] obj The NavigationBar object
674 * @param[in] title The title string
675 * @param[in] prev_btn The previous button
676 * @param[in] next_btn The next button
677 * @param[in] unused Unused.
678 * @param[in] content The object to push
680 * @ingroup NavigationBar
683 elm_navigationbar_push(Evas_Object *obj, const char *title, Evas_Object *prev_btn, Evas_Object *next_btn, Evas_Object *unused __UNUSED__, Evas_Object *content)
685 ELM_CHECK_WIDTYPE(obj, widtype);
688 Elm_Navigationbar_Item *it;
689 Elm_Navigationbar_Item *top_it;
691 if (!content) return;
693 wd = elm_widget_data_get(obj);
696 if (evas_object_data_get(content, _navigationbar_key)) return;
698 it = elm_widget_item_new(obj, Elm_Navigationbar_Item);
701 top_it = eina_list_data_get(eina_list_last(wd->stack));
703 _title_btn_set(it, prev_btn, ELM_NAVIGATIONBAR_PREV_BUTTON, EINA_FALSE);
704 _title_btn_set(it, next_btn, ELM_NAVIGATIONBAR_NEXT_BUTTON, EINA_FALSE);
706 it->content = content;
707 evas_object_event_callback_add(content, EVAS_CALLBACK_DEL, _content_del, it);
708 evas_object_data_set(content, _navigationbar_key, it);
710 //Add a prev-button automatically.
711 if ((!prev_btn) && (top_it))
714 _title_btn_set(it, _create_back_btn(obj, top_it->title, it), ELM_NAVIGATIONBAR_PREV_BUTTON, EINA_TRUE);
716 _title_btn_set(it, _create_back_btn(obj, _ELM_NAVIBAR_PREV_BTN_DEFAULT_LABEL, it), ELM_NAVIGATIONBAR_PREV_BUTTON, EINA_TRUE);
719 eina_stringshare_replace(&it->title, title);
720 edje_object_part_text_set(wd->base, "elm.text", title);
721 _item_sizing_eval(it);
723 Transit_Cb_Data *cb = ELM_NEW(Transit_Cb_Data);
724 // unswallow items and start transition
725 // TODO: For what? why does it need to unswallow?
728 cb->prev_it = top_it;
729 cb->first_page = EINA_FALSE;
730 if (top_it->title_obj) edje_object_part_unswallow(wd->base, top_it->title_obj);
731 if (top_it->title_btns[ELM_NAVIGATIONBAR_PREV_BUTTON])
732 edje_object_part_unswallow(wd->base, top_it->title_btns[ELM_NAVIGATIONBAR_PREV_BUTTON]);
733 if (top_it->title_btns[ELM_NAVIGATIONBAR_NEXT_BUTTON])
734 edje_object_part_unswallow(wd->base, top_it->title_btns[ELM_NAVIGATIONBAR_NEXT_BUTTON]);
736 edje_object_part_unswallow(wd->base, top_it->icon);
738 //If page is the first, then do not run the transition... but if user want.. ?
742 cb->first_page = EINA_TRUE;
746 cb->pop = EINA_FALSE;
748 _transition_complete_cb(cb);
750 elm_pager_content_push(wd->pager, it->content);
752 wd->stack = eina_list_append(wd->stack, it);
757 * This pops the object that is on top (visible) in the navigationbar, makes it disappear, then deletes the object.
758 * The object that was underneath it, on the stack will become visible.
760 * @param[in] obj The NavigationBar object
762 * @ingroup NavigationBar
765 elm_navigationbar_pop(Evas_Object *obj)
767 ELM_CHECK_WIDTYPE(obj, widtype);
768 Widget_Data *wd = elm_widget_data_get(obj);
771 Elm_Navigationbar_Item *it = NULL;
772 Elm_Navigationbar_Item *prev_it = NULL;
774 //TODO: It's impossible to pop while popping?
775 if (wd->popping) return;
776 if (!wd->stack) return;
778 //find item to be popped and to be shown
779 //TODO: hmm.. i think it's hard to manager separated list from elm_pager internal list. but how about use evas_object_data_set to each content??
780 ll = eina_list_last(wd->stack);
788 //unswallow items and start trasition
789 cb = ELM_NEW(Transit_Cb_Data);
791 //Previous page is exist.
794 cb->prev_it = prev_it;
797 if (prev_it->title_obj)
798 edje_object_part_unswallow(wd->base, prev_it->title_obj);
799 if (prev_it->title_btns[ELM_NAVIGATIONBAR_PREV_BUTTON])
800 edje_object_part_unswallow(wd->base, prev_it->title_btns[ELM_NAVIGATIONBAR_PREV_BUTTON]);
801 if (prev_it->title_btns[ELM_NAVIGATIONBAR_NEXT_BUTTON])
802 edje_object_part_unswallow(wd->base, prev_it->title_btns[ELM_NAVIGATIONBAR_NEXT_BUTTON]);
804 edje_object_part_unswallow(wd->base, prev_it->icon);
805 _item_sizing_eval(it);
807 //This case, it's the last page.
810 cb->prev_it = prev_it;
813 //TODO: seems that flag is inverted.
814 cb->first_page = EINA_FALSE;
816 if (prev_it->content)
817 elm_object_tree_unfocusable_set(prev_it->content, EINA_TRUE);
819 _transition_complete_cb(cb);
820 wd->popping = EINA_TRUE;
822 elm_pager_content_pop(wd->pager);
824 if ((prev_it) && (!it))
825 edje_object_part_text_set(wd->base, "elm.text", NULL);
831 * This Pops to the given content object (and update it) by deleting rest of the objects in between.
833 * @param[in] obj The NavigationBar object
834 * @param[in] content the object to show
836 * @ingroup NavigationBar
839 elm_navigationbar_to_content_pop(Evas_Object *obj, Evas_Object *content)
841 ELM_CHECK_WIDTYPE(obj, widtype);
845 Elm_Navigationbar_Item *it;
846 Elm_Navigationbar_Item *prev_it;
849 wd = elm_widget_data_get(obj);
850 if ((!wd) || (!content) || (!wd->stack)) return;
852 //find item to be popped and to be shown
854 ll = eina_list_last(wd->stack);
863 if ((it->base.widget) && (it->content != content))
866 wd->stack = eina_list_remove_list(wd->stack, ll);
875 //unswallow items and start trasition
876 cb = ELM_NEW(Transit_Cb_Data);
877 cb->prev_it = prev_it;
880 cb->first_page = EINA_FALSE;
883 //TODO: make one call.
884 if (prev_it->title_obj)
885 edje_object_part_unswallow(wd->base, prev_it->title_obj);
886 if (prev_it->title_btns[ELM_NAVIGATIONBAR_PREV_BUTTON])
887 edje_object_part_unswallow(wd->base, prev_it->title_btns[ELM_NAVIGATIONBAR_PREV_BUTTON]);
888 if (prev_it->title_btns[ELM_NAVIGATIONBAR_NEXT_BUTTON])
889 edje_object_part_unswallow(wd->base, prev_it->title_btns[ELM_NAVIGATIONBAR_NEXT_BUTTON]);
891 _item_sizing_eval(it);
892 _transition_complete_cb(cb);
894 elm_pager_to_content_pop(wd->pager, content);
899 * Set the title string for the pushed content
901 * @param[in] obj The NavigationBar object
902 * @param[in] content The object to push or pushed
903 * @param[in] title The title string
905 * @ingroup NavigationBar
908 elm_navigationbar_title_label_set(Evas_Object *obj, Evas_Object *content, const char *title)
910 ELM_CHECK_WIDTYPE(obj, widtype);
912 Elm_Navigationbar_Item *it;
914 if (!content) return;
916 wd = elm_widget_data_get(obj);
919 it = evas_object_data_get(content, _navigationbar_key);
922 eina_stringshare_replace(&it->title, title);
923 edje_object_part_text_set(wd->base, "elm.text", title);
924 _item_sizing_eval(it);
928 * Return the title string of the pushed content
930 * @param[in] obj The NavigationBar object
931 * @param[in] content The object to push or pushed
932 * @return The title string or NULL if none
934 * @ingroup NavigationBar
937 elm_navigationbar_title_label_get(Evas_Object *obj, Evas_Object *content)
939 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
941 Elm_Navigationbar_Item *it;
943 if (!content) return NULL;
945 wd = elm_widget_data_get(obj);
946 if (!wd) return NULL;
948 it = evas_object_data_get(content, _navigationbar_key);
949 if (!it) return NULL;
954 * Set the title icon for the pushed content
956 * @param[in] obj The NavigationBar object
957 * @param[in] content The object to push or pushed
958 * @param[in] icon The icon object
960 * @ingroup NavigationBar
963 elm_navigationbar_title_icon_set(Evas_Object *obj, Evas_Object *content, Evas_Object *icon)
965 ELM_CHECK_WIDTYPE(obj, widtype);
967 Elm_Navigationbar_Item *it;
968 Evas_Object *swallow;
970 if (!content) return;
972 wd = elm_widget_data_get(obj);
975 it = evas_object_data_get(content, _navigationbar_key);
978 if (it->icon == icon) return;
979 if (it->icon) evas_object_del(it->icon);
984 elm_widget_sub_object_add(obj, icon);
985 evas_object_event_callback_add(icon, EVAS_CALLBACK_DEL, _title_icon_del, it);
986 _item_sizing_eval(it);
987 //update if the content is the top item
988 if (elm_navigationbar_content_top_get(obj) != content)
991 swallow = edje_object_part_swallow_get(wd->base, "elm.swallow.icon");
994 edje_object_signal_emit(wd->base, "elm,state,icon,hidden", "elm");
995 edje_object_part_unswallow(wd->base, swallow);
996 evas_object_hide(swallow);
998 if (wd->title_visible)
1000 edje_object_part_swallow(wd->base, "elm.swallow.icon", icon);
1001 edje_object_signal_emit(wd->base, "elm,state,icon,visible", "elm");
1002 edje_object_message_signal_process(wd->base);
1005 edje_object_signal_emit(wd->base, "elm,state,icon,hidden", "elm");
1009 * Get the title icon for the pushed content
1011 * @param[in] obj The NavigationBar object
1012 * @param[in] content The object to push or pushed
1013 * @return The icon object or NULL if none
1015 * @ingroup NavigationBar
1018 elm_navigationbar_title_icon_get(Evas_Object *obj, Evas_Object *content)
1020 ELM_CHECK_WIDTYPE(obj, widtype)NULL;
1022 Elm_Navigationbar_Item *it;
1024 if (!content) return NULL;
1026 wd = elm_widget_data_get(obj);
1027 if (!wd) return NULL;
1029 it = evas_object_data_get(content, _navigationbar_key);
1030 if (!it) return NULL;
1036 * Add a title object for the content.
1038 * @param[in] obj The NavigationBar object
1039 * @param[in] content The object pushed
1040 * @param[in] title_obj a title object (normally button or segment_control)
1042 * @ingroup NavigationBar
1044 //TODO: elm_navigationbar_title_object_set ( .... )
1046 elm_navigationbar_title_object_add(Evas_Object *obj, Evas_Object *content, Evas_Object *title_obj)
1048 ELM_CHECK_WIDTYPE(obj, widtype);
1050 Elm_Navigationbar_Item *it;
1052 if ((!title_obj) || (!content)) return;
1054 wd = elm_widget_data_get(obj);
1057 it = evas_object_data_get(content, _navigationbar_key);
1062 evas_object_event_callback_del(it->title_obj, EVAS_CALLBACK_DEL, _title_obj_del);
1063 evas_object_del(it->title_obj);
1066 it->title_obj = title_obj;
1067 elm_widget_sub_object_add(obj, title_obj);
1068 evas_object_event_callback_add(title_obj, EVAS_CALLBACK_DEL, _title_obj_del, it);
1070 //TODO: Conserve this line for a while the object list get API is alive.
1071 eina_list_free(it->title_obj_list);
1072 it->title_obj_list = eina_list_append(NULL, title_obj);
1074 if (elm_navigationbar_content_top_get(obj) != content)
1077 edje_object_part_swallow(wd->base, "elm.swallow.title", title_obj);
1079 //TODO: Looks something incorrect.
1080 if (wd->title_visible)
1084 edje_object_signal_emit(wd->base, "elm,state,show,extended", "elm");
1085 //TODO: for before nbeat?
1086 edje_object_signal_emit(wd->base, "elm,state,show,noanimate,title", "elm");
1087 it->titleobj_visible = EINA_TRUE;
1090 _item_sizing_eval(it);
1094 * Unset the list of title objects corresponding to given content and returns it to
1096 * @param[in] obj The NavigationBar object
1097 * @param[in] content The content object pushed
1098 * @param[out] list updates the list with title objects list, this list has to be freed and the
1099 * objects have to be deleted by application.
1100 * @ingroup NavigationBar
1104 elm_navigationbar_title_object_list_unset(Evas_Object *obj, Evas_Object *content, Eina_List **list)
1106 ELM_CHECK_WIDTYPE(obj, widtype);
1108 Elm_Navigationbar_Item *it;
1109 Evas_Object *swallow;
1111 if ((!list) || (!content)) return;
1113 wd = elm_widget_data_get(obj);
1116 it = evas_object_data_get(content, _navigationbar_key);
1119 *list = eina_list_append(*list, it->title_obj);
1120 it->title_obj = NULL;
1122 if (elm_navigationbar_content_top_get(obj) != content)
1125 //In this case, the content is in the last of the stack
1126 swallow = edje_object_part_swallow_get(wd->base, "elm.swallow.title");
1127 if (!swallow) return;
1129 if (wd->title_visible)
1131 if(it->titleobj_visible)
1133 //TODO: remove the dependency on these signals as related to nbeat?
1134 edje_object_signal_emit(wd->base, "elm,state,hide,noanimate,title", "elm");
1135 it->titleobj_visible = EINA_FALSE;
1137 edje_object_signal_emit(wd->base, "elm,state,hide,extended", "elm");
1139 _item_sizing_eval(it);
1143 elm_navigationbar_title_object_get(Evas_Object *obj, Evas_Object *content)
1145 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1147 Elm_Navigationbar_Item *it;
1149 if (!content) return NULL;
1151 wd = elm_widget_data_get(obj);
1152 if (!wd) return NULL;
1154 it = evas_object_data_get(content, _navigationbar_key);
1155 if (!it) return NULL;
1157 return it->title_obj;
1161 * Return the list of title objects of the pushed content.
1163 * @param[in] obj The NavigationBar object
1164 * @param[in] content The object to push or pushed
1165 * @return The list of title objects
1167 * @ingroup NavigationBar
1171 elm_navigationbar_title_object_list_get(Evas_Object *obj, Evas_Object *content)
1173 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1175 Elm_Navigationbar_Item *it;
1177 if (!content) return NULL;
1179 wd = elm_widget_data_get(obj);
1180 if (!wd) return NULL;
1182 it = evas_object_data_get(content, _navigationbar_key);
1183 if (!it) return NULL;
1185 return it->title_obj_list;
1189 * Return the content object at the top of the NavigationBar stack
1191 * @param[in] obj The NavigationBar object
1192 * @return The top content object or NULL if none
1194 * @ingroup NavigationBar
1197 elm_navigationbar_content_top_get(Evas_Object *obj)
1199 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1200 Widget_Data *wd = elm_widget_data_get(obj);
1201 if (!wd) return NULL;
1202 return elm_pager_content_top_get(wd->pager);
1206 * Return the content object at the bottom of the NavigationBar stack
1208 * @param[in] obj The NavigationBar object
1209 * @return The bottom content object or NULL if none
1211 * @ingroup NavigationBar
1214 elm_navigationbar_content_bottom_get(Evas_Object *obj)
1216 ELM_CHECK_WIDTYPE(obj, widtype)NULL;
1217 Widget_Data *wd = elm_widget_data_get(obj);
1218 if (!wd) return NULL;
1219 return elm_pager_content_bottom_get(wd->pager);
1223 * This hides the title area of navigationbar.
1225 * @param[in] obj The NavigationBar object
1226 * @param[in] hidden if EINA_TRUE the title area is hidden.
1228 * @ingroup NavigationBar
1230 //TODO: does not provide hidden get ?
1232 elm_navigationbar_hidden_set(Evas_Object *obj,
1235 ELM_CHECK_WIDTYPE(obj, widtype);
1236 Widget_Data *wd = elm_widget_data_get(obj);
1240 edje_object_signal_emit(wd->base, "elm,state,item,moveup", "elm");
1242 edje_object_signal_emit(wd->base, "elm,state,item,movedown", "elm");
1244 wd->title_visible = !hidden;
1248 * Set the button object of the pushed content.
1250 * @param[in] obj The NavigationBar object
1251 * @param[in] content The object to push or pushed
1252 * @param[in] button The button
1253 * @param[in] button_type Indicates the position
1255 * @ingroup NavigationBar
1258 elm_navigationbar_title_button_set(Evas_Object *obj, Evas_Object *content, Evas_Object *button, Elm_Navi_Button_Type button_type)
1260 ELM_CHECK_WIDTYPE(obj, widtype);
1263 Elm_Navigationbar_Item *it;
1265 if (!content) return;
1267 wd = elm_widget_data_get(obj);
1270 it = evas_object_data_get(content, _navigationbar_key);
1275 case ELM_NAVIGATIONBAR_PREV_BUTTON:
1276 _elm_navigationbar_prev_btn_set(obj, content, button, it);
1278 case ELM_NAVIGATIONBAR_NEXT_BUTTON:
1279 _elm_navigationbar_next_btn_set(obj, content, button, it);
1282 _elm_navigationbar_prev_btn_set(obj, content, button, it);
1289 * Return the button object of the pushed content
1291 * @param[in] obj The NavigationBar object
1292 * @param[in] content The object to push or pushed
1293 * @param[in] button_type Indicates the position
1294 * @return The button object or NULL if none
1296 * @ingroup NavigationBar
1299 elm_navigationbar_title_button_get(Evas_Object *obj, Evas_Object *content, Elm_Navi_Button_Type button_type)
1301 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1303 Elm_Navigationbar_Item *it;
1305 if (!content) return NULL;
1307 wd = elm_widget_data_get(obj);
1308 if (!wd) return NULL;
1310 it = evas_object_data_get(content, _navigationbar_key);
1311 if (!it) return NULL;
1315 case ELM_NAVIGATIONBAR_PREV_BUTTON:
1316 return it->title_btns[ELM_NAVIGATIONBAR_PREV_BUTTON];
1317 case ELM_NAVIGATIONBAR_NEXT_BUTTON:
1318 return it->title_btns[ELM_NAVIGATIONBAR_NEXT_BUTTON];
1320 return it->title_btns[ELM_NAVIGATIONBAR_PREV_BUTTON];
1326 * Set the sub title string for the pushed content.
1328 * @param[in] obj The NavigationBar object
1329 * @param[in] content The object to push or pushed
1330 * @param[in] subtitle The subtitle string
1332 * @ingroup NavigationBar
1335 elm_navigationbar_subtitle_label_set(Evas_Object *obj, Evas_Object *content, const char *subtitle)
1337 ELM_CHECK_WIDTYPE(obj, widtype);
1339 Elm_Navigationbar_Item *it;
1341 wd = elm_widget_data_get(obj);
1344 it = evas_object_data_get(content, _navigationbar_key);
1347 eina_stringshare_replace(&it->subtitle, subtitle);
1348 edje_object_part_text_set(wd->base, "elm.text.sub", subtitle);
1349 _item_sizing_eval(it);
1353 * Return the subtitle string of the pushed content.
1355 * @param[in] obj The NavigationBar object
1356 * @param[in] content The object to push or pushed
1357 * @return The subtitle string or NULL if none
1359 * @ingroup NavigationBar
1362 elm_navigationbar_subtitle_label_get(Evas_Object *obj, Evas_Object *content)
1364 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1366 Elm_Navigationbar_Item *it;
1368 wd = elm_widget_data_get(obj);
1369 if (!wd) return NULL;
1371 it = evas_object_data_get(content, _navigationbar_key);
1372 if (!it) return NULL;
1373 return it->subtitle;
1377 * This disables content area animation on push/pop.
1379 * @param[in] obj The NavigationBar object
1380 * @param[in] disable if EINA_TRUE animation is disabled.
1382 * @ingroup NavigationBar
1384 //TODO: Let's check to remove this API.
1386 elm_navigationbar_animation_disabled_set(Evas_Object *obj, Eina_Bool disable)
1388 ELM_CHECK_WIDTYPE(obj, widtype);
1389 Widget_Data *wd = elm_widget_data_get(obj);
1391 elm_pager_animation_disabled_set(wd->pager, disable);
1395 * This shows/hides title object area.
1397 * @param[in] obj The NavigationBar object
1398 * @param[in] show if EINA_TRUE title object is shown else its hidden.
1399 * @param[in] content The content object packed in navigationbar.
1400 * @ingroup NavigationBar
1403 elm_navigationbar_title_object_visible_set(Evas_Object *obj, Evas_Object *content, Eina_Bool visible)
1405 ELM_CHECK_WIDTYPE(obj, widtype);
1406 Elm_Navigationbar_Item *it;
1409 if (!content) return;
1411 wd = elm_widget_data_get(obj);
1414 it = evas_object_data_get(content, _navigationbar_key);
1416 if (it->titleobj_visible == visible) return;
1417 it->titleobj_visible = visible;
1418 _titleobj_switching(obj, it);
1422 * This gets the status whether title object is shown/hidden.
1424 * @param[in] obj The NavigationBar object
1425 * @param[in] content The content object packed in navigationbar.
1426 * @return The status whether title object is shown/hidden.
1427 * @ingroup NavigationBar
1430 elm_navigationbar_title_object_visible_get(Evas_Object *obj, Evas_Object *content)
1432 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1433 Elm_Navigationbar_Item *it;
1436 if (!content) return EINA_FALSE;
1438 wd = elm_widget_data_get(obj);
1439 if (!wd) return EINA_FALSE;
1441 it = evas_object_data_get(content, _navigationbar_key);
1442 if (!it) return EINA_FALSE;
1444 return it->titleobj_visible;