1 #include <Elementary.h>
4 #define ELM_POPUP_ACTION_BUTTON_MAX 3
5 typedef struct _Widget_Data Widget_Data;
6 typedef struct _Elm_Popup_Content_Item Elm_Popup_Content_Item;
7 typedef struct _Action_Area_Data Action_Area_Data;
13 Evas_Object *title_icon;
14 Evas_Object *content_area;
15 Evas_Object *content_text_obj;
16 Evas_Object *action_area;
21 const char *title_text;
22 Action_Area_Data *buttons[ELM_POPUP_ACTION_BUTTON_MAX];
23 Elm_Wrap_Type content_text_wrap_type;
24 unsigned int button_count;
27 Eina_Bool scr_size_recalc:1;
30 struct _Elm_Popup_Content_Item
39 struct _Action_Area_Data
46 static const char *widtype = NULL;
47 static void _del_hook(Evas_Object *obj);
48 static void _theme_hook(Evas_Object *obj);
49 static void _text_set_hook(Evas_Object *obj, const char *part,
51 static const char *_text_get_hook(const Evas_Object *obj,
53 static void _content_set_hook(Evas_Object *obj, const char *part,
54 Evas_Object *content);
55 static Evas_Object *_content_get_hook(Evas_Object *obj,
57 static Evas_Object *_content_unset_hook(Evas_Object *obj,
59 static void _item_text_set_hook(Elm_Object_Item *it, const char *part,
61 static const char *_item_text_get_hook(const Elm_Object_Item *it,
63 static void _item_content_set_hook(Elm_Object_Item *it, const char *part,
64 Evas_Object *content);
65 static Evas_Object *_item_content_unset_hook(const Elm_Object_Item *it,
67 static Evas_Object *_item_content_get_hook(const Elm_Object_Item *it,
69 static void _item_disable_hook(Elm_Object_Item *it);
70 static void _item_del_pre_hook(Elm_Object_Item *it);
71 static void _item_signal_emit_hook(Elm_Object_Item *it, const char *emission,
73 static void _sizing_eval(Evas_Object *obj);
74 static void _block_clicked_cb(void *data, Evas_Object *obj, void *event_info);
75 static void _notify_resize(void *data, Evas *e, Evas_Object *obj,
77 static void _scroller_resize(void *data, Evas *e, Evas_Object *obj,
79 static void _timeout(void *data, Evas_Object *obj , void *event_info);
80 static void _sub_del(void *data, Evas_Object *obj, void *event_info);
81 static void _mirrored_set(Evas_Object *obj, Eina_Bool rtl);
82 static void _restack(void *data, Evas *e, Evas_Object *obj, void *event_info);
83 static void _layout_change_cb(void *data, Evas_Object *obj __UNUSED__,
84 const char *emission __UNUSED__,
85 const char *source __UNUSED__);
86 static void _item_new(Elm_Popup_Content_Item *item);
87 static void _remove_items(Widget_Data *wd);
88 static void _list_new(Evas_Object *obj);
89 static void _list_del(Widget_Data *wd);
90 static void _item_sizing_eval(Elm_Popup_Content_Item *item);
91 static void _item_select_cb(void *data, Evas_Object *obj __UNUSED__,
92 const char *emission __UNUSED__,
93 const char *source __UNUSED__);
94 static void _scroller_size_calc(Evas_Object *obj);
95 static void _action_button_set(Evas_Object *obj, Evas_Object *btn,
97 static Evas_Object *_action_button_get(Evas_Object *obj, unsigned int idx);
98 static Evas_Object *_action_button_unset(Evas_Object *obj, unsigned int idx);
99 static void _button_remove(Evas_Object *obj, Evas_Object *content,
101 static void _popup_show(void *data, Evas *e, Evas_Object *obj,
103 static void _popup_hide(void *data, Evas *e, Evas_Object *obj,
105 static const char SIG_BLOCK_CLICKED[] = "block,clicked";
106 static const char SIG_TIMEOUT[] = "timeout";
107 static const Evas_Smart_Cb_Description _signals[] = {
108 {SIG_BLOCK_CLICKED, ""},
113 #define ELM_POPUP_CONTENT_ITEM_CHECK_RETURN(it, ...) \
114 ELM_WIDGET_ITEM_CHECK_OR_RETURN((Elm_Widget_Item *)it, __VA_ARGS__); \
115 ELM_CHECK_WIDTYPE(WIDGET(item), widtype) __VA_ARGS__;
118 _layout_set(Evas_Object *obj)
120 Widget_Data *wd = elm_widget_data_get(obj);
123 if ((!(wd->title_text)) && (!(wd->title_icon)))
124 elm_object_signal_emit(wd->base, "elm,state,title_area,hidden", "elm");
126 elm_object_signal_emit(wd->base, "elm,state,title_area,visible", "elm");
127 if (wd->button_count)
128 elm_object_signal_emit(wd->base, "elm,state,action_area,visible", "elm");
130 elm_object_signal_emit(wd->base, "elm,state,action_area,hidden", "elm");
134 _del_hook(Evas_Object *obj)
136 Widget_Data *wd = elm_widget_data_get(obj);
143 _del_pre_hook(Evas_Object *obj)
146 Widget_Data *wd = elm_widget_data_get(obj);
149 evas_object_smart_callback_del(wd->notify, "block,clicked",
151 evas_object_smart_callback_del(wd->notify, "timeout", _timeout);
152 evas_object_event_callback_del(wd->notify, EVAS_CALLBACK_RESIZE,
154 evas_object_event_callback_del(obj, EVAS_CALLBACK_SHOW, _popup_show);
155 wd->button_count = 0;
156 for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
159 evas_object_del(wd->buttons[i]->btn);
160 free(wd->buttons[i]);
161 wd->buttons[i] = NULL;
171 _theme_hook(Evas_Object *obj)
174 Elm_Popup_Content_Item *item;
177 Widget_Data *wd = elm_widget_data_get(obj);
180 elm_layout_theme_set(wd->base, "popup", "base", elm_widget_style_get(obj));
181 _elm_widget_mirrored_reload(obj);
182 _mirrored_set(obj, elm_widget_mirrored_get(obj));
183 if (wd->button_count)
185 snprintf(buf, sizeof(buf), "buttons%u", wd->button_count);
186 elm_layout_theme_set(wd->action_area, "popup", buf,
187 elm_widget_style_get(obj));
188 for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
190 if (!wd->buttons[i]) continue;
191 elm_object_style_set(wd->buttons[i]->btn, buf);
194 elm_layout_theme_set(wd->content_area, "popup", "content",
195 elm_widget_style_get(obj));
196 if (wd->content_text_obj)
198 snprintf(buf, sizeof(buf), "popup/%s", elm_widget_style_get(obj));
199 elm_object_style_set(wd->content_text_obj, buf);
203 EINA_LIST_FOREACH(wd->items, elist, item)
205 _elm_theme_object_set(obj, VIEW(item), "popup",
206 "item", elm_widget_style_get(obj));
209 edje_object_part_text_set(VIEW(item), "elm.text",
211 edje_object_signal_emit(VIEW(item),
212 "elm,state,item,text,visible", "elm");
215 edje_object_signal_emit(VIEW(item),
216 "elm,state,item,icon,visible", "elm");
218 edje_object_signal_emit(VIEW(item),
219 "elm,state,item,disabled", "elm");
220 evas_object_show(VIEW(item));
221 edje_object_message_signal_process(VIEW(item));
223 _scroller_size_calc(obj);
227 elm_object_part_text_set(wd->base, "elm.text.title", wd->title_text);
228 elm_object_signal_emit(wd->base, "elm,state,title,text,visible", "elm");
231 elm_object_signal_emit(wd->base, "elm,state,title,icon,visible", "elm");
233 edje_object_message_signal_process(elm_layout_edje_get(wd->base));
238 _item_sizing_eval(Elm_Popup_Content_Item *item)
240 Evas_Coord min_w = -1, min_h = -1, max_w = -1, max_h = -1;
242 edje_object_size_min_restricted_calc(VIEW(item), &min_w, &min_h, min_w,
244 evas_object_size_hint_min_set(VIEW(item), min_w, min_h);
245 evas_object_size_hint_max_set(VIEW(item), max_w, max_h);
249 _sizing_eval(Evas_Object *obj)
252 Elm_Popup_Content_Item *item;
253 Evas_Coord w_box = 0, h_box = 0;
254 Evas_Coord minw_box = 0, minh_box = 0;
255 Evas_Coord minw = -1, minh = -1, maxw = -1, maxh = -1;
256 Widget_Data *wd = elm_widget_data_get(obj);
261 EINA_LIST_FOREACH(wd->items, elist, item)
263 _item_sizing_eval(item);
264 evas_object_size_hint_min_get(VIEW(item), &minw_box,
266 if (minw_box > w_box)
271 evas_object_size_hint_min_set(wd->box, w_box, h_box);
272 evas_object_size_hint_min_set(wd->scr, w_box, MIN(h_box, wd->max_sc_h));
273 evas_object_size_hint_max_set(wd->scr, w_box, wd->max_sc_h);
274 evas_object_smart_calculate(wd->scr);
276 edje_object_size_min_calc(elm_layout_edje_get(wd->base), &minw, &minh);
277 evas_object_size_hint_min_set(wd->base, minw, minh);
278 evas_object_size_hint_max_set(wd->base, maxw, maxh);
279 evas_object_size_hint_min_set(obj, minw, minh);
280 evas_object_size_hint_max_set(obj, maxw, maxh);
281 elm_layout_sizing_eval(wd->base);
285 _changed_size_hints(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__,
286 void *event_info __UNUSED__)
292 _sub_del(void *data, Evas_Object *obj, void *event_info)
294 Elm_Popup_Content_Item *item;
296 Evas_Object *sub = event_info;
297 Widget_Data *wd = elm_widget_data_get(data);
302 if ((item = evas_object_data_get(sub, "_popup_content_item")) != NULL)
304 if (sub == item->icon)
306 edje_object_part_unswallow(VIEW(item), sub);
307 edje_object_signal_emit(VIEW(item),
308 "elm,state,item,icon,hidden", "elm");
313 else if (obj == wd->content_area)
315 if (sub == wd->content)
318 elm_object_part_content_unset(wd->base, "elm.swallow.content");
321 else if (sub == wd->content_text_obj)
323 wd->content_text_obj = NULL;
324 elm_object_part_content_unset(wd->base, "elm.swallow.content");
327 else if (sub == wd->scr)
331 elm_object_part_content_unset(wd->base, "elm.swallow.content");
335 else if (obj == wd->action_area)
337 for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
339 if (wd->buttons[i] && sub == wd->buttons[i]->btn &&
340 wd->buttons[i]->delete_me == EINA_TRUE)
342 _button_remove(data, sub, EINA_FALSE);
347 else if (obj == wd->base)
349 if (sub == wd->title_icon)
351 elm_object_signal_emit(wd->base, "elm,state,title,icon,hidden",
353 edje_object_message_signal_process(wd->base);
354 wd->title_icon = NULL;
360 _block_clicked_cb(void *data, Evas_Object *obj __UNUSED__,
361 void *event_info __UNUSED__)
363 Widget_Data *wd = elm_widget_data_get(data);
366 evas_object_smart_callback_call(data, SIG_BLOCK_CLICKED, NULL);
370 _timeout(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
372 evas_object_hide(data);
373 evas_object_smart_callback_call(data, SIG_TIMEOUT, NULL);
377 _mirrored_set(Evas_Object *obj, Eina_Bool rtl)
380 Elm_Popup_Content_Item *item;
381 Widget_Data *wd = elm_widget_data_get(obj);
384 elm_object_mirrored_set(wd->notify, rtl);
386 EINA_LIST_FOREACH(wd->items, elist, item)
387 edje_object_mirrored_set(VIEW(item), rtl);
391 _layout_change_cb(void *data, Evas_Object *obj __UNUSED__,
392 const char *emission __UNUSED__,
393 const char *source __UNUSED__)
395 Widget_Data *wd = elm_widget_data_get((Evas_Object*)data);
399 elm_layout_sizing_eval(wd->base);
403 _restack(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj,
404 void *event_info __UNUSED__)
406 Widget_Data *wd = elm_widget_data_get(obj);
409 evas_object_layer_set(wd->notify, evas_object_layer_get(obj));
413 _scroller_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj,
414 void *event_info __UNUSED__)
417 Widget_Data *wd = elm_widget_data_get(data);
419 if (!wd || wd->scr_size_recalc) return;
420 evas_object_geometry_get(obj, NULL, NULL, &w, &h);
423 if ((w <= wd->max_sc_w) && (h <= wd->max_sc_h))
426 wd->scr_size_recalc = EINA_TRUE;
430 if (wd->max_sc_w < w)
432 if (wd->max_sc_h < h)
438 _list_new(Evas_Object *obj)
440 Widget_Data *wd = elm_widget_data_get(obj);
444 wd->scr = elm_scroller_add(obj);
445 elm_scroller_bounce_set(wd->scr, EINA_FALSE, EINA_TRUE);
446 elm_object_content_set(wd->scr, wd->box);
447 evas_object_size_hint_weight_set(wd->scr, EVAS_HINT_EXPAND,
449 evas_object_size_hint_align_set(wd->scr, EVAS_HINT_FILL, EVAS_HINT_FILL);
450 evas_object_event_callback_add(wd->scr, EVAS_CALLBACK_RESIZE,
451 _scroller_resize, obj);
452 evas_object_event_callback_add(wd->scr,
453 EVAS_CALLBACK_CHANGED_SIZE_HINTS,
454 _changed_size_hints, obj);
455 elm_object_part_content_set(wd->base, "elm.swallow.content", wd->scr);
458 wd->box = elm_box_add(obj);
459 evas_object_size_hint_weight_set(wd->box, EVAS_HINT_EXPAND,
461 evas_object_size_hint_align_set(wd->box, EVAS_HINT_FILL, EVAS_HINT_FILL);
463 elm_object_content_set(wd->scr, wd->box);
467 _list_del(Widget_Data *wd)
469 if (!wd->scr) return;
470 elm_object_part_content_unset(wd->base, "elm.swallow.content");
471 evas_object_event_callback_del(wd->scr, EVAS_CALLBACK_RESIZE,
473 evas_object_event_callback_del(wd->scr, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
474 _changed_size_hints);
475 evas_object_del(wd->scr);
481 _scroller_size_calc(Evas_Object *obj)
484 Evas_Coord h_title = 0;
485 Evas_Coord h_action_area = 0;
486 Evas_Coord h_content = 0;
487 const char *action_area_height;
488 Widget_Data *wd = elm_widget_data_get(obj);
490 if (!wd || !wd->items) return;
491 wd->scr_size_recalc = EINA_FALSE;
494 evas_object_geometry_get(wd->notify, NULL, NULL, NULL, &h);
495 if (wd->title_text || wd->title_icon)
496 edje_object_part_geometry_get(elm_layout_edje_get(wd->base),
497 "elm.bg.title", NULL, NULL, NULL, &h_title);
498 if (wd->button_count)
500 action_area_height = edje_object_data_get(
501 elm_layout_edje_get(wd->action_area), "action_area_height");
502 if (action_area_height) h_action_area = (int)(atoi(action_area_height)
503 * _elm_config->scale * elm_object_scale_get(obj));
505 h_content = h - (h_title + h_action_area);
506 wd->max_sc_h = h_content;
510 _item_select_cb(void *data, Evas_Object *obj __UNUSED__,
511 const char *emission __UNUSED__, const char *source __UNUSED__)
513 Elm_Popup_Content_Item *item = data;
515 if (!item || item->disabled) return;
517 item->func((void*)item->base.data, WIDGET(item), data);
521 _item_new(Elm_Popup_Content_Item *item)
523 Widget_Data *wd = elm_widget_data_get(WIDGET(item));
526 elm_widget_item_text_set_hook_set(item, _item_text_set_hook);
527 elm_widget_item_text_get_hook_set(item, _item_text_get_hook);
528 elm_widget_item_content_set_hook_set(item, _item_content_set_hook);
529 elm_widget_item_content_get_hook_set(item, _item_content_get_hook);
530 elm_widget_item_content_unset_hook_set(item, _item_content_unset_hook);
531 elm_widget_item_disable_hook_set(item, _item_disable_hook);
532 elm_widget_item_del_pre_hook_set(item, _item_del_pre_hook);
533 elm_widget_item_signal_emit_hook_set(item, _item_signal_emit_hook);
534 VIEW(item) = edje_object_add(evas_object_evas_get(wd->base));
535 _elm_theme_object_set(WIDGET(item), VIEW(item), "popup", "item",
536 elm_widget_style_get(WIDGET(item)));
537 edje_object_mirrored_set(VIEW(item), elm_widget_mirrored_get(WIDGET(item)));
538 edje_object_signal_callback_add(VIEW(item), "elm,action,click", "",
539 _item_select_cb, item);
540 evas_object_size_hint_align_set(VIEW(item), EVAS_HINT_FILL,
542 evas_object_show(VIEW(item));
546 _remove_items(Widget_Data *wd)
549 Elm_Popup_Content_Item *item;
551 if (!wd->items) return;
552 EINA_LIST_FOREACH(wd->items, elist, item)
555 eina_stringshare_del(item->label);
558 evas_object_del(item->icon);
561 evas_object_del(VIEW(item));
562 wd->items = eina_list_remove(wd->items, item);
569 _notify_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__,
570 void *event_info __UNUSED__)
572 Widget_Data *wd = elm_widget_data_get(data);
575 _scroller_size_calc(data);
580 _title_text_set(Evas_Object *obj, const char *text)
582 ELM_CHECK_WIDTYPE(obj, widtype);
583 Eina_Bool title_visibility_old, title_visibility_current;
584 Widget_Data *wd = elm_widget_data_get(obj);
587 if (wd->title_text == text) return;
588 title_visibility_old = (wd->title_text) || (wd->title_icon);
589 eina_stringshare_replace(&wd->title_text, text);
590 elm_object_part_text_set(wd->base, "elm.text.title", text);
592 elm_object_signal_emit(wd->base, "elm,state,title,text,visible", "elm");
594 elm_object_signal_emit(wd->base, "elm,state,title,text,hidden", "elm");
595 title_visibility_current = (wd->title_text) || (wd->title_icon);
596 if (title_visibility_old != title_visibility_current)
598 edje_object_message_signal_process(wd->base);
603 _content_text_set(Evas_Object *obj, const char *text)
605 ELM_CHECK_WIDTYPE(obj, widtype);
606 Evas_Object *prev_content;
608 Widget_Data *wd = elm_widget_data_get(obj);
616 prev_content = elm_object_part_content_get(wd->content_area,
617 "elm.swallow.content");
619 evas_object_del(prev_content);
622 elm_object_part_content_set(wd->base, "elm.swallow.content",
624 wd->content_text_obj = elm_label_add(obj);
625 snprintf(buf, sizeof(buf), "popup/%s",
626 elm_widget_style_get(obj));
627 elm_object_style_set(wd->content_text_obj, buf);
628 elm_label_line_wrap_set(wd->content_text_obj,
629 wd->content_text_wrap_type);
630 elm_object_text_set(wd->content_text_obj, text);
631 evas_object_size_hint_weight_set(wd->content_text_obj, EVAS_HINT_EXPAND,
633 evas_object_size_hint_align_set(wd->content_text_obj, EVAS_HINT_FILL,
635 elm_object_part_content_set(wd->content_area, "elm.swallow.content",
636 wd->content_text_obj);
642 _text_set_hook(Evas_Object *obj, const char *part,
645 ELM_CHECK_WIDTYPE(obj, widtype);
646 Widget_Data *wd = elm_widget_data_get(obj);
649 if (!part || !strcmp(part, "default"))
650 _content_text_set(obj, label);
651 else if (!strcmp(part, "title,text"))
652 _title_text_set(obj, label);
654 WRN("The part name is invalid! : popup=%p", obj);
658 _title_text_get(const Evas_Object *obj)
660 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
661 Widget_Data *wd = elm_widget_data_get(obj);
663 if (!wd) return NULL;
664 return wd->title_text;
668 _content_text_get(const Evas_Object *obj)
670 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
671 const char *str = NULL;
672 Widget_Data *wd = elm_widget_data_get(obj);
674 if (!wd) return NULL;
675 if (wd->content_text_obj)
676 str = elm_object_text_get(wd->content_text_obj);
681 _text_get_hook(const Evas_Object *obj, const char *part)
683 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
684 const char *str = NULL;
685 Widget_Data *wd = elm_widget_data_get(obj);
687 if (!wd) return NULL;
688 if (!part || !strcmp(part, "default"))
689 str = _content_text_get(obj);
690 else if (!strcmp(part, "title,text"))
691 str = _title_text_get(obj);
693 WRN("The part name is invalid! : popup=%p", obj);
698 _title_icon_set(Evas_Object *obj, Evas_Object *icon)
700 ELM_CHECK_WIDTYPE(obj, widtype);
701 Eina_Bool title_visibility_old, title_visibility_current;
702 Widget_Data *wd = elm_widget_data_get(obj);
705 if (wd->title_icon == icon) return;
706 title_visibility_old = (wd->title_text) || (wd->title_icon);
707 if (wd->title_icon) evas_object_del(wd->title_icon);
709 wd->title_icon = icon;
710 title_visibility_current = (wd->title_text) || (wd->title_icon);
711 elm_object_part_content_set(wd->base, "elm.swallow.title.icon",
714 elm_object_signal_emit(wd->base, "elm,state,title,icon,visible", "elm");
715 if (title_visibility_old != title_visibility_current) _layout_set(obj);
716 edje_object_message_signal_process(wd->base);
721 _content_set(Evas_Object *obj, Evas_Object *content)
723 ELM_CHECK_WIDTYPE(obj, widtype);
724 Evas_Object *prev_content;
725 Widget_Data *wd = elm_widget_data_get(obj);
728 if (wd->content && wd->content == content) return;
734 prev_content = elm_object_part_content_get(wd->content_area,
735 "elm.swallow.content");
737 evas_object_del(prev_content);
738 wd->content = content;
741 elm_object_part_content_set(wd->base, "elm.swallow.content",
743 elm_object_part_content_set(wd->content_area, "elm.swallow.content",
745 evas_object_show(content);
751 _button_remove(Evas_Object *obj, Evas_Object *content, Eina_Bool delete)
753 unsigned int i = 0, position = 0;
755 Widget_Data *wd = elm_widget_data_get(obj);
757 if (!wd->button_count) return;
758 for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
763 wd->buttons[i]->delete_me = EINA_FALSE;
764 if (wd->buttons[i]->btn == content)
766 snprintf(buf, sizeof(buf), "actionbtn%u", position);
767 elm_object_part_content_unset(wd->action_area, buf);
768 evas_object_hide(content);
769 if (delete) evas_object_del(content);
770 free(wd->buttons[i]);
771 wd->buttons[i] = NULL;
772 wd->button_count -= 1;
777 for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
779 if (!wd->buttons[i]) continue;
781 snprintf(buf, sizeof(buf), "actionbtn%u", position);
782 elm_object_part_content_unset(wd->action_area, buf);
783 elm_object_part_content_set(wd->action_area, buf,
784 wd->buttons[i]->btn);
785 evas_object_show(wd->buttons[i]->btn);
786 wd->buttons[i]->delete_me = EINA_TRUE;
788 if (!wd->button_count)
791 elm_object_part_content_unset(wd->base, "elm.swallow.action_area");
792 evas_object_hide(wd->action_area);
793 edje_object_message_signal_process(elm_layout_edje_get(wd->base));
797 snprintf(buf, sizeof(buf), "buttons%u", wd->button_count);
798 elm_layout_theme_set(wd->action_area, "popup", buf,
799 elm_widget_style_get(obj));
804 _action_button_set(Evas_Object *obj, Evas_Object *btn, unsigned int idx)
806 Action_Area_Data *adata;
808 unsigned int num = idx - 1, i = 0, position = 0;
809 Widget_Data *wd = elm_widget_data_get(obj);
812 if (num >= ELM_POPUP_ACTION_BUTTON_MAX) return;
813 if (wd->buttons[num])
814 _button_remove(obj, wd->buttons[num]->btn, EINA_TRUE);
818 snprintf(buf, sizeof(buf), "buttons%u", wd->button_count);
819 elm_layout_theme_set(wd->action_area, "popup", buf,
820 elm_widget_style_get(obj));
821 adata = ELM_NEW(Action_Area_Data);
824 wd->buttons[num] = adata;
825 /* Adding delete_me state inside action data as unset calls _sub_del
826 too and before setting a new content, the previous one needs to
827 be unset in order to avoid unwanted deletion. This way rearrangement
828 of buttons can be achieved in action area.
830 for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
832 wd->buttons[i]->delete_me = EINA_FALSE;
833 for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
835 if (!wd->buttons[i]) continue;
837 snprintf(buf, sizeof(buf), "actionbtn%u", position);
838 elm_object_part_content_unset(wd->action_area, buf);
839 elm_object_part_content_set(wd->action_area, buf,
840 wd->buttons[i]->btn);
841 evas_object_show(wd->buttons[i]->btn);
842 /* Setting delete_me to TRUE in order to let _sub_del handle it
843 if deleted externally and update the buttons array after freeing
844 action data allocated earlier.
846 wd->buttons[i]->delete_me = EINA_TRUE;
848 elm_object_part_content_set(wd->base, "elm.swallow.action_area",
850 evas_object_show(wd->action_area);
851 if (wd->button_count == 1)
853 edje_object_message_signal_process(wd->base);
855 _scroller_size_calc(obj);
861 _content_set_hook(Evas_Object *obj, const char *part,
862 Evas_Object *content)
864 ELM_CHECK_WIDTYPE(obj, widtype);
867 Widget_Data *wd = elm_widget_data_get(obj);
870 if (!part || !strcmp(part, "default"))
871 _content_set(obj, content);
872 else if (!strcmp(part, "title,icon"))
873 _title_icon_set(obj, content);
874 else if (!strncmp(part, "button", 6))
877 for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
879 snprintf(buff, sizeof(buff), "%u", i+1);
880 if (!strncmp(part, buff, sizeof(buff)))
882 _action_button_set(obj, content, i+1);
888 WRN("The part name is invalid! : popup=%p", obj);
892 _title_icon_get(Evas_Object *obj)
894 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
895 Widget_Data *wd = elm_widget_data_get(obj);
897 if (!wd) return NULL;
898 return wd->title_icon;
902 _content_get(Evas_Object *obj)
904 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
905 Widget_Data *wd = elm_widget_data_get(obj);
907 if (!wd) return NULL;
912 _action_button_get(Evas_Object *obj, unsigned int idx)
914 unsigned int num = idx - 1;
915 Evas_Object *button = NULL;
916 Widget_Data *wd = elm_widget_data_get(obj);
918 if (!wd || !wd->button_count) return NULL;
919 if (wd->buttons[num])
920 button = wd->buttons[num]->btn;
925 _content_get_hook(Evas_Object *obj, const char *part)
927 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
928 Evas_Object *content = NULL;
931 Widget_Data *wd = elm_widget_data_get(obj);
933 if (!wd) return NULL;
934 if (!part || !strcmp(part, "default"))
935 content = _content_get(obj);
936 else if (!strcmp(part, "title,text"))
937 content = _title_icon_get(obj);
938 else if (!strncmp(part, "button", 6))
941 for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
943 snprintf(buff, sizeof(buff), "%u", i+1);
944 if (!strncmp(part, buff, sizeof(buff)))
946 content = _action_button_get(obj, i+1);
952 WRN("The part name is invalid! : popup=%p", obj);
957 _content_unset(Evas_Object *obj)
959 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
960 Evas_Object *content;
961 Widget_Data *wd = elm_widget_data_get(obj);
963 if (!wd || !wd->content) return NULL;
964 content = elm_object_part_content_unset(wd->content_area,
965 "elm.swallow.content");
972 _title_icon_unset(Evas_Object *obj)
974 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
976 Widget_Data *wd = elm_widget_data_get(obj);
978 if (!wd || !wd->title_icon) return NULL;
979 icon = elm_object_part_content_unset(wd->base, "elm.swallow.title.icon");
980 wd->title_icon = NULL;
985 _action_button_unset(Evas_Object *obj, unsigned int idx)
987 unsigned int num = idx -1;
988 Evas_Object *button = NULL;
989 Widget_Data *wd = elm_widget_data_get(obj);
991 if (!wd) return NULL;
992 if ((!wd->button_count) || (num >= ELM_POPUP_ACTION_BUTTON_MAX))
995 if (wd->buttons[num])
997 button = wd->buttons[num]->btn;
998 _button_remove(obj, button, EINA_FALSE);
1003 static Evas_Object *
1004 _content_unset_hook(Evas_Object *obj, const char *part)
1006 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1007 Evas_Object *content = NULL;
1010 Widget_Data *wd = elm_widget_data_get(obj);
1012 if (!wd) return NULL;
1013 if (!part || !strcmp(part, "default"))
1014 content = _content_unset(obj);
1015 else if (!strcmp(part, "title,icon"))
1016 content = _title_icon_unset(obj);
1017 else if (!strncmp(part, "button", 6))
1020 for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
1022 snprintf(buff, sizeof(buff), "%u", i+1);
1023 if (!strncmp(part, buff, sizeof(buff)))
1025 content = _action_button_unset(obj, i+1);
1031 WRN("The part name is invalid! : popup=%p", obj);
1036 _focus_next_hook(const Evas_Object *obj,
1037 Elm_Focus_Direction dir,
1040 Widget_Data *wd = elm_widget_data_get(obj);
1044 return elm_widget_focus_next_get(wd->notify, dir, next);
1048 _item_text_set(Elm_Popup_Content_Item *item, const char *label)
1050 if (!eina_stringshare_replace(&item->label, label)) return;
1051 edje_object_part_text_set(VIEW(item), "elm.text", label);
1053 edje_object_signal_emit(VIEW(item),
1054 "elm,state,item,text,visible", "elm");
1056 edje_object_signal_emit(VIEW(item),
1057 "elm,state,item,text,hidden", "elm");
1058 edje_object_message_signal_process(VIEW(item));
1062 _item_text_set_hook(Elm_Object_Item *it, const char *part, const char *label)
1064 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1065 Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1067 if ((!part) || (!strcmp(part, "default")))
1069 _item_text_set(item, label);
1072 WRN("The part name is invalid! : popup=%p", WIDGET(item));
1076 _item_text_get_hook(const Elm_Object_Item *it, const char *part)
1078 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
1079 Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1081 if ((!part) || (!strcmp(part, "default")))
1083 WRN("The part name is invalid! : popup=%p", WIDGET(item));
1088 _item_icon_set(Elm_Popup_Content_Item *item, Evas_Object *icon)
1090 if (item->icon == icon) return;
1093 evas_object_data_del(item->icon, "_popup_content_item");
1094 evas_object_del(item->icon);
1099 elm_widget_sub_object_add(WIDGET(item), item->icon);
1100 evas_object_data_set(item->icon, "_popup_content_item", item);
1101 edje_object_part_swallow(VIEW(item), "elm.swallow.content",
1103 edje_object_signal_emit(VIEW(item),
1104 "elm,state,item,icon,visible", "elm");
1107 edje_object_signal_emit(VIEW(item),
1108 "elm,state,item,icon,hidden", "elm");
1109 edje_object_message_signal_process(item->base.view);
1113 _item_content_set_hook(Elm_Object_Item *it, const char *part,
1114 Evas_Object *content)
1116 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1117 Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1119 if ((!(part)) || (!strcmp(part, "default")))
1120 _item_icon_set(item, content);
1122 WRN("The part name is invalid! : popup=%p", WIDGET(item));
1125 static Evas_Object *
1126 _item_content_get_hook(const Elm_Object_Item *it,
1129 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
1130 Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1132 if ((!(part)) || (!strcmp(part, "default")))
1134 WRN("The part name is invalid! : popup=%p", WIDGET(item));
1138 static Evas_Object *
1139 _item_icon_unset(Elm_Popup_Content_Item *item)
1141 Evas_Object *icon = item->icon;
1143 if (!item->icon) return NULL;
1144 elm_widget_sub_object_del(WIDGET(item), icon);
1145 evas_object_data_del(icon, "_popup_content_item");
1146 edje_object_part_unswallow(item->base.view, icon);
1147 edje_object_signal_emit(VIEW(item),
1148 "elm,state,item,icon,hidden", "elm");
1153 static Evas_Object *
1154 _item_content_unset_hook(const Elm_Object_Item *it,
1157 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
1158 Evas_Object *content = NULL;
1159 Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1161 if ((!(part)) || (!strcmp(part, "default")))
1162 content = _item_icon_unset(item);
1164 WRN("The part name is invalid! : popup=%p", WIDGET(item));
1169 _item_disable_hook(Elm_Object_Item *it)
1171 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1172 Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1173 Widget_Data *wd = elm_widget_data_get(WIDGET(item));
1176 if (elm_widget_item_disabled_get(it))
1177 edje_object_signal_emit(VIEW(item), "elm,state,item,disabled", "elm");
1179 edje_object_signal_emit(VIEW(item), "elm,state,item,enabled", "elm");
1183 _item_del_pre_hook(Elm_Object_Item *it)
1185 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1186 Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1187 Widget_Data *wd = elm_widget_data_get(WIDGET(item));
1191 evas_object_del(item->icon);
1192 eina_stringshare_del(item->label);
1193 wd->items = eina_list_remove(wd->items, item);
1194 if (!eina_list_count(wd->items))
1202 _item_signal_emit_hook(Elm_Object_Item *it, const char *emission,
1205 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1206 Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1208 edje_object_signal_emit(VIEW(item), emission, source);
1212 _popup_show(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj,
1213 void *event_info __UNUSED__)
1217 wd = elm_widget_data_get(obj);
1220 evas_object_show(wd->notify);
1224 _popup_hide(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj,
1225 void *event_info __UNUSED__)
1229 wd = elm_widget_data_get(obj);
1232 evas_object_hide(wd->notify);
1236 elm_popup_add(Evas_Object *parent)
1243 ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
1244 ELM_SET_WIDTYPE(widtype, "popup");
1245 elm_widget_type_set(obj, widtype);
1246 elm_widget_sub_object_add(parent, obj);
1247 elm_widget_data_set(obj, wd);
1248 elm_widget_del_pre_hook_set(obj, _del_pre_hook);
1249 elm_widget_del_hook_set(obj, _del_hook);
1250 elm_widget_theme_hook_set(obj, _theme_hook);
1251 elm_widget_text_set_hook_set(obj, _text_set_hook);
1252 elm_widget_text_get_hook_set(obj, _text_get_hook);
1253 elm_widget_content_set_hook_set(obj, _content_set_hook);
1254 elm_widget_content_get_hook_set(obj, _content_get_hook);
1255 elm_widget_content_unset_hook_set(obj,_content_unset_hook);
1256 elm_widget_can_focus_set(obj, EINA_FALSE);
1257 elm_widget_focus_next_hook_set(obj, _focus_next_hook);
1258 evas_object_smart_callbacks_descriptions_set(obj, _signals);
1260 wd->notify = elm_notify_add(obj);
1261 elm_notify_parent_set(wd->notify, parent);
1262 elm_notify_orient_set(wd->notify, ELM_NOTIFY_ORIENT_CENTER);
1263 elm_notify_allow_events_set(wd->notify, EINA_FALSE);
1264 evas_object_size_hint_weight_set(wd->notify,
1265 EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
1266 evas_object_size_hint_align_set(wd->notify, EVAS_HINT_FILL, EVAS_HINT_FILL);
1267 elm_object_style_set(wd->notify, "popup");
1269 evas_object_event_callback_add(wd->notify, EVAS_CALLBACK_RESIZE,
1270 _notify_resize, obj);
1271 evas_object_event_callback_add(obj, EVAS_CALLBACK_SHOW, _popup_show,
1273 evas_object_event_callback_add(obj, EVAS_CALLBACK_HIDE, _popup_hide,
1275 evas_object_event_callback_add(obj, EVAS_CALLBACK_RESTACK, _restack, NULL);
1276 wd->base = elm_layout_add(obj);
1277 evas_object_size_hint_weight_set(wd->base, EVAS_HINT_EXPAND,
1279 evas_object_size_hint_align_set(wd->base, EVAS_HINT_FILL, EVAS_HINT_FILL);
1281 elm_layout_theme_set(wd->base, "popup", "base", elm_widget_style_get(obj));
1282 elm_object_content_set(wd->notify, wd->base);
1284 elm_object_signal_callback_add(wd->base, "elm,state,title_area,visible",
1285 "elm", _layout_change_cb, obj);
1286 elm_object_signal_callback_add(wd->base, "elm,state,title_area,hidden",
1287 "elm", _layout_change_cb, obj);
1288 elm_object_signal_callback_add(wd->base, "elm,state,action_area,visible",
1289 "elm", _layout_change_cb, obj);
1290 elm_object_signal_callback_add(wd->base, "elm,state,action_area,hidden",
1291 "elm", _layout_change_cb, obj);
1292 wd->content_area = elm_layout_add(obj);
1293 elm_layout_theme_set(wd->content_area, "popup", "content",
1294 elm_widget_style_get(obj));
1295 wd->action_area = elm_layout_add(obj);
1296 evas_object_size_hint_weight_set(wd->action_area, EVAS_HINT_EXPAND,
1298 evas_object_size_hint_align_set(wd->action_area, EVAS_HINT_FILL,
1300 evas_object_event_callback_add(wd->action_area,
1301 EVAS_CALLBACK_CHANGED_SIZE_HINTS,
1302 _changed_size_hints, obj);
1303 evas_object_event_callback_add(wd->content_area,
1304 EVAS_CALLBACK_CHANGED_SIZE_HINTS,
1305 _changed_size_hints, obj);
1306 evas_object_smart_callback_add(wd->base, "sub-object-del",
1308 evas_object_smart_callback_add(wd->content_area, "sub-object-del",
1310 evas_object_smart_callback_add(wd->action_area, "sub-object-del",
1312 evas_object_smart_callback_add(obj, "sub-object-del",
1315 wd->content_text_wrap_type = ELM_WRAP_MIXED;
1316 evas_object_smart_callback_add(wd->notify, "block,clicked",
1317 _block_clicked_cb, obj);
1318 evas_object_smart_callback_add(wd->notify, "timeout", _timeout, obj);
1319 for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
1320 wd->buttons[i] = NULL;
1322 //TODO: To use scroller for description also
1327 elm_popup_content_text_wrap_type_set(Evas_Object *obj, Elm_Wrap_Type wrap)
1329 ELM_CHECK_WIDTYPE(obj, widtype);
1330 Evas_Object *content_text_obj;
1331 Widget_Data *wd = elm_widget_data_get(obj);
1334 if (wd->content_text_wrap_type == ELM_WRAP_NONE) return;
1335 //Need to wrap the content text, so not allowing ELM_WRAP_NONE
1336 wd->content_text_wrap_type = wrap;
1337 if (wd->content_text_obj)
1339 content_text_obj = elm_object_part_content_get(wd->content_area,
1340 "elm.swallow.content");
1341 elm_label_line_wrap_set(content_text_obj, wrap);
1346 elm_popup_content_text_wrap_type_get(const Evas_Object *obj)
1348 ELM_CHECK_WIDTYPE(obj, widtype) ELM_WRAP_LAST;
1349 Widget_Data *wd = elm_widget_data_get(obj);
1351 if (!wd) return ELM_WRAP_LAST;
1352 return wd->content_text_wrap_type;
1356 elm_popup_orient_set(Evas_Object *obj, Elm_Popup_Orient orient)
1358 ELM_CHECK_WIDTYPE(obj, widtype);
1359 Widget_Data *wd = elm_widget_data_get(obj);
1362 if (orient >= ELM_POPUP_ORIENT_LAST) return;
1363 elm_notify_orient_set(wd->notify, (Elm_Notify_Orient)orient);
1366 EAPI Elm_Popup_Orient
1367 elm_popup_orient_get(const Evas_Object *obj)
1369 ELM_CHECK_WIDTYPE(obj, widtype) -1;
1370 Widget_Data *wd = elm_widget_data_get(obj);
1372 if (!wd) return ELM_POPUP_ORIENT_LAST;
1373 return (Elm_Popup_Orient)elm_notify_orient_get(wd->notify);
1377 elm_popup_timeout_set(Evas_Object *obj, double timeout)
1379 ELM_CHECK_WIDTYPE(obj, widtype);
1380 Widget_Data *wd = elm_widget_data_get(obj);
1383 elm_notify_timeout_set(wd->notify, timeout);
1387 elm_popup_timeout_get(const Evas_Object *obj)
1389 ELM_CHECK_WIDTYPE(obj, widtype) 0.0;
1390 Widget_Data *wd = elm_widget_data_get(obj);
1392 if (!wd) return 0.0;
1393 return elm_notify_timeout_get(wd->notify);
1397 elm_popup_allow_events_set(Evas_Object *obj, Eina_Bool allow)
1399 ELM_CHECK_WIDTYPE(obj, widtype);
1400 Eina_Bool allow_events = !!allow;
1401 Widget_Data *wd = elm_widget_data_get(obj);
1404 elm_notify_allow_events_set(wd->notify, allow_events);
1408 elm_popup_allow_events_get(const Evas_Object *obj)
1410 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1411 Widget_Data *wd = elm_widget_data_get(obj);
1413 if (!wd) return EINA_FALSE;
1414 return elm_notify_allow_events_get(wd->notify);
1417 EAPI Elm_Object_Item *
1418 elm_popup_item_append(Evas_Object *obj, const char *label,
1419 Evas_Object *icon, Evas_Smart_Cb func,
1422 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1423 Evas_Object *prev_content;
1424 Elm_Popup_Content_Item *item;
1425 Widget_Data *wd = elm_widget_data_get(obj);
1427 if (!wd) return NULL;
1428 item = elm_widget_item_new(obj, Elm_Popup_Content_Item);
1429 if (!item) return NULL;
1430 if (wd->content || wd->content_text_obj)
1432 prev_content = elm_object_part_content_get(wd->content_area,
1433 "elm.swallow.content");
1435 evas_object_del(prev_content);
1438 //The first item is appended.
1443 item->base.data = data;
1446 _item_icon_set(item, icon);
1447 _item_text_set(item, label);
1448 elm_box_pack_end(wd->box, VIEW(item));
1449 wd->items = eina_list_append(wd->items, item);
1451 _scroller_size_calc(obj);
1453 return (Elm_Object_Item *)item;