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 const char SIG_BLOCK_CLICKED[] = "block,clicked";
102 static const char SIG_TIMEOUT[] = "timeout";
103 static const Evas_Smart_Cb_Description _signals[] = {
104 {SIG_BLOCK_CLICKED, ""},
109 #define ELM_POPUP_CONTENT_ITEM_CHECK_RETURN(it, ...) \
110 ELM_WIDGET_ITEM_CHECK_OR_RETURN((Elm_Widget_Item *)it, __VA_ARGS__); \
111 ELM_CHECK_WIDTYPE(WIDGET(item), widtype) __VA_ARGS__;
114 _layout_set(Evas_Object *obj)
116 Widget_Data *wd = elm_widget_data_get(obj);
119 if ((!(wd->title_text)) && (!(wd->title_icon)))
120 elm_object_signal_emit(wd->base, "elm,state,title_area,hidden", "elm");
122 elm_object_signal_emit(wd->base, "elm,state,title_area,visible", "elm");
123 if (wd->button_count)
124 elm_object_signal_emit(wd->base, "elm,state,action_area,visible", "elm");
126 elm_object_signal_emit(wd->base, "elm,state,action_area,hidden", "elm");
130 _del_hook(Evas_Object *obj)
132 Widget_Data *wd = elm_widget_data_get(obj);
139 _del_pre_hook(Evas_Object *obj)
142 Widget_Data *wd = elm_widget_data_get(obj);
145 evas_object_smart_callback_del(wd->notify, "block,clicked",
147 evas_object_smart_callback_del(wd->notify, "timeout", _timeout);
148 evas_object_event_callback_del(wd->notify, EVAS_CALLBACK_RESIZE,
150 wd->button_count = 0;
151 for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
154 evas_object_del(wd->buttons[i]->btn);
155 free(wd->buttons[i]);
156 wd->buttons[i] = NULL;
166 _theme_hook(Evas_Object *obj)
169 Elm_Popup_Content_Item *item;
172 Widget_Data *wd = elm_widget_data_get(obj);
175 elm_layout_theme_set(wd->base, "popup", "base", elm_widget_style_get(obj));
176 _elm_widget_mirrored_reload(obj);
177 _mirrored_set(obj, elm_widget_mirrored_get(obj));
178 if (wd->button_count)
180 snprintf(buf, sizeof(buf), "buttons%u", wd->button_count);
181 elm_layout_theme_set(wd->action_area, "popup", buf,
182 elm_widget_style_get(obj));
183 for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
185 if (!wd->buttons[i]) continue;
186 elm_object_style_set(wd->buttons[i]->btn, buf);
189 elm_layout_theme_set(wd->content_area, "popup", "content",
190 elm_widget_style_get(obj));
191 if (wd->content_text_obj)
193 snprintf(buf, sizeof(buf), "popup/%s", elm_widget_style_get(obj));
194 elm_object_style_set(wd->content_text_obj, buf);
198 EINA_LIST_FOREACH(wd->items, elist, item)
200 _elm_theme_object_set(obj, VIEW(item), "popup",
201 "item", elm_widget_style_get(obj));
204 edje_object_part_text_set(VIEW(item), "elm.text",
206 edje_object_signal_emit(VIEW(item),
207 "elm,state,item,text,visible", "elm");
210 edje_object_signal_emit(VIEW(item),
211 "elm,state,item,icon,visible", "elm");
213 edje_object_signal_emit(VIEW(item),
214 "elm,state,item,disabled", "elm");
215 evas_object_show(VIEW(item));
216 edje_object_message_signal_process(VIEW(item));
218 _scroller_size_calc(obj);
222 elm_object_part_text_set(wd->base, "elm.text.title", wd->title_text);
223 elm_object_signal_emit(wd->base, "elm,state,title,text,visible", "elm");
226 elm_object_signal_emit(wd->base, "elm,state,title,icon,visible", "elm");
228 edje_object_message_signal_process(elm_layout_edje_get(wd->base));
233 _item_sizing_eval(Elm_Popup_Content_Item *item)
235 Evas_Coord min_w = -1, min_h = -1, max_w = -1, max_h = -1;
237 edje_object_size_min_restricted_calc(VIEW(item), &min_w, &min_h, min_w,
239 evas_object_size_hint_min_set(VIEW(item), min_w, min_h);
240 evas_object_size_hint_max_set(VIEW(item), max_w, max_h);
244 _sizing_eval(Evas_Object *obj)
247 Elm_Popup_Content_Item *item;
248 Evas_Coord w_box = 0, h_box = 0;
249 Evas_Coord minw_box = 0, minh_box = 0;
250 Evas_Coord minw = -1, minh = -1, maxw = -1, maxh = -1;
251 Widget_Data *wd = elm_widget_data_get(obj);
256 EINA_LIST_FOREACH(wd->items, elist, item)
258 _item_sizing_eval(item);
259 evas_object_size_hint_min_get(VIEW(item), &minw_box,
261 if (minw_box > w_box)
266 evas_object_size_hint_min_set(wd->box, w_box, h_box);
267 evas_object_size_hint_min_set(wd->scr, w_box, MIN(h_box, wd->max_sc_h));
268 evas_object_size_hint_max_set(wd->scr, w_box, wd->max_sc_h);
269 evas_object_smart_calculate(wd->scr);
271 edje_object_size_min_calc(elm_layout_edje_get(wd->base), &minw, &minh);
272 evas_object_size_hint_min_set(wd->base, minw, minh);
273 evas_object_size_hint_max_set(wd->base, maxw, maxh);
274 evas_object_size_hint_min_set(obj, minw, minh);
275 evas_object_size_hint_max_set(obj, maxw, maxh);
276 elm_layout_sizing_eval(wd->base);
280 _changed_size_hints(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__,
281 void *event_info __UNUSED__)
287 _sub_del(void *data, Evas_Object *obj, void *event_info)
289 Elm_Popup_Content_Item *item;
291 Evas_Object *sub = event_info;
292 Widget_Data *wd = elm_widget_data_get(data);
297 if ((item = evas_object_data_get(sub, "_popup_content_item")) != NULL)
299 if (sub == item->icon)
301 edje_object_part_unswallow(VIEW(item), sub);
302 edje_object_signal_emit(VIEW(item),
303 "elm,state,item,icon,hidden", "elm");
308 else if (obj == wd->content_area)
310 if (sub == wd->content)
313 elm_object_part_content_unset(wd->base, "elm.swallow.content");
316 else if (sub == wd->content_text_obj)
318 wd->content_text_obj = NULL;
319 elm_object_part_content_unset(wd->base, "elm.swallow.content");
322 else if (sub == wd->scr)
326 elm_object_part_content_unset(wd->base, "elm.swallow.content");
330 else if (obj == wd->action_area)
332 for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
334 if (wd->buttons[i] && sub == wd->buttons[i]->btn &&
335 wd->buttons[i]->delete_me == EINA_TRUE)
337 _button_remove(data, sub, EINA_FALSE);
342 else if (obj == wd->base)
344 if (sub == wd->title_icon)
346 elm_object_signal_emit(wd->base, "elm,state,title,icon,hidden",
348 edje_object_message_signal_process(wd->base);
349 wd->title_icon = NULL;
355 _block_clicked_cb(void *data, Evas_Object *obj __UNUSED__,
356 void *event_info __UNUSED__)
358 Widget_Data *wd = elm_widget_data_get(data);
361 evas_object_smart_callback_call(data, SIG_BLOCK_CLICKED, NULL);
365 _timeout(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
367 evas_object_hide(data);
368 evas_object_smart_callback_call(data, SIG_TIMEOUT, NULL);
372 _mirrored_set(Evas_Object *obj, Eina_Bool rtl)
375 Elm_Popup_Content_Item *item;
376 Widget_Data *wd = elm_widget_data_get(obj);
379 elm_object_mirrored_set(wd->notify, rtl);
381 EINA_LIST_FOREACH(wd->items, elist, item)
382 edje_object_mirrored_set(VIEW(item), rtl);
386 _layout_change_cb(void *data, Evas_Object *obj __UNUSED__,
387 const char *emission __UNUSED__,
388 const char *source __UNUSED__)
390 Widget_Data *wd = elm_widget_data_get((Evas_Object*)data);
394 elm_layout_sizing_eval(wd->base);
398 _restack(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj,
399 void *event_info __UNUSED__)
401 Widget_Data *wd = elm_widget_data_get(obj);
404 evas_object_layer_set(wd->notify, evas_object_layer_get(obj));
408 _scroller_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj,
409 void *event_info __UNUSED__)
412 Widget_Data *wd = elm_widget_data_get(data);
414 if (!wd || wd->scr_size_recalc) return;
415 evas_object_geometry_get(obj, NULL, NULL, &w, &h);
418 if ((w <= wd->max_sc_w) && (h <= wd->max_sc_h))
421 wd->scr_size_recalc = EINA_TRUE;
425 if (wd->max_sc_w < w)
427 if (wd->max_sc_h < h)
433 _list_new(Evas_Object *obj)
435 Widget_Data *wd = elm_widget_data_get(obj);
439 wd->scr = elm_scroller_add(obj);
440 elm_scroller_bounce_set(wd->scr, EINA_FALSE, EINA_TRUE);
441 elm_object_content_set(wd->scr, wd->box);
442 evas_object_size_hint_weight_set(wd->scr, EVAS_HINT_EXPAND,
444 evas_object_size_hint_align_set(wd->scr, EVAS_HINT_FILL, EVAS_HINT_FILL);
445 evas_object_event_callback_add(wd->scr, EVAS_CALLBACK_RESIZE,
446 _scroller_resize, obj);
447 evas_object_event_callback_add(wd->scr,
448 EVAS_CALLBACK_CHANGED_SIZE_HINTS,
449 _changed_size_hints, obj);
450 elm_object_part_content_set(wd->base, "elm.swallow.content", wd->scr);
453 wd->box = elm_box_add(obj);
454 evas_object_size_hint_weight_set(wd->box, EVAS_HINT_EXPAND,
456 evas_object_size_hint_align_set(wd->box, EVAS_HINT_FILL, EVAS_HINT_FILL);
458 elm_object_content_set(wd->scr, wd->box);
462 _list_del(Widget_Data *wd)
464 if (!wd->scr) return;
465 elm_object_part_content_unset(wd->base, "elm.swallow.content");
466 evas_object_event_callback_del(wd->scr, EVAS_CALLBACK_RESIZE,
468 evas_object_event_callback_del(wd->scr, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
469 _changed_size_hints);
470 evas_object_del(wd->scr);
476 _scroller_size_calc(Evas_Object *obj)
479 Evas_Coord h_title = 0;
480 Evas_Coord h_action_area = 0;
481 Evas_Coord h_content = 0;
482 const char *action_area_height;
483 Widget_Data *wd = elm_widget_data_get(obj);
485 if (!wd || !wd->items) return;
486 wd->scr_size_recalc = EINA_FALSE;
489 evas_object_geometry_get(wd->notify, NULL, NULL, NULL, &h);
490 if (wd->title_text || wd->title_icon)
491 edje_object_part_geometry_get(elm_layout_edje_get(wd->base),
492 "elm.bg.title", NULL, NULL, NULL, &h_title);
493 if (wd->button_count)
495 action_area_height = edje_object_data_get(
496 elm_layout_edje_get(wd->action_area), "action_area_height");
497 if (action_area_height) h_action_area = (int)(atoi(action_area_height)
498 * _elm_config->scale * elm_object_scale_get(obj));
500 h_content = h - (h_title + h_action_area);
501 wd->max_sc_h = h_content;
505 _item_select_cb(void *data, Evas_Object *obj __UNUSED__,
506 const char *emission __UNUSED__, const char *source __UNUSED__)
508 Elm_Popup_Content_Item *item = data;
510 if (!item || item->disabled) return;
512 item->func((void*)item->base.data, WIDGET(item), data);
516 _item_new(Elm_Popup_Content_Item *item)
518 Widget_Data *wd = elm_widget_data_get(WIDGET(item));
521 elm_widget_item_text_set_hook_set(item, _item_text_set_hook);
522 elm_widget_item_text_get_hook_set(item, _item_text_get_hook);
523 elm_widget_item_content_set_hook_set(item, _item_content_set_hook);
524 elm_widget_item_content_get_hook_set(item, _item_content_get_hook);
525 elm_widget_item_content_unset_hook_set(item, _item_content_unset_hook);
526 elm_widget_item_disable_hook_set(item, _item_disable_hook);
527 elm_widget_item_del_pre_hook_set(item, _item_del_pre_hook);
528 elm_widget_item_signal_emit_hook_set(item, _item_signal_emit_hook);
529 VIEW(item) = edje_object_add(evas_object_evas_get(wd->base));
530 _elm_theme_object_set(WIDGET(item), VIEW(item), "popup", "item",
531 elm_widget_style_get(WIDGET(item)));
532 edje_object_mirrored_set(VIEW(item), elm_widget_mirrored_get(WIDGET(item)));
533 edje_object_signal_callback_add(VIEW(item), "elm,action,click", "",
534 _item_select_cb, item);
535 evas_object_size_hint_align_set(VIEW(item), EVAS_HINT_FILL,
537 evas_object_show(VIEW(item));
541 _remove_items(Widget_Data *wd)
544 Elm_Popup_Content_Item *item;
546 if (!wd->items) return;
547 EINA_LIST_FOREACH(wd->items, elist, item)
550 eina_stringshare_del(item->label);
553 evas_object_del(item->icon);
556 evas_object_del(VIEW(item));
557 wd->items = eina_list_remove(wd->items, item);
564 _notify_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__,
565 void *event_info __UNUSED__)
567 Widget_Data *wd = elm_widget_data_get(data);
570 _scroller_size_calc(data);
575 _title_text_set(Evas_Object *obj, const char *text)
577 ELM_CHECK_WIDTYPE(obj, widtype);
578 Eina_Bool title_visibility_old, title_visibility_current;
579 Widget_Data *wd = elm_widget_data_get(obj);
582 if (wd->title_text == text) return;
583 title_visibility_old = (wd->title_text) || (wd->title_icon);
584 eina_stringshare_replace(&wd->title_text, text);
585 elm_object_part_text_set(wd->base, "elm.text.title", text);
587 elm_object_signal_emit(wd->base, "elm,state,title,text,visible", "elm");
589 elm_object_signal_emit(wd->base, "elm,state,title,text,hidden", "elm");
590 title_visibility_current = (wd->title_text) || (wd->title_icon);
591 if (title_visibility_old != title_visibility_current)
593 edje_object_message_signal_process(wd->base);
598 _content_text_set(Evas_Object *obj, const char *text)
600 ELM_CHECK_WIDTYPE(obj, widtype);
601 Evas_Object *prev_content;
603 Widget_Data *wd = elm_widget_data_get(obj);
611 prev_content = elm_object_part_content_get(wd->content_area,
612 "elm.swallow.content");
614 evas_object_del(prev_content);
617 elm_object_part_content_set(wd->base, "elm.swallow.content",
619 wd->content_text_obj = elm_label_add(obj);
620 snprintf(buf, sizeof(buf), "popup/%s",
621 elm_widget_style_get(obj));
622 elm_object_style_set(wd->content_text_obj, buf);
623 elm_label_line_wrap_set(wd->content_text_obj,
624 wd->content_text_wrap_type);
625 elm_object_text_set(wd->content_text_obj, text);
626 evas_object_size_hint_weight_set(wd->content_text_obj, EVAS_HINT_EXPAND,
628 evas_object_size_hint_align_set(wd->content_text_obj, EVAS_HINT_FILL,
630 elm_object_part_content_set(wd->content_area, "elm.swallow.content",
631 wd->content_text_obj);
637 _text_set_hook(Evas_Object *obj, const char *part,
640 ELM_CHECK_WIDTYPE(obj, widtype);
641 Widget_Data *wd = elm_widget_data_get(obj);
644 if (!part || !strcmp(part, "default"))
645 _content_text_set(obj, label);
646 else if (!strcmp(part, "title,text"))
647 _title_text_set(obj, label);
649 WRN("The part name is invalid! : popup=%p", obj);
653 _title_text_get(const Evas_Object *obj)
655 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
656 Widget_Data *wd = elm_widget_data_get(obj);
658 if (!wd) return NULL;
659 return wd->title_text;
663 _content_text_get(const Evas_Object *obj)
665 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
666 const char *str = NULL;
667 Widget_Data *wd = elm_widget_data_get(obj);
669 if (!wd) return NULL;
670 if (wd->content_text_obj)
671 str = elm_object_text_get(wd->content_text_obj);
676 _text_get_hook(const Evas_Object *obj, const char *part)
678 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
679 const char *str = NULL;
680 Widget_Data *wd = elm_widget_data_get(obj);
682 if (!wd) return NULL;
683 if (!part || !strcmp(part, "default"))
684 str = _content_text_get(obj);
685 else if (!strcmp(part, "title,text"))
686 str = _title_text_get(obj);
688 WRN("The part name is invalid! : popup=%p", obj);
693 _title_icon_set(Evas_Object *obj, Evas_Object *icon)
695 ELM_CHECK_WIDTYPE(obj, widtype);
696 Eina_Bool title_visibility_old, title_visibility_current;
697 Widget_Data *wd = elm_widget_data_get(obj);
700 if (wd->title_icon == icon) return;
701 title_visibility_old = (wd->title_text) || (wd->title_icon);
704 evas_object_del(wd->title_icon);
705 wd->title_icon = NULL;
707 wd->title_icon = icon;
708 title_visibility_current = (wd->title_text) || (wd->title_icon);
709 elm_object_part_content_set(wd->base, "elm.swallow.title.icon",
712 elm_object_signal_emit(wd->base, "elm,state,title,icon,visible", "elm");
713 if (title_visibility_old != title_visibility_current) _layout_set(obj);
714 edje_object_message_signal_process(wd->base);
719 _content_set(Evas_Object *obj, Evas_Object *content)
721 ELM_CHECK_WIDTYPE(obj, widtype);
722 Evas_Object *prev_content;
723 Widget_Data *wd = elm_widget_data_get(obj);
726 if (wd->content && wd->content == content) return;
732 prev_content = elm_object_part_content_get(wd->content_area,
733 "elm.swallow.content");
735 evas_object_del(prev_content);
736 wd->content = content;
739 elm_object_part_content_set(wd->base, "elm.swallow.content",
741 elm_object_part_content_set(wd->content_area, "elm.swallow.content",
748 _button_remove(Evas_Object *obj, Evas_Object *content, Eina_Bool delete)
750 unsigned int i = 0, position = 0;
752 Widget_Data *wd = elm_widget_data_get(obj);
754 if (!wd->button_count) return;
755 for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
760 wd->buttons[i]->delete_me = EINA_FALSE;
761 if (wd->buttons[i]->btn == content)
763 snprintf(buf, sizeof(buf), "actionbtn%u", position);
764 elm_object_part_content_unset(wd->action_area, buf);
765 evas_object_hide(content);
766 if (delete) evas_object_del(content);
767 free(wd->buttons[i]);
768 wd->buttons[i] = NULL;
769 wd->button_count -= 1;
774 for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
776 if (!wd->buttons[i]) continue;
778 snprintf(buf, sizeof(buf), "actionbtn%u", position);
779 elm_object_part_content_unset(wd->action_area, buf);
780 elm_object_part_content_set(wd->action_area, buf,
781 wd->buttons[i]->btn);
782 wd->buttons[i]->delete_me = EINA_TRUE;
784 if (!wd->button_count)
787 edje_object_message_signal_process(elm_layout_edje_get(wd->base));
791 snprintf(buf, sizeof(buf), "buttons%u", wd->button_count);
792 elm_layout_theme_set(wd->action_area, "popup", buf,
793 elm_widget_style_get(obj));
798 _action_button_set(Evas_Object *obj, Evas_Object *btn, unsigned int idx)
800 Action_Area_Data *adata;
802 unsigned int num = idx - 1, i = 0, position = 0;
803 Widget_Data *wd = elm_widget_data_get(obj);
806 if (num >= ELM_POPUP_ACTION_BUTTON_MAX) return;
807 if (wd->buttons[num])
808 _button_remove(obj, wd->buttons[num]->btn, EINA_TRUE);
812 snprintf(buf, sizeof(buf), "buttons%u", wd->button_count);
813 elm_layout_theme_set(wd->action_area, "popup", buf,
814 elm_widget_style_get(obj));
815 adata = ELM_NEW(Action_Area_Data);
818 wd->buttons[num] = adata;
819 /* Adding delete_me state inside action data as unset calls _sub_del
820 too and before setting a new content, the previous one needs to
821 be unset in order to avoid unwanted deletion. This way rearrangement
822 of buttons can be achieved in action area.
824 for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
826 wd->buttons[i]->delete_me = EINA_FALSE;
827 for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
829 if (!wd->buttons[i]) continue;
831 snprintf(buf, sizeof(buf), "actionbtn%u", position);
832 elm_object_part_content_unset(wd->action_area, buf);
833 elm_object_part_content_set(wd->action_area, buf,
834 wd->buttons[i]->btn);
835 /* Setting delete_me to TRUE in order to let _sub_del handle it
836 if deleted externally and update the buttons array after freeing
837 action data allocated earlier.
839 wd->buttons[i]->delete_me = EINA_TRUE;
841 elm_object_part_content_set(wd->base, "elm.swallow.action_area",
843 if (wd->button_count == 1)
845 edje_object_message_signal_process(wd->base);
847 _scroller_size_calc(obj);
853 _content_set_hook(Evas_Object *obj, const char *part,
854 Evas_Object *content)
856 ELM_CHECK_WIDTYPE(obj, widtype);
859 Widget_Data *wd = elm_widget_data_get(obj);
862 if (!part || !strcmp(part, "default"))
863 _content_set(obj, content);
864 else if (!strcmp(part, "title,icon"))
865 _title_icon_set(obj, content);
866 else if (!strncmp(part, "button", 6))
869 for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
871 snprintf(buff, sizeof(buff), "%u", i+1);
872 if (!strncmp(part, buff, sizeof(buff)))
874 _action_button_set(obj, content, i+1);
880 WRN("The part name is invalid! : popup=%p", obj);
884 _title_icon_get(Evas_Object *obj)
886 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
887 Widget_Data *wd = elm_widget_data_get(obj);
889 if (!wd) return NULL;
890 return wd->title_icon;
894 _content_get(Evas_Object *obj)
896 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
897 Widget_Data *wd = elm_widget_data_get(obj);
899 if (!wd) return NULL;
904 _action_button_get(Evas_Object *obj, unsigned int idx)
906 unsigned int num = idx - 1;
907 Evas_Object *button = NULL;
908 Widget_Data *wd = elm_widget_data_get(obj);
910 if (!wd || !wd->button_count) return NULL;
911 if (wd->buttons[num])
912 button = wd->buttons[num]->btn;
917 _content_get_hook(Evas_Object *obj, const char *part)
919 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
920 Evas_Object *content = NULL;
923 Widget_Data *wd = elm_widget_data_get(obj);
925 if (!wd) return NULL;
926 if (!part || !strcmp(part, "default"))
927 content = _content_get(obj);
928 else if (!strcmp(part, "title,text"))
929 content = _title_icon_get(obj);
930 else if (!strncmp(part, "button", 6))
933 for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
935 snprintf(buff, sizeof(buff), "%u", i+1);
936 if (!strncmp(part, buff, sizeof(buff)))
938 content = _action_button_get(obj, i+1);
944 WRN("The part name is invalid! : popup=%p", obj);
949 _content_unset(Evas_Object *obj)
951 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
952 Evas_Object *content;
953 Widget_Data *wd = elm_widget_data_get(obj);
955 if (!wd || !wd->content) return NULL;
956 content = elm_object_part_content_unset(wd->content_area,
957 "elm.swallow.content");
964 _title_icon_unset(Evas_Object *obj)
966 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
968 Widget_Data *wd = elm_widget_data_get(obj);
970 if (!wd || !wd->title_icon) return NULL;
971 icon = elm_object_part_content_unset(wd->base, "elm.swallow.title.icon");
972 wd->title_icon = NULL;
977 _action_button_unset(Evas_Object *obj, unsigned int idx)
979 unsigned int num = idx -1;
980 Evas_Object *button = NULL;
981 Widget_Data *wd = elm_widget_data_get(obj);
983 if (!wd) return NULL;
984 if ((!wd->button_count) || (num >= ELM_POPUP_ACTION_BUTTON_MAX))
987 if (wd->buttons[num])
989 button = wd->buttons[num]->btn;
990 _button_remove(obj, button, EINA_FALSE);
996 _content_unset_hook(Evas_Object *obj, const char *part)
998 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
999 Evas_Object *content = NULL;
1002 Widget_Data *wd = elm_widget_data_get(obj);
1004 if (!wd) return NULL;
1005 if (!part || !strcmp(part, "default"))
1006 content = _content_unset(obj);
1007 else if (!strcmp(part, "title,icon"))
1008 content = _title_icon_unset(obj);
1009 else if (!strncmp(part, "button", 6))
1012 for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
1014 snprintf(buff, sizeof(buff), "%u", i+1);
1015 if (!strncmp(part, buff, sizeof(buff)))
1017 content = _action_button_unset(obj, i+1);
1023 WRN("The part name is invalid! : popup=%p", obj);
1028 _focus_next_hook(const Evas_Object *obj __UNUSED__,
1029 Elm_Focus_Direction dir __UNUSED__,
1030 Evas_Object **next __UNUSED__)
1032 //TODO: Implement Focus chanin Handling in Popup for action area buttons
1036 _item_text_set(Elm_Popup_Content_Item *item, const char *label)
1038 if (!eina_stringshare_replace(&item->label, label)) return;
1039 edje_object_part_text_set(VIEW(item), "elm.text", label);
1041 edje_object_signal_emit(VIEW(item),
1042 "elm,state,item,text,visible", "elm");
1044 edje_object_signal_emit(VIEW(item),
1045 "elm,state,item,text,hidden", "elm");
1046 edje_object_message_signal_process(VIEW(item));
1050 _item_text_set_hook(Elm_Object_Item *it, const char *part, const char *label)
1052 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1053 Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1055 if ((!part) || (!strcmp(part, "default")))
1057 _item_text_set(item, label);
1060 WRN("The part name is invalid! : popup=%p", WIDGET(item));
1064 _item_text_get_hook(const Elm_Object_Item *it, const char *part)
1066 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
1067 Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1069 if ((!part) || (!strcmp(part, "default")))
1071 WRN("The part name is invalid! : popup=%p", WIDGET(item));
1076 _item_icon_set(Elm_Popup_Content_Item *item, Evas_Object *icon)
1078 if (item->icon == icon) return;
1081 elm_widget_sub_object_del(WIDGET(item), item->icon);
1082 evas_object_data_del(item->icon, "_popup_content_item");
1083 evas_object_del(item->icon);
1088 elm_widget_sub_object_add(WIDGET(item), item->icon);
1089 evas_object_data_set(item->icon, "_popup_content_item", item);
1090 edje_object_part_swallow(VIEW(item), "elm.swallow.content",
1092 edje_object_signal_emit(VIEW(item),
1093 "elm,state,item,icon,visible", "elm");
1096 edje_object_signal_emit(VIEW(item),
1097 "elm,state,item,icon,hidden", "elm");
1098 edje_object_message_signal_process(item->base.view);
1102 _item_content_set_hook(Elm_Object_Item *it, const char *part,
1103 Evas_Object *content)
1105 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1106 Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1108 if ((!(part)) || (!strcmp(part, "default")))
1109 _item_icon_set(item, content);
1111 WRN("The part name is invalid! : popup=%p", WIDGET(item));
1114 static Evas_Object *
1115 _item_content_get_hook(const Elm_Object_Item *it,
1118 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
1119 Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1121 if ((!(part)) || (!strcmp(part, "default")))
1123 WRN("The part name is invalid! : popup=%p", WIDGET(item));
1127 static Evas_Object *
1128 _item_icon_unset(Elm_Popup_Content_Item *item)
1130 Evas_Object *icon = item->icon;
1132 if (!item->icon) return NULL;
1133 elm_widget_sub_object_del(WIDGET(item), icon);
1134 evas_object_data_del(icon, "_popup_content_item");
1135 edje_object_part_unswallow(item->base.view, icon);
1136 edje_object_signal_emit(VIEW(item),
1137 "elm,state,item,icon,hidden", "elm");
1142 static Evas_Object *
1143 _item_content_unset_hook(const Elm_Object_Item *it,
1146 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
1147 Evas_Object *content = NULL;
1148 Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1150 if ((!(part)) || (!strcmp(part, "default")))
1151 content = _item_icon_unset(item);
1153 WRN("The part name is invalid! : popup=%p", WIDGET(item));
1158 _item_disable_hook(Elm_Object_Item *it)
1160 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1161 Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1162 Widget_Data *wd = elm_widget_data_get(WIDGET(item));
1165 if (elm_widget_item_disabled_get(it))
1166 edje_object_signal_emit(VIEW(item), "elm,state,item,disabled", "elm");
1168 edje_object_signal_emit(VIEW(item), "elm,state,item,enabled", "elm");
1172 _item_del_pre_hook(Elm_Object_Item *it)
1174 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1175 Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1176 Widget_Data *wd = elm_widget_data_get(WIDGET(item));
1180 evas_object_del(item->icon);
1181 eina_stringshare_del(item->label);
1182 wd->items = eina_list_remove(wd->items, item);
1183 if (!eina_list_count(wd->items))
1191 _item_signal_emit_hook(Elm_Object_Item *it, const char *emission,
1194 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1195 Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1197 edje_object_signal_emit(VIEW(item), emission, source);
1201 elm_popup_add(Evas_Object *parent)
1208 ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
1209 ELM_SET_WIDTYPE(widtype, "popup");
1210 elm_widget_type_set(obj, widtype);
1211 elm_widget_sub_object_add(parent, obj);
1212 elm_widget_data_set(obj, wd);
1213 elm_widget_del_pre_hook_set(obj, _del_pre_hook);
1214 elm_widget_del_hook_set(obj, _del_hook);
1215 elm_widget_theme_hook_set(obj, _theme_hook);
1216 elm_widget_text_set_hook_set(obj, _text_set_hook);
1217 elm_widget_text_get_hook_set(obj, _text_get_hook);
1218 elm_widget_content_set_hook_set(obj, _content_set_hook);
1219 elm_widget_content_get_hook_set(obj, _content_get_hook);
1220 elm_widget_content_unset_hook_set(obj,_content_unset_hook);
1221 elm_widget_focus_next_hook_set(obj, _focus_next_hook);
1222 evas_object_smart_callbacks_descriptions_set(obj, _signals);
1224 wd->notify = elm_notify_add(obj);
1225 elm_widget_resize_object_set(obj, wd->notify);
1226 elm_notify_parent_set(wd->notify, parent);
1227 elm_notify_orient_set(wd->notify, ELM_NOTIFY_ORIENT_CENTER);
1228 elm_notify_allow_events_set(wd->notify, EINA_FALSE);
1229 evas_object_size_hint_weight_set(wd->notify,
1230 EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
1231 evas_object_size_hint_align_set(wd->notify, EVAS_HINT_FILL, EVAS_HINT_FILL);
1232 elm_object_style_set(wd->notify, "popup");
1234 evas_object_event_callback_add(wd->notify, EVAS_CALLBACK_RESIZE,
1235 _notify_resize, obj);
1236 evas_object_event_callback_add(obj, EVAS_CALLBACK_RESTACK, _restack, NULL);
1237 wd->base = elm_layout_add(obj);
1238 evas_object_size_hint_weight_set(wd->base, EVAS_HINT_EXPAND,
1240 evas_object_size_hint_align_set(wd->base, EVAS_HINT_FILL, EVAS_HINT_FILL);
1242 elm_layout_theme_set(wd->base, "popup", "base", elm_widget_style_get(obj));
1243 elm_object_content_set(wd->notify, wd->base);
1245 elm_object_signal_callback_add(wd->base, "elm,state,title_area,visible",
1246 "elm", _layout_change_cb, obj);
1247 elm_object_signal_callback_add(wd->base, "elm,state,title_area,hidden",
1248 "elm", _layout_change_cb, obj);
1249 elm_object_signal_callback_add(wd->base, "elm,state,action_area,visible",
1250 "elm", _layout_change_cb, obj);
1251 elm_object_signal_callback_add(wd->base, "elm,state,action_area,hidden",
1252 "elm", _layout_change_cb, obj);
1253 wd->content_area = elm_layout_add(obj);
1254 elm_layout_theme_set(wd->content_area, "popup", "content",
1255 elm_widget_style_get(obj));
1256 wd->action_area = elm_layout_add(obj);
1257 evas_object_size_hint_weight_set(wd->action_area, EVAS_HINT_EXPAND,
1259 evas_object_size_hint_align_set(wd->action_area, EVAS_HINT_FILL,
1261 evas_object_event_callback_add(wd->action_area,
1262 EVAS_CALLBACK_CHANGED_SIZE_HINTS,
1263 _changed_size_hints, obj);
1264 evas_object_event_callback_add(wd->content_area,
1265 EVAS_CALLBACK_CHANGED_SIZE_HINTS,
1266 _changed_size_hints, obj);
1267 evas_object_smart_callback_add(wd->base, "sub-object-del",
1269 evas_object_smart_callback_add(wd->content_area, "sub-object-del",
1271 evas_object_smart_callback_add(wd->action_area, "sub-object-del",
1273 evas_object_smart_callback_add(obj, "sub-object-del",
1276 wd->content_text_wrap_type = ELM_WRAP_MIXED;
1277 evas_object_smart_callback_add(wd->notify, "block,clicked",
1278 _block_clicked_cb, obj);
1279 evas_object_smart_callback_add(wd->notify, "timeout", _timeout, obj);
1280 for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
1281 wd->buttons[i] = NULL;
1283 //TODO: To use scroller for description also
1288 elm_popup_content_text_wrap_type_set(Evas_Object *obj, Elm_Wrap_Type wrap)
1290 ELM_CHECK_WIDTYPE(obj, widtype);
1291 Evas_Object *content_text_obj;
1292 Widget_Data *wd = elm_widget_data_get(obj);
1295 if (wd->content_text_wrap_type == ELM_WRAP_NONE) return;
1296 //Need to wrap the content text, so not allowing ELM_WRAP_NONE
1297 wd->content_text_wrap_type = wrap;
1298 if (wd->content_text_obj)
1300 content_text_obj = elm_object_part_content_get(wd->content_area,
1301 "elm.swallow.content");
1302 elm_label_line_wrap_set(content_text_obj, wrap);
1307 elm_popup_content_text_wrap_type_get(const Evas_Object *obj)
1309 ELM_CHECK_WIDTYPE(obj, widtype) ELM_WRAP_LAST;
1310 Widget_Data *wd = elm_widget_data_get(obj);
1312 if (!wd) return ELM_WRAP_LAST;
1313 return wd->content_text_wrap_type;
1317 elm_popup_orient_set(Evas_Object *obj, Elm_Popup_Orient orient)
1319 ELM_CHECK_WIDTYPE(obj, widtype);
1320 Widget_Data *wd = elm_widget_data_get(obj);
1323 if (orient >= ELM_POPUP_ORIENT_LAST) return;
1324 elm_notify_orient_set(wd->notify, (Elm_Notify_Orient)orient);
1327 EAPI Elm_Popup_Orient
1328 elm_popup_orient_get(const Evas_Object *obj)
1330 ELM_CHECK_WIDTYPE(obj, widtype) -1;
1331 Widget_Data *wd = elm_widget_data_get(obj);
1333 if (!wd) return ELM_POPUP_ORIENT_LAST;
1334 return (Elm_Popup_Orient)elm_notify_orient_get(wd->notify);
1338 elm_popup_timeout_set(Evas_Object *obj, double timeout)
1340 ELM_CHECK_WIDTYPE(obj, widtype);
1341 Widget_Data *wd = elm_widget_data_get(obj);
1344 elm_notify_timeout_set(wd->notify, timeout);
1348 elm_popup_timeout_get(const Evas_Object *obj)
1350 ELM_CHECK_WIDTYPE(obj, widtype) 0.0;
1351 Widget_Data *wd = elm_widget_data_get(obj);
1353 if (!wd) return 0.0;
1354 return elm_notify_timeout_get(wd->notify);
1358 elm_popup_allow_events_set(Evas_Object *obj, Eina_Bool allow)
1360 ELM_CHECK_WIDTYPE(obj, widtype);
1361 Eina_Bool allow_events = !!allow;
1362 Widget_Data *wd = elm_widget_data_get(obj);
1365 elm_notify_allow_events_set(wd->notify, allow_events);
1369 elm_popup_allow_events_get(const Evas_Object *obj)
1371 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1372 Widget_Data *wd = elm_widget_data_get(obj);
1374 if (!wd) return EINA_FALSE;
1375 return elm_notify_allow_events_get(wd->notify);
1378 EAPI Elm_Object_Item *
1379 elm_popup_item_append(Evas_Object *obj, const char *label,
1380 Evas_Object *icon, Evas_Smart_Cb func,
1383 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1384 Evas_Object *prev_content;
1385 Elm_Popup_Content_Item *item;
1386 Widget_Data *wd = elm_widget_data_get(obj);
1388 if (!wd) return NULL;
1389 item = elm_widget_item_new(obj, Elm_Popup_Content_Item);
1390 if (!item) return NULL;
1391 if (wd->content || wd->content_text_obj)
1393 prev_content = elm_object_part_content_get(wd->content_area,
1394 "elm.swallow.content");
1396 evas_object_del(prev_content);
1399 //The first item is appended.
1404 item->base.data = data;
1407 _item_icon_set(item, icon);
1408 _item_text_set(item, label);
1409 elm_box_pack_end(wd->box, VIEW(item));
1410 wd->items = eina_list_append(wd->items, item);
1412 _scroller_size_calc(obj);
1414 return (Elm_Object_Item *)item;