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_scale_set(wd->base, elm_widget_scale_get(obj) *
178 _elm_widget_mirrored_reload(obj);
179 _mirrored_set(obj, elm_widget_mirrored_get(obj));
180 if (wd->button_count)
182 snprintf(buf, sizeof(buf), "buttons%u", wd->button_count);
183 elm_layout_theme_set(wd->action_area, "popup", buf,
184 elm_widget_style_get(obj));
185 for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
187 if (!wd->buttons[i]) continue;
188 elm_object_style_set(wd->buttons[i]->btn, buf);
191 elm_layout_theme_set(wd->content_area, "popup", "content",
192 elm_widget_style_get(obj));
193 if (wd->content_text_obj)
195 snprintf(buf, sizeof(buf), "popup/%s", elm_widget_style_get(obj));
196 elm_object_style_set(wd->content_text_obj, buf);
200 EINA_LIST_FOREACH(wd->items, elist, item)
202 _elm_theme_object_set(obj, VIEW(item), "popup",
203 "item", elm_widget_style_get(obj));
206 edje_object_part_text_set(VIEW(item), "elm.text",
208 edje_object_signal_emit(VIEW(item),
209 "elm,state,item,text,visible", "elm");
212 edje_object_signal_emit(VIEW(item),
213 "elm,state,item,icon,visible", "elm");
215 edje_object_signal_emit(VIEW(item),
216 "elm,state,item,disabled", "elm");
217 evas_object_show(VIEW(item));
218 edje_object_message_signal_process(VIEW(item));
220 _scroller_size_calc(obj);
224 elm_object_part_text_set(wd->base, "elm.text.title", wd->title_text);
225 elm_object_signal_emit(wd->base, "elm,state,title,text,visible", "elm");
228 elm_object_signal_emit(wd->base, "elm,state,title,icon,visible", "elm");
230 edje_object_message_signal_process(elm_layout_edje_get(wd->base));
235 _item_sizing_eval(Elm_Popup_Content_Item *item)
237 Evas_Coord min_w = -1, min_h = -1, max_w = -1, max_h = -1;
239 edje_object_size_min_restricted_calc(VIEW(item), &min_w, &min_h, min_w,
241 evas_object_size_hint_min_set(VIEW(item), min_w, min_h);
242 evas_object_size_hint_max_set(VIEW(item), max_w, max_h);
246 _sizing_eval(Evas_Object *obj)
249 Elm_Popup_Content_Item *item;
250 Evas_Coord w_box = 0, h_box = 0;
251 Evas_Coord minw_box = 0, minh_box = 0;
252 Evas_Coord minw = -1, minh = -1, maxw = -1, maxh = -1;
253 Widget_Data *wd = elm_widget_data_get(obj);
258 EINA_LIST_FOREACH(wd->items, elist, item)
260 _item_sizing_eval(item);
261 evas_object_size_hint_min_get(VIEW(item), &minw_box,
263 if (minw_box > w_box)
268 evas_object_size_hint_min_set(wd->box, w_box, h_box);
269 evas_object_size_hint_min_set(wd->scr, w_box, MIN(h_box, wd->max_sc_h));
270 evas_object_size_hint_max_set(wd->scr, w_box, wd->max_sc_h);
271 evas_object_smart_calculate(wd->scr);
273 edje_object_size_min_calc(elm_layout_edje_get(wd->base), &minw, &minh);
274 evas_object_size_hint_min_set(wd->base, minw, minh);
275 evas_object_size_hint_max_set(wd->base, maxw, maxh);
276 evas_object_size_hint_min_set(obj, minw, minh);
277 evas_object_size_hint_max_set(obj, maxw, maxh);
278 elm_layout_sizing_eval(wd->base);
282 _changed_size_hints(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__,
283 void *event_info __UNUSED__)
289 _sub_del(void *data, Evas_Object *obj, void *event_info)
291 Elm_Popup_Content_Item *item;
293 Evas_Object *sub = event_info;
294 Widget_Data *wd = elm_widget_data_get(data);
299 if ((item = evas_object_data_get(sub, "_popup_content_item")) != NULL)
301 if (sub == item->icon)
303 edje_object_part_unswallow(VIEW(item), sub);
304 edje_object_signal_emit(VIEW(item),
305 "elm,state,item,icon,hidden", "elm");
310 else if (obj == wd->content_area)
312 if (sub == wd->content)
315 elm_object_part_content_unset(wd->base, "elm.swallow.content");
318 else if (sub == wd->content_text_obj)
320 wd->content_text_obj = NULL;
321 elm_object_part_content_unset(wd->base, "elm.swallow.content");
324 else if (sub == wd->scr)
328 elm_object_part_content_unset(wd->base, "elm.swallow.content");
332 else if (obj == wd->action_area)
334 for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
336 if (wd->buttons[i] && sub == wd->buttons[i]->btn &&
337 wd->buttons[i]->delete_me == EINA_TRUE)
339 _button_remove(data, sub, EINA_FALSE);
344 else if (obj == wd->base)
346 if (sub == wd->title_icon)
348 elm_object_signal_emit(wd->base, "elm,state,title,icon,hidden",
350 edje_object_message_signal_process(wd->base);
351 wd->title_icon = NULL;
357 _block_clicked_cb(void *data, Evas_Object *obj __UNUSED__,
358 void *event_info __UNUSED__)
360 Widget_Data *wd = elm_widget_data_get(data);
363 evas_object_smart_callback_call(data, SIG_BLOCK_CLICKED, NULL);
367 _timeout(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
369 evas_object_hide(data);
370 evas_object_smart_callback_call(data, SIG_TIMEOUT, NULL);
374 _mirrored_set(Evas_Object *obj, Eina_Bool rtl)
377 Elm_Popup_Content_Item *item;
378 Widget_Data *wd = elm_widget_data_get(obj);
381 elm_object_mirrored_set(wd->notify, rtl);
383 EINA_LIST_FOREACH(wd->items, elist, item)
384 edje_object_mirrored_set(VIEW(item), rtl);
388 _layout_change_cb(void *data, Evas_Object *obj __UNUSED__,
389 const char *emission __UNUSED__,
390 const char *source __UNUSED__)
392 Widget_Data *wd = elm_widget_data_get((Evas_Object*)data);
396 elm_layout_sizing_eval(wd->base);
400 _restack(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj,
401 void *event_info __UNUSED__)
403 Widget_Data *wd = elm_widget_data_get(obj);
406 evas_object_layer_set(wd->notify, evas_object_layer_get(obj));
410 _scroller_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj,
411 void *event_info __UNUSED__)
414 Widget_Data *wd = elm_widget_data_get(data);
416 if (!wd || wd->scr_size_recalc) return;
417 evas_object_geometry_get(obj, NULL, NULL, &w, &h);
420 if ((w <= wd->max_sc_w) && (h <= wd->max_sc_h))
423 wd->scr_size_recalc = EINA_TRUE;
427 if (wd->max_sc_w < w)
429 if (wd->max_sc_h < h)
435 _list_new(Evas_Object *obj)
437 Widget_Data *wd = elm_widget_data_get(obj);
441 wd->scr = elm_scroller_add(obj);
442 elm_scroller_bounce_set(wd->scr, EINA_FALSE, EINA_TRUE);
443 elm_object_content_set(wd->scr, wd->box);
444 evas_object_size_hint_weight_set(wd->scr, EVAS_HINT_EXPAND,
446 evas_object_size_hint_align_set(wd->scr, EVAS_HINT_FILL, EVAS_HINT_FILL);
447 evas_object_event_callback_add(wd->scr, EVAS_CALLBACK_RESIZE,
448 _scroller_resize, obj);
449 evas_object_event_callback_add(wd->scr,
450 EVAS_CALLBACK_CHANGED_SIZE_HINTS,
451 _changed_size_hints, obj);
452 elm_object_part_content_set(wd->base, "elm.swallow.content", wd->scr);
455 wd->box = elm_box_add(obj);
456 evas_object_size_hint_weight_set(wd->box, EVAS_HINT_EXPAND,
458 evas_object_size_hint_align_set(wd->box, EVAS_HINT_FILL, EVAS_HINT_FILL);
460 elm_object_content_set(wd->scr, wd->box);
464 _list_del(Widget_Data *wd)
466 if (!wd->scr) return;
467 elm_object_part_content_unset(wd->base, "elm.swallow.content");
468 evas_object_event_callback_del(wd->scr, EVAS_CALLBACK_RESIZE,
470 evas_object_event_callback_del(wd->scr, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
471 _changed_size_hints);
472 evas_object_del(wd->scr);
478 _scroller_size_calc(Evas_Object *obj)
481 Evas_Coord h_title = 0;
482 Evas_Coord h_action_area = 0;
483 Evas_Coord h_content = 0;
484 const char *action_area_height;
485 Widget_Data *wd = elm_widget_data_get(obj);
487 if (!wd || !wd->items) return;
488 wd->scr_size_recalc = EINA_FALSE;
491 evas_object_geometry_get(wd->notify, NULL, NULL, NULL, &h);
492 if (wd->title_text || wd->title_icon)
493 edje_object_part_geometry_get(elm_layout_edje_get(wd->base),
494 "elm.bg.title", NULL, NULL, NULL, &h_title);
495 if (wd->button_count)
497 action_area_height = edje_object_data_get(
498 elm_layout_edje_get(wd->action_area), "action_area_height");
499 if (action_area_height) h_action_area = (int)(atoi(action_area_height)
500 * _elm_config->scale * elm_object_scale_get(obj));
502 h_content = h - (h_title + h_action_area);
503 wd->max_sc_h = h_content;
507 _item_select_cb(void *data, Evas_Object *obj __UNUSED__,
508 const char *emission __UNUSED__, const char *source __UNUSED__)
510 Elm_Popup_Content_Item *item = data;
512 if (!item || item->disabled) return;
514 item->func((void*)item->base.data, WIDGET(item), data);
518 _item_new(Elm_Popup_Content_Item *item)
520 Widget_Data *wd = elm_widget_data_get(WIDGET(item));
523 elm_widget_item_text_set_hook_set(item, _item_text_set_hook);
524 elm_widget_item_text_get_hook_set(item, _item_text_get_hook);
525 elm_widget_item_content_set_hook_set(item, _item_content_set_hook);
526 elm_widget_item_content_get_hook_set(item, _item_content_get_hook);
527 elm_widget_item_content_unset_hook_set(item, _item_content_unset_hook);
528 elm_widget_item_disable_hook_set(item, _item_disable_hook);
529 elm_widget_item_del_pre_hook_set(item, _item_del_pre_hook);
530 elm_widget_item_signal_emit_hook_set(item, _item_signal_emit_hook);
531 VIEW(item) = edje_object_add(evas_object_evas_get(wd->base));
532 _elm_theme_object_set(WIDGET(item), VIEW(item), "popup", "item",
533 elm_widget_style_get(WIDGET(item)));
534 edje_object_mirrored_set(VIEW(item), elm_widget_mirrored_get(WIDGET(item)));
535 edje_object_signal_callback_add(VIEW(item), "elm,action,click", "",
536 _item_select_cb, item);
537 evas_object_size_hint_align_set(VIEW(item), EVAS_HINT_FILL,
539 evas_object_show(VIEW(item));
543 _remove_items(Widget_Data *wd)
546 Elm_Popup_Content_Item *item;
548 if (!wd->items) return;
549 EINA_LIST_FOREACH(wd->items, elist, item)
552 eina_stringshare_del(item->label);
555 evas_object_del(item->icon);
558 evas_object_del(VIEW(item));
559 wd->items = eina_list_remove(wd->items, item);
566 _notify_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__,
567 void *event_info __UNUSED__)
569 Widget_Data *wd = elm_widget_data_get(data);
572 _scroller_size_calc(data);
577 _title_text_set(Evas_Object *obj, const char *text)
579 ELM_CHECK_WIDTYPE(obj, widtype);
580 Eina_Bool title_visibility_old, title_visibility_current;
581 Widget_Data *wd = elm_widget_data_get(obj);
584 if (wd->title_text == text) return;
585 title_visibility_old = (wd->title_text) || (wd->title_icon);
586 eina_stringshare_replace(&wd->title_text, text);
587 elm_object_part_text_set(wd->base, "elm.text.title", text);
589 elm_object_signal_emit(wd->base, "elm,state,title,text,visible", "elm");
591 elm_object_signal_emit(wd->base, "elm,state,title,text,hidden", "elm");
592 title_visibility_current = (wd->title_text) || (wd->title_icon);
593 if (title_visibility_old != title_visibility_current)
595 edje_object_message_signal_process(wd->base);
600 _content_text_set(Evas_Object *obj, const char *text)
602 ELM_CHECK_WIDTYPE(obj, widtype);
603 Evas_Object *prev_content;
605 Widget_Data *wd = elm_widget_data_get(obj);
613 prev_content = elm_object_part_content_get(wd->content_area,
614 "elm.swallow.content");
616 evas_object_del(prev_content);
619 elm_object_part_content_set(wd->base, "elm.swallow.content",
621 wd->content_text_obj = elm_label_add(obj);
622 snprintf(buf, sizeof(buf), "popup/%s",
623 elm_widget_style_get(obj));
624 elm_object_style_set(wd->content_text_obj, buf);
625 elm_label_line_wrap_set(wd->content_text_obj,
626 wd->content_text_wrap_type);
627 elm_object_text_set(wd->content_text_obj, text);
628 evas_object_size_hint_weight_set(wd->content_text_obj, EVAS_HINT_EXPAND,
630 evas_object_size_hint_align_set(wd->content_text_obj, EVAS_HINT_FILL,
632 elm_object_part_content_set(wd->content_area, "elm.swallow.content",
633 wd->content_text_obj);
639 _text_set_hook(Evas_Object *obj, const char *part,
642 ELM_CHECK_WIDTYPE(obj, widtype);
643 Widget_Data *wd = elm_widget_data_get(obj);
646 if (!part || !strcmp(part, "default"))
647 _content_text_set(obj, label);
648 else if (!strcmp(part, "title,text"))
649 _title_text_set(obj, label);
651 WRN("The part name is invalid! : popup=%p", obj);
655 _title_text_get(const Evas_Object *obj)
657 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
658 Widget_Data *wd = elm_widget_data_get(obj);
660 if (!wd) return NULL;
661 return wd->title_text;
665 _content_text_get(const Evas_Object *obj)
667 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
668 const char *str = NULL;
669 Widget_Data *wd = elm_widget_data_get(obj);
671 if (!wd) return NULL;
672 if (wd->content_text_obj)
673 str = elm_object_text_get(wd->content_text_obj);
678 _text_get_hook(const Evas_Object *obj, const char *part)
680 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
681 const char *str = NULL;
682 Widget_Data *wd = elm_widget_data_get(obj);
684 if (!wd) return NULL;
685 if (!part || !strcmp(part, "default"))
686 str = _content_text_get(obj);
687 else if (!strcmp(part, "title,text"))
688 str = _title_text_get(obj);
690 WRN("The part name is invalid! : popup=%p", obj);
695 _title_icon_set(Evas_Object *obj, Evas_Object *icon)
697 ELM_CHECK_WIDTYPE(obj, widtype);
698 Eina_Bool title_visibility_old, title_visibility_current;
699 Widget_Data *wd = elm_widget_data_get(obj);
702 if (wd->title_icon == icon) return;
703 title_visibility_old = (wd->title_text) || (wd->title_icon);
706 evas_object_del(wd->title_icon);
707 wd->title_icon = NULL;
709 wd->title_icon = icon;
710 title_visibility_current = (wd->title_text) || (wd->title_icon);
711 elm_object_part_content_set(wd->base, "elm.swallow.title.icon",
714 elm_object_signal_emit(wd->base, "elm,state,title,icon,visible", "elm");
715 if (title_visibility_old != title_visibility_current) _layout_set(obj);
716 edje_object_message_signal_process(wd->base);
721 _content_set(Evas_Object *obj, Evas_Object *content)
723 ELM_CHECK_WIDTYPE(obj, widtype);
724 Evas_Object *prev_content;
725 Widget_Data *wd = elm_widget_data_get(obj);
728 if (wd->content && wd->content == content) return;
734 prev_content = elm_object_part_content_get(wd->content_area,
735 "elm.swallow.content");
737 evas_object_del(prev_content);
738 wd->content = content;
741 elm_object_part_content_set(wd->base, "elm.swallow.content",
743 elm_object_part_content_set(wd->content_area, "elm.swallow.content",
750 _button_remove(Evas_Object *obj, Evas_Object *content, Eina_Bool delete)
752 unsigned int i = 0, position = 0;
754 Widget_Data *wd = elm_widget_data_get(obj);
756 if (!wd->button_count) return;
757 for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
762 wd->buttons[i]->delete_me = EINA_FALSE;
763 if (wd->buttons[i]->btn == content)
765 snprintf(buf, sizeof(buf), "actionbtn%u", position);
766 elm_object_part_content_unset(wd->action_area, buf);
767 evas_object_hide(content);
768 if (delete) evas_object_del(content);
769 free(wd->buttons[i]);
770 wd->buttons[i] = NULL;
771 wd->button_count -= 1;
776 for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
778 if (!wd->buttons[i]) continue;
780 snprintf(buf, sizeof(buf), "actionbtn%u", position);
781 elm_object_part_content_unset(wd->action_area, buf);
782 elm_object_part_content_set(wd->action_area, buf,
783 wd->buttons[i]->btn);
784 wd->buttons[i]->delete_me = EINA_TRUE;
786 if (!wd->button_count)
789 edje_object_message_signal_process(elm_layout_edje_get(wd->base));
793 snprintf(buf, sizeof(buf), "buttons%u", wd->button_count);
794 elm_layout_theme_set(wd->action_area, "popup", buf,
795 elm_widget_style_get(obj));
800 _action_button_set(Evas_Object *obj, Evas_Object *btn, unsigned int idx)
802 Action_Area_Data *adata;
804 unsigned int index = idx - 1, i = 0, position = 0;
805 Widget_Data *wd = elm_widget_data_get(obj);
808 if (index >= ELM_POPUP_ACTION_BUTTON_MAX) return;
809 if (wd->buttons[index])
810 _button_remove(obj, wd->buttons[index]->btn, EINA_TRUE);
814 snprintf(buf, sizeof(buf), "buttons%u", wd->button_count);
815 elm_layout_theme_set(wd->action_area, "popup", buf,
816 elm_widget_style_get(obj));
817 adata = ELM_NEW(Action_Area_Data);
820 wd->buttons[index] = adata;
821 /* Adding delete_me state inside action data as unset calls _sub_del
822 too and before setting a new content, the previous one needs to
823 be unset in order to avoid unwanted deletion. This way rearrangement
824 of buttons can be achieved in action area.
826 for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
828 wd->buttons[i]->delete_me = EINA_FALSE;
829 for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
831 if (!wd->buttons[i]) continue;
833 snprintf(buf, sizeof(buf), "actionbtn%u", position);
834 elm_object_part_content_unset(wd->action_area, buf);
835 elm_object_part_content_set(wd->action_area, buf,
836 wd->buttons[i]->btn);
837 /* Setting delete_me to TRUE in order to let _sub_del handle it
838 if deleted externally and update the buttons array after freeing
839 action data allocated earlier.
841 wd->buttons[i]->delete_me = EINA_TRUE;
843 elm_object_part_content_set(wd->base, "elm.swallow.action_area",
845 if (wd->button_count == 1)
847 edje_object_message_signal_process(wd->base);
849 _scroller_size_calc(obj);
855 _content_set_hook(Evas_Object *obj, const char *part,
856 Evas_Object *content)
858 ELM_CHECK_WIDTYPE(obj, widtype);
861 Widget_Data *wd = elm_widget_data_get(obj);
864 if (!part || !strcmp(part, "default"))
865 _content_set(obj, content);
866 else if (!strcmp(part, "title,icon"))
867 _title_icon_set(obj, content);
868 else if (!strncmp(part, "button", 6))
871 for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
873 snprintf(buff, sizeof(buff), "%u", i+1);
874 if (!strncmp(part, buff, sizeof(buff)))
876 _action_button_set(obj, content, i+1);
882 WRN("The part name is invalid! : popup=%p", obj);
886 _title_icon_get(Evas_Object *obj)
888 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
889 Widget_Data *wd = elm_widget_data_get(obj);
891 if (!wd) return NULL;
892 return wd->title_icon;
896 _content_get(Evas_Object *obj)
898 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
899 Widget_Data *wd = elm_widget_data_get(obj);
901 if (!wd) return NULL;
906 _action_button_get(Evas_Object *obj, unsigned int idx)
908 unsigned int index = idx - 1;
909 Evas_Object *button = NULL;
910 Widget_Data *wd = elm_widget_data_get(obj);
912 if (!wd || !wd->button_count) return NULL;
913 if (wd->buttons[index])
914 button = wd->buttons[index]->btn;
919 _content_get_hook(Evas_Object *obj, const char *part)
921 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
922 Evas_Object *content = NULL;
925 Widget_Data *wd = elm_widget_data_get(obj);
927 if (!wd) return NULL;
928 if (!part || !strcmp(part, "default"))
929 content = _content_get(obj);
930 else if (!strcmp(part, "title,text"))
931 content = _title_icon_get(obj);
932 else if (!strncmp(part, "button", 6))
935 for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
937 snprintf(buff, sizeof(buff), "%u", i+1);
938 if (!strncmp(part, buff, sizeof(buff)))
940 content = _action_button_get(obj, i+1);
946 WRN("The part name is invalid! : popup=%p", obj);
951 _content_unset(Evas_Object *obj)
953 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
954 Evas_Object *content;
955 Widget_Data *wd = elm_widget_data_get(obj);
957 if (!wd || !wd->content) return NULL;
958 content = elm_object_part_content_unset(wd->content_area,
959 "elm.swallow.content");
966 _title_icon_unset(Evas_Object *obj)
968 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
970 Widget_Data *wd = elm_widget_data_get(obj);
972 if (!wd || !wd->title_icon) return NULL;
973 icon = elm_object_part_content_unset(wd->base, "elm.swallow.title.icon");
974 wd->title_icon = NULL;
979 _action_button_unset(Evas_Object *obj, unsigned int idx)
981 unsigned int index = idx -1;
982 Evas_Object *button = NULL;
983 Widget_Data *wd = elm_widget_data_get(obj);
985 if (!wd) return NULL;
986 if ((!wd->button_count) || (index >= ELM_POPUP_ACTION_BUTTON_MAX))
989 if (wd->buttons[index])
991 button = wd->buttons[index]->btn;
992 _button_remove(obj, button, EINA_FALSE);
998 _content_unset_hook(Evas_Object *obj, const char *part)
1000 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1001 Evas_Object *content = NULL;
1004 Widget_Data *wd = elm_widget_data_get(obj);
1006 if (!wd) return NULL;
1007 if (!part || !strcmp(part, "default"))
1008 content = _content_unset(obj);
1009 else if (!strcmp(part, "title,icon"))
1010 content = _title_icon_unset(obj);
1011 else if (!strncmp(part, "button", 6))
1014 for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
1016 snprintf(buff, sizeof(buff), "%u", i+1);
1017 if (!strncmp(part, buff, sizeof(buff)))
1019 content = _action_button_unset(obj, i+1);
1025 WRN("The part name is invalid! : popup=%p", obj);
1030 _focus_next_hook(const Evas_Object *obj __UNUSED__,
1031 Elm_Focus_Direction dir __UNUSED__,
1032 Evas_Object **next __UNUSED__)
1034 //TODO: Implement Focus chanin Handling in Popup for action area buttons
1038 _item_text_set(Elm_Popup_Content_Item *item, const char *label)
1040 if (!eina_stringshare_replace(&item->label, label)) return;
1041 edje_object_part_text_set(VIEW(item), "elm.text", label);
1043 edje_object_signal_emit(VIEW(item),
1044 "elm,state,item,text,visible", "elm");
1046 edje_object_signal_emit(VIEW(item),
1047 "elm,state,item,text,hidden", "elm");
1048 edje_object_message_signal_process(VIEW(item));
1052 _item_text_set_hook(Elm_Object_Item *it, const char *part, const char *label)
1054 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1055 Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1057 if ((!part) || (!strcmp(part, "default")))
1059 _item_text_set(item, label);
1062 WRN("The part name is invalid! : popup=%p", WIDGET(item));
1066 _item_text_get_hook(const Elm_Object_Item *it, const char *part)
1068 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
1069 Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1071 if ((!part) || (!strcmp(part, "default")))
1073 WRN("The part name is invalid! : popup=%p", WIDGET(item));
1078 _item_icon_set(Elm_Popup_Content_Item *item, Evas_Object *icon)
1080 if (item->icon == icon) return;
1083 elm_widget_sub_object_del(WIDGET(item), item->icon);
1084 evas_object_data_del(item->icon, "_popup_content_item");
1085 evas_object_del(item->icon);
1090 elm_widget_sub_object_add(WIDGET(item), item->icon);
1091 evas_object_data_set(item->icon, "_popup_content_item", item);
1092 edje_object_part_swallow(VIEW(item), "elm.swallow.content",
1094 edje_object_signal_emit(VIEW(item),
1095 "elm,state,item,icon,visible", "elm");
1098 edje_object_signal_emit(VIEW(item),
1099 "elm,state,item,icon,hidden", "elm");
1100 edje_object_message_signal_process(item->base.view);
1104 _item_content_set_hook(Elm_Object_Item *it, const char *part,
1105 Evas_Object *content)
1107 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1108 Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1110 if ((!(part)) || (!strcmp(part, "default")))
1111 _item_icon_set(item, content);
1113 WRN("The part name is invalid! : popup=%p", WIDGET(item));
1116 static Evas_Object *
1117 _item_content_get_hook(const Elm_Object_Item *it,
1120 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
1121 Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1123 if ((!(part)) || (!strcmp(part, "default")))
1125 WRN("The part name is invalid! : popup=%p", WIDGET(item));
1129 static Evas_Object *
1130 _item_icon_unset(Elm_Popup_Content_Item *item)
1132 Evas_Object *icon = item->icon;
1134 if (!item->icon) return NULL;
1135 elm_widget_sub_object_del(WIDGET(item), icon);
1136 evas_object_data_del(icon, "_popup_content_item");
1137 edje_object_part_unswallow(item->base.view, icon);
1138 edje_object_signal_emit(VIEW(item),
1139 "elm,state,item,icon,hidden", "elm");
1144 static Evas_Object *
1145 _item_content_unset_hook(const Elm_Object_Item *it,
1148 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
1149 Evas_Object *content = NULL;
1150 Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1152 if ((!(part)) || (!strcmp(part, "default")))
1153 content = _item_icon_unset(item);
1155 WRN("The part name is invalid! : popup=%p", WIDGET(item));
1160 _item_disable_hook(Elm_Object_Item *it)
1162 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1163 Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1164 Widget_Data *wd = elm_widget_data_get(WIDGET(item));
1167 if (elm_widget_item_disabled_get(it))
1168 edje_object_signal_emit(VIEW(item), "elm,state,item,disabled", "elm");
1170 edje_object_signal_emit(VIEW(item), "elm,state,item,enabled", "elm");
1174 _item_del_pre_hook(Elm_Object_Item *it)
1176 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1177 Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1178 Widget_Data *wd = elm_widget_data_get(WIDGET(item));
1182 evas_object_del(item->icon);
1183 eina_stringshare_del(item->label);
1184 wd->items = eina_list_remove(wd->items, item);
1185 if (!eina_list_count(wd->items))
1193 _item_signal_emit_hook(Elm_Object_Item *it, const char *emission,
1196 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1197 Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1199 edje_object_signal_emit(VIEW(item), emission, source);
1203 elm_popup_add(Evas_Object *parent)
1210 ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
1211 ELM_SET_WIDTYPE(widtype, "popup");
1212 elm_widget_type_set(obj, widtype);
1213 elm_widget_sub_object_add(parent, obj);
1214 elm_widget_data_set(obj, wd);
1215 elm_widget_del_pre_hook_set(obj, _del_pre_hook);
1216 elm_widget_del_hook_set(obj, _del_hook);
1217 elm_widget_theme_hook_set(obj, _theme_hook);
1218 elm_widget_text_set_hook_set(obj, _text_set_hook);
1219 elm_widget_text_get_hook_set(obj, _text_get_hook);
1220 elm_widget_content_set_hook_set(obj, _content_set_hook);
1221 elm_widget_content_get_hook_set(obj, _content_get_hook);
1222 elm_widget_content_unset_hook_set(obj,_content_unset_hook);
1223 elm_widget_focus_next_hook_set(obj, _focus_next_hook);
1224 evas_object_smart_callbacks_descriptions_set(obj, _signals);
1226 wd->notify = elm_notify_add(obj);
1227 elm_widget_resize_object_set(obj, wd->notify);
1228 elm_notify_parent_set(wd->notify, parent);
1229 elm_notify_orient_set(wd->notify, ELM_NOTIFY_ORIENT_CENTER);
1230 elm_notify_allow_events_set(wd->notify, EINA_FALSE);
1231 evas_object_size_hint_weight_set(wd->notify,
1232 EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
1233 evas_object_size_hint_align_set(wd->notify, EVAS_HINT_FILL, EVAS_HINT_FILL);
1234 elm_object_style_set(wd->notify, "popup");
1236 evas_object_event_callback_add(wd->notify, EVAS_CALLBACK_RESIZE,
1237 _notify_resize, obj);
1238 evas_object_event_callback_add(obj, EVAS_CALLBACK_RESTACK, _restack, NULL);
1239 wd->base = elm_layout_add(obj);
1240 evas_object_size_hint_weight_set(wd->base, EVAS_HINT_EXPAND,
1242 evas_object_size_hint_align_set(wd->base, EVAS_HINT_FILL, EVAS_HINT_FILL);
1244 elm_layout_theme_set(wd->base, "popup", "base", elm_widget_style_get(obj));
1245 elm_object_content_set(wd->notify, wd->base);
1247 elm_object_signal_callback_add(wd->base, "elm,state,title_area,visible",
1248 "elm", _layout_change_cb, obj);
1249 elm_object_signal_callback_add(wd->base, "elm,state,title_area,hidden",
1250 "elm", _layout_change_cb, obj);
1251 elm_object_signal_callback_add(wd->base, "elm,state,action_area,visible",
1252 "elm", _layout_change_cb, obj);
1253 elm_object_signal_callback_add(wd->base, "elm,state,action_area,hidden",
1254 "elm", _layout_change_cb, obj);
1255 wd->content_area = elm_layout_add(obj);
1256 elm_layout_theme_set(wd->content_area, "popup", "content",
1257 elm_widget_style_get(obj));
1258 wd->action_area = elm_layout_add(obj);
1259 evas_object_size_hint_weight_set(wd->action_area, EVAS_HINT_EXPAND,
1261 evas_object_size_hint_align_set(wd->action_area, EVAS_HINT_FILL,
1263 evas_object_event_callback_add(wd->action_area,
1264 EVAS_CALLBACK_CHANGED_SIZE_HINTS,
1265 _changed_size_hints, obj);
1266 evas_object_event_callback_add(wd->content_area,
1267 EVAS_CALLBACK_CHANGED_SIZE_HINTS,
1268 _changed_size_hints, obj);
1269 evas_object_smart_callback_add(wd->base, "sub-object-del",
1271 evas_object_smart_callback_add(wd->content_area, "sub-object-del",
1273 evas_object_smart_callback_add(wd->action_area, "sub-object-del",
1275 evas_object_smart_callback_add(obj, "sub-object-del",
1278 wd->content_text_wrap_type = ELM_WRAP_MIXED;
1279 evas_object_smart_callback_add(wd->notify, "block,clicked",
1280 _block_clicked_cb, obj);
1281 evas_object_smart_callback_add(wd->notify, "timeout", _timeout, obj);
1282 for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
1283 wd->buttons[i] = NULL;
1285 //TODO: To use scroller for description also
1290 elm_popup_content_text_wrap_type_set(Evas_Object *obj, Elm_Wrap_Type wrap)
1292 ELM_CHECK_WIDTYPE(obj, widtype);
1293 Evas_Object *content_text_obj;
1294 Widget_Data *wd = elm_widget_data_get(obj);
1297 if (wd->content_text_wrap_type == ELM_WRAP_NONE) return;
1298 //Need to wrap the content text, so not allowing ELM_WRAP_NONE
1299 wd->content_text_wrap_type = wrap;
1300 if (wd->content_text_obj)
1302 content_text_obj = elm_object_part_content_get(wd->content_area,
1303 "elm.swallow.content");
1304 elm_label_line_wrap_set(content_text_obj, wrap);
1309 elm_popup_content_text_wrap_type_get(Evas_Object *obj)
1311 ELM_CHECK_WIDTYPE(obj, widtype) ELM_WRAP_LAST;
1312 Widget_Data *wd = elm_widget_data_get(obj);
1314 if (!wd) return ELM_WRAP_LAST;
1315 return wd->content_text_wrap_type;
1319 elm_popup_orient_set(Evas_Object *obj, Elm_Popup_Orient orient)
1321 ELM_CHECK_WIDTYPE(obj, widtype);
1322 Widget_Data *wd = elm_widget_data_get(obj);
1325 if (orient >= ELM_POPUP_ORIENT_LAST) return;
1326 elm_notify_orient_set(wd->notify, (Elm_Notify_Orient)orient);
1329 EAPI Elm_Popup_Orient
1330 elm_popup_orient_get(Evas_Object *obj)
1332 ELM_CHECK_WIDTYPE(obj, widtype) -1;
1333 Widget_Data *wd = elm_widget_data_get(obj);
1335 if (!wd) return ELM_POPUP_ORIENT_LAST;
1336 return (Elm_Popup_Orient)elm_notify_orient_get(wd->notify);
1340 elm_popup_timeout_set(Evas_Object *obj, double timeout)
1342 ELM_CHECK_WIDTYPE(obj, widtype);
1343 Widget_Data *wd = elm_widget_data_get(obj);
1346 elm_notify_timeout_set(wd->notify, timeout);
1350 elm_popup_timeout_get(Evas_Object *obj)
1352 ELM_CHECK_WIDTYPE(obj, widtype) 0.0;
1353 Widget_Data *wd = elm_widget_data_get(obj);
1355 if (!wd) return 0.0;
1356 return elm_notify_timeout_get(wd->notify);
1360 elm_popup_allow_events_set(Evas_Object *obj, Eina_Bool allow)
1362 ELM_CHECK_WIDTYPE(obj, widtype);
1363 Eina_Bool allow_events = !!allow;
1364 Widget_Data *wd = elm_widget_data_get(obj);
1367 elm_notify_allow_events_set(wd->notify, allow_events);
1371 elm_popup_allow_events_get(Evas_Object *obj)
1373 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1374 Widget_Data *wd = elm_widget_data_get(obj);
1376 if (!wd) return EINA_FALSE;
1377 return elm_notify_allow_events_get(wd->notify);
1380 EAPI Elm_Object_Item *
1381 elm_popup_item_append(Evas_Object *obj, const char *label,
1382 Evas_Object *icon, Evas_Smart_Cb func,
1385 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1386 Evas_Object *prev_content;
1387 Elm_Popup_Content_Item *item;
1388 Widget_Data *wd = elm_widget_data_get(obj);
1390 if (!wd) return NULL;
1391 item = elm_widget_item_new(obj, Elm_Popup_Content_Item);
1392 if (!item) return NULL;
1393 if (wd->content || wd->content_text_obj)
1395 prev_content = elm_object_part_content_get(wd->content_area,
1396 "elm.swallow.content");
1398 evas_object_del(prev_content);
1401 //The first item is appended.
1406 item->base.data = data;
1409 _item_icon_set(item, icon);
1410 _item_text_set(item, label);
1411 elm_box_pack_end(wd->box, VIEW(item));
1412 wd->items = eina_list_append(wd->items, item);
1414 _scroller_size_calc(obj);
1416 return (Elm_Object_Item *)item;