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
1037 _item_text_set(Elm_Popup_Content_Item *item, const char *label)
1039 if (!eina_stringshare_replace(&item->label, label)) return;
1040 edje_object_part_text_set(VIEW(item), "elm.text", label);
1042 edje_object_signal_emit(VIEW(item),
1043 "elm,state,item,text,visible", "elm");
1045 edje_object_signal_emit(VIEW(item),
1046 "elm,state,item,text,hidden", "elm");
1047 edje_object_message_signal_process(VIEW(item));
1051 _item_text_set_hook(Elm_Object_Item *it, const char *part, const char *label)
1053 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1054 Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1056 if ((!part) || (!strcmp(part, "default")))
1058 _item_text_set(item, label);
1061 WRN("The part name is invalid! : popup=%p", WIDGET(item));
1065 _item_text_get_hook(const Elm_Object_Item *it, const char *part)
1067 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
1068 Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1070 if ((!part) || (!strcmp(part, "default")))
1072 WRN("The part name is invalid! : popup=%p", WIDGET(item));
1077 _item_icon_set(Elm_Popup_Content_Item *item, Evas_Object *icon)
1079 if (item->icon == icon) return;
1082 elm_widget_sub_object_del(WIDGET(item), item->icon);
1083 evas_object_data_del(item->icon, "_popup_content_item");
1084 evas_object_del(item->icon);
1089 elm_widget_sub_object_add(WIDGET(item), item->icon);
1090 evas_object_data_set(item->icon, "_popup_content_item", item);
1091 edje_object_part_swallow(VIEW(item), "elm.swallow.content",
1093 edje_object_signal_emit(VIEW(item),
1094 "elm,state,item,icon,visible", "elm");
1097 edje_object_signal_emit(VIEW(item),
1098 "elm,state,item,icon,hidden", "elm");
1099 edje_object_message_signal_process(item->base.view);
1103 _item_content_set_hook(Elm_Object_Item *it, const char *part,
1104 Evas_Object *content)
1106 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1107 Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1109 if ((!(part)) || (!strcmp(part, "default")))
1110 _item_icon_set(item, content);
1112 WRN("The part name is invalid! : popup=%p", WIDGET(item));
1115 static Evas_Object *
1116 _item_content_get_hook(const Elm_Object_Item *it,
1119 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
1120 Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1122 if ((!(part)) || (!strcmp(part, "default")))
1124 WRN("The part name is invalid! : popup=%p", WIDGET(item));
1128 static Evas_Object *
1129 _item_icon_unset(Elm_Popup_Content_Item *item)
1131 Evas_Object *icon = item->icon;
1133 if (!item->icon) return NULL;
1134 elm_widget_sub_object_del(WIDGET(item), icon);
1135 evas_object_data_del(icon, "_popup_content_item");
1136 edje_object_part_unswallow(item->base.view, icon);
1137 edje_object_signal_emit(VIEW(item),
1138 "elm,state,item,icon,hidden", "elm");
1143 static Evas_Object *
1144 _item_content_unset_hook(const Elm_Object_Item *it,
1147 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
1148 Evas_Object *content = NULL;
1149 Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1151 if ((!(part)) || (!strcmp(part, "default")))
1152 content = _item_icon_unset(item);
1154 WRN("The part name is invalid! : popup=%p", WIDGET(item));
1159 _item_disable_hook(Elm_Object_Item *it)
1161 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1162 Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1163 Widget_Data *wd = elm_widget_data_get(WIDGET(item));
1166 if (elm_widget_item_disabled_get(it))
1167 edje_object_signal_emit(VIEW(item), "elm,state,item,disabled", "elm");
1169 edje_object_signal_emit(VIEW(item), "elm,state,item,enabled", "elm");
1173 _item_del_pre_hook(Elm_Object_Item *it)
1175 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1176 Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1177 Widget_Data *wd = elm_widget_data_get(WIDGET(item));
1181 evas_object_del(item->icon);
1182 eina_stringshare_del(item->label);
1183 wd->items = eina_list_remove(wd->items, item);
1184 if (!eina_list_count(wd->items))
1192 _item_signal_emit_hook(Elm_Object_Item *it, const char *emission,
1195 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1196 Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1198 edje_object_signal_emit(VIEW(item), emission, source);
1202 elm_popup_add(Evas_Object *parent)
1209 ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
1210 ELM_SET_WIDTYPE(widtype, "popup");
1211 elm_widget_type_set(obj, widtype);
1212 elm_widget_sub_object_add(parent, obj);
1213 elm_widget_data_set(obj, wd);
1214 elm_widget_del_pre_hook_set(obj, _del_pre_hook);
1215 elm_widget_del_hook_set(obj, _del_hook);
1216 elm_widget_theme_hook_set(obj, _theme_hook);
1217 elm_widget_text_set_hook_set(obj, _text_set_hook);
1218 elm_widget_text_get_hook_set(obj, _text_get_hook);
1219 elm_widget_content_set_hook_set(obj, _content_set_hook);
1220 elm_widget_content_get_hook_set(obj, _content_get_hook);
1221 elm_widget_content_unset_hook_set(obj,_content_unset_hook);
1222 elm_widget_focus_next_hook_set(obj, _focus_next_hook);
1223 evas_object_smart_callbacks_descriptions_set(obj, _signals);
1225 wd->notify = elm_notify_add(obj);
1226 elm_widget_resize_object_set(obj, wd->notify);
1227 elm_notify_parent_set(wd->notify, parent);
1228 elm_notify_orient_set(wd->notify, ELM_NOTIFY_ORIENT_CENTER);
1229 elm_notify_allow_events_set(wd->notify, EINA_FALSE);
1230 evas_object_size_hint_weight_set(wd->notify,
1231 EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
1232 evas_object_size_hint_align_set(wd->notify, EVAS_HINT_FILL, EVAS_HINT_FILL);
1233 elm_object_style_set(wd->notify, "popup");
1235 evas_object_event_callback_add(wd->notify, EVAS_CALLBACK_RESIZE,
1236 _notify_resize, obj);
1237 evas_object_event_callback_add(obj, EVAS_CALLBACK_RESTACK, _restack, NULL);
1238 wd->base = elm_layout_add(obj);
1239 evas_object_size_hint_weight_set(wd->base, EVAS_HINT_EXPAND,
1241 evas_object_size_hint_align_set(wd->base, EVAS_HINT_FILL, EVAS_HINT_FILL);
1243 elm_layout_theme_set(wd->base, "popup", "base", elm_widget_style_get(obj));
1244 elm_object_content_set(wd->notify, wd->base);
1246 elm_object_signal_callback_add(wd->base, "elm,state,title_area,visible",
1247 "elm", _layout_change_cb, obj);
1248 elm_object_signal_callback_add(wd->base, "elm,state,title_area,hidden",
1249 "elm", _layout_change_cb, obj);
1250 elm_object_signal_callback_add(wd->base, "elm,state,action_area,visible",
1251 "elm", _layout_change_cb, obj);
1252 elm_object_signal_callback_add(wd->base, "elm,state,action_area,hidden",
1253 "elm", _layout_change_cb, obj);
1254 wd->content_area = elm_layout_add(obj);
1255 elm_layout_theme_set(wd->content_area, "popup", "content",
1256 elm_widget_style_get(obj));
1257 wd->action_area = elm_layout_add(obj);
1258 evas_object_size_hint_weight_set(wd->action_area, EVAS_HINT_EXPAND,
1260 evas_object_size_hint_align_set(wd->action_area, EVAS_HINT_FILL,
1262 evas_object_event_callback_add(wd->action_area,
1263 EVAS_CALLBACK_CHANGED_SIZE_HINTS,
1264 _changed_size_hints, obj);
1265 evas_object_event_callback_add(wd->content_area,
1266 EVAS_CALLBACK_CHANGED_SIZE_HINTS,
1267 _changed_size_hints, obj);
1268 evas_object_smart_callback_add(wd->base, "sub-object-del",
1270 evas_object_smart_callback_add(wd->content_area, "sub-object-del",
1272 evas_object_smart_callback_add(wd->action_area, "sub-object-del",
1274 evas_object_smart_callback_add(obj, "sub-object-del",
1277 wd->content_text_wrap_type = ELM_WRAP_MIXED;
1278 evas_object_smart_callback_add(wd->notify, "block,clicked",
1279 _block_clicked_cb, obj);
1280 evas_object_smart_callback_add(wd->notify, "timeout", _timeout, obj);
1281 for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
1282 wd->buttons[i] = NULL;
1284 //TODO: To use scroller for description also
1289 elm_popup_content_text_wrap_type_set(Evas_Object *obj, Elm_Wrap_Type wrap)
1291 ELM_CHECK_WIDTYPE(obj, widtype);
1292 Evas_Object *content_text_obj;
1293 Widget_Data *wd = elm_widget_data_get(obj);
1296 if (wd->content_text_wrap_type == ELM_WRAP_NONE) return;
1297 //Need to wrap the content text, so not allowing ELM_WRAP_NONE
1298 wd->content_text_wrap_type = wrap;
1299 if (wd->content_text_obj)
1301 content_text_obj = elm_object_part_content_get(wd->content_area,
1302 "elm.swallow.content");
1303 elm_label_line_wrap_set(content_text_obj, wrap);
1308 elm_popup_content_text_wrap_type_get(const Evas_Object *obj)
1310 ELM_CHECK_WIDTYPE(obj, widtype) ELM_WRAP_LAST;
1311 Widget_Data *wd = elm_widget_data_get(obj);
1313 if (!wd) return ELM_WRAP_LAST;
1314 return wd->content_text_wrap_type;
1318 elm_popup_orient_set(Evas_Object *obj, Elm_Popup_Orient orient)
1320 ELM_CHECK_WIDTYPE(obj, widtype);
1321 Widget_Data *wd = elm_widget_data_get(obj);
1324 if (orient >= ELM_POPUP_ORIENT_LAST) return;
1325 elm_notify_orient_set(wd->notify, (Elm_Notify_Orient)orient);
1328 EAPI Elm_Popup_Orient
1329 elm_popup_orient_get(const Evas_Object *obj)
1331 ELM_CHECK_WIDTYPE(obj, widtype) -1;
1332 Widget_Data *wd = elm_widget_data_get(obj);
1334 if (!wd) return ELM_POPUP_ORIENT_LAST;
1335 return (Elm_Popup_Orient)elm_notify_orient_get(wd->notify);
1339 elm_popup_timeout_set(Evas_Object *obj, double timeout)
1341 ELM_CHECK_WIDTYPE(obj, widtype);
1342 Widget_Data *wd = elm_widget_data_get(obj);
1345 elm_notify_timeout_set(wd->notify, timeout);
1349 elm_popup_timeout_get(const Evas_Object *obj)
1351 ELM_CHECK_WIDTYPE(obj, widtype) 0.0;
1352 Widget_Data *wd = elm_widget_data_get(obj);
1354 if (!wd) return 0.0;
1355 return elm_notify_timeout_get(wd->notify);
1359 elm_popup_allow_events_set(Evas_Object *obj, Eina_Bool allow)
1361 ELM_CHECK_WIDTYPE(obj, widtype);
1362 Eina_Bool allow_events = !!allow;
1363 Widget_Data *wd = elm_widget_data_get(obj);
1366 elm_notify_allow_events_set(wd->notify, allow_events);
1370 elm_popup_allow_events_get(const Evas_Object *obj)
1372 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1373 Widget_Data *wd = elm_widget_data_get(obj);
1375 if (!wd) return EINA_FALSE;
1376 return elm_notify_allow_events_get(wd->notify);
1379 EAPI Elm_Object_Item *
1380 elm_popup_item_append(Evas_Object *obj, const char *label,
1381 Evas_Object *icon, Evas_Smart_Cb func,
1384 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1385 Evas_Object *prev_content;
1386 Elm_Popup_Content_Item *item;
1387 Widget_Data *wd = elm_widget_data_get(obj);
1389 if (!wd) return NULL;
1390 item = elm_widget_item_new(obj, Elm_Popup_Content_Item);
1391 if (!item) return NULL;
1392 if (wd->content || wd->content_text_obj)
1394 prev_content = elm_object_part_content_get(wd->content_area,
1395 "elm.swallow.content");
1397 evas_object_del(prev_content);
1400 //The first item is appended.
1405 item->base.data = data;
1408 _item_icon_set(item, icon);
1409 _item_text_set(item, label);
1410 elm_box_pack_end(wd->box, VIEW(item));
1411 wd->items = eina_list_append(wd->items, item);
1413 _scroller_size_calc(obj);
1415 return (Elm_Object_Item *)item;