[navigationbar]: active sync app, text overlapping issue.
[framework/uifw/elementary.git] / src / lib / elm_navigationbar.c
1 #include <Elementary.h>
2 #include "elm_priv.h"
3
4 /**
5  * @defgroup NavigationBar NavigationBar
6  * @ingroup Elementary
7  *
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.
11  *
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().
19  */
20
21 typedef struct _Widget_Data Widget_Data;
22 typedef struct _Item Item;
23 typedef struct _Transit_Cb_Data Transit_Cb_Data;
24
25 struct _Widget_Data
26 {
27    Eina_List *stack;
28    Evas_Object *base;
29    Evas_Object *pager;
30    Eina_Bool hidden :1;
31    Eina_Bool popping: 1;
32  };
33
34 struct _Item
35 {
36    Evas_Object *obj;
37    const char *title;
38    const char *subtitle;
39    Evas_Object *title_obj;
40    Eina_List *title_list;
41    Evas_Object *fn_btn1;
42    Evas_Object *fn_btn2;
43    Evas_Object *fn_btn3;
44    Evas_Object *back_btn;
45    Evas_Object *content;
46    int fn_btn1_w;
47    int fn_btn2_w;
48    int fn_btn3_w;
49    int title_w;
50 };
51
52 struct _Transit_Cb_Data
53 {
54    Item* prev_it;
55    Item* it;
56    Eina_Bool pop;
57    Eina_Bool first_page;
58 };
59
60 static const char *widtype = NULL;
61
62 static void _del_hook(Evas_Object *obj);
63 static void _theme_hook(Evas_Object *obj);
64 static void _sizing_eval(Evas_Object *obj);
65 static void _resize(void *data, Evas *e, Evas_Object *obj, void *event_info);
66 static void _item_sizing_eval(Item *it);
67 static void _delete_item(Item *it);
68 static void _back_button_clicked(void *data, Evas_Object *obj, void *event_info);
69 static int _set_button_width(Evas_Object *obj);
70 static Eina_Bool _button_set(Evas_Object *obj, Evas_Object *prev_btn, Evas_Object *new_btn, Eina_Bool back_btn);
71 static Evas_Object *_multiple_object_set(Evas_Object *obj, Evas_Object *sub_obj, Eina_List *list, int width);
72 static Item *_check_item_is_added(Evas_Object *obj, Evas_Object *content);
73 static void _transition_complete_cb(void *data);
74 static void _elm_navigationbar_back_button_set(Evas_Object *obj, Evas_Object *content, Evas_Object *button);
75 static Evas_Object *_elm_navigationbar_back_button_get(Evas_Object *obj, Evas_Object *content);
76 static void _elm_navigationbar_function_button1_set(Evas_Object *obj, Evas_Object *content, Evas_Object *button);
77 static Evas_Object *_elm_navigationbar_function_button1_get(Evas_Object *obj, Evas_Object *content);
78 static void _elm_navigationbar_function_button2_set(Evas_Object *obj, Evas_Object *content, Evas_Object *button);
79 static Evas_Object *_elm_navigationbar_function_button2_get(Evas_Object *obj, Evas_Object *content);
80 static void _elm_navigationbar_function_button3_set(Evas_Object *obj, Evas_Object *content, Evas_Object *button);
81 static Evas_Object *_elm_navigationbar_function_button3_get(Evas_Object *obj, Evas_Object *content);
82
83 static void
84 _del_hook(Evas_Object *obj)
85 {
86    Widget_Data *wd = elm_widget_data_get(obj);
87    Eina_List *list;
88    Item *it;
89    
90    EINA_LIST_FOREACH(wd->stack, list, it)
91      _delete_item(it);
92    eina_list_free(wd->stack);
93    free(wd);
94 }
95
96 static void
97 _theme_hook(Evas_Object *obj)
98 {
99    Widget_Data *wd = elm_widget_data_get(obj);
100    Eina_List *list = NULL;
101    Item *it = NULL;
102    char buf_fn[4096];
103    char buf_bk[4096];
104    
105    if (!wd) return;
106    _elm_theme_object_set(obj, wd->base, "navigationbar", "base", elm_widget_style_get(obj));
107    edje_object_scale_set(wd->base, elm_widget_scale_get(obj) * _elm_config->scale);
108    EINA_LIST_FOREACH(wd->stack, list, it)
109      {
110         if (it->fn_btn1)
111          {  
112             snprintf(buf_fn, sizeof(buf_fn), "navigationbar_functionbutton/%s", elm_widget_style_get(obj));
113             elm_object_style_set(it->fn_btn1, buf_fn);            
114          }
115         if (it->fn_btn2)
116          {        
117             snprintf(buf_fn, sizeof(buf_fn), "navigationbar_functionbutton/%s", elm_widget_style_get(obj));
118             elm_object_style_set(it->fn_btn2, buf_fn);               
119          }
120         if (it->fn_btn3)
121          {
122             snprintf(buf_fn, sizeof(buf_fn), "navigationbar_functionbutton/%s", elm_widget_style_get(obj));
123             elm_object_style_set(it->fn_btn3, buf_fn);            
124          }
125         snprintf(buf_bk, sizeof(buf_bk), "navigationbar_backbutton/%s", elm_widget_style_get(obj));
126         elm_object_style_set(it->back_btn, buf_bk);
127      }
128    edje_object_message_signal_process(wd->base);
129    _sizing_eval(obj);
130 }
131
132 static void
133 _delete_item(Item *it)
134 {
135    Eina_List *ll;
136    if (!it) return;
137    Evas_Object *list_obj;
138    
139    evas_object_del(it->back_btn);
140    elm_object_unfocus(it->fn_btn1);
141    evas_object_del(it->fn_btn1);
142    elm_object_unfocus(it->fn_btn2);
143    evas_object_del(it->fn_btn2);
144    elm_object_unfocus(it->fn_btn3);
145    evas_object_del(it->fn_btn3); 
146    if (it->title) 
147      eina_stringshare_del(it->title);
148    if (it->subtitle) 
149      eina_stringshare_del(it->subtitle);
150    EINA_LIST_FOREACH(it->title_list, ll, list_obj)
151      evas_object_del(list_obj);
152    eina_list_free(it->title_list);
153    free(it);   
154 }
155
156 static void
157 _sizing_eval(Evas_Object *obj)
158 {
159    Widget_Data *wd = elm_widget_data_get(obj);
160    Evas_Coord minw = -1, minh = -1;
161    Evas_Coord w = -1, h = -1;
162    Eina_List *list;
163
164    edje_object_size_min_calc(wd->base, &minw, &minh);
165    evas_object_size_hint_min_get(obj, &w, &h);
166    if (w > minw) minw = w;
167    if (h > minw) minh = h;
168
169    evas_object_size_hint_min_set(obj, minw, minh);
170    evas_object_size_hint_max_set(obj, -1, -1);
171
172    list = eina_list_last(wd->stack);
173    if (list)
174      {
175         Item *it = list->data;
176         _item_sizing_eval(it);
177      }
178 }
179
180 static void
181 _item_sizing_eval(Item *it)
182 {
183    Widget_Data *wd = elm_widget_data_get(it->obj);
184    Evas_Coord pad, height, minw, w;
185    int pad_count = 2;
186
187    if (!it) return;
188
189    edje_object_size_min_calc(wd->base, &minw, NULL);
190    evas_object_geometry_get(wd->base, NULL, NULL, &w, NULL);
191    if (w < minw) w = minw;   
192    edje_object_part_geometry_get(wd->base, "elm.rect.pad1", NULL, NULL, &pad, NULL);
193    edje_object_part_geometry_get(wd->base, "elm.swallow.title", NULL, NULL, NULL, &height);
194
195    if (it->fn_btn1) 
196      {
197         it->fn_btn1_w = _set_button_width(it->fn_btn1);
198         pad_count++;
199      }
200    else if (it->back_btn)
201      {
202         it->fn_btn1_w = _set_button_width(it->back_btn);
203         pad_count++;
204      }
205    if (it->fn_btn2)
206      {
207         it->fn_btn2_w = _set_button_width(it->fn_btn2);
208         pad_count++;
209      }
210    if (it->fn_btn3)
211      {
212         it->fn_btn3_w = _set_button_width(it->fn_btn3);
213         pad_count++;
214      }
215    if (it->title_list)
216      {  
217         it->title_w = _set_button_width(it->title_obj);
218         it->title_obj = _multiple_object_set(it->obj, it->title_obj, it->title_list, it->title_w);
219         evas_object_resize(it->title_obj, it->title_w, height);
220         evas_object_size_hint_min_set(it->title_obj, it->title_w, height);
221      }
222 }
223
224 static void
225 _resize(void *data, Evas *e, Evas_Object *obj, void *event_info)
226 {
227    _sizing_eval(obj);
228 }
229
230 static void 
231 _transition_complete_cb(void *data)
232 {
233    Transit_Cb_Data *cb = data;
234    if (!cb) return;
235    Evas_Object *navi_bar = NULL;
236    Evas_Object *content = NULL;
237    Widget_Data *wd = NULL;
238    Item *prev_it = cb->prev_it;
239    Item *it = cb->it;
240
241    if (prev_it)
242      {
243         navi_bar = prev_it->obj;
244      }
245    else if (it)
246      {
247         navi_bar = it->obj;
248      }
249    wd = elm_widget_data_get(navi_bar);
250    if (cb->pop && prev_it)
251      {
252         Eina_List *ll;
253         ll = eina_list_last(wd->stack);
254         if (ll->data == prev_it)
255           {
256              _delete_item(prev_it);
257              wd->stack = eina_list_remove_list(wd->stack, ll);
258           }
259      }  
260    else if (prev_it)
261      {
262         evas_object_hide(prev_it->fn_btn1);
263         evas_object_hide(prev_it->back_btn);
264         evas_object_hide(prev_it->title_obj);
265         evas_object_hide(prev_it->fn_btn2);
266         evas_object_hide(prev_it->fn_btn3);
267      }
268    if ((it) && (!wd->hidden))
269      {
270         edje_object_part_text_set(wd->base, "elm.text", it->title);
271         if (!cb->first_page)
272           {
273              if (cb->pop)
274                {
275                   edje_object_signal_emit(wd->base, "elm,action,pop", "elm");
276                }
277              else
278                {
279                   edje_object_signal_emit(wd->base, "elm,action,push", "elm");
280                }
281              edje_object_signal_emit(wd->base, "elm,state,rect,enabled", "elm");
282           }
283         if (it->title_obj) 
284           {
285              edje_object_part_swallow(wd->base, "elm.swallow.title", it->title_obj);
286              edje_object_signal_emit(wd->base, "elm,state,retract,title", "elm");
287           }
288         if (it->title) 
289           {
290              edje_object_signal_emit(wd->base, "elm,state,retract,title", "elm");
291           }
292         if (it->subtitle) 
293           {
294              edje_object_part_text_set(wd->base, "elm.text.sub", it->subtitle);
295           }
296         else
297           edje_object_part_text_set(wd->base, "elm.text.sub", NULL);
298         if (it->fn_btn1) 
299           {
300              edje_object_signal_emit(wd->base, "elm,state,item,add,leftpad", "elm");
301              edje_object_part_swallow(wd->base, "elm.swallow.btn1", it->fn_btn1);
302           }
303         else if (it->back_btn) 
304           {
305              edje_object_signal_emit(wd->base, "elm,state,item,add,leftpad", "elm");
306              edje_object_part_swallow(wd->base, "elm.swallow.btn1", it->back_btn);
307           }
308         else
309           edje_object_signal_emit(wd->base, "elm,state,item,reset,leftpad", "elm");
310         if (it->fn_btn2) 
311           {
312              edje_object_signal_emit(wd->base, "elm,state,item,add,rightpad", "elm");
313              edje_object_part_swallow(wd->base, "elm.swallow.btn2", it->fn_btn2);
314           }
315         else
316           edje_object_signal_emit(wd->base, "elm,state,item,reset,rightpad", "elm");
317         if (it->fn_btn3) 
318           {
319              edje_object_signal_emit(wd->base, "elm,state,item,add,rightpad2", "elm");
320              edje_object_signal_emit(wd->base, "elm,state,item,fn_btn3_set", "elm");
321              edje_object_part_swallow(wd->base, "elm.swallow.btn3", it->fn_btn3);
322           }
323         else
324           edje_object_signal_emit(wd->base, "elm,state,item,reset,rightpad2", "elm");  
325         if ((it->title_obj) && (it->title))
326           {
327              edje_object_signal_emit(wd->base, "elm,state,extend,title", "elm");
328           }  
329         content = it->content;
330      }
331    edje_object_message_signal_process(wd->base);
332 }
333
334 static void 
335 _back_button_clicked(void *data, Evas_Object *obj, void *event_info)
336 {
337    Item *it = data;
338    
339    elm_navigationbar_pop(it->obj);
340 }
341
342 static void 
343 _hide_finished(void *data, Evas_Object *obj, void *event_info)
344 {
345    Evas_Object *navi_bar = data; 
346    Widget_Data *wd =  elm_widget_data_get(navi_bar);
347    wd->popping = EINA_FALSE;
348    evas_object_smart_callback_call(navi_bar, "hide,finished", event_info);
349    edje_object_signal_emit(wd->base, "elm,state,rect,disabled", "elm");
350 }
351
352 static int
353 _set_button_width(Evas_Object *obj)
354 {
355    Evas_Coord minw = -1, minh = -1, maxw= -1, maxh = -1;
356    Evas_Coord w = 0, h = 0;
357
358    evas_object_size_hint_min_get(obj, &minw, &minh);
359    evas_object_size_hint_max_get(obj, &maxw, &maxh);
360    evas_object_geometry_get(obj, NULL, NULL, &w, &h);
361    if (w < minw) w = minw;
362    if (h < minh) h = minh;
363    if ((maxw >= 0) && (w > maxw)) w = maxw;
364    if ((maxh >= 0) && (h > maxh)) h = maxh;
365    evas_object_resize(obj, w, h);
366    return w;
367 }
368
369 static Eina_Bool 
370 _button_set(Evas_Object *obj, Evas_Object *prev_btn, Evas_Object *new_btn, Eina_Bool back_btn)
371 {
372    char buf[4096];
373    Eina_Bool changed = EINA_FALSE;
374    
375    if (prev_btn) 
376      {
377         evas_object_del(prev_btn);
378         prev_btn = NULL;
379      }
380    if (new_btn) 
381      {
382         if (back_btn) 
383           {
384              snprintf(buf, sizeof(buf), "navigationbar_backbutton/%s", elm_widget_style_get(obj));
385              elm_object_style_set(new_btn, buf);
386           }
387         else 
388           {           
389              snprintf(buf, sizeof(buf), "navigationbar_functionbutton/%s", elm_widget_style_get(obj));
390              elm_object_style_set(new_btn, buf);             
391           }
392         elm_widget_sub_object_add(obj, new_btn);
393         changed = EINA_TRUE;
394      }
395    return changed;
396 }
397
398 static Item *
399 _check_item_is_added(Evas_Object *obj, Evas_Object *content)
400 {
401    Widget_Data *wd = elm_widget_data_get(obj);
402    Eina_List *ll;
403    Item *it;
404    
405    EINA_LIST_FOREACH(wd->stack, ll, it)
406      {
407         if (it->content == content) 
408           {
409              return it;
410           }
411      }
412    return NULL;
413 }
414
415 static Evas_Object *
416 _multiple_object_set(Evas_Object *obj, Evas_Object *sub_obj, Eina_List *list, int width)
417 {
418    Widget_Data *wd = elm_widget_data_get(obj);
419    Eina_List *ll;
420    Evas_Object *new_obj, *list_obj;
421    Evas_Coord pad, height;
422    char buf[32];
423    int num = 1;
424    int count;
425    
426    edje_object_part_geometry_get(wd->base, "elm.rect.pad1", NULL, NULL, &pad, NULL);
427    edje_object_part_geometry_get(wd->base, "elm.swallow.title", NULL, NULL, NULL, &height);
428    if (!sub_obj)
429      {
430         new_obj = elm_layout_add(obj);
431         elm_widget_sub_object_add(obj, new_obj);
432         elm_layout_theme_set(new_obj, "navigationbar", "title", elm_widget_style_get(obj));
433      }
434    else 
435      new_obj = sub_obj;
436    count = eina_list_count(list);
437    EINA_LIST_FOREACH(list, ll, list_obj)
438      {  
439         evas_object_resize(list_obj, (width-(count-1)*pad)/count, height);
440         evas_object_size_hint_min_set(list_obj, (width-(count-1)*pad)/count, height);    
441         memset(buf, 0, sizeof(buf));
442         sprintf(buf, "elm,state,item,add,%d", num);
443         edje_object_signal_emit(elm_layout_edje_get(new_obj), buf, "elm");
444         memset(buf, 0, sizeof(buf));
445         sprintf(buf, "elm.swallow.title%d", num++);
446         elm_layout_content_set(new_obj, buf, list_obj);
447      }
448    return new_obj;
449 }
450
451 static void
452 _multiple_object_unset(Item *it, Eina_List **list)
453 {
454    Evas_Object *list_obj = NULL;
455    Eina_List *l = NULL;
456    Evas_Object *temp_obj;
457    char buf[1024];
458    int num = 1;
459    if (it->title_obj)
460      {
461         EINA_LIST_FOREACH (it->title_list, l, list_obj)
462           {
463              memset(buf, 0, sizeof(buf));
464              sprintf(buf, "elm.swallow.title%d", num++);
465              temp_obj = elm_layout_content_unset(it->title_obj, buf);
466              *list = eina_list_append(*list, temp_obj);
467              evas_object_hide(temp_obj);
468           }
469         eina_list_free(it->title_list);
470         it->title_list = NULL;
471      }
472 }
473
474
475 /**
476  * Add a new navigationbar to the parent
477  *
478  * @param[in] parent The parent object
479  * @return The new object or NULL if it cannot be created
480  *
481  * @ingroup NavigationBar
482  */
483 EAPI Evas_Object *
484 elm_navigationbar_add(Evas_Object *parent)
485 {
486    Evas_Object *obj;
487    Evas *e;
488    Widget_Data *wd;
489
490    wd = ELM_NEW(Widget_Data);
491    e = evas_object_evas_get(parent);
492    obj = elm_widget_add(e);
493    ELM_SET_WIDTYPE(widtype, "navigationbar");
494    elm_widget_type_set(obj, "navigationbar");
495    elm_widget_sub_object_add(parent, obj);
496    elm_widget_data_set(obj, wd);
497    elm_widget_del_hook_set(obj, _del_hook);
498    elm_widget_theme_hook_set(obj, _theme_hook);
499
500    wd->base = edje_object_add(e);
501    _elm_theme_object_set(obj, wd->base, "navigationbar", "base", "default");
502    elm_widget_resize_object_set(obj, wd->base);
503
504    wd->pager = elm_pager_add(obj);
505    elm_object_style_set(wd->pager, "navigationbar");
506    elm_widget_sub_object_add(obj, wd->pager);
507    edje_object_part_swallow(wd->base, "elm.swallow.content", wd->pager);
508    evas_object_smart_callback_add(wd->pager, "hide,finished", _hide_finished, obj); 
509    evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE, _resize, NULL);  
510
511    _sizing_eval(obj);
512    return obj;
513 }
514
515 /**
516  * Push an object to the top of the NavigationBar stack (and show it)
517  * The object pushed becomes a child of the navigationbar and will be controlled
518  * it is deleted when the navigationbar is deleted or when the content is popped.
519  *
520  * @param[in] obj The NavigationBar object
521  * @param[in] title The title string
522  * @param[in] fn_btn1 The left button
523  * @param[in] fn_btn2 The right button
524  * @param[in] fn_btn3 The button placed before right most button.
525  * @param[in] content The object to push
526  *
527  * @ingroup NavigationBar
528  */
529 EAPI void 
530 elm_navigationbar_push(Evas_Object *obj, const char *title, Evas_Object *fn_btn1, Evas_Object *fn_btn2, Evas_Object *fn_btn3, Evas_Object *content)
531 {
532    ELM_CHECK_WIDTYPE(obj, widtype);
533    Widget_Data *wd = elm_widget_data_get(obj);
534    Eina_List *ll;
535    Item *it;
536    Item *prev_it = NULL;
537
538    if (!wd) return;
539    it = _check_item_is_added(obj, content);
540    if (it) return;
541    if (!it) it = ELM_NEW(Item); 
542    if (!it) return;
543    
544    // add and set new items      
545    _button_set(obj, NULL, fn_btn1, EINA_FALSE);
546    _button_set(obj, NULL, fn_btn2, EINA_FALSE);
547    _button_set(obj, NULL, fn_btn3, EINA_FALSE);
548    
549    ll = eina_list_last(wd->stack);
550    if (ll)
551      {
552         prev_it = ll->data;
553      }
554    it->obj = obj;
555    it->fn_btn1 = fn_btn1;
556    it->fn_btn2 = fn_btn2;
557    it->fn_btn3 = fn_btn3;
558    it->content = content;
559
560    if (!fn_btn1 && prev_it)
561    {
562       char *prev_title = NULL;
563
564       it->back_btn = elm_button_add(obj);
565       prev_title = (char *)prev_it->title;
566       if (prev_title)
567          {
568             elm_button_label_set(it->back_btn, prev_title); 
569          }
570       else
571          {
572             elm_button_label_set(it->back_btn, "Previous");
573          }
574       evas_object_smart_callback_add(it->back_btn, "clicked", _back_button_clicked, it); 
575       _button_set(obj, NULL, it->back_btn, EINA_TRUE);
576       elm_object_focus_allow_set(it->back_btn, EINA_FALSE);
577    }
578    
579    eina_stringshare_replace(&it->title, title);
580    edje_object_part_text_set(wd->base, "elm.text", title);
581    _item_sizing_eval(it);
582
583    Transit_Cb_Data *cb = ELM_NEW(Transit_Cb_Data);    
584    // unswallow items and start transition
585    if (prev_it)
586      {
587         cb->prev_it = prev_it;
588         cb->it = it;
589         cb->pop = EINA_FALSE;
590         cb->first_page = EINA_FALSE;
591         if (prev_it->title_obj) edje_object_part_unswallow(wd->base, prev_it->title_obj);
592         if (prev_it->fn_btn1) edje_object_part_unswallow(wd->base, prev_it->fn_btn1);
593         else if (prev_it->back_btn) edje_object_part_unswallow(wd->base, prev_it->back_btn);
594         if (prev_it->fn_btn2) edje_object_part_unswallow(wd->base, prev_it->fn_btn2);
595         if (prev_it->fn_btn3) edje_object_part_unswallow(wd->base, prev_it->fn_btn3);
596      }
597    else  
598      {
599         cb->prev_it = NULL;
600         cb->it = it;
601         cb->pop = EINA_FALSE;   
602         cb->first_page = EINA_TRUE;
603      }  
604    _transition_complete_cb(cb);
605    free(cb);
606    elm_pager_content_push(wd->pager, it->content); 
607    //push item into the stack. it should be always the tail
608    if (!_check_item_is_added(obj, content))
609      wd->stack = eina_list_append(wd->stack, it); 
610    else
611      {
612         EINA_LIST_FOREACH(wd->stack, ll, it)
613           {
614              if (it->content == content) 
615                {
616                   wd->stack = eina_list_demote_list(wd->stack, ll);
617                   break;
618                }
619           }
620      }
621    _sizing_eval(obj);
622 }
623
624 /**
625  * This pops the object that is on top (visible) in the navigationbar, makes it disappear, then deletes the object. 
626  * The object that was underneath it, on the stack will become visible.
627  *
628  * @param[in] obj The NavigationBar object
629  *
630  * @ingroup NavigationBar
631  */
632 EAPI void 
633 elm_navigationbar_pop(Evas_Object *obj)
634 {
635    ELM_CHECK_WIDTYPE(obj, widtype);
636    Widget_Data *wd = elm_widget_data_get(obj);
637    Eina_List *ll;
638    Item *it = NULL;
639    Item *prev_it = NULL;
640    
641    if(wd->popping) return;
642    if (!wd->stack) return;
643
644    //find item to be popped and to be shown
645    ll = eina_list_last(wd->stack);
646    if (ll)
647      {
648         prev_it = ll->data;
649         ll = ll->prev;
650         if (ll)
651           {
652              it = ll->data;
653           }
654      }
655    //unswallow items and start trasition
656    Transit_Cb_Data *cb = ELM_NEW(Transit_Cb_Data);
657    if (prev_it && it) 
658      {
659         cb->prev_it = prev_it;
660         cb->it = it;
661         cb->pop = EINA_TRUE; 
662         if (prev_it->title_obj) edje_object_part_unswallow(wd->base, prev_it->title_obj);
663         if (prev_it->fn_btn1) edje_object_part_unswallow(wd->base, prev_it->fn_btn1);
664         else if (prev_it->back_btn) edje_object_part_unswallow(wd->base, prev_it->back_btn);
665         if (prev_it->fn_btn2) edje_object_part_unswallow(wd->base, prev_it->fn_btn2);
666         if (prev_it->fn_btn3) edje_object_part_unswallow(wd->base, prev_it->fn_btn3);
667         _item_sizing_eval(it);
668      }
669    else if (prev_it)
670      {
671         cb->prev_it = prev_it;
672         cb->it = NULL;
673         cb->pop = EINA_TRUE;
674         cb->first_page = EINA_FALSE;
675      }
676    _transition_complete_cb(cb);
677    wd->popping = EINA_TRUE;
678    //pop content from pager
679    elm_pager_content_pop(wd->pager);
680    if (prev_it && !it)
681       {
682          edje_object_part_text_set(wd->base, "elm.text", NULL);
683       }
684    free(cb);
685 }
686    
687 /**
688  * This Pops to the given content object (and update it) by deleting rest of the objects in between.
689  *
690  * @param[in] obj The NavigationBar object
691  * @param[in] content the object to show
692  *
693  * @ingroup NavigationBar
694  */
695 EAPI void 
696 elm_navigationbar_to_content_pop(Evas_Object *obj, Evas_Object *content)
697 {
698    ELM_CHECK_WIDTYPE(obj, widtype);
699    if (!content) return;
700    Widget_Data *wd = elm_widget_data_get(obj);
701    Eina_List *ll;
702    Item *it = NULL;
703    Item *prev_it = NULL;
704
705    if (!wd->stack) return;
706    //find item to be popped and to be shown
707    ll = eina_list_last(wd->stack);
708    if (ll)
709      {
710         prev_it = ll->data;
711         ll =  ll->prev;   
712         while (ll) 
713           {
714              it = ll->data;    
715              if (it->obj && (it->content != content)) 
716                { 
717                   _delete_item(ll->data);
718                   wd->stack = eina_list_remove_list(wd->stack, ll);
719                   it = NULL;
720                }
721              else
722                break;
723              ll =  ll->prev;   
724           }
725      }
726    if (prev_it && it) 
727      {
728         //unswallow items and start trasition
729         Transit_Cb_Data *cb = ELM_NEW(Transit_Cb_Data);
730         cb->prev_it = prev_it;
731         cb->it = it;
732         cb->pop = EINA_TRUE;
733         cb->first_page = EINA_FALSE;
734         if (prev_it->title_obj) edje_object_part_unswallow(wd->base, prev_it->title_obj);
735         if (prev_it->fn_btn1) edje_object_part_unswallow(wd->base, prev_it->fn_btn1);
736         else if (prev_it->back_btn) edje_object_part_unswallow(wd->base, prev_it->back_btn);
737         if (prev_it->fn_btn2) edje_object_part_unswallow(wd->base, prev_it->fn_btn2);
738         if (prev_it->fn_btn3) edje_object_part_unswallow(wd->base, prev_it->fn_btn3);
739         _item_sizing_eval(it);
740         _transition_complete_cb(cb);
741         //pop content from pager
742         elm_pager_to_content_pop(wd->pager, content);
743      }
744 }
745
746 /**
747  * Set the title string for the pushed content
748  *
749  * @param[in] obj The NavigationBar object
750  * @param[in] content The object to push or pushed
751  * @param[in] title The title string
752  *
753  * @ingroup NavigationBar
754  */
755 EAPI void
756 elm_navigationbar_title_label_set(Evas_Object *obj, Evas_Object *content, const char *title)
757 {
758    ELM_CHECK_WIDTYPE(obj, widtype);
759    Widget_Data *wd = elm_widget_data_get(obj);
760    Eina_List *ll;
761    Item *it;
762
763    if (!wd) return;
764    EINA_LIST_FOREACH(wd->stack, ll, it)
765      {
766         if (it->content == content) 
767           {
768              eina_stringshare_replace(&it->title, title);
769              edje_object_part_text_set(wd->base, "elm.text", title);
770              if (!wd->hidden)
771                {
772                   if ((it->title_obj) && (it->title))
773                     { 
774                        edje_object_signal_emit(wd->base, "elm,state,extend,title", "elm");
775                     }
776                   else
777                     edje_object_signal_emit(wd->base, "elm,state,retract,title", "elm");
778                }
779              _item_sizing_eval(it);
780              break;
781           }
782      }
783 }
784
785 /**
786  * Return the title string of the pushed content
787  *
788  * @param[in] obj The NavigationBar object
789  * @param[in] content The object to push or pushed
790  * @return The title string or NULL if none
791  *
792  * @ingroup NavigationBar
793  */
794 EAPI const char *
795 elm_navigationbar_title_label_get(Evas_Object *obj, Evas_Object *content)
796 {
797    ELM_CHECK_WIDTYPE(obj, widtype)NULL;
798    Widget_Data *wd = elm_widget_data_get(obj);
799    Eina_List *ll;
800    Item *it;
801
802    if (!wd) return NULL;
803    EINA_LIST_FOREACH(wd->stack, ll, it)
804      {
805         if (it->content == content) 
806           return it->title;
807      }
808    return NULL;
809 }
810
811 /**
812  * Add a title object for the content.
813  *
814  * @param[in] obj The NavigationBar object
815  * @param[in] content The object pushed
816  * @param[in] title_obj a title object (normally button or segment_control)
817  *
818  * @ingroup NavigationBar
819  */
820 EAPI void
821 elm_navigationbar_title_object_add(Evas_Object *obj, Evas_Object *content, Evas_Object *title_obj)
822 {
823    ELM_CHECK_WIDTYPE(obj, widtype);
824    Widget_Data *wd = elm_widget_data_get(obj);
825    Eina_List *ll;
826    Item *it;
827    Item *last_it;
828
829    if (!title_obj) return;
830    if (!content) return;
831    if (!wd) return;
832    it = _check_item_is_added(obj, content);
833    if (!it) 
834      {
835         ERR("[ERROR]Push the Item first, later add the title object");
836         return;
837      } 
838    it->title_list = eina_list_append(it->title_list, title_obj);  
839    if (it->obj) _item_sizing_eval(it);  
840    //update if the content is the top item
841    ll = eina_list_last(wd->stack);
842    if (ll) 
843      {
844         last_it = ll->data;
845         if (last_it->content == content) 
846           {
847              Evas_Object *swallow;
848              swallow = edje_object_part_swallow_get(wd->base, "elm.swallow.title");
849              if (swallow) {
850                 edje_object_part_unswallow(wd->base, swallow);
851                 evas_object_hide(swallow);
852              }
853              edje_object_part_swallow(wd->base, "elm.swallow.title", it->title_obj);
854              if (!wd->hidden)
855                {
856                   if (it->fn_btn3)
857                     {
858                        edje_object_signal_emit(wd->base, "elm,state,item,add,rightpad2", "elm");
859                        edje_object_signal_emit(wd->base, "elm,state,item,fn_btn3_set", "elm");
860                     }        
861                   if ((it->title_obj) && (it->title))
862                     { 
863                        edje_object_signal_emit(wd->base, "elm,state,extend,title", "elm");
864                     }
865                }
866              _item_sizing_eval(it);  
867           }
868      }
869 }
870
871 /**
872  * Unset the list of title objects corresponding to given content and returns it to  
873  * the application.
874  * @param[in] obj The NavigationBar object
875  * @param[in] content The content object pushed
876  * @param[out] list updates the list with title objects list, this list has to be freed and the
877  * objects have to be deleted by application.
878  * @ingroup NavigationBar
879  */
880 EAPI void
881 elm_navigationbar_title_object_list_unset(Evas_Object *obj, Evas_Object *content, Eina_List **list)
882 {
883    ELM_CHECK_WIDTYPE(obj, widtype);
884    Widget_Data *wd = elm_widget_data_get(obj);
885    Eina_List *ll;
886    Item *it;
887    Item *last_it = NULL;
888    ll = eina_list_last(wd->stack);
889
890    if (ll) 
891      {
892         last_it = ll->data;
893      }
894    if (!wd) return;
895    EINA_LIST_FOREACH(wd->stack, ll, it)
896      {
897         if (it->content == content)   
898           {
899              if (last_it->content == it->content) 
900                {
901                   Evas_Object *swallow;
902                   swallow = edje_object_part_swallow_get(wd->base, "elm.swallow.title");
903                   if (swallow) 
904                     {
905                        edje_object_part_unswallow(wd->base, swallow);
906                        evas_object_hide(swallow);
907                     }
908                } 
909              _multiple_object_unset(it, list);   
910              evas_object_del(it->title_obj);
911              it->title_obj = NULL;      
912              if (!wd->hidden)
913                {
914                   edje_object_signal_emit(wd->base, "elm,state,retract,title", "elm");
915                   if(it->fn_btn3)
916                      {
917                         edje_object_signal_emit(wd->base, "elm,state,item,add,rightpad2", "elm");
918                         edje_object_signal_emit(wd->base, "elm,state,item,fn_btn3_set", "elm");
919                      }
920                }
921              _item_sizing_eval(it);
922          }
923      }
924 }
925
926
927 /**
928  * Return the list of title objects of the pushed content.
929  *
930  * @param[in] obj The NavigationBar object
931  * @param[in] content The object to push or pushed
932  * @return The list of title objects
933  *
934  * @ingroup NavigationBar
935  */
936 EAPI Eina_List *
937 elm_navigationbar_title_object_list_get(Evas_Object *obj, Evas_Object *content)
938 {
939    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
940    Widget_Data *wd = elm_widget_data_get(obj);
941    Eina_List *ll;
942    Item *it;
943
944    if (!wd) return NULL;
945    EINA_LIST_FOREACH(wd->stack, ll, it)
946      {
947         if (it->content == content)   
948           return it->title_list;
949      }  
950    return NULL;
951 }
952
953 static void
954 _elm_navigationbar_back_button_set(Evas_Object *obj, Evas_Object *content, Evas_Object *button)
955 {
956    Widget_Data *wd = elm_widget_data_get(obj);
957    Eina_List *ll;
958    Item *it;
959    Eina_Bool changed;
960
961    if (!wd) return;
962    EINA_LIST_FOREACH(wd->stack, ll, it)
963      {
964         if (it->content == content) 
965           {
966              if(it->back_btn == button)
967                return;
968              changed = _button_set(obj, it->back_btn, button, EINA_TRUE);
969              it->back_btn = button;
970              _item_sizing_eval(it);
971              break;
972           }
973      }
974    
975    //update if the content is the top item
976    ll = eina_list_last(wd->stack);
977    if (ll) 
978      {
979         it = ll->data;
980         if (it->back_btn && changed && (it->content == content) && (!it->fn_btn1)) 
981           {
982              edje_object_part_swallow(wd->base, "elm.swallow.btn1", it->back_btn);   
983              evas_object_smart_callback_add(it->back_btn, "clicked", _back_button_clicked, it); 
984           }
985      }
986 }
987
988 static Evas_Object *
989 _elm_navigationbar_back_button_get(Evas_Object *obj, Evas_Object *content)
990 {
991    Widget_Data *wd = elm_widget_data_get(obj);
992    Eina_List *ll;
993    Item *it;
994    
995    if (!wd) return NULL;
996    EINA_LIST_FOREACH(wd->stack, ll, it)
997      {
998         if (it->content == content)
999           return it->back_btn;
1000      }  
1001    return NULL;
1002 }
1003
1004 static void 
1005 _elm_navigationbar_function_button1_set(Evas_Object *obj, Evas_Object *content, Evas_Object *button)
1006 {
1007    Widget_Data *wd = elm_widget_data_get(obj);
1008    Eina_List *ll;
1009    Item *it;
1010    Eina_Bool changed;
1011
1012    if (!wd) return;
1013    EINA_LIST_FOREACH(wd->stack, ll, it)
1014      {
1015         if (it->content == content) 
1016           {
1017              if(it->fn_btn1 == button)
1018                return;
1019              changed = _button_set(obj, it->fn_btn1, button, EINA_FALSE);
1020              it->fn_btn1 = button;
1021              _item_sizing_eval(it);
1022              break;
1023           }
1024      }
1025
1026    //update if the content is the top item
1027    ll = eina_list_last(wd->stack);
1028    if (ll)
1029      {
1030         it = ll->data;
1031         if (it->fn_btn1 && changed && (it->content == content)) 
1032           {
1033              if (edje_object_part_swallow_get(wd->base, "elm.swallow.btn1") == it->back_btn)
1034                {
1035                   edje_object_part_unswallow(wd->base, it->back_btn);
1036                   evas_object_hide(it->back_btn);
1037                }
1038              edje_object_part_swallow(wd->base, "elm.swallow.btn1", it->fn_btn1);
1039           }
1040      }
1041 }
1042
1043 static Evas_Object *
1044 _elm_navigationbar_function_button1_get(Evas_Object *obj, Evas_Object *content)
1045 {
1046    Widget_Data *wd = elm_widget_data_get(obj);
1047    Eina_List *ll;
1048    Item *it;
1049    
1050    if (!wd) return NULL;
1051    EINA_LIST_FOREACH(wd->stack, ll, it)
1052      {
1053         if (it->content == content) 
1054           return it->fn_btn1;
1055      }  
1056    return NULL;
1057 }
1058
1059 static void 
1060 _elm_navigationbar_function_button2_set(Evas_Object *obj, Evas_Object *content, Evas_Object *button)
1061 {
1062    Widget_Data *wd = elm_widget_data_get(obj);
1063    Eina_List *ll;
1064    Item *it;
1065    Eina_Bool changed;
1066
1067    if (!wd) return;
1068    EINA_LIST_FOREACH(wd->stack, ll, it)
1069      {
1070         if (it->content == content) 
1071           {
1072              if(it->fn_btn2 == button)
1073                return;
1074              changed = _button_set(obj, it->fn_btn2, button, EINA_FALSE);
1075              it->fn_btn2 = button;
1076              _item_sizing_eval(it);
1077              break;
1078           }
1079      } 
1080     
1081    //update if the content is the top item
1082    ll = eina_list_last(wd->stack);
1083    if (ll) 
1084       {
1085          it = ll->data;
1086          if (it->fn_btn2 && changed && (it->content == content)) 
1087             {
1088                edje_object_part_swallow(wd->base, "elm.swallow.btn2", it->fn_btn2);
1089             }
1090       }
1091 }
1092
1093 static Evas_Object *
1094 _elm_navigationbar_function_button2_get(Evas_Object *obj, 
1095                               Evas_Object *content)
1096 {
1097    Widget_Data *wd = elm_widget_data_get(obj);
1098    Eina_List *ll;
1099    Item *it;
1100
1101    if (!wd) return NULL;
1102    EINA_LIST_FOREACH(wd->stack, ll, it)
1103      {
1104         if (it->content == content) 
1105           return it->fn_btn2;
1106      }
1107    return NULL;
1108 }
1109
1110 static void 
1111 _elm_navigationbar_function_button3_set(Evas_Object *obj, Evas_Object *content, Evas_Object *button)
1112 {
1113    Widget_Data *wd = elm_widget_data_get(obj);
1114    Eina_List *ll;
1115    Item *it;
1116    Eina_Bool changed;
1117
1118    if (!wd) return;
1119    EINA_LIST_FOREACH(wd->stack, ll, it)
1120      {
1121         if (it->content == content) 
1122           {
1123              if(it->fn_btn3 == button)
1124                return;
1125              changed = _button_set(obj, it->fn_btn3, button, EINA_FALSE);
1126              it->fn_btn3 = button;
1127              _item_sizing_eval(it);
1128              break;
1129           }
1130      } 
1131
1132    //update if the content is the top item
1133    ll = eina_list_last(wd->stack);
1134    if (ll) 
1135      {
1136         it = ll->data;
1137         if (it->fn_btn3 && changed && (it->content == content)) 
1138           {
1139              edje_object_signal_emit(wd->base, "elm,state,item,add,rightpad2", "elm");
1140              edje_object_signal_emit(wd->base, "elm,state,item,fn_btn3_set", "elm");
1141              edje_object_part_swallow(wd->base, "elm.swallow.btn3", it->fn_btn3);
1142           }
1143         else
1144           edje_object_signal_emit(wd->base, "elm,state,retract,title", "elm");
1145      }
1146 }
1147
1148 static Evas_Object *
1149 _elm_navigationbar_function_button3_get(Evas_Object *obj, 
1150                               Evas_Object *content)
1151 {
1152    Widget_Data *wd = elm_widget_data_get(obj);
1153    Eina_List *ll;
1154    Item *it;
1155
1156    if (!wd) return NULL;
1157    EINA_LIST_FOREACH(wd->stack, ll, it)
1158      {
1159         if (it->content == content) 
1160           return it->fn_btn3;
1161      }
1162    return NULL;
1163 }
1164
1165 /**
1166  * Return the content object at the top of the NavigationBar stack
1167  *
1168  * @param[in] obj The NavigationBar object
1169  * @return The top content object or NULL if none
1170  *
1171  * @ingroup NavigationBar
1172  */
1173 EAPI Evas_Object *
1174 elm_navigationbar_content_top_get(Evas_Object *obj)
1175 {
1176    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1177    Widget_Data *wd = elm_widget_data_get(obj);
1178    
1179    if (!wd) return NULL;
1180    return elm_pager_content_top_get(wd->pager);
1181 }
1182
1183 /**
1184  * Return the content object at the bottom of the NavigationBar stack
1185  *
1186  * @param[in] obj The NavigationBar object
1187  * @return The bottom content object or NULL if none
1188  *
1189  * @ingroup NavigationBar
1190  */
1191 EAPI Evas_Object *
1192 elm_navigationbar_content_bottom_get(Evas_Object *obj)
1193 {
1194    ELM_CHECK_WIDTYPE(obj, widtype)NULL;
1195    Widget_Data *wd = elm_widget_data_get(obj);
1196    
1197    if (!wd) return NULL;
1198    return elm_pager_content_bottom_get(wd->pager);
1199 }
1200
1201 /**
1202  * This hides the title area of navigationbar.
1203  *
1204  * @param[in] obj The NavigationBar object
1205  * @param[in] hidden if EINA_TRUE the title area is hidden.
1206  *
1207  * @ingroup NavigationBar
1208  */
1209 EAPI void
1210 elm_navigationbar_hidden_set(Evas_Object *obj, 
1211                         Eina_Bool hidden)
1212 {
1213    ELM_CHECK_WIDTYPE(obj, widtype);
1214    Widget_Data *wd = elm_widget_data_get(obj);
1215    
1216    if (!wd) return;
1217    if (hidden) 
1218      edje_object_signal_emit(wd->base, "elm,state,item,moveup", "elm");
1219    else 
1220      edje_object_signal_emit(wd->base, "elm,state,item,movedown", "elm");
1221    wd->hidden = hidden;
1222 }
1223
1224 /**
1225  * Set the button object of the pushed content.
1226  *
1227  * @param[in] obj The NavigationBar object
1228  * @param[in] content The object to push or pushed
1229  * @param[in] button The button
1230  * @param[in] button_type Indicates the position
1231  *
1232  * @ingroup NavigationBar
1233  */
1234 EAPI void 
1235 elm_navigationbar_title_button_set(Evas_Object *obj, Evas_Object *content, Evas_Object *button, Elm_Navi_Button_Type button_type)
1236 {
1237    ELM_CHECK_WIDTYPE(obj, widtype);
1238    if (!content) return;
1239    
1240    switch(button_type)
1241      {
1242       case ELM_NAVIGATIONBAR_FUNCTION_BUTTON1:
1243         _elm_navigationbar_function_button1_set(obj, content, button);
1244         break;
1245       case ELM_NAVIGATIONBAR_FUNCTION_BUTTON2:
1246         _elm_navigationbar_function_button2_set(obj, content, button);
1247         break;
1248       case ELM_NAVIGATIONBAR_FUNCTION_BUTTON3:
1249         _elm_navigationbar_function_button3_set(obj, content, button);
1250         break;
1251       case ELM_NAVIGATIONBAR_BACK_BUTTON:
1252         _elm_navigationbar_back_button_set(obj, content, button);
1253         break;
1254       default: 
1255         break;
1256      }        
1257    _sizing_eval(obj);
1258 }
1259
1260 /**
1261  * Return the button object of the pushed content
1262  *
1263  * @param[in] obj The NavigationBar object
1264  * @param[in] content The object to push or pushed
1265  * @param[in] button_type Indicates the position
1266  * @return The button object or NULL if none
1267  *
1268  * @ingroup NavigationBar
1269  */
1270 EAPI Evas_Object *
1271 elm_navigationbar_title_button_get(Evas_Object *obj, Evas_Object *content, Elm_Navi_Button_Type button_type)
1272 {
1273    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1274    Evas_Object *button=NULL;
1275    
1276    if (!content || !obj) return NULL;   
1277    switch(button_type)
1278      {
1279       case ELM_NAVIGATIONBAR_FUNCTION_BUTTON1:
1280         button  = _elm_navigationbar_function_button1_get(obj, content);
1281         break;
1282       case ELM_NAVIGATIONBAR_FUNCTION_BUTTON2:
1283         button = _elm_navigationbar_function_button2_get(obj, content);
1284         break;
1285       case ELM_NAVIGATIONBAR_FUNCTION_BUTTON3:
1286         button  = _elm_navigationbar_function_button3_get(obj, content);
1287         break;
1288       case ELM_NAVIGATIONBAR_BACK_BUTTON:
1289         button = _elm_navigationbar_back_button_get(obj, content);
1290         break;
1291       default: 
1292         break;
1293      }  
1294    return button;
1295 }
1296
1297 /**
1298  * Set the sub title string for the pushed content.
1299  *
1300  * @param[in] obj The NavigationBar object
1301  * @param[in] content The object to push or pushed
1302  * @param[in] subtitle The subtitle string
1303  *
1304  * @ingroup NavigationBar
1305  */
1306 EAPI void 
1307 elm_navigationbar_subtitle_label_set(Evas_Object *obj, Evas_Object *content, const char *subtitle)
1308 {
1309    ELM_CHECK_WIDTYPE(obj, widtype);
1310    Widget_Data *wd = elm_widget_data_get(obj);
1311    Eina_List *ll;
1312    Item *it;
1313
1314    if (!wd) return;
1315    EINA_LIST_FOREACH(wd->stack, ll, it)
1316      {
1317         if (it->content == content) 
1318           {
1319              eina_stringshare_replace(&it->subtitle, subtitle);
1320              edje_object_part_text_set(wd->base, "elm.text.sub", subtitle);
1321              _item_sizing_eval(it);
1322              break;
1323           }
1324      }
1325 }
1326
1327 /**
1328  * Return the subtitle string of the pushed content.
1329  *
1330  * @param[in] obj The NavigationBar object
1331  * @param[in] content The object to push or pushed
1332  * @return The subtitle string or NULL if none
1333  *
1334  * @ingroup NavigationBar
1335  */
1336 EAPI const char *
1337 elm_navigationbar_subtitle_label_get(Evas_Object *obj, Evas_Object *content)
1338 {
1339    ELM_CHECK_WIDTYPE(obj, widtype)NULL;
1340    Widget_Data *wd = elm_widget_data_get(obj);
1341    Eina_List *ll;
1342    Item *it;
1343
1344    if (!wd) return NULL;
1345    EINA_LIST_FOREACH(wd->stack, ll, it)
1346      {
1347         if (it->content == content) 
1348           return it->subtitle;
1349      }
1350    return NULL;
1351 }
1352
1353 /**
1354  * This disables content area animation on push/pop.
1355  *
1356  * @param[in] obj The NavigationBar object
1357  * @param[in] disable  if EINA_TRUE animation is disabled.
1358  *
1359  * @ingroup NavigationBar
1360  */
1361 EAPI void 
1362 elm_navigationbar_animation_disable_set(Evas_Object *obj, Eina_Bool disable)
1363 {
1364    ELM_CHECK_WIDTYPE(obj, widtype);
1365    Widget_Data *wd = elm_widget_data_get(obj);
1366    
1367    elm_pager_animation_disable_set(wd->pager, disable);
1368 }
1369