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 void _popup_show(void *data, Evas *e, Evas_Object *obj,
103 static const char SIG_BLOCK_CLICKED[] = "block,clicked";
104 static const char SIG_TIMEOUT[] = "timeout";
105 static const Evas_Smart_Cb_Description _signals[] = {
106 {SIG_BLOCK_CLICKED, ""},
111 #define ELM_POPUP_CONTENT_ITEM_CHECK_RETURN(it, ...) \
112 ELM_WIDGET_ITEM_CHECK_OR_RETURN((Elm_Widget_Item *)it, __VA_ARGS__); \
113 ELM_CHECK_WIDTYPE(WIDGET(item), widtype) __VA_ARGS__;
116 _layout_set(Evas_Object *obj)
118 Widget_Data *wd = elm_widget_data_get(obj);
121 if ((!(wd->title_text)) && (!(wd->title_icon)))
122 elm_object_signal_emit(wd->base, "elm,state,title_area,hidden", "elm");
124 elm_object_signal_emit(wd->base, "elm,state,title_area,visible", "elm");
125 if (wd->button_count)
126 elm_object_signal_emit(wd->base, "elm,state,action_area,visible", "elm");
128 elm_object_signal_emit(wd->base, "elm,state,action_area,hidden", "elm");
132 _del_hook(Evas_Object *obj)
134 Widget_Data *wd = elm_widget_data_get(obj);
141 _del_pre_hook(Evas_Object *obj)
144 Widget_Data *wd = elm_widget_data_get(obj);
147 evas_object_smart_callback_del(wd->notify, "block,clicked",
149 evas_object_smart_callback_del(wd->notify, "timeout", _timeout);
150 evas_object_event_callback_del(wd->notify, EVAS_CALLBACK_RESIZE,
152 evas_object_event_callback_del(obj, EVAS_CALLBACK_SHOW, _popup_show);
153 wd->button_count = 0;
154 for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
157 evas_object_del(wd->buttons[i]->btn);
158 free(wd->buttons[i]);
159 wd->buttons[i] = NULL;
169 _theme_hook(Evas_Object *obj)
172 Elm_Popup_Content_Item *item;
175 Widget_Data *wd = elm_widget_data_get(obj);
178 elm_layout_theme_set(wd->base, "popup", "base", elm_widget_style_get(obj));
179 _elm_widget_mirrored_reload(obj);
180 _mirrored_set(obj, elm_widget_mirrored_get(obj));
181 if (wd->button_count)
183 snprintf(buf, sizeof(buf), "buttons%u", wd->button_count);
184 elm_layout_theme_set(wd->action_area, "popup", buf,
185 elm_widget_style_get(obj));
186 for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
188 if (!wd->buttons[i]) continue;
189 elm_object_style_set(wd->buttons[i]->btn, buf);
192 elm_layout_theme_set(wd->content_area, "popup", "content",
193 elm_widget_style_get(obj));
194 if (wd->content_text_obj)
196 snprintf(buf, sizeof(buf), "popup/%s", elm_widget_style_get(obj));
197 elm_object_style_set(wd->content_text_obj, buf);
201 EINA_LIST_FOREACH(wd->items, elist, item)
203 _elm_theme_object_set(obj, VIEW(item), "popup",
204 "item", elm_widget_style_get(obj));
207 edje_object_part_text_set(VIEW(item), "elm.text",
209 edje_object_signal_emit(VIEW(item),
210 "elm,state,item,text,visible", "elm");
213 edje_object_signal_emit(VIEW(item),
214 "elm,state,item,icon,visible", "elm");
216 edje_object_signal_emit(VIEW(item),
217 "elm,state,item,disabled", "elm");
218 evas_object_show(VIEW(item));
219 edje_object_message_signal_process(VIEW(item));
221 _scroller_size_calc(obj);
225 elm_object_part_text_set(wd->base, "elm.text.title", wd->title_text);
226 elm_object_signal_emit(wd->base, "elm,state,title,text,visible", "elm");
229 elm_object_signal_emit(wd->base, "elm,state,title,icon,visible", "elm");
231 edje_object_message_signal_process(elm_layout_edje_get(wd->base));
236 _item_sizing_eval(Elm_Popup_Content_Item *item)
238 Evas_Coord min_w = -1, min_h = -1, max_w = -1, max_h = -1;
240 edje_object_size_min_restricted_calc(VIEW(item), &min_w, &min_h, min_w,
242 evas_object_size_hint_min_set(VIEW(item), min_w, min_h);
243 evas_object_size_hint_max_set(VIEW(item), max_w, max_h);
247 _sizing_eval(Evas_Object *obj)
250 Elm_Popup_Content_Item *item;
251 Evas_Coord w_box = 0, h_box = 0;
252 Evas_Coord minw_box = 0, minh_box = 0;
253 Evas_Coord minw = -1, minh = -1, maxw = -1, maxh = -1;
254 Widget_Data *wd = elm_widget_data_get(obj);
259 EINA_LIST_FOREACH(wd->items, elist, item)
261 _item_sizing_eval(item);
262 evas_object_size_hint_min_get(VIEW(item), &minw_box,
264 if (minw_box > w_box)
269 evas_object_size_hint_min_set(wd->box, w_box, h_box);
270 evas_object_size_hint_min_set(wd->scr, w_box, MIN(h_box, wd->max_sc_h));
271 evas_object_size_hint_max_set(wd->scr, w_box, wd->max_sc_h);
272 evas_object_smart_calculate(wd->scr);
274 edje_object_size_min_calc(elm_layout_edje_get(wd->base), &minw, &minh);
275 evas_object_size_hint_min_set(wd->base, minw, minh);
276 evas_object_size_hint_max_set(wd->base, maxw, maxh);
277 evas_object_size_hint_min_set(obj, minw, minh);
278 evas_object_size_hint_max_set(obj, maxw, maxh);
279 elm_layout_sizing_eval(wd->base);
283 _changed_size_hints(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__,
284 void *event_info __UNUSED__)
290 _sub_del(void *data, Evas_Object *obj, void *event_info)
292 Elm_Popup_Content_Item *item;
294 Evas_Object *sub = event_info;
295 Widget_Data *wd = elm_widget_data_get(data);
300 if ((item = evas_object_data_get(sub, "_popup_content_item")) != NULL)
302 if (sub == item->icon)
304 edje_object_part_unswallow(VIEW(item), sub);
305 edje_object_signal_emit(VIEW(item),
306 "elm,state,item,icon,hidden", "elm");
311 else if (obj == wd->content_area)
313 if (sub == wd->content)
316 elm_object_part_content_unset(wd->base, "elm.swallow.content");
319 else if (sub == wd->content_text_obj)
321 wd->content_text_obj = NULL;
322 elm_object_part_content_unset(wd->base, "elm.swallow.content");
325 else if (sub == wd->scr)
329 elm_object_part_content_unset(wd->base, "elm.swallow.content");
333 else if (obj == wd->action_area)
335 for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
337 if (wd->buttons[i] && sub == wd->buttons[i]->btn &&
338 wd->buttons[i]->delete_me == EINA_TRUE)
340 _button_remove(data, sub, EINA_FALSE);
345 else if (obj == wd->base)
347 if (sub == wd->title_icon)
349 elm_object_signal_emit(wd->base, "elm,state,title,icon,hidden",
351 edje_object_message_signal_process(wd->base);
352 wd->title_icon = NULL;
358 _block_clicked_cb(void *data, Evas_Object *obj __UNUSED__,
359 void *event_info __UNUSED__)
361 Widget_Data *wd = elm_widget_data_get(data);
364 evas_object_smart_callback_call(data, SIG_BLOCK_CLICKED, NULL);
368 _timeout(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
370 evas_object_hide(data);
371 evas_object_smart_callback_call(data, SIG_TIMEOUT, NULL);
375 _mirrored_set(Evas_Object *obj, Eina_Bool rtl)
378 Elm_Popup_Content_Item *item;
379 Widget_Data *wd = elm_widget_data_get(obj);
382 elm_object_mirrored_set(wd->notify, rtl);
384 EINA_LIST_FOREACH(wd->items, elist, item)
385 edje_object_mirrored_set(VIEW(item), rtl);
389 _layout_change_cb(void *data, Evas_Object *obj __UNUSED__,
390 const char *emission __UNUSED__,
391 const char *source __UNUSED__)
393 Widget_Data *wd = elm_widget_data_get((Evas_Object*)data);
397 elm_layout_sizing_eval(wd->base);
401 _restack(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj,
402 void *event_info __UNUSED__)
404 Widget_Data *wd = elm_widget_data_get(obj);
407 evas_object_layer_set(wd->notify, evas_object_layer_get(obj));
411 _scroller_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj,
412 void *event_info __UNUSED__)
415 Widget_Data *wd = elm_widget_data_get(data);
417 if (!wd || wd->scr_size_recalc) return;
418 evas_object_geometry_get(obj, NULL, NULL, &w, &h);
421 if ((w <= wd->max_sc_w) && (h <= wd->max_sc_h))
424 wd->scr_size_recalc = EINA_TRUE;
428 if (wd->max_sc_w < w)
430 if (wd->max_sc_h < h)
436 _list_new(Evas_Object *obj)
438 Widget_Data *wd = elm_widget_data_get(obj);
442 wd->scr = elm_scroller_add(obj);
443 elm_scroller_bounce_set(wd->scr, EINA_FALSE, EINA_TRUE);
444 elm_object_content_set(wd->scr, wd->box);
445 evas_object_size_hint_weight_set(wd->scr, EVAS_HINT_EXPAND,
447 evas_object_size_hint_align_set(wd->scr, EVAS_HINT_FILL, EVAS_HINT_FILL);
448 evas_object_event_callback_add(wd->scr, EVAS_CALLBACK_RESIZE,
449 _scroller_resize, obj);
450 evas_object_event_callback_add(wd->scr,
451 EVAS_CALLBACK_CHANGED_SIZE_HINTS,
452 _changed_size_hints, obj);
453 elm_object_part_content_set(wd->base, "elm.swallow.content", wd->scr);
456 wd->box = elm_box_add(obj);
457 evas_object_size_hint_weight_set(wd->box, EVAS_HINT_EXPAND,
459 evas_object_size_hint_align_set(wd->box, EVAS_HINT_FILL, EVAS_HINT_FILL);
461 elm_object_content_set(wd->scr, wd->box);
465 _list_del(Widget_Data *wd)
467 if (!wd->scr) return;
468 elm_object_part_content_unset(wd->base, "elm.swallow.content");
469 evas_object_event_callback_del(wd->scr, EVAS_CALLBACK_RESIZE,
471 evas_object_event_callback_del(wd->scr, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
472 _changed_size_hints);
473 evas_object_del(wd->scr);
479 _scroller_size_calc(Evas_Object *obj)
482 Evas_Coord h_title = 0;
483 Evas_Coord h_action_area = 0;
484 Evas_Coord h_content = 0;
485 const char *action_area_height;
486 Widget_Data *wd = elm_widget_data_get(obj);
488 if (!wd || !wd->items) return;
489 wd->scr_size_recalc = EINA_FALSE;
492 evas_object_geometry_get(wd->notify, NULL, NULL, NULL, &h);
493 if (wd->title_text || wd->title_icon)
494 edje_object_part_geometry_get(elm_layout_edje_get(wd->base),
495 "elm.bg.title", NULL, NULL, NULL, &h_title);
496 if (wd->button_count)
498 action_area_height = edje_object_data_get(
499 elm_layout_edje_get(wd->action_area), "action_area_height");
500 if (action_area_height) h_action_area = (int)(atoi(action_area_height)
501 * _elm_config->scale * elm_object_scale_get(obj));
503 h_content = h - (h_title + h_action_area);
504 wd->max_sc_h = h_content;
508 _item_select_cb(void *data, Evas_Object *obj __UNUSED__,
509 const char *emission __UNUSED__, const char *source __UNUSED__)
511 Elm_Popup_Content_Item *item = data;
513 if (!item || item->disabled) return;
515 item->func((void*)item->base.data, WIDGET(item), data);
519 _item_new(Elm_Popup_Content_Item *item)
521 Widget_Data *wd = elm_widget_data_get(WIDGET(item));
524 elm_widget_item_text_set_hook_set(item, _item_text_set_hook);
525 elm_widget_item_text_get_hook_set(item, _item_text_get_hook);
526 elm_widget_item_content_set_hook_set(item, _item_content_set_hook);
527 elm_widget_item_content_get_hook_set(item, _item_content_get_hook);
528 elm_widget_item_content_unset_hook_set(item, _item_content_unset_hook);
529 elm_widget_item_disable_hook_set(item, _item_disable_hook);
530 elm_widget_item_del_pre_hook_set(item, _item_del_pre_hook);
531 elm_widget_item_signal_emit_hook_set(item, _item_signal_emit_hook);
532 VIEW(item) = edje_object_add(evas_object_evas_get(wd->base));
533 _elm_theme_object_set(WIDGET(item), VIEW(item), "popup", "item",
534 elm_widget_style_get(WIDGET(item)));
535 edje_object_mirrored_set(VIEW(item), elm_widget_mirrored_get(WIDGET(item)));
536 edje_object_signal_callback_add(VIEW(item), "elm,action,click", "",
537 _item_select_cb, item);
538 evas_object_size_hint_align_set(VIEW(item), EVAS_HINT_FILL,
540 evas_object_show(VIEW(item));
544 _remove_items(Widget_Data *wd)
547 Elm_Popup_Content_Item *item;
549 if (!wd->items) return;
550 EINA_LIST_FOREACH(wd->items, elist, item)
553 eina_stringshare_del(item->label);
556 evas_object_del(item->icon);
559 evas_object_del(VIEW(item));
560 wd->items = eina_list_remove(wd->items, item);
567 _notify_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__,
568 void *event_info __UNUSED__)
570 Widget_Data *wd = elm_widget_data_get(data);
573 _scroller_size_calc(data);
578 _title_text_set(Evas_Object *obj, const char *text)
580 ELM_CHECK_WIDTYPE(obj, widtype);
581 Eina_Bool title_visibility_old, title_visibility_current;
582 Widget_Data *wd = elm_widget_data_get(obj);
585 if (wd->title_text == text) return;
586 title_visibility_old = (wd->title_text) || (wd->title_icon);
587 eina_stringshare_replace(&wd->title_text, text);
588 elm_object_part_text_set(wd->base, "elm.text.title", text);
590 elm_object_signal_emit(wd->base, "elm,state,title,text,visible", "elm");
592 elm_object_signal_emit(wd->base, "elm,state,title,text,hidden", "elm");
593 title_visibility_current = (wd->title_text) || (wd->title_icon);
594 if (title_visibility_old != title_visibility_current)
596 edje_object_message_signal_process(wd->base);
601 _content_text_set(Evas_Object *obj, const char *text)
603 ELM_CHECK_WIDTYPE(obj, widtype);
604 Evas_Object *prev_content;
606 Widget_Data *wd = elm_widget_data_get(obj);
614 prev_content = elm_object_part_content_get(wd->content_area,
615 "elm.swallow.content");
617 evas_object_del(prev_content);
620 elm_object_part_content_set(wd->base, "elm.swallow.content",
622 wd->content_text_obj = elm_label_add(obj);
623 snprintf(buf, sizeof(buf), "popup/%s",
624 elm_widget_style_get(obj));
625 elm_object_style_set(wd->content_text_obj, buf);
626 elm_label_line_wrap_set(wd->content_text_obj,
627 wd->content_text_wrap_type);
628 elm_object_text_set(wd->content_text_obj, text);
629 evas_object_size_hint_weight_set(wd->content_text_obj, EVAS_HINT_EXPAND,
631 evas_object_size_hint_align_set(wd->content_text_obj, EVAS_HINT_FILL,
633 elm_object_part_content_set(wd->content_area, "elm.swallow.content",
634 wd->content_text_obj);
640 _text_set_hook(Evas_Object *obj, const char *part,
643 ELM_CHECK_WIDTYPE(obj, widtype);
644 Widget_Data *wd = elm_widget_data_get(obj);
647 if (!part || !strcmp(part, "default"))
648 _content_text_set(obj, label);
649 else if (!strcmp(part, "title,text"))
650 _title_text_set(obj, label);
652 WRN("The part name is invalid! : popup=%p", obj);
656 _title_text_get(const Evas_Object *obj)
658 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
659 Widget_Data *wd = elm_widget_data_get(obj);
661 if (!wd) return NULL;
662 return wd->title_text;
666 _content_text_get(const Evas_Object *obj)
668 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
669 const char *str = NULL;
670 Widget_Data *wd = elm_widget_data_get(obj);
672 if (!wd) return NULL;
673 if (wd->content_text_obj)
674 str = elm_object_text_get(wd->content_text_obj);
679 _text_get_hook(const Evas_Object *obj, const char *part)
681 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
682 const char *str = NULL;
683 Widget_Data *wd = elm_widget_data_get(obj);
685 if (!wd) return NULL;
686 if (!part || !strcmp(part, "default"))
687 str = _content_text_get(obj);
688 else if (!strcmp(part, "title,text"))
689 str = _title_text_get(obj);
691 WRN("The part name is invalid! : popup=%p", obj);
696 _title_icon_set(Evas_Object *obj, Evas_Object *icon)
698 ELM_CHECK_WIDTYPE(obj, widtype);
699 Eina_Bool title_visibility_old, title_visibility_current;
700 Widget_Data *wd = elm_widget_data_get(obj);
703 if (wd->title_icon == icon) return;
704 title_visibility_old = (wd->title_text) || (wd->title_icon);
705 if (wd->title_icon) evas_object_del(wd->title_icon);
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",
743 evas_object_show(content);
749 _button_remove(Evas_Object *obj, Evas_Object *content, Eina_Bool delete)
751 unsigned int i = 0, position = 0;
753 Widget_Data *wd = elm_widget_data_get(obj);
755 if (!wd->button_count) return;
756 for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
761 wd->buttons[i]->delete_me = EINA_FALSE;
762 if (wd->buttons[i]->btn == content)
764 snprintf(buf, sizeof(buf), "actionbtn%u", position);
765 elm_object_part_content_unset(wd->action_area, buf);
766 evas_object_hide(content);
767 if (delete) evas_object_del(content);
768 free(wd->buttons[i]);
769 wd->buttons[i] = NULL;
770 wd->button_count -= 1;
775 for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
777 if (!wd->buttons[i]) continue;
779 snprintf(buf, sizeof(buf), "actionbtn%u", position);
780 elm_object_part_content_unset(wd->action_area, buf);
781 elm_object_part_content_set(wd->action_area, buf,
782 wd->buttons[i]->btn);
783 evas_object_show(wd->buttons[i]->btn);
784 wd->buttons[i]->delete_me = EINA_TRUE;
786 if (!wd->button_count)
789 elm_object_part_content_unset(wd->base, "elm.swallow.action_area");
790 evas_object_hide(wd->action_area);
791 edje_object_message_signal_process(elm_layout_edje_get(wd->base));
795 snprintf(buf, sizeof(buf), "buttons%u", wd->button_count);
796 elm_layout_theme_set(wd->action_area, "popup", buf,
797 elm_widget_style_get(obj));
802 _action_button_set(Evas_Object *obj, Evas_Object *btn, unsigned int idx)
804 Action_Area_Data *adata;
806 unsigned int num = idx - 1, i = 0, position = 0;
807 Widget_Data *wd = elm_widget_data_get(obj);
810 if (num >= ELM_POPUP_ACTION_BUTTON_MAX) return;
811 if (wd->buttons[num])
812 _button_remove(obj, wd->buttons[num]->btn, EINA_TRUE);
816 snprintf(buf, sizeof(buf), "buttons%u", wd->button_count);
817 elm_layout_theme_set(wd->action_area, "popup", buf,
818 elm_widget_style_get(obj));
819 adata = ELM_NEW(Action_Area_Data);
822 wd->buttons[num] = adata;
823 /* Adding delete_me state inside action data as unset calls _sub_del
824 too and before setting a new content, the previous one needs to
825 be unset in order to avoid unwanted deletion. This way rearrangement
826 of buttons can be achieved in action area.
828 for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
830 wd->buttons[i]->delete_me = EINA_FALSE;
831 for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
833 if (!wd->buttons[i]) continue;
835 snprintf(buf, sizeof(buf), "actionbtn%u", position);
836 elm_object_part_content_unset(wd->action_area, buf);
837 elm_object_part_content_set(wd->action_area, buf,
838 wd->buttons[i]->btn);
839 evas_object_show(wd->buttons[i]->btn);
840 /* Setting delete_me to TRUE in order to let _sub_del handle it
841 if deleted externally and update the buttons array after freeing
842 action data allocated earlier.
844 wd->buttons[i]->delete_me = EINA_TRUE;
846 elm_object_part_content_set(wd->base, "elm.swallow.action_area",
848 evas_object_show(wd->action_area);
849 if (wd->button_count == 1)
851 edje_object_message_signal_process(wd->base);
853 _scroller_size_calc(obj);
859 _content_set_hook(Evas_Object *obj, const char *part,
860 Evas_Object *content)
862 ELM_CHECK_WIDTYPE(obj, widtype);
865 Widget_Data *wd = elm_widget_data_get(obj);
868 if (!part || !strcmp(part, "default"))
869 _content_set(obj, content);
870 else if (!strcmp(part, "title,icon"))
871 _title_icon_set(obj, content);
872 else if (!strncmp(part, "button", 6))
875 for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
877 snprintf(buff, sizeof(buff), "%u", i+1);
878 if (!strncmp(part, buff, sizeof(buff)))
880 _action_button_set(obj, content, i+1);
886 WRN("The part name is invalid! : popup=%p", obj);
890 _title_icon_get(Evas_Object *obj)
892 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
893 Widget_Data *wd = elm_widget_data_get(obj);
895 if (!wd) return NULL;
896 return wd->title_icon;
900 _content_get(Evas_Object *obj)
902 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
903 Widget_Data *wd = elm_widget_data_get(obj);
905 if (!wd) return NULL;
910 _action_button_get(Evas_Object *obj, unsigned int idx)
912 unsigned int num = idx - 1;
913 Evas_Object *button = NULL;
914 Widget_Data *wd = elm_widget_data_get(obj);
916 if (!wd || !wd->button_count) return NULL;
917 if (wd->buttons[num])
918 button = wd->buttons[num]->btn;
923 _content_get_hook(Evas_Object *obj, const char *part)
925 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
926 Evas_Object *content = NULL;
929 Widget_Data *wd = elm_widget_data_get(obj);
931 if (!wd) return NULL;
932 if (!part || !strcmp(part, "default"))
933 content = _content_get(obj);
934 else if (!strcmp(part, "title,text"))
935 content = _title_icon_get(obj);
936 else if (!strncmp(part, "button", 6))
939 for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
941 snprintf(buff, sizeof(buff), "%u", i+1);
942 if (!strncmp(part, buff, sizeof(buff)))
944 content = _action_button_get(obj, i+1);
950 WRN("The part name is invalid! : popup=%p", obj);
955 _content_unset(Evas_Object *obj)
957 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
958 Evas_Object *content;
959 Widget_Data *wd = elm_widget_data_get(obj);
961 if (!wd || !wd->content) return NULL;
962 content = elm_object_part_content_unset(wd->content_area,
963 "elm.swallow.content");
970 _title_icon_unset(Evas_Object *obj)
972 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
974 Widget_Data *wd = elm_widget_data_get(obj);
976 if (!wd || !wd->title_icon) return NULL;
977 icon = elm_object_part_content_unset(wd->base, "elm.swallow.title.icon");
978 wd->title_icon = NULL;
983 _action_button_unset(Evas_Object *obj, unsigned int idx)
985 unsigned int num = idx -1;
986 Evas_Object *button = NULL;
987 Widget_Data *wd = elm_widget_data_get(obj);
989 if (!wd) return NULL;
990 if ((!wd->button_count) || (num >= ELM_POPUP_ACTION_BUTTON_MAX))
993 if (wd->buttons[num])
995 button = wd->buttons[num]->btn;
996 _button_remove(obj, button, EINA_FALSE);
1001 static Evas_Object *
1002 _content_unset_hook(Evas_Object *obj, const char *part)
1004 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1005 Evas_Object *content = NULL;
1008 Widget_Data *wd = elm_widget_data_get(obj);
1010 if (!wd) return NULL;
1011 if (!part || !strcmp(part, "default"))
1012 content = _content_unset(obj);
1013 else if (!strcmp(part, "title,icon"))
1014 content = _title_icon_unset(obj);
1015 else if (!strncmp(part, "button", 6))
1018 for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
1020 snprintf(buff, sizeof(buff), "%u", i+1);
1021 if (!strncmp(part, buff, sizeof(buff)))
1023 content = _action_button_unset(obj, i+1);
1029 WRN("The part name is invalid! : popup=%p", obj);
1034 _focus_next_hook(const Evas_Object *obj,
1035 Elm_Focus_Direction dir,
1038 Widget_Data *wd = elm_widget_data_get(obj);
1042 return elm_widget_focus_next_get(wd->notify, dir, next);
1046 _item_text_set(Elm_Popup_Content_Item *item, const char *label)
1048 if (!eina_stringshare_replace(&item->label, label)) return;
1049 edje_object_part_text_set(VIEW(item), "elm.text", label);
1051 edje_object_signal_emit(VIEW(item),
1052 "elm,state,item,text,visible", "elm");
1054 edje_object_signal_emit(VIEW(item),
1055 "elm,state,item,text,hidden", "elm");
1056 edje_object_message_signal_process(VIEW(item));
1060 _item_text_set_hook(Elm_Object_Item *it, const char *part, const char *label)
1062 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1063 Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1065 if ((!part) || (!strcmp(part, "default")))
1067 _item_text_set(item, label);
1070 WRN("The part name is invalid! : popup=%p", WIDGET(item));
1074 _item_text_get_hook(const Elm_Object_Item *it, const char *part)
1076 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
1077 Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1079 if ((!part) || (!strcmp(part, "default")))
1081 WRN("The part name is invalid! : popup=%p", WIDGET(item));
1086 _item_icon_set(Elm_Popup_Content_Item *item, Evas_Object *icon)
1088 if (item->icon == icon) return;
1091 evas_object_data_del(item->icon, "_popup_content_item");
1092 evas_object_del(item->icon);
1097 elm_widget_sub_object_add(WIDGET(item), item->icon);
1098 evas_object_data_set(item->icon, "_popup_content_item", item);
1099 edje_object_part_swallow(VIEW(item), "elm.swallow.content",
1101 edje_object_signal_emit(VIEW(item),
1102 "elm,state,item,icon,visible", "elm");
1105 edje_object_signal_emit(VIEW(item),
1106 "elm,state,item,icon,hidden", "elm");
1107 edje_object_message_signal_process(item->base.view);
1111 _item_content_set_hook(Elm_Object_Item *it, const char *part,
1112 Evas_Object *content)
1114 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1115 Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1117 if ((!(part)) || (!strcmp(part, "default")))
1118 _item_icon_set(item, content);
1120 WRN("The part name is invalid! : popup=%p", WIDGET(item));
1123 static Evas_Object *
1124 _item_content_get_hook(const Elm_Object_Item *it,
1127 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
1128 Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1130 if ((!(part)) || (!strcmp(part, "default")))
1132 WRN("The part name is invalid! : popup=%p", WIDGET(item));
1136 static Evas_Object *
1137 _item_icon_unset(Elm_Popup_Content_Item *item)
1139 Evas_Object *icon = item->icon;
1141 if (!item->icon) return NULL;
1142 elm_widget_sub_object_del(WIDGET(item), icon);
1143 evas_object_data_del(icon, "_popup_content_item");
1144 edje_object_part_unswallow(item->base.view, icon);
1145 edje_object_signal_emit(VIEW(item),
1146 "elm,state,item,icon,hidden", "elm");
1151 static Evas_Object *
1152 _item_content_unset_hook(const Elm_Object_Item *it,
1155 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
1156 Evas_Object *content = NULL;
1157 Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1159 if ((!(part)) || (!strcmp(part, "default")))
1160 content = _item_icon_unset(item);
1162 WRN("The part name is invalid! : popup=%p", WIDGET(item));
1167 _item_disable_hook(Elm_Object_Item *it)
1169 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1170 Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1171 Widget_Data *wd = elm_widget_data_get(WIDGET(item));
1174 if (elm_widget_item_disabled_get(it))
1175 edje_object_signal_emit(VIEW(item), "elm,state,item,disabled", "elm");
1177 edje_object_signal_emit(VIEW(item), "elm,state,item,enabled", "elm");
1181 _item_del_pre_hook(Elm_Object_Item *it)
1183 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1184 Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1185 Widget_Data *wd = elm_widget_data_get(WIDGET(item));
1189 evas_object_del(item->icon);
1190 eina_stringshare_del(item->label);
1191 wd->items = eina_list_remove(wd->items, item);
1192 if (!eina_list_count(wd->items))
1200 _item_signal_emit_hook(Elm_Object_Item *it, const char *emission,
1203 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1204 Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1206 edje_object_signal_emit(VIEW(item), emission, source);
1210 _popup_show(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj,
1211 void *event_info __UNUSED__)
1215 wd = elm_widget_data_get(obj);
1218 evas_object_show(wd->notify);
1222 elm_popup_add(Evas_Object *parent)
1229 ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
1230 ELM_SET_WIDTYPE(widtype, "popup");
1231 elm_widget_type_set(obj, widtype);
1232 elm_widget_sub_object_add(parent, obj);
1233 elm_widget_data_set(obj, wd);
1234 elm_widget_del_pre_hook_set(obj, _del_pre_hook);
1235 elm_widget_del_hook_set(obj, _del_hook);
1236 elm_widget_theme_hook_set(obj, _theme_hook);
1237 elm_widget_text_set_hook_set(obj, _text_set_hook);
1238 elm_widget_text_get_hook_set(obj, _text_get_hook);
1239 elm_widget_content_set_hook_set(obj, _content_set_hook);
1240 elm_widget_content_get_hook_set(obj, _content_get_hook);
1241 elm_widget_content_unset_hook_set(obj,_content_unset_hook);
1242 elm_widget_can_focus_set(obj, EINA_FALSE);
1243 elm_widget_focus_next_hook_set(obj, _focus_next_hook);
1244 evas_object_smart_callbacks_descriptions_set(obj, _signals);
1246 wd->notify = elm_notify_add(obj);
1247 elm_notify_parent_set(wd->notify, parent);
1248 elm_notify_orient_set(wd->notify, ELM_NOTIFY_ORIENT_CENTER);
1249 elm_notify_allow_events_set(wd->notify, EINA_FALSE);
1250 evas_object_size_hint_weight_set(wd->notify,
1251 EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
1252 evas_object_size_hint_align_set(wd->notify, EVAS_HINT_FILL, EVAS_HINT_FILL);
1253 elm_object_style_set(wd->notify, "popup");
1255 evas_object_event_callback_add(wd->notify, EVAS_CALLBACK_RESIZE,
1256 _notify_resize, obj);
1257 evas_object_event_callback_add(obj, EVAS_CALLBACK_SHOW, _popup_show,
1259 evas_object_event_callback_add(obj, EVAS_CALLBACK_RESTACK, _restack, NULL);
1260 wd->base = elm_layout_add(obj);
1261 evas_object_size_hint_weight_set(wd->base, EVAS_HINT_EXPAND,
1263 evas_object_size_hint_align_set(wd->base, EVAS_HINT_FILL, EVAS_HINT_FILL);
1265 elm_layout_theme_set(wd->base, "popup", "base", elm_widget_style_get(obj));
1266 elm_object_content_set(wd->notify, wd->base);
1268 elm_object_signal_callback_add(wd->base, "elm,state,title_area,visible",
1269 "elm", _layout_change_cb, obj);
1270 elm_object_signal_callback_add(wd->base, "elm,state,title_area,hidden",
1271 "elm", _layout_change_cb, obj);
1272 elm_object_signal_callback_add(wd->base, "elm,state,action_area,visible",
1273 "elm", _layout_change_cb, obj);
1274 elm_object_signal_callback_add(wd->base, "elm,state,action_area,hidden",
1275 "elm", _layout_change_cb, obj);
1276 wd->content_area = elm_layout_add(obj);
1277 elm_layout_theme_set(wd->content_area, "popup", "content",
1278 elm_widget_style_get(obj));
1279 wd->action_area = elm_layout_add(obj);
1280 evas_object_size_hint_weight_set(wd->action_area, EVAS_HINT_EXPAND,
1282 evas_object_size_hint_align_set(wd->action_area, EVAS_HINT_FILL,
1284 evas_object_event_callback_add(wd->action_area,
1285 EVAS_CALLBACK_CHANGED_SIZE_HINTS,
1286 _changed_size_hints, obj);
1287 evas_object_event_callback_add(wd->content_area,
1288 EVAS_CALLBACK_CHANGED_SIZE_HINTS,
1289 _changed_size_hints, obj);
1290 evas_object_smart_callback_add(wd->base, "sub-object-del",
1292 evas_object_smart_callback_add(wd->content_area, "sub-object-del",
1294 evas_object_smart_callback_add(wd->action_area, "sub-object-del",
1296 evas_object_smart_callback_add(obj, "sub-object-del",
1299 wd->content_text_wrap_type = ELM_WRAP_MIXED;
1300 evas_object_smart_callback_add(wd->notify, "block,clicked",
1301 _block_clicked_cb, obj);
1302 evas_object_smart_callback_add(wd->notify, "timeout", _timeout, obj);
1303 for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
1304 wd->buttons[i] = NULL;
1306 //TODO: To use scroller for description also
1311 elm_popup_content_text_wrap_type_set(Evas_Object *obj, Elm_Wrap_Type wrap)
1313 ELM_CHECK_WIDTYPE(obj, widtype);
1314 Evas_Object *content_text_obj;
1315 Widget_Data *wd = elm_widget_data_get(obj);
1318 if (wd->content_text_wrap_type == ELM_WRAP_NONE) return;
1319 //Need to wrap the content text, so not allowing ELM_WRAP_NONE
1320 wd->content_text_wrap_type = wrap;
1321 if (wd->content_text_obj)
1323 content_text_obj = elm_object_part_content_get(wd->content_area,
1324 "elm.swallow.content");
1325 elm_label_line_wrap_set(content_text_obj, wrap);
1330 elm_popup_content_text_wrap_type_get(const Evas_Object *obj)
1332 ELM_CHECK_WIDTYPE(obj, widtype) ELM_WRAP_LAST;
1333 Widget_Data *wd = elm_widget_data_get(obj);
1335 if (!wd) return ELM_WRAP_LAST;
1336 return wd->content_text_wrap_type;
1340 elm_popup_orient_set(Evas_Object *obj, Elm_Popup_Orient orient)
1342 ELM_CHECK_WIDTYPE(obj, widtype);
1343 Widget_Data *wd = elm_widget_data_get(obj);
1346 if (orient >= ELM_POPUP_ORIENT_LAST) return;
1347 elm_notify_orient_set(wd->notify, (Elm_Notify_Orient)orient);
1350 EAPI Elm_Popup_Orient
1351 elm_popup_orient_get(const Evas_Object *obj)
1353 ELM_CHECK_WIDTYPE(obj, widtype) -1;
1354 Widget_Data *wd = elm_widget_data_get(obj);
1356 if (!wd) return ELM_POPUP_ORIENT_LAST;
1357 return (Elm_Popup_Orient)elm_notify_orient_get(wd->notify);
1361 elm_popup_timeout_set(Evas_Object *obj, double timeout)
1363 ELM_CHECK_WIDTYPE(obj, widtype);
1364 Widget_Data *wd = elm_widget_data_get(obj);
1367 elm_notify_timeout_set(wd->notify, timeout);
1371 elm_popup_timeout_get(const Evas_Object *obj)
1373 ELM_CHECK_WIDTYPE(obj, widtype) 0.0;
1374 Widget_Data *wd = elm_widget_data_get(obj);
1376 if (!wd) return 0.0;
1377 return elm_notify_timeout_get(wd->notify);
1381 elm_popup_allow_events_set(Evas_Object *obj, Eina_Bool allow)
1383 ELM_CHECK_WIDTYPE(obj, widtype);
1384 Eina_Bool allow_events = !!allow;
1385 Widget_Data *wd = elm_widget_data_get(obj);
1388 elm_notify_allow_events_set(wd->notify, allow_events);
1392 elm_popup_allow_events_get(const Evas_Object *obj)
1394 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1395 Widget_Data *wd = elm_widget_data_get(obj);
1397 if (!wd) return EINA_FALSE;
1398 return elm_notify_allow_events_get(wd->notify);
1401 EAPI Elm_Object_Item *
1402 elm_popup_item_append(Evas_Object *obj, const char *label,
1403 Evas_Object *icon, Evas_Smart_Cb func,
1406 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1407 Evas_Object *prev_content;
1408 Elm_Popup_Content_Item *item;
1409 Widget_Data *wd = elm_widget_data_get(obj);
1411 if (!wd) return NULL;
1412 item = elm_widget_item_new(obj, Elm_Popup_Content_Item);
1413 if (!item) return NULL;
1414 if (wd->content || wd->content_text_obj)
1416 prev_content = elm_object_part_content_get(wd->content_area,
1417 "elm.swallow.content");
1419 evas_object_del(prev_content);
1422 //The first item is appended.
1427 item->base.data = data;
1430 _item_icon_set(item, icon);
1431 _item_text_set(item, label);
1432 elm_box_pack_end(wd->box, VIEW(item));
1433 wd->items = eina_list_append(wd->items, item);
1435 _scroller_size_calc(obj);
1437 return (Elm_Object_Item *)item;