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);
702 if (wd->title_icon) evas_object_del(wd->title_icon);
704 wd->title_icon = icon;
705 title_visibility_current = (wd->title_text) || (wd->title_icon);
706 elm_object_part_content_set(wd->base, "elm.swallow.title.icon",
709 elm_object_signal_emit(wd->base, "elm,state,title,icon,visible", "elm");
710 if (title_visibility_old != title_visibility_current) _layout_set(obj);
711 edje_object_message_signal_process(wd->base);
716 _content_set(Evas_Object *obj, Evas_Object *content)
718 ELM_CHECK_WIDTYPE(obj, widtype);
719 Evas_Object *prev_content;
720 Widget_Data *wd = elm_widget_data_get(obj);
723 if (wd->content && wd->content == content) return;
729 prev_content = elm_object_part_content_get(wd->content_area,
730 "elm.swallow.content");
732 evas_object_del(prev_content);
733 wd->content = content;
736 elm_object_part_content_set(wd->base, "elm.swallow.content",
738 elm_object_part_content_set(wd->content_area, "elm.swallow.content",
745 _button_remove(Evas_Object *obj, Evas_Object *content, Eina_Bool delete)
747 unsigned int i = 0, position = 0;
749 Widget_Data *wd = elm_widget_data_get(obj);
751 if (!wd->button_count) return;
752 for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
757 wd->buttons[i]->delete_me = EINA_FALSE;
758 if (wd->buttons[i]->btn == content)
760 snprintf(buf, sizeof(buf), "actionbtn%u", position);
761 elm_object_part_content_unset(wd->action_area, buf);
762 evas_object_hide(content);
763 if (delete) evas_object_del(content);
764 free(wd->buttons[i]);
765 wd->buttons[i] = NULL;
766 wd->button_count -= 1;
771 for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
773 if (!wd->buttons[i]) continue;
775 snprintf(buf, sizeof(buf), "actionbtn%u", position);
776 elm_object_part_content_unset(wd->action_area, buf);
777 elm_object_part_content_set(wd->action_area, buf,
778 wd->buttons[i]->btn);
779 wd->buttons[i]->delete_me = EINA_TRUE;
781 if (!wd->button_count)
784 edje_object_message_signal_process(elm_layout_edje_get(wd->base));
788 snprintf(buf, sizeof(buf), "buttons%u", wd->button_count);
789 elm_layout_theme_set(wd->action_area, "popup", buf,
790 elm_widget_style_get(obj));
795 _action_button_set(Evas_Object *obj, Evas_Object *btn, unsigned int idx)
797 Action_Area_Data *adata;
799 unsigned int num = idx - 1, i = 0, position = 0;
800 Widget_Data *wd = elm_widget_data_get(obj);
803 if (num >= ELM_POPUP_ACTION_BUTTON_MAX) return;
804 if (wd->buttons[num])
805 _button_remove(obj, wd->buttons[num]->btn, EINA_TRUE);
809 snprintf(buf, sizeof(buf), "buttons%u", wd->button_count);
810 elm_layout_theme_set(wd->action_area, "popup", buf,
811 elm_widget_style_get(obj));
812 adata = ELM_NEW(Action_Area_Data);
815 wd->buttons[num] = adata;
816 /* Adding delete_me state inside action data as unset calls _sub_del
817 too and before setting a new content, the previous one needs to
818 be unset in order to avoid unwanted deletion. This way rearrangement
819 of buttons can be achieved in action area.
821 for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
823 wd->buttons[i]->delete_me = EINA_FALSE;
824 for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
826 if (!wd->buttons[i]) continue;
828 snprintf(buf, sizeof(buf), "actionbtn%u", position);
829 elm_object_part_content_unset(wd->action_area, buf);
830 elm_object_part_content_set(wd->action_area, buf,
831 wd->buttons[i]->btn);
832 /* Setting delete_me to TRUE in order to let _sub_del handle it
833 if deleted externally and update the buttons array after freeing
834 action data allocated earlier.
836 wd->buttons[i]->delete_me = EINA_TRUE;
838 elm_object_part_content_set(wd->base, "elm.swallow.action_area",
840 if (wd->button_count == 1)
842 edje_object_message_signal_process(wd->base);
844 _scroller_size_calc(obj);
850 _content_set_hook(Evas_Object *obj, const char *part,
851 Evas_Object *content)
853 ELM_CHECK_WIDTYPE(obj, widtype);
856 Widget_Data *wd = elm_widget_data_get(obj);
859 if (!part || !strcmp(part, "default"))
860 _content_set(obj, content);
861 else if (!strcmp(part, "title,icon"))
862 _title_icon_set(obj, content);
863 else if (!strncmp(part, "button", 6))
866 for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
868 snprintf(buff, sizeof(buff), "%u", i+1);
869 if (!strncmp(part, buff, sizeof(buff)))
871 _action_button_set(obj, content, i+1);
877 WRN("The part name is invalid! : popup=%p", obj);
881 _title_icon_get(Evas_Object *obj)
883 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
884 Widget_Data *wd = elm_widget_data_get(obj);
886 if (!wd) return NULL;
887 return wd->title_icon;
891 _content_get(Evas_Object *obj)
893 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
894 Widget_Data *wd = elm_widget_data_get(obj);
896 if (!wd) return NULL;
901 _action_button_get(Evas_Object *obj, unsigned int idx)
903 unsigned int num = idx - 1;
904 Evas_Object *button = NULL;
905 Widget_Data *wd = elm_widget_data_get(obj);
907 if (!wd || !wd->button_count) return NULL;
908 if (wd->buttons[num])
909 button = wd->buttons[num]->btn;
914 _content_get_hook(Evas_Object *obj, const char *part)
916 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
917 Evas_Object *content = NULL;
920 Widget_Data *wd = elm_widget_data_get(obj);
922 if (!wd) return NULL;
923 if (!part || !strcmp(part, "default"))
924 content = _content_get(obj);
925 else if (!strcmp(part, "title,text"))
926 content = _title_icon_get(obj);
927 else if (!strncmp(part, "button", 6))
930 for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
932 snprintf(buff, sizeof(buff), "%u", i+1);
933 if (!strncmp(part, buff, sizeof(buff)))
935 content = _action_button_get(obj, i+1);
941 WRN("The part name is invalid! : popup=%p", obj);
946 _content_unset(Evas_Object *obj)
948 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
949 Evas_Object *content;
950 Widget_Data *wd = elm_widget_data_get(obj);
952 if (!wd || !wd->content) return NULL;
953 content = elm_object_part_content_unset(wd->content_area,
954 "elm.swallow.content");
961 _title_icon_unset(Evas_Object *obj)
963 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
965 Widget_Data *wd = elm_widget_data_get(obj);
967 if (!wd || !wd->title_icon) return NULL;
968 icon = elm_object_part_content_unset(wd->base, "elm.swallow.title.icon");
969 wd->title_icon = NULL;
974 _action_button_unset(Evas_Object *obj, unsigned int idx)
976 unsigned int num = idx -1;
977 Evas_Object *button = NULL;
978 Widget_Data *wd = elm_widget_data_get(obj);
980 if (!wd) return NULL;
981 if ((!wd->button_count) || (num >= ELM_POPUP_ACTION_BUTTON_MAX))
984 if (wd->buttons[num])
986 button = wd->buttons[num]->btn;
987 _button_remove(obj, button, EINA_FALSE);
993 _content_unset_hook(Evas_Object *obj, const char *part)
995 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
996 Evas_Object *content = NULL;
999 Widget_Data *wd = elm_widget_data_get(obj);
1001 if (!wd) return NULL;
1002 if (!part || !strcmp(part, "default"))
1003 content = _content_unset(obj);
1004 else if (!strcmp(part, "title,icon"))
1005 content = _title_icon_unset(obj);
1006 else if (!strncmp(part, "button", 6))
1009 for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
1011 snprintf(buff, sizeof(buff), "%u", i+1);
1012 if (!strncmp(part, buff, sizeof(buff)))
1014 content = _action_button_unset(obj, i+1);
1020 WRN("The part name is invalid! : popup=%p", obj);
1025 _focus_next_hook(const Evas_Object *obj __UNUSED__,
1026 Elm_Focus_Direction dir __UNUSED__,
1027 Evas_Object **next __UNUSED__)
1029 //TODO: Implement Focus chanin Handling in Popup for action area buttons
1034 _item_text_set(Elm_Popup_Content_Item *item, const char *label)
1036 if (!eina_stringshare_replace(&item->label, label)) return;
1037 edje_object_part_text_set(VIEW(item), "elm.text", label);
1039 edje_object_signal_emit(VIEW(item),
1040 "elm,state,item,text,visible", "elm");
1042 edje_object_signal_emit(VIEW(item),
1043 "elm,state,item,text,hidden", "elm");
1044 edje_object_message_signal_process(VIEW(item));
1048 _item_text_set_hook(Elm_Object_Item *it, const char *part, const char *label)
1050 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1051 Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1053 if ((!part) || (!strcmp(part, "default")))
1055 _item_text_set(item, label);
1058 WRN("The part name is invalid! : popup=%p", WIDGET(item));
1062 _item_text_get_hook(const Elm_Object_Item *it, const char *part)
1064 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
1065 Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1067 if ((!part) || (!strcmp(part, "default")))
1069 WRN("The part name is invalid! : popup=%p", WIDGET(item));
1074 _item_icon_set(Elm_Popup_Content_Item *item, Evas_Object *icon)
1076 if (item->icon == icon) return;
1079 evas_object_data_del(item->icon, "_popup_content_item");
1080 evas_object_del(item->icon);
1085 elm_widget_sub_object_add(WIDGET(item), item->icon);
1086 evas_object_data_set(item->icon, "_popup_content_item", item);
1087 edje_object_part_swallow(VIEW(item), "elm.swallow.content",
1089 edje_object_signal_emit(VIEW(item),
1090 "elm,state,item,icon,visible", "elm");
1093 edje_object_signal_emit(VIEW(item),
1094 "elm,state,item,icon,hidden", "elm");
1095 edje_object_message_signal_process(item->base.view);
1099 _item_content_set_hook(Elm_Object_Item *it, const char *part,
1100 Evas_Object *content)
1102 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1103 Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1105 if ((!(part)) || (!strcmp(part, "default")))
1106 _item_icon_set(item, content);
1108 WRN("The part name is invalid! : popup=%p", WIDGET(item));
1111 static Evas_Object *
1112 _item_content_get_hook(const Elm_Object_Item *it,
1115 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
1116 Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1118 if ((!(part)) || (!strcmp(part, "default")))
1120 WRN("The part name is invalid! : popup=%p", WIDGET(item));
1124 static Evas_Object *
1125 _item_icon_unset(Elm_Popup_Content_Item *item)
1127 Evas_Object *icon = item->icon;
1129 if (!item->icon) return NULL;
1130 elm_widget_sub_object_del(WIDGET(item), icon);
1131 evas_object_data_del(icon, "_popup_content_item");
1132 edje_object_part_unswallow(item->base.view, icon);
1133 edje_object_signal_emit(VIEW(item),
1134 "elm,state,item,icon,hidden", "elm");
1139 static Evas_Object *
1140 _item_content_unset_hook(const Elm_Object_Item *it,
1143 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
1144 Evas_Object *content = NULL;
1145 Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1147 if ((!(part)) || (!strcmp(part, "default")))
1148 content = _item_icon_unset(item);
1150 WRN("The part name is invalid! : popup=%p", WIDGET(item));
1155 _item_disable_hook(Elm_Object_Item *it)
1157 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1158 Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1159 Widget_Data *wd = elm_widget_data_get(WIDGET(item));
1162 if (elm_widget_item_disabled_get(it))
1163 edje_object_signal_emit(VIEW(item), "elm,state,item,disabled", "elm");
1165 edje_object_signal_emit(VIEW(item), "elm,state,item,enabled", "elm");
1169 _item_del_pre_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));
1177 evas_object_del(item->icon);
1178 eina_stringshare_del(item->label);
1179 wd->items = eina_list_remove(wd->items, item);
1180 if (!eina_list_count(wd->items))
1188 _item_signal_emit_hook(Elm_Object_Item *it, const char *emission,
1191 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1192 Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1194 edje_object_signal_emit(VIEW(item), emission, source);
1198 _popup_show(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj,
1199 void *event_info __UNUSED__)
1203 wd = elm_widget_data_get(obj);
1206 evas_object_show(wd->notify);
1210 elm_popup_add(Evas_Object *parent)
1217 ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
1218 ELM_SET_WIDTYPE(widtype, "popup");
1219 elm_widget_type_set(obj, widtype);
1220 elm_widget_sub_object_add(parent, obj);
1221 elm_widget_data_set(obj, wd);
1222 elm_widget_del_pre_hook_set(obj, _del_pre_hook);
1223 elm_widget_del_hook_set(obj, _del_hook);
1224 elm_widget_theme_hook_set(obj, _theme_hook);
1225 elm_widget_text_set_hook_set(obj, _text_set_hook);
1226 elm_widget_text_get_hook_set(obj, _text_get_hook);
1227 elm_widget_content_set_hook_set(obj, _content_set_hook);
1228 elm_widget_content_get_hook_set(obj, _content_get_hook);
1229 elm_widget_content_unset_hook_set(obj,_content_unset_hook);
1230 elm_widget_focus_next_hook_set(obj, _focus_next_hook);
1231 evas_object_smart_callbacks_descriptions_set(obj, _signals);
1233 wd->notify = elm_notify_add(obj);
1234 elm_notify_parent_set(wd->notify, parent);
1235 elm_notify_orient_set(wd->notify, ELM_NOTIFY_ORIENT_CENTER);
1236 elm_notify_allow_events_set(wd->notify, EINA_FALSE);
1237 evas_object_size_hint_weight_set(wd->notify,
1238 EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
1239 evas_object_size_hint_align_set(wd->notify, EVAS_HINT_FILL, EVAS_HINT_FILL);
1240 elm_object_style_set(wd->notify, "popup");
1242 evas_object_event_callback_add(wd->notify, EVAS_CALLBACK_RESIZE,
1243 _notify_resize, obj);
1244 evas_object_event_callback_add(obj, EVAS_CALLBACK_SHOW, _popup_show,
1246 evas_object_event_callback_add(obj, EVAS_CALLBACK_RESTACK, _restack, NULL);
1247 wd->base = elm_layout_add(obj);
1248 evas_object_size_hint_weight_set(wd->base, EVAS_HINT_EXPAND,
1250 evas_object_size_hint_align_set(wd->base, EVAS_HINT_FILL, EVAS_HINT_FILL);
1252 elm_layout_theme_set(wd->base, "popup", "base", elm_widget_style_get(obj));
1253 elm_object_content_set(wd->notify, wd->base);
1255 elm_object_signal_callback_add(wd->base, "elm,state,title_area,visible",
1256 "elm", _layout_change_cb, obj);
1257 elm_object_signal_callback_add(wd->base, "elm,state,title_area,hidden",
1258 "elm", _layout_change_cb, obj);
1259 elm_object_signal_callback_add(wd->base, "elm,state,action_area,visible",
1260 "elm", _layout_change_cb, obj);
1261 elm_object_signal_callback_add(wd->base, "elm,state,action_area,hidden",
1262 "elm", _layout_change_cb, obj);
1263 wd->content_area = elm_layout_add(obj);
1264 elm_layout_theme_set(wd->content_area, "popup", "content",
1265 elm_widget_style_get(obj));
1266 wd->action_area = elm_layout_add(obj);
1267 evas_object_size_hint_weight_set(wd->action_area, EVAS_HINT_EXPAND,
1269 evas_object_size_hint_align_set(wd->action_area, EVAS_HINT_FILL,
1271 evas_object_event_callback_add(wd->action_area,
1272 EVAS_CALLBACK_CHANGED_SIZE_HINTS,
1273 _changed_size_hints, obj);
1274 evas_object_event_callback_add(wd->content_area,
1275 EVAS_CALLBACK_CHANGED_SIZE_HINTS,
1276 _changed_size_hints, obj);
1277 evas_object_smart_callback_add(wd->base, "sub-object-del",
1279 evas_object_smart_callback_add(wd->content_area, "sub-object-del",
1281 evas_object_smart_callback_add(wd->action_area, "sub-object-del",
1283 evas_object_smart_callback_add(obj, "sub-object-del",
1286 wd->content_text_wrap_type = ELM_WRAP_MIXED;
1287 evas_object_smart_callback_add(wd->notify, "block,clicked",
1288 _block_clicked_cb, obj);
1289 evas_object_smart_callback_add(wd->notify, "timeout", _timeout, obj);
1290 for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
1291 wd->buttons[i] = NULL;
1293 //TODO: To use scroller for description also
1298 elm_popup_content_text_wrap_type_set(Evas_Object *obj, Elm_Wrap_Type wrap)
1300 ELM_CHECK_WIDTYPE(obj, widtype);
1301 Evas_Object *content_text_obj;
1302 Widget_Data *wd = elm_widget_data_get(obj);
1305 if (wd->content_text_wrap_type == ELM_WRAP_NONE) return;
1306 //Need to wrap the content text, so not allowing ELM_WRAP_NONE
1307 wd->content_text_wrap_type = wrap;
1308 if (wd->content_text_obj)
1310 content_text_obj = elm_object_part_content_get(wd->content_area,
1311 "elm.swallow.content");
1312 elm_label_line_wrap_set(content_text_obj, wrap);
1317 elm_popup_content_text_wrap_type_get(const Evas_Object *obj)
1319 ELM_CHECK_WIDTYPE(obj, widtype) ELM_WRAP_LAST;
1320 Widget_Data *wd = elm_widget_data_get(obj);
1322 if (!wd) return ELM_WRAP_LAST;
1323 return wd->content_text_wrap_type;
1327 elm_popup_orient_set(Evas_Object *obj, Elm_Popup_Orient orient)
1329 ELM_CHECK_WIDTYPE(obj, widtype);
1330 Widget_Data *wd = elm_widget_data_get(obj);
1333 if (orient >= ELM_POPUP_ORIENT_LAST) return;
1334 elm_notify_orient_set(wd->notify, (Elm_Notify_Orient)orient);
1337 EAPI Elm_Popup_Orient
1338 elm_popup_orient_get(const Evas_Object *obj)
1340 ELM_CHECK_WIDTYPE(obj, widtype) -1;
1341 Widget_Data *wd = elm_widget_data_get(obj);
1343 if (!wd) return ELM_POPUP_ORIENT_LAST;
1344 return (Elm_Popup_Orient)elm_notify_orient_get(wd->notify);
1348 elm_popup_timeout_set(Evas_Object *obj, double timeout)
1350 ELM_CHECK_WIDTYPE(obj, widtype);
1351 Widget_Data *wd = elm_widget_data_get(obj);
1354 elm_notify_timeout_set(wd->notify, timeout);
1358 elm_popup_timeout_get(const Evas_Object *obj)
1360 ELM_CHECK_WIDTYPE(obj, widtype) 0.0;
1361 Widget_Data *wd = elm_widget_data_get(obj);
1363 if (!wd) return 0.0;
1364 return elm_notify_timeout_get(wd->notify);
1368 elm_popup_allow_events_set(Evas_Object *obj, Eina_Bool allow)
1370 ELM_CHECK_WIDTYPE(obj, widtype);
1371 Eina_Bool allow_events = !!allow;
1372 Widget_Data *wd = elm_widget_data_get(obj);
1375 elm_notify_allow_events_set(wd->notify, allow_events);
1379 elm_popup_allow_events_get(const Evas_Object *obj)
1381 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1382 Widget_Data *wd = elm_widget_data_get(obj);
1384 if (!wd) return EINA_FALSE;
1385 return elm_notify_allow_events_get(wd->notify);
1388 EAPI Elm_Object_Item *
1389 elm_popup_item_append(Evas_Object *obj, const char *label,
1390 Evas_Object *icon, Evas_Smart_Cb func,
1393 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1394 Evas_Object *prev_content;
1395 Elm_Popup_Content_Item *item;
1396 Widget_Data *wd = elm_widget_data_get(obj);
1398 if (!wd) return NULL;
1399 item = elm_widget_item_new(obj, Elm_Popup_Content_Item);
1400 if (!item) return NULL;
1401 if (wd->content || wd->content_text_obj)
1403 prev_content = elm_object_part_content_get(wd->content_area,
1404 "elm.swallow.content");
1406 evas_object_del(prev_content);
1409 //The first item is appended.
1414 item->base.data = data;
1417 _item_icon_set(item, icon);
1418 _item_text_set(item, label);
1419 elm_box_pack_end(wd->box, VIEW(item));
1420 wd->items = eina_list_append(wd->items, item);
1422 _scroller_size_calc(obj);
1424 return (Elm_Object_Item *)item;