1 #include <Elementary.h>
4 typedef struct _Widget_Data Widget_Data;
5 typedef struct _Elm_Naviframe_Item Elm_Naviframe_Item;
11 Eina_Bool preserve: 1;
12 Eina_Bool pass_events: 1;
15 struct _Elm_Naviframe_Item
20 const char *title_label;
21 const char *title_sublabel;
22 Evas_Object *title_prev_btn;
23 Evas_Object *title_next_btn;
24 Evas_Object *title_icon;
26 Eina_Bool back_btn: 1;
27 Eina_Bool title_visible: 1;
30 static const char *widtype = NULL;
32 static const char SIG_TRANSITION_FINISHED[] = "transition,finished";
33 static const char SIG_TITLE_CLICKED[] = "title,clicked";
35 static const Evas_Smart_Cb_Description _signals[] = {
36 {SIG_TRANSITION_FINISHED, ""},
37 {SIG_TITLE_CLICKED, ""},
41 #define ELM_NAVIFRAME_ITEM_CHECK_RETURN(it, ...) \
42 ELM_WIDGET_ITEM_CHECK_OR_RETURN((Elm_Widget_Item *) it, __VA_ARGS__); \
43 ELM_CHECK_WIDTYPE(it->base.widget, widtype) __VA_ARGS__;
45 static void _del_hook(Evas_Object *obj);
46 static void _theme_hook(Evas_Object *obj);
47 static void _disable_hook(Evas_Object *obj);
48 static void _sizing_eval(Evas_Object *obj);
49 static void _item_sizing_eval(Elm_Naviframe_Item *it);
50 static void _move(void *data, Evas *e, Evas_Object *obj, void *event_info);
51 static void _resize(void *data,
55 static void _title_clicked(void *data, Evas_Object *obj,
58 static void _back_btn_clicked(void *data,
61 static Evas_Object *_back_btn_new(Evas_Object *obj);
62 static void _title_prev_btn_del(void *data,
66 static void _title_next_btn_del(void *data,
70 static void _title_icon_del(void *data,
74 static void _content_del(void *data,
78 static void _title_prev_btn_set(Elm_Naviframe_Item *it,
81 static void _title_next_btn_set(Elm_Naviframe_Item *it, Evas_Object *btn);
82 static void _item_del(Elm_Naviframe_Item *it);
83 static void _pushed_finished(void *data,
87 static void _popped_finished(void *data,
91 static void _show_finished(void *data,
97 _del_hook(Evas_Object *obj)
101 Elm_Naviframe_Item *it;
103 wd = elm_widget_data_get(obj);
106 EINA_LIST_FOREACH(wd->stack, list, it)
108 eina_list_free(wd->stack);
113 _theme_hook(Evas_Object *obj __UNUSED__)
119 _disable_hook(Evas_Object *obj __UNUSED__)
125 _sizing_eval(Evas_Object *obj)
129 Elm_Naviframe_Item *it;
130 wd = elm_widget_data_get(obj);
133 list = eina_list_last(wd->stack);
136 EINA_LIST_FOREACH(wd->stack, list, it)
137 _item_sizing_eval(it);
141 _item_sizing_eval(Elm_Naviframe_Item *it)
144 Evas_Coord x, y, w, h;
147 wd = elm_widget_data_get(it->base.widget);
150 evas_object_geometry_get(it->base.widget, &x, &y, &w, &h);
151 evas_object_move(it->base.view, x, y);
152 evas_object_resize(it->base.view, w, h);
156 _move(void *data __UNUSED__,
159 void *event_info __UNUSED__)
165 _resize(void *data __UNUSED__,
168 void *event_info __UNUSED__)
174 _title_clicked(void *data,
175 Evas_Object *obj __UNUSED__,
176 const char *emission __UNUSED__,
177 const char *source __UNUSED__)
179 Elm_Naviframe_Item *it = data;
180 evas_object_smart_callback_call(it->base.widget, SIG_TITLE_CLICKED, it);
184 _back_btn_clicked(void *data,
185 Evas_Object *obj __UNUSED__,
186 void *event_info __UNUSED__)
188 elm_naviframe_item_pop(data);
192 _back_btn_new(Evas_Object *obj)
195 char buf[256]; //FIXME: How to guarantee the size of style name?
196 btn = elm_button_add(obj);
197 if (!btn) return NULL;
198 evas_object_smart_callback_add(btn, "clicked", _back_btn_clicked, obj);
199 snprintf(buf, sizeof(buf), "naviframe/back_btn/%s", elm_widget_style_get(obj));
200 elm_object_style_set(btn, buf);
205 _title_prev_btn_del(void *data,
207 Evas_Object *obj __UNUSED__,
208 void *event_info __UNUSED__)
210 Elm_Naviframe_Item *it = data;
211 it->back_btn = EINA_FALSE;
212 it->title_prev_btn = NULL;
216 _title_next_btn_del(void *data,
218 Evas_Object *obj __UNUSED__,
219 void *event_info __UNUSED__)
221 Elm_Naviframe_Item *it = data;
222 it->title_next_btn = NULL;
226 _title_icon_del(void *data,
228 Evas_Object *obj __UNUSED__,
229 void *event_info __UNUSED__)
231 Elm_Naviframe_Item *it = data;
232 it->title_icon = NULL;
233 edje_object_signal_emit(it->base.view, "elm,state,icon,hide", "elm");
237 _content_del(void *data,
239 Evas_Object *obj __UNUSED__,
240 void *event_info __UNUSED__)
242 Elm_Naviframe_Item *it = data;
244 edje_object_signal_emit(it->base.view, "elm,state,content,hide", "elm");
248 _title_prev_btn_set(Elm_Naviframe_Item *it, Evas_Object *btn, Eina_Bool back_btn)
250 char buf[256]; //FIXME: How to guarantee the size of style name?
252 if (it->title_prev_btn == btn) return;
254 if (it->title_prev_btn)
255 evas_object_del(it->title_prev_btn);
257 it->title_prev_btn = btn;
265 "naviframe/prev_btn/%s",
266 elm_widget_style_get(it->base.widget));
267 elm_object_style_set(btn, buf);
269 elm_widget_sub_object_add(it->base.widget, btn);
270 evas_object_event_callback_add(btn,
274 edje_object_part_swallow(it->title, "elm.swallow.prev_btn", btn);
275 it->back_btn = back_btn;
279 _title_next_btn_set(Elm_Naviframe_Item *it, Evas_Object *btn)
281 char buf[256]; //FIXME: How to guarantee the size of style name?
283 if (it->title_next_btn == btn) return;
285 if (it->title_next_btn)
286 evas_object_del(it->title_next_btn);
288 it->title_next_btn = btn;
294 "naviframe/next_btn/%s",
295 elm_widget_style_get(it->base.widget));
296 elm_object_style_set(btn, buf);
297 elm_widget_sub_object_add(it->base.widget, btn);
298 evas_object_event_callback_add(btn,
302 edje_object_part_swallow(it->title, "elm.swallow.next_btn", btn);
306 _item_del(Elm_Naviframe_Item *it)
312 wd = elm_widget_data_get(it->base.widget);
315 if (it->title_prev_btn)
316 evas_object_del(it->title_prev_btn);
317 if (it->title_next_btn)
318 evas_object_del(it->title_next_btn);
320 evas_object_del(it->title_icon);
321 if ((it->content) && (!wd->preserve))
322 evas_object_del(it->content);
324 evas_object_del(it->title);
325 evas_object_del(it->base.view);
327 wd->stack = eina_list_remove(wd->stack, it);
333 _pushed_finished(void *data,
334 Evas_Object *obj __UNUSED__,
335 const char *emission __UNUSED__,
336 const char *source __UNUSED__)
338 Elm_Naviframe_Item *it = data;
340 evas_object_hide(it->base.view);
344 _popped_finished(void *data,
345 Evas_Object *obj __UNUSED__,
346 const char *emission __UNUSED__,
347 const char *source __UNUSED__)
353 _show_finished(void *data,
354 Evas_Object *obj __UNUSED__,
355 const char *emission __UNUSED__,
356 const char *source __UNUSED__)
358 Elm_Naviframe_Item *it;
363 wd = elm_widget_data_get(it->base.widget);
366 evas_object_smart_callback_call(it->base.widget,
367 SIG_TRANSITION_FINISHED,
370 evas_object_pass_events_set(wd->base, EINA_FALSE);
374 elm_naviframe_add(Evas_Object *parent)
380 ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
381 ELM_SET_WIDTYPE(widtype, "naviframe");
382 elm_widget_type_set(obj, "naviframe");
383 elm_widget_sub_object_add(parent, obj);
384 elm_widget_data_set(obj, wd);
385 elm_widget_del_hook_set(obj, _del_hook);
386 elm_widget_disable_hook_set(obj, _disable_hook);
387 elm_widget_theme_hook_set(obj, _theme_hook);
390 wd->base = edje_object_add(e);
391 elm_widget_resize_object_set(obj, wd->base);
392 _elm_theme_object_set(obj, wd->base, "naviframe", "base", "default");
394 evas_object_event_callback_add(obj, EVAS_CALLBACK_MOVE, _move, obj);
395 evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE, _resize, obj);
396 evas_object_smart_callbacks_descriptions_set(obj, _signals);
398 wd->pass_events = EINA_TRUE;
403 EAPI Elm_Object_Item *
404 elm_naviframe_item_push(Evas_Object *obj, const char *title_label, Evas_Object *prev_btn, Evas_Object *next_btn, Evas_Object *content, const char *item_style)
406 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
408 Elm_Naviframe_Item *prev_it, *it;
410 wd = elm_widget_data_get(obj);
411 if (!wd) return NULL;
414 it = elm_widget_item_new(obj, Elm_Naviframe_Item);
417 ERR("Failed to allocate new item! : naviframe=%p", obj);
421 it->base.view = edje_object_add(evas_object_evas_get(obj));
422 evas_object_smart_member_add(it->base.view, wd->base);
423 elm_widget_sub_object_add(obj, it->base.view);
424 edje_object_signal_callback_add(it->base.view,
425 "elm,action,show,finished",
428 edje_object_signal_callback_add(it->base.view,
429 "elm,action,pushed,finished",
431 _pushed_finished, it);
432 edje_object_signal_callback_add(it->base.view,
433 "elm,action,popped,finished",
435 _popped_finished, it);
436 elm_naviframe_item_style_set(ELM_CAST(it), item_style);
439 it->title = edje_object_add(evas_object_evas_get(obj));
440 elm_widget_sub_object_add(obj, it->title);
441 _elm_theme_object_set(obj,
442 it->title, "naviframe",
444 elm_widget_style_get(obj));
445 edje_object_signal_callback_add(it->title,
446 "elm,action,clicked",
450 elm_naviframe_item_title_label_set(ELM_CAST(it), title_label);
453 if ((!prev_btn) && (eina_list_count(wd->stack)))
455 prev_btn = _back_btn_new(obj);
456 _title_prev_btn_set(it, prev_btn, EINA_TRUE);
459 _title_prev_btn_set(it, prev_btn, EINA_FALSE);
461 _title_next_btn_set(it, next_btn);
462 edje_object_part_swallow(it->base.view, "elm.swallow.title", it->title);
464 elm_naviframe_item_content_set(ELM_CAST(it), content);
466 _item_sizing_eval(it);
467 evas_object_show(it->base.view);
469 prev_it = ELM_CAST(elm_naviframe_top_item_get(obj));
473 evas_object_pass_events_set(wd->base, EINA_TRUE);
474 edje_object_signal_emit(prev_it->base.view,
477 edje_object_signal_emit(it->base.view,
482 edje_object_signal_emit(it->base.view, "elm,state,visible", "elm");
483 it->title_visible = EINA_TRUE;
484 wd->stack = eina_list_append(wd->stack, it);
489 elm_naviframe_item_pop(Evas_Object *obj)
491 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
492 Elm_Naviframe_Item *it, *prev_it;
494 Evas_Object *content = NULL;
496 wd = elm_widget_data_get(obj);
497 if (!wd) return NULL;
499 it = ELM_CAST(elm_naviframe_top_item_get(obj));
500 if (!it) return NULL;
501 wd->stack = eina_list_remove(wd->stack, it);
504 content = it->content;
506 prev_it = ELM_CAST(elm_naviframe_top_item_get(obj));
510 evas_object_pass_events_set(wd->base, EINA_TRUE);
511 evas_object_show(prev_it->base.view);
512 evas_object_raise(prev_it->base.view);
513 edje_object_signal_emit(prev_it->base.view,
516 edje_object_signal_emit(it->base.view, "elm,state,popped", "elm");
525 elm_naviframe_content_preserve_on_pop_set(Evas_Object *obj, Eina_Bool preserve)
527 ELM_CHECK_WIDTYPE(obj, widtype);
528 Widget_Data *wd = elm_widget_data_get(obj);
530 wd->preserve = !!preserve;
534 elm_naviframe_content_preserve_on_pop_get(const Evas_Object *obj)
536 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
537 Widget_Data *wd = elm_widget_data_get(obj);
538 if (!wd) return EINA_FALSE;
543 elm_naviframe_item_content_set(Elm_Object_Item *it, Evas_Object *content)
545 Elm_Naviframe_Item *navi_it = ELM_CAST(it);
546 ELM_NAVIFRAME_ITEM_CHECK_RETURN(navi_it);
548 if (navi_it->content == content) return;
549 if (navi_it->content) evas_object_del(navi_it->content);
550 elm_widget_sub_object_add(navi_it->base.widget, content);
551 edje_object_part_swallow(navi_it->base.view, "elm.swallow.content", content);
553 edje_object_signal_emit(navi_it->base.view,
554 "elm,state,content,show",
557 edje_object_signal_emit(navi_it->base.view,
558 "elm,state,content,hide",
560 evas_object_event_callback_add(content,
564 navi_it->content = content;
565 _item_sizing_eval(navi_it);
569 elm_naviframe_item_content_get(const Elm_Object_Item *it)
571 Elm_Naviframe_Item *navi_it = ELM_CAST(it);
572 ELM_NAVIFRAME_ITEM_CHECK_RETURN(navi_it, NULL);
573 return navi_it->content;
577 elm_naviframe_item_title_label_set(Elm_Object_Item *it, const char *label)
579 Elm_Naviframe_Item *navi_it = ELM_CAST(it);
580 ELM_NAVIFRAME_ITEM_CHECK_RETURN(navi_it);
582 edje_object_part_text_set(navi_it->title, "elm.text.title", label);
584 edje_object_signal_emit(navi_it->title, "elm,state,title,show", "elm");
586 edje_object_signal_emit(navi_it->title, "elm,state,title,hidew", "elm");
588 eina_stringshare_replace(&navi_it->title_label, label);
589 _item_sizing_eval(navi_it);
593 elm_naviframe_item_title_label_get(const Elm_Object_Item *it)
595 Elm_Naviframe_Item *navi_it = ELM_CAST(it);
596 ELM_NAVIFRAME_ITEM_CHECK_RETURN(navi_it, NULL);
598 return navi_it->title_label;
602 elm_naviframe_item_subtitle_label_set(Elm_Object_Item *it, const char *label)
604 Elm_Naviframe_Item *navi_it = ELM_CAST(it);
605 ELM_NAVIFRAME_ITEM_CHECK_RETURN(navi_it);
607 edje_object_part_text_set(navi_it->title, "elm.text.subtitle", label);
609 edje_object_signal_emit(navi_it->title, "elm,state,subtitle,show", "elm");
611 edje_object_signal_emit(navi_it->title, "elm,state,subtitle,hide", "elm");
613 eina_stringshare_replace(&navi_it->title_sublabel, label);
614 _item_sizing_eval(navi_it);
618 elm_naviframe_item_subtitle_label_get(const Elm_Object_Item *it)
620 Elm_Naviframe_Item *navi_it = ELM_CAST(it);
621 ELM_NAVIFRAME_ITEM_CHECK_RETURN(navi_it, NULL);
622 return navi_it->title_sublabel;
625 EAPI Elm_Object_Item*
626 elm_naviframe_top_item_get(const Evas_Object *obj)
628 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
629 Widget_Data *wd = elm_widget_data_get(obj);
630 if ((!wd) || (!wd->stack)) return NULL;
631 return eina_list_last(wd->stack)->data;
634 EAPI Elm_Object_Item*
635 elm_naviframe_bottom_item_get(const Evas_Object *obj)
637 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
638 Widget_Data *wd = elm_widget_data_get(obj);
639 if (!wd) return NULL;
644 elm_naviframe_item_button_set(Elm_Object_Item *it, Evas_Object *btn, Elm_Naviframe_Button_Type btn_type)
646 Elm_Naviframe_Item *navi_it = ELM_CAST(it);
647 ELM_NAVIFRAME_ITEM_CHECK_RETURN(navi_it);
651 case ELM_NAVIFRAME_PREV_BUTTON:
652 _title_prev_btn_set(navi_it, btn, EINA_FALSE);
654 case ELM_NAVIFRAME_NEXT_BUTTON:
655 _title_next_btn_set(navi_it, btn);
658 WRN("Button type is invalid! : naviframe=%p", navi_it->base.widget);
661 _item_sizing_eval(navi_it);
665 elm_naviframe_item_button_get(const Elm_Object_Item *it, Elm_Naviframe_Button_Type btn_type)
667 Elm_Naviframe_Item *navi_it = ELM_CAST(it);
668 ELM_NAVIFRAME_ITEM_CHECK_RETURN(navi_it, NULL);
672 case ELM_NAVIFRAME_PREV_BUTTON:
673 return navi_it->title_prev_btn;
674 case ELM_NAVIFRAME_NEXT_BUTTON:
675 return navi_it->title_next_btn;
677 WRN("Button type is invalid! : naviframe=%p", navi_it->base.widget);
684 elm_naviframe_item_icon_set(Elm_Object_Item *it, Evas_Object *icon)
686 Elm_Naviframe_Item *navi_it = ELM_CAST(it);
687 ELM_NAVIFRAME_ITEM_CHECK_RETURN(navi_it);
689 Widget_Data *wd = elm_widget_data_get(navi_it->base.widget);
692 if (navi_it->title_icon == icon) return;
693 if (navi_it->title_icon) evas_object_del(navi_it->title_icon);
694 navi_it->title_icon = icon;
697 edje_object_signal_emit(navi_it->title,
698 "elm,state,icon,hide",
702 elm_widget_sub_object_add(navi_it->base.widget, icon);
703 edje_object_part_swallow(navi_it->title, "elm.swallow.icon", icon);
704 edje_object_signal_emit(navi_it->title, "elm,state,icon,show", "elm");
706 evas_object_event_callback_add(icon, EVAS_CALLBACK_DEL, _title_icon_del, navi_it);
707 _item_sizing_eval(navi_it);
711 elm_naviframe_item_icon_get(const Elm_Object_Item *it)
713 Elm_Naviframe_Item *navi_it = ELM_CAST(it);
714 ELM_NAVIFRAME_ITEM_CHECK_RETURN(navi_it, NULL);
715 return navi_it->title_icon;
719 elm_naviframe_item_style_set(Elm_Object_Item *it, const char *item_style)
721 Elm_Naviframe_Item *navi_it = ELM_CAST(it);
722 ELM_NAVIFRAME_ITEM_CHECK_RETURN(navi_it);
726 if (!item_style) sprintf(buf, "item/basic");
729 if (strlen(item_style) > sizeof(buf))
730 WRN("too much long style name! : naviframe=%p", navi_it->base.widget);
732 sprintf(buf, "item/%s", item_style);
734 _elm_theme_object_set(navi_it->base.widget,
738 elm_widget_style_get(navi_it->base.widget));
742 elm_naviframe_item_style_get(const Elm_Object_Item *it)
744 Elm_Naviframe_Item *navi_it = ELM_CAST(it);
745 ELM_NAVIFRAME_ITEM_CHECK_RETURN(navi_it, NULL);
746 return navi_it->style;
750 elm_naviframe_item_title_visible_set(Elm_Object_Item *it, Eina_Bool visible)
752 Elm_Naviframe_Item *navi_it = ELM_CAST(it);
753 ELM_NAVIFRAME_ITEM_CHECK_RETURN(navi_it);
756 if (navi_it->title_visible == visible) return;
759 edje_object_signal_emit(navi_it->base.view, "elm,state,title,show", "elm");
761 edje_object_signal_emit(navi_it->base.view, "elm,state,title,hide", "elm");
763 navi_it->title_visible = visible;
767 elm_naviframe_item_title_visible_get(const Elm_Object_Item *it)
769 Elm_Naviframe_Item *navi_it = ELM_CAST(it);
770 ELM_NAVIFRAME_ITEM_CHECK_RETURN(navi_it, EINA_FALSE);
771 return navi_it->title_visible;