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 void _popup_hide(void *data, Evas *e, Evas_Object *obj,
105 static const char SIG_BLOCK_CLICKED[] = "block,clicked";
106 static const char SIG_TIMEOUT[] = "timeout";
107 static const Evas_Smart_Cb_Description _signals[] = {
108 {SIG_BLOCK_CLICKED, ""},
113 #define ELM_POPUP_CONTENT_ITEM_CHECK_RETURN(it, ...) \
114 ELM_WIDGET_ITEM_CHECK_OR_RETURN((Elm_Widget_Item *)it, __VA_ARGS__); \
115 ELM_CHECK_WIDTYPE(WIDGET(item), widtype) __VA_ARGS__;
118 _layout_set(Evas_Object *obj)
120 Widget_Data *wd = elm_widget_data_get(obj);
123 if ((!(wd->title_text)) && (!(wd->title_icon)))
124 elm_object_signal_emit(wd->base, "elm,state,title_area,hidden", "elm");
126 elm_object_signal_emit(wd->base, "elm,state,title_area,visible", "elm");
127 if (wd->button_count)
128 elm_object_signal_emit(wd->base, "elm,state,action_area,visible", "elm");
130 elm_object_signal_emit(wd->base, "elm,state,action_area,hidden", "elm");
134 _del_hook(Evas_Object *obj)
136 Widget_Data *wd = elm_widget_data_get(obj);
143 _del_pre_hook(Evas_Object *obj)
146 Widget_Data *wd = elm_widget_data_get(obj);
149 evas_object_smart_callback_del(wd->notify, "block,clicked",
151 evas_object_smart_callback_del(wd->notify, "timeout", _timeout);
152 evas_object_event_callback_del(wd->notify, EVAS_CALLBACK_RESIZE,
154 evas_object_event_callback_del(obj, EVAS_CALLBACK_SHOW, _popup_show);
155 wd->button_count = 0;
156 for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
159 evas_object_del(wd->buttons[i]->btn);
160 free(wd->buttons[i]);
161 wd->buttons[i] = NULL;
171 _theme_hook(Evas_Object *obj)
174 Elm_Popup_Content_Item *item;
177 Widget_Data *wd = elm_widget_data_get(obj);
180 elm_layout_theme_set(wd->base, "popup", "base", elm_widget_style_get(obj));
181 _elm_widget_mirrored_reload(obj);
182 _mirrored_set(obj, elm_widget_mirrored_get(obj));
183 if (wd->button_count)
185 snprintf(buf, sizeof(buf), "buttons%u", wd->button_count);
186 elm_layout_theme_set(wd->action_area, "popup", buf,
187 elm_widget_style_get(obj));
188 for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
190 if (!wd->buttons[i]) continue;
191 elm_object_style_set(wd->buttons[i]->btn, buf);
194 elm_layout_theme_set(wd->content_area, "popup", "content",
195 elm_widget_style_get(obj));
196 if (wd->content_text_obj)
198 snprintf(buf, sizeof(buf), "popup/%s", elm_widget_style_get(obj));
199 elm_object_style_set(wd->content_text_obj, buf);
203 EINA_LIST_FOREACH(wd->items, elist, item)
205 _elm_theme_object_set(obj, VIEW(item), "popup",
206 "item", elm_widget_style_get(obj));
209 edje_object_part_text_escaped_set(VIEW(item), "elm.text",
211 edje_object_signal_emit(VIEW(item),
212 "elm,state,item,text,visible", "elm");
215 edje_object_signal_emit(VIEW(item),
216 "elm,state,item,icon,visible", "elm");
218 edje_object_signal_emit(VIEW(item),
219 "elm,state,item,disabled", "elm");
220 evas_object_show(VIEW(item));
221 edje_object_message_signal_process(VIEW(item));
223 _scroller_size_calc(obj);
227 elm_object_part_text_set(wd->base, "elm.text.title", wd->title_text);
228 elm_object_signal_emit(wd->base, "elm,state,title,text,visible", "elm");
231 elm_object_signal_emit(wd->base, "elm,state,title,icon,visible", "elm");
233 edje_object_message_signal_process(elm_layout_edje_get(wd->base));
238 _item_sizing_eval(Elm_Popup_Content_Item *item)
240 Evas_Coord min_w = -1, min_h = -1, max_w = -1, max_h = -1;
242 edje_object_size_min_restricted_calc(VIEW(item), &min_w, &min_h, min_w,
244 evas_object_size_hint_min_set(VIEW(item), min_w, min_h);
245 evas_object_size_hint_max_set(VIEW(item), max_w, max_h);
249 _sizing_eval(Evas_Object *obj)
252 Elm_Popup_Content_Item *item;
253 Evas_Coord w_box = 0, h_box = 0;
254 Evas_Coord minw_box = 0, minh_box = 0;
255 Evas_Coord minw = -1, minh = -1, maxw = -1, maxh = -1;
256 Widget_Data *wd = elm_widget_data_get(obj);
257 Evas_Coord bx, by, bw, bh;
262 EINA_LIST_FOREACH(wd->items, elist, item)
264 _item_sizing_eval(item);
265 evas_object_size_hint_min_get(VIEW(item), &minw_box,
267 if (minw_box > w_box)
272 evas_object_size_hint_min_set(wd->box, w_box, h_box);
273 evas_object_size_hint_min_set(wd->scr, w_box, MIN(h_box, wd->max_sc_h));
274 evas_object_size_hint_max_set(wd->scr, w_box, wd->max_sc_h);
275 evas_object_smart_calculate(wd->scr);
277 edje_object_size_min_calc(elm_layout_edje_get(wd->base), &minw, &minh);
278 evas_object_size_hint_min_set(wd->base, minw, minh);
279 evas_object_size_hint_max_set(wd->base, maxw, maxh);
280 evas_object_size_hint_min_set(obj, minw, minh);
281 evas_object_size_hint_max_set(obj, maxw, maxh);
282 elm_layout_sizing_eval(wd->base);
284 // hack hack hack. this widget needs a ... redo.
285 evas_object_geometry_get(wd->base, &bx, &by, &bw, &bh);
286 evas_object_resize(obj, bw, bh);
287 evas_object_move(obj, bx, by);
291 _changed_size_hints(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__,
292 void *event_info __UNUSED__)
298 _sub_del(void *data, Evas_Object *obj, void *event_info)
300 Elm_Popup_Content_Item *item;
302 Evas_Object *sub = event_info;
303 Widget_Data *wd = elm_widget_data_get(data);
308 if ((item = evas_object_data_get(sub, "_popup_content_item")) != NULL)
310 if (sub == item->icon)
312 edje_object_part_unswallow(VIEW(item), sub);
313 edje_object_signal_emit(VIEW(item),
314 "elm,state,item,icon,hidden", "elm");
319 else if (obj == wd->content_area)
321 if (sub == wd->content)
324 elm_object_part_content_unset(wd->base, "elm.swallow.content");
327 else if (sub == wd->content_text_obj)
329 wd->content_text_obj = NULL;
330 elm_object_part_content_unset(wd->base, "elm.swallow.content");
333 else if (sub == wd->scr)
337 elm_object_part_content_unset(wd->base, "elm.swallow.content");
341 else if (obj == wd->action_area)
343 for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
345 if (wd->buttons[i] && sub == wd->buttons[i]->btn &&
346 wd->buttons[i]->delete_me == EINA_TRUE)
348 _button_remove(data, sub, EINA_FALSE);
353 else if (obj == wd->base)
355 if (sub == wd->title_icon)
357 elm_object_signal_emit(wd->base, "elm,state,title,icon,hidden",
359 edje_object_message_signal_process(wd->base);
360 wd->title_icon = NULL;
366 _block_clicked_cb(void *data, Evas_Object *obj __UNUSED__,
367 void *event_info __UNUSED__)
369 Widget_Data *wd = elm_widget_data_get(data);
372 evas_object_smart_callback_call(data, SIG_BLOCK_CLICKED, NULL);
376 _timeout(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
378 evas_object_hide(data);
379 evas_object_smart_callback_call(data, SIG_TIMEOUT, NULL);
383 _mirrored_set(Evas_Object *obj, Eina_Bool rtl)
386 Elm_Popup_Content_Item *item;
387 Widget_Data *wd = elm_widget_data_get(obj);
390 elm_object_mirrored_set(wd->notify, rtl);
392 EINA_LIST_FOREACH(wd->items, elist, item)
393 edje_object_mirrored_set(VIEW(item), rtl);
397 _layout_change_cb(void *data, Evas_Object *obj __UNUSED__,
398 const char *emission __UNUSED__,
399 const char *source __UNUSED__)
401 Widget_Data *wd = elm_widget_data_get((Evas_Object*)data);
405 elm_layout_sizing_eval(wd->base);
409 _restack(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj,
410 void *event_info __UNUSED__)
412 Widget_Data *wd = elm_widget_data_get(obj);
415 evas_object_layer_set(wd->notify, evas_object_layer_get(obj));
419 _scroller_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj,
420 void *event_info __UNUSED__)
423 Widget_Data *wd = elm_widget_data_get(data);
425 if (!wd || wd->scr_size_recalc) return;
426 evas_object_geometry_get(obj, NULL, NULL, &w, &h);
429 if ((w <= wd->max_sc_w) && (h <= wd->max_sc_h))
432 wd->scr_size_recalc = EINA_TRUE;
436 if (wd->max_sc_w < w)
438 if (wd->max_sc_h < h)
444 _list_new(Evas_Object *obj)
446 Widget_Data *wd = elm_widget_data_get(obj);
450 wd->scr = elm_scroller_add(obj);
451 elm_scroller_bounce_set(wd->scr, EINA_FALSE, EINA_TRUE);
452 elm_object_content_set(wd->scr, wd->box);
453 evas_object_size_hint_weight_set(wd->scr, EVAS_HINT_EXPAND,
455 evas_object_size_hint_align_set(wd->scr, EVAS_HINT_FILL, EVAS_HINT_FILL);
456 evas_object_event_callback_add(wd->scr, EVAS_CALLBACK_RESIZE,
457 _scroller_resize, obj);
458 evas_object_event_callback_add(wd->scr,
459 EVAS_CALLBACK_CHANGED_SIZE_HINTS,
460 _changed_size_hints, obj);
461 elm_object_part_content_set(wd->base, "elm.swallow.content", wd->scr);
464 wd->box = elm_box_add(obj);
465 evas_object_size_hint_weight_set(wd->box, EVAS_HINT_EXPAND,
467 evas_object_size_hint_align_set(wd->box, EVAS_HINT_FILL, EVAS_HINT_FILL);
469 elm_object_content_set(wd->scr, wd->box);
473 _list_del(Widget_Data *wd)
475 if (!wd->scr) return;
476 elm_object_part_content_unset(wd->base, "elm.swallow.content");
477 evas_object_event_callback_del(wd->scr, EVAS_CALLBACK_RESIZE,
479 evas_object_event_callback_del(wd->scr, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
480 _changed_size_hints);
481 evas_object_del(wd->scr);
487 _scroller_size_calc(Evas_Object *obj)
490 Evas_Coord h_title = 0;
491 Evas_Coord h_action_area = 0;
492 Evas_Coord h_content = 0;
493 const char *action_area_height;
494 Widget_Data *wd = elm_widget_data_get(obj);
496 if (!wd || !wd->items) return;
497 wd->scr_size_recalc = EINA_FALSE;
500 evas_object_geometry_get(wd->notify, NULL, NULL, NULL, &h);
501 if (wd->title_text || wd->title_icon)
502 edje_object_part_geometry_get(elm_layout_edje_get(wd->base),
503 "elm.bg.title", NULL, NULL, NULL, &h_title);
504 if (wd->button_count)
506 action_area_height = edje_object_data_get(
507 elm_layout_edje_get(wd->action_area), "action_area_height");
508 if (action_area_height) h_action_area = (int)(atoi(action_area_height)
509 * _elm_config->scale * elm_object_scale_get(obj));
511 h_content = h - (h_title + h_action_area);
512 wd->max_sc_h = h_content;
516 _item_select_cb(void *data, Evas_Object *obj __UNUSED__,
517 const char *emission __UNUSED__, const char *source __UNUSED__)
519 Elm_Popup_Content_Item *item = data;
521 if (!item || item->disabled) return;
523 item->func((void*)item->base.data, WIDGET(item), data);
527 _item_new(Elm_Popup_Content_Item *item)
529 Widget_Data *wd = elm_widget_data_get(WIDGET(item));
532 elm_widget_item_text_set_hook_set(item, _item_text_set_hook);
533 elm_widget_item_text_get_hook_set(item, _item_text_get_hook);
534 elm_widget_item_content_set_hook_set(item, _item_content_set_hook);
535 elm_widget_item_content_get_hook_set(item, _item_content_get_hook);
536 elm_widget_item_content_unset_hook_set(item, _item_content_unset_hook);
537 elm_widget_item_disable_hook_set(item, _item_disable_hook);
538 elm_widget_item_del_pre_hook_set(item, _item_del_pre_hook);
539 elm_widget_item_signal_emit_hook_set(item, _item_signal_emit_hook);
540 VIEW(item) = edje_object_add(evas_object_evas_get(wd->base));
541 _elm_theme_object_set(WIDGET(item), VIEW(item), "popup", "item",
542 elm_widget_style_get(WIDGET(item)));
543 edje_object_mirrored_set(VIEW(item), elm_widget_mirrored_get(WIDGET(item)));
544 edje_object_signal_callback_add(VIEW(item), "elm,action,click", "",
545 _item_select_cb, item);
546 evas_object_size_hint_align_set(VIEW(item), EVAS_HINT_FILL,
548 evas_object_show(VIEW(item));
552 _remove_items(Widget_Data *wd)
555 Elm_Popup_Content_Item *item;
557 if (!wd->items) return;
558 EINA_LIST_FOREACH(wd->items, elist, item)
561 eina_stringshare_del(item->label);
564 evas_object_del(item->icon);
567 evas_object_del(VIEW(item));
568 wd->items = eina_list_remove(wd->items, item);
575 _notify_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__,
576 void *event_info __UNUSED__)
578 Widget_Data *wd = elm_widget_data_get(data);
581 _scroller_size_calc(data);
586 _title_text_set(Evas_Object *obj, const char *text)
588 ELM_CHECK_WIDTYPE(obj, widtype);
589 Eina_Bool title_visibility_old, title_visibility_current;
590 Widget_Data *wd = elm_widget_data_get(obj);
593 if (wd->title_text == text) return;
594 title_visibility_old = (wd->title_text) || (wd->title_icon);
595 eina_stringshare_replace(&wd->title_text, text);
596 elm_object_part_text_set(wd->base, "elm.text.title", text);
598 elm_object_signal_emit(wd->base, "elm,state,title,text,visible", "elm");
600 elm_object_signal_emit(wd->base, "elm,state,title,text,hidden", "elm");
601 title_visibility_current = (wd->title_text) || (wd->title_icon);
602 if (title_visibility_old != title_visibility_current)
604 edje_object_message_signal_process(wd->base);
609 _content_text_set(Evas_Object *obj, const char *text)
611 ELM_CHECK_WIDTYPE(obj, widtype);
612 Evas_Object *prev_content;
614 Widget_Data *wd = elm_widget_data_get(obj);
622 prev_content = elm_object_part_content_get(wd->content_area,
623 "elm.swallow.content");
625 evas_object_del(prev_content);
628 elm_object_part_content_set(wd->base, "elm.swallow.content",
630 wd->content_text_obj = elm_label_add(obj);
631 snprintf(buf, sizeof(buf), "popup/%s",
632 elm_widget_style_get(obj));
633 elm_object_style_set(wd->content_text_obj, buf);
634 elm_label_line_wrap_set(wd->content_text_obj,
635 wd->content_text_wrap_type);
636 elm_object_text_set(wd->content_text_obj, text);
637 evas_object_size_hint_weight_set(wd->content_text_obj, EVAS_HINT_EXPAND,
639 evas_object_size_hint_align_set(wd->content_text_obj, EVAS_HINT_FILL,
641 elm_object_part_content_set(wd->content_area, "elm.swallow.content",
642 wd->content_text_obj);
648 _text_set_hook(Evas_Object *obj, const char *part,
651 ELM_CHECK_WIDTYPE(obj, widtype);
652 Widget_Data *wd = elm_widget_data_get(obj);
655 if (!part || !strcmp(part, "default"))
656 _content_text_set(obj, label);
657 else if (!strcmp(part, "title,text"))
658 _title_text_set(obj, label);
660 WRN("The part name is invalid! : popup=%p", obj);
664 _title_text_get(const Evas_Object *obj)
666 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
667 Widget_Data *wd = elm_widget_data_get(obj);
669 if (!wd) return NULL;
670 return wd->title_text;
674 _content_text_get(const Evas_Object *obj)
676 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
677 const char *str = NULL;
678 Widget_Data *wd = elm_widget_data_get(obj);
680 if (!wd) return NULL;
681 if (wd->content_text_obj)
682 str = elm_object_text_get(wd->content_text_obj);
687 _text_get_hook(const Evas_Object *obj, const char *part)
689 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
690 const char *str = NULL;
691 Widget_Data *wd = elm_widget_data_get(obj);
693 if (!wd) return NULL;
694 if (!part || !strcmp(part, "default"))
695 str = _content_text_get(obj);
696 else if (!strcmp(part, "title,text"))
697 str = _title_text_get(obj);
699 WRN("The part name is invalid! : popup=%p", obj);
704 _title_icon_set(Evas_Object *obj, Evas_Object *icon)
706 ELM_CHECK_WIDTYPE(obj, widtype);
707 Eina_Bool title_visibility_old, title_visibility_current;
708 Widget_Data *wd = elm_widget_data_get(obj);
711 if (wd->title_icon == icon) return;
712 title_visibility_old = (wd->title_text) || (wd->title_icon);
713 if (wd->title_icon) evas_object_del(wd->title_icon);
715 wd->title_icon = icon;
716 title_visibility_current = (wd->title_text) || (wd->title_icon);
717 elm_object_part_content_set(wd->base, "elm.swallow.title.icon",
720 elm_object_signal_emit(wd->base, "elm,state,title,icon,visible", "elm");
721 if (title_visibility_old != title_visibility_current) _layout_set(obj);
722 edje_object_message_signal_process(wd->base);
727 _content_set(Evas_Object *obj, Evas_Object *content)
729 ELM_CHECK_WIDTYPE(obj, widtype);
730 Evas_Object *prev_content;
731 Widget_Data *wd = elm_widget_data_get(obj);
734 if (wd->content && wd->content == content) return;
740 prev_content = elm_object_part_content_get(wd->content_area,
741 "elm.swallow.content");
743 evas_object_del(prev_content);
744 wd->content = content;
747 elm_object_part_content_set(wd->base, "elm.swallow.content",
749 elm_object_part_content_set(wd->content_area, "elm.swallow.content",
751 evas_object_show(content);
757 _button_remove(Evas_Object *obj, Evas_Object *content, Eina_Bool delete)
759 unsigned int i = 0, position = 0;
761 Widget_Data *wd = elm_widget_data_get(obj);
763 if (!wd->button_count) return;
764 for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
769 wd->buttons[i]->delete_me = EINA_FALSE;
770 if (wd->buttons[i]->btn == content)
772 snprintf(buf, sizeof(buf), "actionbtn%u", position);
773 elm_object_part_content_unset(wd->action_area, buf);
774 evas_object_hide(content);
775 if (delete) evas_object_del(content);
776 free(wd->buttons[i]);
777 wd->buttons[i] = NULL;
778 wd->button_count -= 1;
783 for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
785 if (!wd->buttons[i]) continue;
787 snprintf(buf, sizeof(buf), "actionbtn%u", position);
788 elm_object_part_content_unset(wd->action_area, buf);
789 elm_object_part_content_set(wd->action_area, buf,
790 wd->buttons[i]->btn);
791 evas_object_show(wd->buttons[i]->btn);
792 wd->buttons[i]->delete_me = EINA_TRUE;
794 if (!wd->button_count)
797 elm_object_part_content_unset(wd->base, "elm.swallow.action_area");
798 evas_object_hide(wd->action_area);
799 edje_object_message_signal_process(elm_layout_edje_get(wd->base));
803 snprintf(buf, sizeof(buf), "buttons%u", wd->button_count);
804 elm_layout_theme_set(wd->action_area, "popup", buf,
805 elm_widget_style_get(obj));
810 _action_button_set(Evas_Object *obj, Evas_Object *btn, unsigned int idx)
812 Action_Area_Data *adata;
814 unsigned int num = idx - 1, i = 0, position = 0;
815 Widget_Data *wd = elm_widget_data_get(obj);
818 if (num >= ELM_POPUP_ACTION_BUTTON_MAX) return;
819 if (wd->buttons[num])
820 _button_remove(obj, wd->buttons[num]->btn, EINA_TRUE);
824 snprintf(buf, sizeof(buf), "buttons%u", wd->button_count);
825 elm_layout_theme_set(wd->action_area, "popup", buf,
826 elm_widget_style_get(obj));
827 adata = ELM_NEW(Action_Area_Data);
830 wd->buttons[num] = adata;
831 /* Adding delete_me state inside action data as unset calls _sub_del
832 too and before setting a new content, the previous one needs to
833 be unset in order to avoid unwanted deletion. This way rearrangement
834 of buttons can be achieved in action area.
836 for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
838 wd->buttons[i]->delete_me = EINA_FALSE;
839 for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
841 if (!wd->buttons[i]) continue;
843 snprintf(buf, sizeof(buf), "actionbtn%u", position);
844 elm_object_part_content_unset(wd->action_area, buf);
845 elm_object_part_content_set(wd->action_area, buf,
846 wd->buttons[i]->btn);
847 evas_object_show(wd->buttons[i]->btn);
848 /* Setting delete_me to TRUE in order to let _sub_del handle it
849 if deleted externally and update the buttons array after freeing
850 action data allocated earlier.
852 wd->buttons[i]->delete_me = EINA_TRUE;
854 elm_object_part_content_set(wd->base, "elm.swallow.action_area",
856 evas_object_show(wd->action_area);
857 if (wd->button_count == 1)
859 edje_object_message_signal_process(wd->base);
861 _scroller_size_calc(obj);
867 _content_set_hook(Evas_Object *obj, const char *part,
868 Evas_Object *content)
870 ELM_CHECK_WIDTYPE(obj, widtype);
873 Widget_Data *wd = elm_widget_data_get(obj);
876 if (!part || !strcmp(part, "default"))
877 _content_set(obj, content);
878 else if (!strcmp(part, "title,icon"))
879 _title_icon_set(obj, content);
880 else if (!strncmp(part, "button", 6))
883 for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
885 snprintf(buff, sizeof(buff), "%u", i+1);
886 if (!strncmp(part, buff, sizeof(buff)))
888 _action_button_set(obj, content, i+1);
894 WRN("The part name is invalid! : popup=%p", obj);
898 _title_icon_get(Evas_Object *obj)
900 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
901 Widget_Data *wd = elm_widget_data_get(obj);
903 if (!wd) return NULL;
904 return wd->title_icon;
908 _content_get(Evas_Object *obj)
910 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
911 Widget_Data *wd = elm_widget_data_get(obj);
913 if (!wd) return NULL;
918 _action_button_get(Evas_Object *obj, unsigned int idx)
920 unsigned int num = idx - 1;
921 Evas_Object *button = NULL;
922 Widget_Data *wd = elm_widget_data_get(obj);
924 if (!wd || !wd->button_count) return NULL;
925 if (wd->buttons[num])
926 button = wd->buttons[num]->btn;
931 _content_get_hook(Evas_Object *obj, const char *part)
933 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
934 Evas_Object *content = NULL;
937 Widget_Data *wd = elm_widget_data_get(obj);
939 if (!wd) return NULL;
940 if (!part || !strcmp(part, "default"))
941 content = _content_get(obj);
942 else if (!strcmp(part, "title,text"))
943 content = _title_icon_get(obj);
944 else if (!strncmp(part, "button", 6))
947 for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
949 snprintf(buff, sizeof(buff), "%u", i+1);
950 if (!strncmp(part, buff, sizeof(buff)))
952 content = _action_button_get(obj, i+1);
958 WRN("The part name is invalid! : popup=%p", obj);
963 _content_unset(Evas_Object *obj)
965 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
966 Evas_Object *content;
967 Widget_Data *wd = elm_widget_data_get(obj);
969 if (!wd || !wd->content) return NULL;
970 content = elm_object_part_content_unset(wd->content_area,
971 "elm.swallow.content");
978 _title_icon_unset(Evas_Object *obj)
980 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
982 Widget_Data *wd = elm_widget_data_get(obj);
984 if (!wd || !wd->title_icon) return NULL;
985 icon = elm_object_part_content_unset(wd->base, "elm.swallow.title.icon");
986 wd->title_icon = NULL;
991 _action_button_unset(Evas_Object *obj, unsigned int idx)
993 unsigned int num = idx -1;
994 Evas_Object *button = NULL;
995 Widget_Data *wd = elm_widget_data_get(obj);
997 if (!wd) return NULL;
998 if ((!wd->button_count) || (num >= ELM_POPUP_ACTION_BUTTON_MAX))
1001 if (wd->buttons[num])
1003 button = wd->buttons[num]->btn;
1004 _button_remove(obj, button, EINA_FALSE);
1009 static Evas_Object *
1010 _content_unset_hook(Evas_Object *obj, const char *part)
1012 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1013 Evas_Object *content = NULL;
1016 Widget_Data *wd = elm_widget_data_get(obj);
1018 if (!wd) return NULL;
1019 if (!part || !strcmp(part, "default"))
1020 content = _content_unset(obj);
1021 else if (!strcmp(part, "title,icon"))
1022 content = _title_icon_unset(obj);
1023 else if (!strncmp(part, "button", 6))
1026 for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
1028 snprintf(buff, sizeof(buff), "%u", i+1);
1029 if (!strncmp(part, buff, sizeof(buff)))
1031 content = _action_button_unset(obj, i+1);
1037 WRN("The part name is invalid! : popup=%p", obj);
1042 _focus_next_hook(const Evas_Object *obj,
1043 Elm_Focus_Direction dir,
1046 Widget_Data *wd = elm_widget_data_get(obj);
1050 return elm_widget_focus_next_get(wd->notify, dir, next);
1054 _item_text_set(Elm_Popup_Content_Item *item, const char *label)
1056 if (!eina_stringshare_replace(&item->label, label)) return;
1057 edje_object_part_text_escaped_set(VIEW(item), "elm.text", label);
1059 edje_object_signal_emit(VIEW(item),
1060 "elm,state,item,text,visible", "elm");
1062 edje_object_signal_emit(VIEW(item),
1063 "elm,state,item,text,hidden", "elm");
1064 edje_object_message_signal_process(VIEW(item));
1068 _item_text_set_hook(Elm_Object_Item *it, const char *part, const char *label)
1070 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1071 Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1073 if ((!part) || (!strcmp(part, "default")))
1075 _item_text_set(item, label);
1078 WRN("The part name is invalid! : popup=%p", WIDGET(item));
1082 _item_text_get_hook(const Elm_Object_Item *it, const char *part)
1084 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
1085 Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1087 if ((!part) || (!strcmp(part, "default")))
1089 WRN("The part name is invalid! : popup=%p", WIDGET(item));
1094 _item_icon_set(Elm_Popup_Content_Item *item, Evas_Object *icon)
1096 if (item->icon == icon) return;
1099 evas_object_data_del(item->icon, "_popup_content_item");
1100 evas_object_del(item->icon);
1105 elm_widget_sub_object_add(WIDGET(item), item->icon);
1106 evas_object_data_set(item->icon, "_popup_content_item", item);
1107 edje_object_part_swallow(VIEW(item), "elm.swallow.content",
1109 edje_object_signal_emit(VIEW(item),
1110 "elm,state,item,icon,visible", "elm");
1113 edje_object_signal_emit(VIEW(item),
1114 "elm,state,item,icon,hidden", "elm");
1115 edje_object_message_signal_process(item->base.view);
1119 _item_content_set_hook(Elm_Object_Item *it, const char *part,
1120 Evas_Object *content)
1122 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1123 Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1125 if ((!(part)) || (!strcmp(part, "default")))
1126 _item_icon_set(item, content);
1128 WRN("The part name is invalid! : popup=%p", WIDGET(item));
1131 static Evas_Object *
1132 _item_content_get_hook(const Elm_Object_Item *it,
1135 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
1136 Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1138 if ((!(part)) || (!strcmp(part, "default")))
1140 WRN("The part name is invalid! : popup=%p", WIDGET(item));
1144 static Evas_Object *
1145 _item_icon_unset(Elm_Popup_Content_Item *item)
1147 Evas_Object *icon = item->icon;
1149 if (!item->icon) return NULL;
1150 elm_widget_sub_object_del(WIDGET(item), icon);
1151 evas_object_data_del(icon, "_popup_content_item");
1152 edje_object_part_unswallow(item->base.view, icon);
1153 edje_object_signal_emit(VIEW(item),
1154 "elm,state,item,icon,hidden", "elm");
1159 static Evas_Object *
1160 _item_content_unset_hook(const Elm_Object_Item *it,
1163 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
1164 Evas_Object *content = NULL;
1165 Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1167 if ((!(part)) || (!strcmp(part, "default")))
1168 content = _item_icon_unset(item);
1170 WRN("The part name is invalid! : popup=%p", WIDGET(item));
1175 _item_disable_hook(Elm_Object_Item *it)
1177 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1178 Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1179 Widget_Data *wd = elm_widget_data_get(WIDGET(item));
1182 if (elm_widget_item_disabled_get(it))
1183 edje_object_signal_emit(VIEW(item), "elm,state,item,disabled", "elm");
1185 edje_object_signal_emit(VIEW(item), "elm,state,item,enabled", "elm");
1189 _item_del_pre_hook(Elm_Object_Item *it)
1191 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1192 Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1193 Widget_Data *wd = elm_widget_data_get(WIDGET(item));
1197 evas_object_del(item->icon);
1198 eina_stringshare_del(item->label);
1199 wd->items = eina_list_remove(wd->items, item);
1200 if (!eina_list_count(wd->items))
1208 _item_signal_emit_hook(Elm_Object_Item *it, const char *emission,
1211 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1212 Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1214 edje_object_signal_emit(VIEW(item), emission, source);
1218 _popup_show(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj,
1219 void *event_info __UNUSED__)
1223 wd = elm_widget_data_get(obj);
1226 evas_object_show(wd->notify);
1230 _popup_hide(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj,
1231 void *event_info __UNUSED__)
1235 wd = elm_widget_data_get(obj);
1238 evas_object_hide(wd->notify);
1242 elm_popup_add(Evas_Object *parent)
1249 ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
1250 ELM_SET_WIDTYPE(widtype, "popup");
1251 elm_widget_type_set(obj, widtype);
1252 elm_widget_sub_object_add(parent, obj);
1253 elm_widget_data_set(obj, wd);
1254 elm_widget_del_pre_hook_set(obj, _del_pre_hook);
1255 elm_widget_del_hook_set(obj, _del_hook);
1256 elm_widget_theme_hook_set(obj, _theme_hook);
1257 elm_widget_text_set_hook_set(obj, _text_set_hook);
1258 elm_widget_text_get_hook_set(obj, _text_get_hook);
1259 elm_widget_content_set_hook_set(obj, _content_set_hook);
1260 elm_widget_content_get_hook_set(obj, _content_get_hook);
1261 elm_widget_content_unset_hook_set(obj,_content_unset_hook);
1262 elm_widget_can_focus_set(obj, EINA_FALSE);
1263 elm_widget_focus_next_hook_set(obj, _focus_next_hook);
1264 evas_object_smart_callbacks_descriptions_set(obj, _signals);
1266 wd->notify = elm_notify_add(obj);
1267 elm_notify_parent_set(wd->notify, parent);
1268 elm_notify_orient_set(wd->notify, ELM_NOTIFY_ORIENT_CENTER);
1269 elm_notify_allow_events_set(wd->notify, EINA_FALSE);
1270 evas_object_size_hint_weight_set(wd->notify,
1271 EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
1272 evas_object_size_hint_align_set(wd->notify, EVAS_HINT_FILL, EVAS_HINT_FILL);
1273 elm_object_style_set(wd->notify, "popup");
1275 evas_object_event_callback_add(wd->notify, EVAS_CALLBACK_RESIZE,
1276 _notify_resize, obj);
1277 evas_object_event_callback_add(obj, EVAS_CALLBACK_SHOW, _popup_show,
1279 evas_object_event_callback_add(obj, EVAS_CALLBACK_HIDE, _popup_hide,
1281 evas_object_event_callback_add(obj, EVAS_CALLBACK_RESTACK, _restack, NULL);
1282 wd->base = elm_layout_add(obj);
1283 evas_object_size_hint_weight_set(wd->base, EVAS_HINT_EXPAND,
1285 evas_object_size_hint_align_set(wd->base, EVAS_HINT_FILL, EVAS_HINT_FILL);
1287 elm_layout_theme_set(wd->base, "popup", "base", elm_widget_style_get(obj));
1288 elm_object_content_set(wd->notify, wd->base);
1290 elm_object_signal_callback_add(wd->base, "elm,state,title_area,visible",
1291 "elm", _layout_change_cb, obj);
1292 elm_object_signal_callback_add(wd->base, "elm,state,title_area,hidden",
1293 "elm", _layout_change_cb, obj);
1294 elm_object_signal_callback_add(wd->base, "elm,state,action_area,visible",
1295 "elm", _layout_change_cb, obj);
1296 elm_object_signal_callback_add(wd->base, "elm,state,action_area,hidden",
1297 "elm", _layout_change_cb, obj);
1298 wd->content_area = elm_layout_add(obj);
1299 elm_layout_theme_set(wd->content_area, "popup", "content",
1300 elm_widget_style_get(obj));
1301 wd->action_area = elm_layout_add(obj);
1302 evas_object_size_hint_weight_set(wd->action_area, EVAS_HINT_EXPAND,
1304 evas_object_size_hint_align_set(wd->action_area, EVAS_HINT_FILL,
1306 evas_object_event_callback_add(wd->action_area,
1307 EVAS_CALLBACK_CHANGED_SIZE_HINTS,
1308 _changed_size_hints, obj);
1309 evas_object_event_callback_add(wd->content_area,
1310 EVAS_CALLBACK_CHANGED_SIZE_HINTS,
1311 _changed_size_hints, obj);
1312 evas_object_smart_callback_add(wd->base, "sub-object-del",
1314 evas_object_smart_callback_add(wd->content_area, "sub-object-del",
1316 evas_object_smart_callback_add(wd->action_area, "sub-object-del",
1318 evas_object_smart_callback_add(obj, "sub-object-del",
1321 wd->content_text_wrap_type = ELM_WRAP_MIXED;
1322 evas_object_smart_callback_add(wd->notify, "block,clicked",
1323 _block_clicked_cb, obj);
1324 evas_object_smart_callback_add(wd->notify, "timeout", _timeout, obj);
1325 for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
1326 wd->buttons[i] = NULL;
1328 //TODO: To use scroller for description also
1333 elm_popup_content_text_wrap_type_set(Evas_Object *obj, Elm_Wrap_Type wrap)
1335 ELM_CHECK_WIDTYPE(obj, widtype);
1336 Evas_Object *content_text_obj;
1337 Widget_Data *wd = elm_widget_data_get(obj);
1340 if (wd->content_text_wrap_type == ELM_WRAP_NONE) return;
1341 //Need to wrap the content text, so not allowing ELM_WRAP_NONE
1342 wd->content_text_wrap_type = wrap;
1343 if (wd->content_text_obj)
1345 content_text_obj = elm_object_part_content_get(wd->content_area,
1346 "elm.swallow.content");
1347 elm_label_line_wrap_set(content_text_obj, wrap);
1352 elm_popup_content_text_wrap_type_get(const Evas_Object *obj)
1354 ELM_CHECK_WIDTYPE(obj, widtype) ELM_WRAP_LAST;
1355 Widget_Data *wd = elm_widget_data_get(obj);
1357 if (!wd) return ELM_WRAP_LAST;
1358 return wd->content_text_wrap_type;
1362 elm_popup_orient_set(Evas_Object *obj, Elm_Popup_Orient orient)
1364 ELM_CHECK_WIDTYPE(obj, widtype);
1365 Widget_Data *wd = elm_widget_data_get(obj);
1368 if (orient >= ELM_POPUP_ORIENT_LAST) return;
1369 elm_notify_orient_set(wd->notify, (Elm_Notify_Orient)orient);
1372 EAPI Elm_Popup_Orient
1373 elm_popup_orient_get(const Evas_Object *obj)
1375 ELM_CHECK_WIDTYPE(obj, widtype) -1;
1376 Widget_Data *wd = elm_widget_data_get(obj);
1378 if (!wd) return ELM_POPUP_ORIENT_LAST;
1379 return (Elm_Popup_Orient)elm_notify_orient_get(wd->notify);
1383 elm_popup_timeout_set(Evas_Object *obj, double timeout)
1385 ELM_CHECK_WIDTYPE(obj, widtype);
1386 Widget_Data *wd = elm_widget_data_get(obj);
1389 elm_notify_timeout_set(wd->notify, timeout);
1393 elm_popup_timeout_get(const Evas_Object *obj)
1395 ELM_CHECK_WIDTYPE(obj, widtype) 0.0;
1396 Widget_Data *wd = elm_widget_data_get(obj);
1398 if (!wd) return 0.0;
1399 return elm_notify_timeout_get(wd->notify);
1403 elm_popup_allow_events_set(Evas_Object *obj, Eina_Bool allow)
1405 ELM_CHECK_WIDTYPE(obj, widtype);
1406 Eina_Bool allow_events = !!allow;
1407 Widget_Data *wd = elm_widget_data_get(obj);
1410 elm_notify_allow_events_set(wd->notify, allow_events);
1414 elm_popup_allow_events_get(const Evas_Object *obj)
1416 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1417 Widget_Data *wd = elm_widget_data_get(obj);
1419 if (!wd) return EINA_FALSE;
1420 return elm_notify_allow_events_get(wd->notify);
1423 EAPI Elm_Object_Item *
1424 elm_popup_item_append(Evas_Object *obj, const char *label,
1425 Evas_Object *icon, Evas_Smart_Cb func,
1428 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1429 Evas_Object *prev_content;
1430 Elm_Popup_Content_Item *item;
1431 Widget_Data *wd = elm_widget_data_get(obj);
1433 if (!wd) return NULL;
1434 item = elm_widget_item_new(obj, Elm_Popup_Content_Item);
1435 if (!item) return NULL;
1436 if (wd->content || wd->content_text_obj)
1438 prev_content = elm_object_part_content_get(wd->content_area,
1439 "elm.swallow.content");
1441 evas_object_del(prev_content);
1444 //The first item is appended.
1449 item->base.data = data;
1452 _item_icon_set(item, icon);
1453 _item_text_set(item, label);
1454 elm_box_pack_end(wd->box, VIEW(item));
1455 wd->items = eina_list_append(wd->items, item);
1457 _scroller_size_calc(obj);
1459 return (Elm_Object_Item *)item;