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
1033 _item_text_set(Elm_Popup_Content_Item *item, const char *label)
1035 if (!eina_stringshare_replace(&item->label, label)) return;
1036 edje_object_part_text_set(VIEW(item), "elm.text", label);
1038 edje_object_signal_emit(VIEW(item),
1039 "elm,state,item,text,visible", "elm");
1041 edje_object_signal_emit(VIEW(item),
1042 "elm,state,item,text,hidden", "elm");
1043 edje_object_message_signal_process(VIEW(item));
1047 _item_text_set_hook(Elm_Object_Item *it, const char *part, const char *label)
1049 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1050 Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1052 if ((!part) || (!strcmp(part, "default")))
1054 _item_text_set(item, label);
1057 WRN("The part name is invalid! : popup=%p", WIDGET(item));
1061 _item_text_get_hook(const Elm_Object_Item *it, const char *part)
1063 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
1064 Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1066 if ((!part) || (!strcmp(part, "default")))
1068 WRN("The part name is invalid! : popup=%p", WIDGET(item));
1073 _item_icon_set(Elm_Popup_Content_Item *item, Evas_Object *icon)
1075 if (item->icon == icon) return;
1078 evas_object_data_del(item->icon, "_popup_content_item");
1079 evas_object_del(item->icon);
1084 elm_widget_sub_object_add(WIDGET(item), item->icon);
1085 evas_object_data_set(item->icon, "_popup_content_item", item);
1086 edje_object_part_swallow(VIEW(item), "elm.swallow.content",
1088 edje_object_signal_emit(VIEW(item),
1089 "elm,state,item,icon,visible", "elm");
1092 edje_object_signal_emit(VIEW(item),
1093 "elm,state,item,icon,hidden", "elm");
1094 edje_object_message_signal_process(item->base.view);
1098 _item_content_set_hook(Elm_Object_Item *it, const char *part,
1099 Evas_Object *content)
1101 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1102 Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1104 if ((!(part)) || (!strcmp(part, "default")))
1105 _item_icon_set(item, content);
1107 WRN("The part name is invalid! : popup=%p", WIDGET(item));
1110 static Evas_Object *
1111 _item_content_get_hook(const Elm_Object_Item *it,
1114 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
1115 Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1117 if ((!(part)) || (!strcmp(part, "default")))
1119 WRN("The part name is invalid! : popup=%p", WIDGET(item));
1123 static Evas_Object *
1124 _item_icon_unset(Elm_Popup_Content_Item *item)
1126 Evas_Object *icon = item->icon;
1128 if (!item->icon) return NULL;
1129 elm_widget_sub_object_del(WIDGET(item), icon);
1130 evas_object_data_del(icon, "_popup_content_item");
1131 edje_object_part_unswallow(item->base.view, icon);
1132 edje_object_signal_emit(VIEW(item),
1133 "elm,state,item,icon,hidden", "elm");
1138 static Evas_Object *
1139 _item_content_unset_hook(const Elm_Object_Item *it,
1142 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
1143 Evas_Object *content = NULL;
1144 Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1146 if ((!(part)) || (!strcmp(part, "default")))
1147 content = _item_icon_unset(item);
1149 WRN("The part name is invalid! : popup=%p", WIDGET(item));
1154 _item_disable_hook(Elm_Object_Item *it)
1156 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1157 Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1158 Widget_Data *wd = elm_widget_data_get(WIDGET(item));
1161 if (elm_widget_item_disabled_get(it))
1162 edje_object_signal_emit(VIEW(item), "elm,state,item,disabled", "elm");
1164 edje_object_signal_emit(VIEW(item), "elm,state,item,enabled", "elm");
1168 _item_del_pre_hook(Elm_Object_Item *it)
1170 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1171 Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1172 Widget_Data *wd = elm_widget_data_get(WIDGET(item));
1176 evas_object_del(item->icon);
1177 eina_stringshare_del(item->label);
1178 wd->items = eina_list_remove(wd->items, item);
1179 if (!eina_list_count(wd->items))
1187 _item_signal_emit_hook(Elm_Object_Item *it, const char *emission,
1190 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1191 Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1193 edje_object_signal_emit(VIEW(item), emission, source);
1197 elm_popup_add(Evas_Object *parent)
1204 ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
1205 ELM_SET_WIDTYPE(widtype, "popup");
1206 elm_widget_type_set(obj, widtype);
1207 elm_widget_sub_object_add(parent, obj);
1208 elm_widget_data_set(obj, wd);
1209 elm_widget_del_pre_hook_set(obj, _del_pre_hook);
1210 elm_widget_del_hook_set(obj, _del_hook);
1211 elm_widget_theme_hook_set(obj, _theme_hook);
1212 elm_widget_text_set_hook_set(obj, _text_set_hook);
1213 elm_widget_text_get_hook_set(obj, _text_get_hook);
1214 elm_widget_content_set_hook_set(obj, _content_set_hook);
1215 elm_widget_content_get_hook_set(obj, _content_get_hook);
1216 elm_widget_content_unset_hook_set(obj,_content_unset_hook);
1217 elm_widget_focus_next_hook_set(obj, _focus_next_hook);
1218 evas_object_smart_callbacks_descriptions_set(obj, _signals);
1220 wd->notify = elm_notify_add(obj);
1221 elm_widget_resize_object_set(obj, wd->notify);
1222 elm_notify_parent_set(wd->notify, parent);
1223 elm_notify_orient_set(wd->notify, ELM_NOTIFY_ORIENT_CENTER);
1224 elm_notify_allow_events_set(wd->notify, EINA_FALSE);
1225 evas_object_size_hint_weight_set(wd->notify,
1226 EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
1227 evas_object_size_hint_align_set(wd->notify, EVAS_HINT_FILL, EVAS_HINT_FILL);
1228 elm_object_style_set(wd->notify, "popup");
1230 evas_object_event_callback_add(wd->notify, EVAS_CALLBACK_RESIZE,
1231 _notify_resize, obj);
1232 evas_object_event_callback_add(obj, EVAS_CALLBACK_RESTACK, _restack, NULL);
1233 wd->base = elm_layout_add(obj);
1234 evas_object_size_hint_weight_set(wd->base, EVAS_HINT_EXPAND,
1236 evas_object_size_hint_align_set(wd->base, EVAS_HINT_FILL, EVAS_HINT_FILL);
1238 elm_layout_theme_set(wd->base, "popup", "base", elm_widget_style_get(obj));
1239 elm_object_content_set(wd->notify, wd->base);
1241 elm_object_signal_callback_add(wd->base, "elm,state,title_area,visible",
1242 "elm", _layout_change_cb, obj);
1243 elm_object_signal_callback_add(wd->base, "elm,state,title_area,hidden",
1244 "elm", _layout_change_cb, obj);
1245 elm_object_signal_callback_add(wd->base, "elm,state,action_area,visible",
1246 "elm", _layout_change_cb, obj);
1247 elm_object_signal_callback_add(wd->base, "elm,state,action_area,hidden",
1248 "elm", _layout_change_cb, obj);
1249 wd->content_area = elm_layout_add(obj);
1250 elm_layout_theme_set(wd->content_area, "popup", "content",
1251 elm_widget_style_get(obj));
1252 wd->action_area = elm_layout_add(obj);
1253 evas_object_size_hint_weight_set(wd->action_area, EVAS_HINT_EXPAND,
1255 evas_object_size_hint_align_set(wd->action_area, EVAS_HINT_FILL,
1257 evas_object_event_callback_add(wd->action_area,
1258 EVAS_CALLBACK_CHANGED_SIZE_HINTS,
1259 _changed_size_hints, obj);
1260 evas_object_event_callback_add(wd->content_area,
1261 EVAS_CALLBACK_CHANGED_SIZE_HINTS,
1262 _changed_size_hints, obj);
1263 evas_object_smart_callback_add(wd->base, "sub-object-del",
1265 evas_object_smart_callback_add(wd->content_area, "sub-object-del",
1267 evas_object_smart_callback_add(wd->action_area, "sub-object-del",
1269 evas_object_smart_callback_add(obj, "sub-object-del",
1272 wd->content_text_wrap_type = ELM_WRAP_MIXED;
1273 evas_object_smart_callback_add(wd->notify, "block,clicked",
1274 _block_clicked_cb, obj);
1275 evas_object_smart_callback_add(wd->notify, "timeout", _timeout, obj);
1276 for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
1277 wd->buttons[i] = NULL;
1279 //TODO: To use scroller for description also
1284 elm_popup_content_text_wrap_type_set(Evas_Object *obj, Elm_Wrap_Type wrap)
1286 ELM_CHECK_WIDTYPE(obj, widtype);
1287 Evas_Object *content_text_obj;
1288 Widget_Data *wd = elm_widget_data_get(obj);
1291 if (wd->content_text_wrap_type == ELM_WRAP_NONE) return;
1292 //Need to wrap the content text, so not allowing ELM_WRAP_NONE
1293 wd->content_text_wrap_type = wrap;
1294 if (wd->content_text_obj)
1296 content_text_obj = elm_object_part_content_get(wd->content_area,
1297 "elm.swallow.content");
1298 elm_label_line_wrap_set(content_text_obj, wrap);
1303 elm_popup_content_text_wrap_type_get(const Evas_Object *obj)
1305 ELM_CHECK_WIDTYPE(obj, widtype) ELM_WRAP_LAST;
1306 Widget_Data *wd = elm_widget_data_get(obj);
1308 if (!wd) return ELM_WRAP_LAST;
1309 return wd->content_text_wrap_type;
1313 elm_popup_orient_set(Evas_Object *obj, Elm_Popup_Orient orient)
1315 ELM_CHECK_WIDTYPE(obj, widtype);
1316 Widget_Data *wd = elm_widget_data_get(obj);
1319 if (orient >= ELM_POPUP_ORIENT_LAST) return;
1320 elm_notify_orient_set(wd->notify, (Elm_Notify_Orient)orient);
1323 EAPI Elm_Popup_Orient
1324 elm_popup_orient_get(const Evas_Object *obj)
1326 ELM_CHECK_WIDTYPE(obj, widtype) -1;
1327 Widget_Data *wd = elm_widget_data_get(obj);
1329 if (!wd) return ELM_POPUP_ORIENT_LAST;
1330 return (Elm_Popup_Orient)elm_notify_orient_get(wd->notify);
1334 elm_popup_timeout_set(Evas_Object *obj, double timeout)
1336 ELM_CHECK_WIDTYPE(obj, widtype);
1337 Widget_Data *wd = elm_widget_data_get(obj);
1340 elm_notify_timeout_set(wd->notify, timeout);
1344 elm_popup_timeout_get(const Evas_Object *obj)
1346 ELM_CHECK_WIDTYPE(obj, widtype) 0.0;
1347 Widget_Data *wd = elm_widget_data_get(obj);
1349 if (!wd) return 0.0;
1350 return elm_notify_timeout_get(wd->notify);
1354 elm_popup_allow_events_set(Evas_Object *obj, Eina_Bool allow)
1356 ELM_CHECK_WIDTYPE(obj, widtype);
1357 Eina_Bool allow_events = !!allow;
1358 Widget_Data *wd = elm_widget_data_get(obj);
1361 elm_notify_allow_events_set(wd->notify, allow_events);
1365 elm_popup_allow_events_get(const Evas_Object *obj)
1367 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1368 Widget_Data *wd = elm_widget_data_get(obj);
1370 if (!wd) return EINA_FALSE;
1371 return elm_notify_allow_events_get(wd->notify);
1374 EAPI Elm_Object_Item *
1375 elm_popup_item_append(Evas_Object *obj, const char *label,
1376 Evas_Object *icon, Evas_Smart_Cb func,
1379 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1380 Evas_Object *prev_content;
1381 Elm_Popup_Content_Item *item;
1382 Widget_Data *wd = elm_widget_data_get(obj);
1384 if (!wd) return NULL;
1385 item = elm_widget_item_new(obj, Elm_Popup_Content_Item);
1386 if (!item) return NULL;
1387 if (wd->content || wd->content_text_obj)
1389 prev_content = elm_object_part_content_get(wd->content_area,
1390 "elm.swallow.content");
1392 evas_object_del(prev_content);
1395 //The first item is appended.
1400 item->base.data = data;
1403 _item_icon_set(item, icon);
1404 _item_text_set(item, label);
1405 elm_box_pack_end(wd->box, VIEW(item));
1406 wd->items = eina_list_append(wd->items, item);
1408 _scroller_size_calc(obj);
1410 return (Elm_Object_Item *)item;