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));
177 _elm_widget_mirrored_reload(obj);
178 _mirrored_set(obj, elm_widget_mirrored_get(obj));
179 if (wd->button_count)
181 snprintf(buf, sizeof(buf), "buttons%u", wd->button_count);
182 elm_layout_theme_set(wd->action_area, "popup", buf,
183 elm_widget_style_get(obj));
184 for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
186 if (!wd->buttons[i]) continue;
187 elm_object_style_set(wd->buttons[i]->btn, buf);
190 elm_layout_theme_set(wd->content_area, "popup", "content",
191 elm_widget_style_get(obj));
192 if (wd->content_text_obj)
194 snprintf(buf, sizeof(buf), "popup/%s", elm_widget_style_get(obj));
195 elm_object_style_set(wd->content_text_obj, buf);
199 EINA_LIST_FOREACH(wd->items, elist, item)
201 _elm_theme_object_set(obj, VIEW(item), "popup",
202 "item", elm_widget_style_get(obj));
205 edje_object_part_text_set(VIEW(item), "elm.text",
207 edje_object_signal_emit(VIEW(item),
208 "elm,state,item,text,visible", "elm");
211 edje_object_signal_emit(VIEW(item),
212 "elm,state,item,icon,visible", "elm");
214 edje_object_signal_emit(VIEW(item),
215 "elm,state,item,disabled", "elm");
216 evas_object_show(VIEW(item));
217 edje_object_message_signal_process(VIEW(item));
219 _scroller_size_calc(obj);
223 elm_object_part_text_set(wd->base, "elm.text.title", wd->title_text);
224 elm_object_signal_emit(wd->base, "elm,state,title,text,visible", "elm");
227 elm_object_signal_emit(wd->base, "elm,state,title,icon,visible", "elm");
229 edje_object_message_signal_process(elm_layout_edje_get(wd->base));
234 _item_sizing_eval(Elm_Popup_Content_Item *item)
236 Evas_Coord min_w = -1, min_h = -1, max_w = -1, max_h = -1;
238 edje_object_size_min_restricted_calc(VIEW(item), &min_w, &min_h, min_w,
240 evas_object_size_hint_min_set(VIEW(item), min_w, min_h);
241 evas_object_size_hint_max_set(VIEW(item), max_w, max_h);
245 _sizing_eval(Evas_Object *obj)
248 Elm_Popup_Content_Item *item;
249 Evas_Coord w_box = 0, h_box = 0;
250 Evas_Coord minw_box = 0, minh_box = 0;
251 Evas_Coord minw = -1, minh = -1, maxw = -1, maxh = -1;
252 Widget_Data *wd = elm_widget_data_get(obj);
257 EINA_LIST_FOREACH(wd->items, elist, item)
259 _item_sizing_eval(item);
260 evas_object_size_hint_min_get(VIEW(item), &minw_box,
262 if (minw_box > w_box)
267 evas_object_size_hint_min_set(wd->box, w_box, h_box);
268 evas_object_size_hint_min_set(wd->scr, w_box, MIN(h_box, wd->max_sc_h));
269 evas_object_size_hint_max_set(wd->scr, w_box, wd->max_sc_h);
270 evas_object_smart_calculate(wd->scr);
272 edje_object_size_min_calc(elm_layout_edje_get(wd->base), &minw, &minh);
273 evas_object_size_hint_min_set(wd->base, minw, minh);
274 evas_object_size_hint_max_set(wd->base, maxw, maxh);
275 evas_object_size_hint_min_set(obj, minw, minh);
276 evas_object_size_hint_max_set(obj, maxw, maxh);
277 elm_layout_sizing_eval(wd->base);
281 _changed_size_hints(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__,
282 void *event_info __UNUSED__)
288 _sub_del(void *data, Evas_Object *obj, void *event_info)
290 Elm_Popup_Content_Item *item;
292 Evas_Object *sub = event_info;
293 Widget_Data *wd = elm_widget_data_get(data);
298 if ((item = evas_object_data_get(sub, "_popup_content_item")) != NULL)
300 if (sub == item->icon)
302 edje_object_part_unswallow(VIEW(item), sub);
303 edje_object_signal_emit(VIEW(item),
304 "elm,state,item,icon,hidden", "elm");
309 else if (obj == wd->content_area)
311 if (sub == wd->content)
314 elm_object_part_content_unset(wd->base, "elm.swallow.content");
317 else if (sub == wd->content_text_obj)
319 wd->content_text_obj = NULL;
320 elm_object_part_content_unset(wd->base, "elm.swallow.content");
323 else if (sub == wd->scr)
327 elm_object_part_content_unset(wd->base, "elm.swallow.content");
331 else if (obj == wd->action_area)
333 for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
335 if (wd->buttons[i] && sub == wd->buttons[i]->btn &&
336 wd->buttons[i]->delete_me == EINA_TRUE)
338 _button_remove(data, sub, EINA_FALSE);
343 else if (obj == wd->base)
345 if (sub == wd->title_icon)
347 elm_object_signal_emit(wd->base, "elm,state,title,icon,hidden",
349 edje_object_message_signal_process(wd->base);
350 wd->title_icon = NULL;
356 _block_clicked_cb(void *data, Evas_Object *obj __UNUSED__,
357 void *event_info __UNUSED__)
359 Widget_Data *wd = elm_widget_data_get(data);
362 evas_object_smart_callback_call(data, SIG_BLOCK_CLICKED, NULL);
366 _timeout(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
368 evas_object_hide(data);
369 evas_object_smart_callback_call(data, SIG_TIMEOUT, NULL);
373 _mirrored_set(Evas_Object *obj, Eina_Bool rtl)
376 Elm_Popup_Content_Item *item;
377 Widget_Data *wd = elm_widget_data_get(obj);
380 elm_object_mirrored_set(wd->notify, rtl);
382 EINA_LIST_FOREACH(wd->items, elist, item)
383 edje_object_mirrored_set(VIEW(item), rtl);
387 _layout_change_cb(void *data, Evas_Object *obj __UNUSED__,
388 const char *emission __UNUSED__,
389 const char *source __UNUSED__)
391 Widget_Data *wd = elm_widget_data_get((Evas_Object*)data);
395 elm_layout_sizing_eval(wd->base);
399 _restack(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj,
400 void *event_info __UNUSED__)
402 Widget_Data *wd = elm_widget_data_get(obj);
405 evas_object_layer_set(wd->notify, evas_object_layer_get(obj));
409 _scroller_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj,
410 void *event_info __UNUSED__)
413 Widget_Data *wd = elm_widget_data_get(data);
415 if (!wd || wd->scr_size_recalc) return;
416 evas_object_geometry_get(obj, NULL, NULL, &w, &h);
419 if ((w <= wd->max_sc_w) && (h <= wd->max_sc_h))
422 wd->scr_size_recalc = EINA_TRUE;
426 if (wd->max_sc_w < w)
428 if (wd->max_sc_h < h)
434 _list_new(Evas_Object *obj)
436 Widget_Data *wd = elm_widget_data_get(obj);
440 wd->scr = elm_scroller_add(obj);
441 elm_scroller_bounce_set(wd->scr, EINA_FALSE, EINA_TRUE);
442 elm_object_content_set(wd->scr, wd->box);
443 evas_object_size_hint_weight_set(wd->scr, EVAS_HINT_EXPAND,
445 evas_object_size_hint_align_set(wd->scr, EVAS_HINT_FILL, EVAS_HINT_FILL);
446 evas_object_event_callback_add(wd->scr, EVAS_CALLBACK_RESIZE,
447 _scroller_resize, obj);
448 evas_object_event_callback_add(wd->scr,
449 EVAS_CALLBACK_CHANGED_SIZE_HINTS,
450 _changed_size_hints, obj);
451 elm_object_part_content_set(wd->base, "elm.swallow.content", wd->scr);
454 wd->box = elm_box_add(obj);
455 evas_object_size_hint_weight_set(wd->box, EVAS_HINT_EXPAND,
457 evas_object_size_hint_align_set(wd->box, EVAS_HINT_FILL, EVAS_HINT_FILL);
459 elm_object_content_set(wd->scr, wd->box);
463 _list_del(Widget_Data *wd)
465 if (!wd->scr) return;
466 elm_object_part_content_unset(wd->base, "elm.swallow.content");
467 evas_object_event_callback_del(wd->scr, EVAS_CALLBACK_RESIZE,
469 evas_object_event_callback_del(wd->scr, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
470 _changed_size_hints);
471 evas_object_del(wd->scr);
477 _scroller_size_calc(Evas_Object *obj)
480 Evas_Coord h_title = 0;
481 Evas_Coord h_action_area = 0;
482 Evas_Coord h_content = 0;
483 const char *action_area_height;
484 Widget_Data *wd = elm_widget_data_get(obj);
486 if (!wd || !wd->items) return;
487 wd->scr_size_recalc = EINA_FALSE;
490 evas_object_geometry_get(wd->notify, NULL, NULL, NULL, &h);
491 if (wd->title_text || wd->title_icon)
492 edje_object_part_geometry_get(elm_layout_edje_get(wd->base),
493 "elm.bg.title", NULL, NULL, NULL, &h_title);
494 if (wd->button_count)
496 action_area_height = edje_object_data_get(
497 elm_layout_edje_get(wd->action_area), "action_area_height");
498 if (action_area_height) h_action_area = (int)(atoi(action_area_height)
499 * _elm_config->scale * elm_object_scale_get(obj));
501 h_content = h - (h_title + h_action_area);
502 wd->max_sc_h = h_content;
506 _item_select_cb(void *data, Evas_Object *obj __UNUSED__,
507 const char *emission __UNUSED__, const char *source __UNUSED__)
509 Elm_Popup_Content_Item *item = data;
511 if (!item || item->disabled) return;
513 item->func((void*)item->base.data, WIDGET(item), data);
517 _item_new(Elm_Popup_Content_Item *item)
519 Widget_Data *wd = elm_widget_data_get(WIDGET(item));
522 elm_widget_item_text_set_hook_set(item, _item_text_set_hook);
523 elm_widget_item_text_get_hook_set(item, _item_text_get_hook);
524 elm_widget_item_content_set_hook_set(item, _item_content_set_hook);
525 elm_widget_item_content_get_hook_set(item, _item_content_get_hook);
526 elm_widget_item_content_unset_hook_set(item, _item_content_unset_hook);
527 elm_widget_item_disable_hook_set(item, _item_disable_hook);
528 elm_widget_item_del_pre_hook_set(item, _item_del_pre_hook);
529 elm_widget_item_signal_emit_hook_set(item, _item_signal_emit_hook);
530 VIEW(item) = edje_object_add(evas_object_evas_get(wd->base));
531 _elm_theme_object_set(WIDGET(item), VIEW(item), "popup", "item",
532 elm_widget_style_get(WIDGET(item)));
533 edje_object_mirrored_set(VIEW(item), elm_widget_mirrored_get(WIDGET(item)));
534 edje_object_signal_callback_add(VIEW(item), "elm,action,click", "",
535 _item_select_cb, item);
536 evas_object_size_hint_align_set(VIEW(item), EVAS_HINT_FILL,
538 evas_object_show(VIEW(item));
542 _remove_items(Widget_Data *wd)
545 Elm_Popup_Content_Item *item;
547 if (!wd->items) return;
548 EINA_LIST_FOREACH(wd->items, elist, item)
551 eina_stringshare_del(item->label);
554 evas_object_del(item->icon);
557 evas_object_del(VIEW(item));
558 wd->items = eina_list_remove(wd->items, item);
565 _notify_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__,
566 void *event_info __UNUSED__)
568 Widget_Data *wd = elm_widget_data_get(data);
571 _scroller_size_calc(data);
576 _title_text_set(Evas_Object *obj, const char *text)
578 ELM_CHECK_WIDTYPE(obj, widtype);
579 Eina_Bool title_visibility_old, title_visibility_current;
580 Widget_Data *wd = elm_widget_data_get(obj);
583 if (wd->title_text == text) return;
584 title_visibility_old = (wd->title_text) || (wd->title_icon);
585 eina_stringshare_replace(&wd->title_text, text);
586 elm_object_part_text_set(wd->base, "elm.text.title", text);
588 elm_object_signal_emit(wd->base, "elm,state,title,text,visible", "elm");
590 elm_object_signal_emit(wd->base, "elm,state,title,text,hidden", "elm");
591 title_visibility_current = (wd->title_text) || (wd->title_icon);
592 if (title_visibility_old != title_visibility_current)
594 edje_object_message_signal_process(wd->base);
599 _content_text_set(Evas_Object *obj, const char *text)
601 ELM_CHECK_WIDTYPE(obj, widtype);
602 Evas_Object *prev_content;
604 Widget_Data *wd = elm_widget_data_get(obj);
612 prev_content = elm_object_part_content_get(wd->content_area,
613 "elm.swallow.content");
615 evas_object_del(prev_content);
618 elm_object_part_content_set(wd->base, "elm.swallow.content",
620 wd->content_text_obj = elm_label_add(obj);
621 snprintf(buf, sizeof(buf), "popup/%s",
622 elm_widget_style_get(obj));
623 elm_object_style_set(wd->content_text_obj, buf);
624 elm_label_line_wrap_set(wd->content_text_obj,
625 wd->content_text_wrap_type);
626 elm_object_text_set(wd->content_text_obj, text);
627 evas_object_size_hint_weight_set(wd->content_text_obj, EVAS_HINT_EXPAND,
629 evas_object_size_hint_align_set(wd->content_text_obj, EVAS_HINT_FILL,
631 elm_object_part_content_set(wd->content_area, "elm.swallow.content",
632 wd->content_text_obj);
638 _text_set_hook(Evas_Object *obj, const char *part,
641 ELM_CHECK_WIDTYPE(obj, widtype);
642 Widget_Data *wd = elm_widget_data_get(obj);
645 if (!part || !strcmp(part, "default"))
646 _content_text_set(obj, label);
647 else if (!strcmp(part, "title,text"))
648 _title_text_set(obj, label);
650 WRN("The part name is invalid! : popup=%p", obj);
654 _title_text_get(const Evas_Object *obj)
656 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
657 Widget_Data *wd = elm_widget_data_get(obj);
659 if (!wd) return NULL;
660 return wd->title_text;
664 _content_text_get(const Evas_Object *obj)
666 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
667 const char *str = NULL;
668 Widget_Data *wd = elm_widget_data_get(obj);
670 if (!wd) return NULL;
671 if (wd->content_text_obj)
672 str = elm_object_text_get(wd->content_text_obj);
677 _text_get_hook(const Evas_Object *obj, const char *part)
679 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
680 const char *str = NULL;
681 Widget_Data *wd = elm_widget_data_get(obj);
683 if (!wd) return NULL;
684 if (!part || !strcmp(part, "default"))
685 str = _content_text_get(obj);
686 else if (!strcmp(part, "title,text"))
687 str = _title_text_get(obj);
689 WRN("The part name is invalid! : popup=%p", obj);
694 _title_icon_set(Evas_Object *obj, Evas_Object *icon)
696 ELM_CHECK_WIDTYPE(obj, widtype);
697 Eina_Bool title_visibility_old, title_visibility_current;
698 Widget_Data *wd = elm_widget_data_get(obj);
701 if (wd->title_icon == icon) return;
702 title_visibility_old = (wd->title_text) || (wd->title_icon);
705 evas_object_del(wd->title_icon);
706 wd->title_icon = NULL;
708 wd->title_icon = icon;
709 title_visibility_current = (wd->title_text) || (wd->title_icon);
710 elm_object_part_content_set(wd->base, "elm.swallow.title.icon",
713 elm_object_signal_emit(wd->base, "elm,state,title,icon,visible", "elm");
714 if (title_visibility_old != title_visibility_current) _layout_set(obj);
715 edje_object_message_signal_process(wd->base);
720 _content_set(Evas_Object *obj, Evas_Object *content)
722 ELM_CHECK_WIDTYPE(obj, widtype);
723 Evas_Object *prev_content;
724 Widget_Data *wd = elm_widget_data_get(obj);
727 if (wd->content && wd->content == content) return;
733 prev_content = elm_object_part_content_get(wd->content_area,
734 "elm.swallow.content");
736 evas_object_del(prev_content);
737 wd->content = content;
740 elm_object_part_content_set(wd->base, "elm.swallow.content",
742 elm_object_part_content_set(wd->content_area, "elm.swallow.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 wd->buttons[i]->delete_me = EINA_TRUE;
785 if (!wd->button_count)
788 edje_object_message_signal_process(elm_layout_edje_get(wd->base));
792 snprintf(buf, sizeof(buf), "buttons%u", wd->button_count);
793 elm_layout_theme_set(wd->action_area, "popup", buf,
794 elm_widget_style_get(obj));
799 _action_button_set(Evas_Object *obj, Evas_Object *btn, unsigned int idx)
801 Action_Area_Data *adata;
803 unsigned int num = idx - 1, i = 0, position = 0;
804 Widget_Data *wd = elm_widget_data_get(obj);
807 if (num >= ELM_POPUP_ACTION_BUTTON_MAX) return;
808 if (wd->buttons[num])
809 _button_remove(obj, wd->buttons[num]->btn, EINA_TRUE);
813 snprintf(buf, sizeof(buf), "buttons%u", wd->button_count);
814 elm_layout_theme_set(wd->action_area, "popup", buf,
815 elm_widget_style_get(obj));
816 adata = ELM_NEW(Action_Area_Data);
819 wd->buttons[num] = adata;
820 /* Adding delete_me state inside action data as unset calls _sub_del
821 too and before setting a new content, the previous one needs to
822 be unset in order to avoid unwanted deletion. This way rearrangement
823 of buttons can be achieved in action area.
825 for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
827 wd->buttons[i]->delete_me = EINA_FALSE;
828 for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
830 if (!wd->buttons[i]) continue;
832 snprintf(buf, sizeof(buf), "actionbtn%u", position);
833 elm_object_part_content_unset(wd->action_area, buf);
834 elm_object_part_content_set(wd->action_area, buf,
835 wd->buttons[i]->btn);
836 /* Setting delete_me to TRUE in order to let _sub_del handle it
837 if deleted externally and update the buttons array after freeing
838 action data allocated earlier.
840 wd->buttons[i]->delete_me = EINA_TRUE;
842 elm_object_part_content_set(wd->base, "elm.swallow.action_area",
844 if (wd->button_count == 1)
846 edje_object_message_signal_process(wd->base);
848 _scroller_size_calc(obj);
854 _content_set_hook(Evas_Object *obj, const char *part,
855 Evas_Object *content)
857 ELM_CHECK_WIDTYPE(obj, widtype);
860 Widget_Data *wd = elm_widget_data_get(obj);
863 if (!part || !strcmp(part, "default"))
864 _content_set(obj, content);
865 else if (!strcmp(part, "title,icon"))
866 _title_icon_set(obj, content);
867 else if (!strncmp(part, "button", 6))
870 for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
872 snprintf(buff, sizeof(buff), "%u", i+1);
873 if (!strncmp(part, buff, sizeof(buff)))
875 _action_button_set(obj, content, i+1);
881 WRN("The part name is invalid! : popup=%p", obj);
885 _title_icon_get(Evas_Object *obj)
887 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
888 Widget_Data *wd = elm_widget_data_get(obj);
890 if (!wd) return NULL;
891 return wd->title_icon;
895 _content_get(Evas_Object *obj)
897 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
898 Widget_Data *wd = elm_widget_data_get(obj);
900 if (!wd) return NULL;
905 _action_button_get(Evas_Object *obj, unsigned int idx)
907 unsigned int num = idx - 1;
908 Evas_Object *button = NULL;
909 Widget_Data *wd = elm_widget_data_get(obj);
911 if (!wd || !wd->button_count) return NULL;
912 if (wd->buttons[num])
913 button = wd->buttons[num]->btn;
918 _content_get_hook(Evas_Object *obj, const char *part)
920 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
921 Evas_Object *content = NULL;
924 Widget_Data *wd = elm_widget_data_get(obj);
926 if (!wd) return NULL;
927 if (!part || !strcmp(part, "default"))
928 content = _content_get(obj);
929 else if (!strcmp(part, "title,text"))
930 content = _title_icon_get(obj);
931 else if (!strncmp(part, "button", 6))
934 for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
936 snprintf(buff, sizeof(buff), "%u", i+1);
937 if (!strncmp(part, buff, sizeof(buff)))
939 content = _action_button_get(obj, i+1);
945 WRN("The part name is invalid! : popup=%p", obj);
950 _content_unset(Evas_Object *obj)
952 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
953 Evas_Object *content;
954 Widget_Data *wd = elm_widget_data_get(obj);
956 if (!wd || !wd->content) return NULL;
957 content = elm_object_part_content_unset(wd->content_area,
958 "elm.swallow.content");
965 _title_icon_unset(Evas_Object *obj)
967 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
969 Widget_Data *wd = elm_widget_data_get(obj);
971 if (!wd || !wd->title_icon) return NULL;
972 icon = elm_object_part_content_unset(wd->base, "elm.swallow.title.icon");
973 wd->title_icon = NULL;
978 _action_button_unset(Evas_Object *obj, unsigned int idx)
980 unsigned int num = idx -1;
981 Evas_Object *button = NULL;
982 Widget_Data *wd = elm_widget_data_get(obj);
984 if (!wd) return NULL;
985 if ((!wd->button_count) || (num >= ELM_POPUP_ACTION_BUTTON_MAX))
988 if (wd->buttons[num])
990 button = wd->buttons[num]->btn;
991 _button_remove(obj, button, EINA_FALSE);
997 _content_unset_hook(Evas_Object *obj, const char *part)
999 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1000 Evas_Object *content = NULL;
1003 Widget_Data *wd = elm_widget_data_get(obj);
1005 if (!wd) return NULL;
1006 if (!part || !strcmp(part, "default"))
1007 content = _content_unset(obj);
1008 else if (!strcmp(part, "title,icon"))
1009 content = _title_icon_unset(obj);
1010 else if (!strncmp(part, "button", 6))
1013 for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
1015 snprintf(buff, sizeof(buff), "%u", i+1);
1016 if (!strncmp(part, buff, sizeof(buff)))
1018 content = _action_button_unset(obj, i+1);
1024 WRN("The part name is invalid! : popup=%p", obj);
1029 _focus_next_hook(const Evas_Object *obj __UNUSED__,
1030 Elm_Focus_Direction dir __UNUSED__,
1031 Evas_Object **next __UNUSED__)
1033 //TODO: Implement Focus chanin Handling in Popup for action area buttons
1037 _item_text_set(Elm_Popup_Content_Item *item, const char *label)
1039 if (!eina_stringshare_replace(&item->label, label)) return;
1040 edje_object_part_text_set(VIEW(item), "elm.text", label);
1042 edje_object_signal_emit(VIEW(item),
1043 "elm,state,item,text,visible", "elm");
1045 edje_object_signal_emit(VIEW(item),
1046 "elm,state,item,text,hidden", "elm");
1047 edje_object_message_signal_process(VIEW(item));
1051 _item_text_set_hook(Elm_Object_Item *it, const char *part, const char *label)
1053 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1054 Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1056 if ((!part) || (!strcmp(part, "default")))
1058 _item_text_set(item, label);
1061 WRN("The part name is invalid! : popup=%p", WIDGET(item));
1065 _item_text_get_hook(const Elm_Object_Item *it, const char *part)
1067 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
1068 Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1070 if ((!part) || (!strcmp(part, "default")))
1072 WRN("The part name is invalid! : popup=%p", WIDGET(item));
1077 _item_icon_set(Elm_Popup_Content_Item *item, Evas_Object *icon)
1079 if (item->icon == icon) return;
1082 elm_widget_sub_object_del(WIDGET(item), item->icon);
1083 evas_object_data_del(item->icon, "_popup_content_item");
1084 evas_object_del(item->icon);
1089 elm_widget_sub_object_add(WIDGET(item), item->icon);
1090 evas_object_data_set(item->icon, "_popup_content_item", item);
1091 edje_object_part_swallow(VIEW(item), "elm.swallow.content",
1093 edje_object_signal_emit(VIEW(item),
1094 "elm,state,item,icon,visible", "elm");
1097 edje_object_signal_emit(VIEW(item),
1098 "elm,state,item,icon,hidden", "elm");
1099 edje_object_message_signal_process(item->base.view);
1103 _item_content_set_hook(Elm_Object_Item *it, const char *part,
1104 Evas_Object *content)
1106 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1107 Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1109 if ((!(part)) || (!strcmp(part, "default")))
1110 _item_icon_set(item, content);
1112 WRN("The part name is invalid! : popup=%p", WIDGET(item));
1115 static Evas_Object *
1116 _item_content_get_hook(const Elm_Object_Item *it,
1119 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
1120 Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1122 if ((!(part)) || (!strcmp(part, "default")))
1124 WRN("The part name is invalid! : popup=%p", WIDGET(item));
1128 static Evas_Object *
1129 _item_icon_unset(Elm_Popup_Content_Item *item)
1131 Evas_Object *icon = item->icon;
1133 if (!item->icon) return NULL;
1134 elm_widget_sub_object_del(WIDGET(item), icon);
1135 evas_object_data_del(icon, "_popup_content_item");
1136 edje_object_part_unswallow(item->base.view, icon);
1137 edje_object_signal_emit(VIEW(item),
1138 "elm,state,item,icon,hidden", "elm");
1143 static Evas_Object *
1144 _item_content_unset_hook(const Elm_Object_Item *it,
1147 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
1148 Evas_Object *content = NULL;
1149 Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1151 if ((!(part)) || (!strcmp(part, "default")))
1152 content = _item_icon_unset(item);
1154 WRN("The part name is invalid! : popup=%p", WIDGET(item));
1159 _item_disable_hook(Elm_Object_Item *it)
1161 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1162 Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1163 Widget_Data *wd = elm_widget_data_get(WIDGET(item));
1166 if (elm_widget_item_disabled_get(it))
1167 edje_object_signal_emit(VIEW(item), "elm,state,item,disabled", "elm");
1169 edje_object_signal_emit(VIEW(item), "elm,state,item,enabled", "elm");
1173 _item_del_pre_hook(Elm_Object_Item *it)
1175 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1176 Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1177 Widget_Data *wd = elm_widget_data_get(WIDGET(item));
1181 evas_object_del(item->icon);
1182 eina_stringshare_del(item->label);
1183 wd->items = eina_list_remove(wd->items, item);
1184 if (!eina_list_count(wd->items))
1192 _item_signal_emit_hook(Elm_Object_Item *it, const char *emission,
1195 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1196 Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1198 edje_object_signal_emit(VIEW(item), emission, source);
1202 elm_popup_add(Evas_Object *parent)
1209 ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
1210 ELM_SET_WIDTYPE(widtype, "popup");
1211 elm_widget_type_set(obj, widtype);
1212 elm_widget_sub_object_add(parent, obj);
1213 elm_widget_data_set(obj, wd);
1214 elm_widget_del_pre_hook_set(obj, _del_pre_hook);
1215 elm_widget_del_hook_set(obj, _del_hook);
1216 elm_widget_theme_hook_set(obj, _theme_hook);
1217 elm_widget_text_set_hook_set(obj, _text_set_hook);
1218 elm_widget_text_get_hook_set(obj, _text_get_hook);
1219 elm_widget_content_set_hook_set(obj, _content_set_hook);
1220 elm_widget_content_get_hook_set(obj, _content_get_hook);
1221 elm_widget_content_unset_hook_set(obj,_content_unset_hook);
1222 elm_widget_focus_next_hook_set(obj, _focus_next_hook);
1223 evas_object_smart_callbacks_descriptions_set(obj, _signals);
1225 wd->notify = elm_notify_add(obj);
1226 elm_widget_resize_object_set(obj, wd->notify);
1227 elm_notify_parent_set(wd->notify, parent);
1228 elm_notify_orient_set(wd->notify, ELM_NOTIFY_ORIENT_CENTER);
1229 elm_notify_allow_events_set(wd->notify, EINA_FALSE);
1230 evas_object_size_hint_weight_set(wd->notify,
1231 EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
1232 evas_object_size_hint_align_set(wd->notify, EVAS_HINT_FILL, EVAS_HINT_FILL);
1233 elm_object_style_set(wd->notify, "popup");
1235 evas_object_event_callback_add(wd->notify, EVAS_CALLBACK_RESIZE,
1236 _notify_resize, obj);
1237 evas_object_event_callback_add(obj, EVAS_CALLBACK_RESTACK, _restack, NULL);
1238 wd->base = elm_layout_add(obj);
1239 evas_object_size_hint_weight_set(wd->base, EVAS_HINT_EXPAND,
1241 evas_object_size_hint_align_set(wd->base, EVAS_HINT_FILL, EVAS_HINT_FILL);
1243 elm_layout_theme_set(wd->base, "popup", "base", elm_widget_style_get(obj));
1244 elm_object_content_set(wd->notify, wd->base);
1246 elm_object_signal_callback_add(wd->base, "elm,state,title_area,visible",
1247 "elm", _layout_change_cb, obj);
1248 elm_object_signal_callback_add(wd->base, "elm,state,title_area,hidden",
1249 "elm", _layout_change_cb, obj);
1250 elm_object_signal_callback_add(wd->base, "elm,state,action_area,visible",
1251 "elm", _layout_change_cb, obj);
1252 elm_object_signal_callback_add(wd->base, "elm,state,action_area,hidden",
1253 "elm", _layout_change_cb, obj);
1254 wd->content_area = elm_layout_add(obj);
1255 elm_layout_theme_set(wd->content_area, "popup", "content",
1256 elm_widget_style_get(obj));
1257 wd->action_area = elm_layout_add(obj);
1258 evas_object_size_hint_weight_set(wd->action_area, EVAS_HINT_EXPAND,
1260 evas_object_size_hint_align_set(wd->action_area, EVAS_HINT_FILL,
1262 evas_object_event_callback_add(wd->action_area,
1263 EVAS_CALLBACK_CHANGED_SIZE_HINTS,
1264 _changed_size_hints, obj);
1265 evas_object_event_callback_add(wd->content_area,
1266 EVAS_CALLBACK_CHANGED_SIZE_HINTS,
1267 _changed_size_hints, obj);
1268 evas_object_smart_callback_add(wd->base, "sub-object-del",
1270 evas_object_smart_callback_add(wd->content_area, "sub-object-del",
1272 evas_object_smart_callback_add(wd->action_area, "sub-object-del",
1274 evas_object_smart_callback_add(obj, "sub-object-del",
1277 wd->content_text_wrap_type = ELM_WRAP_MIXED;
1278 evas_object_smart_callback_add(wd->notify, "block,clicked",
1279 _block_clicked_cb, obj);
1280 evas_object_smart_callback_add(wd->notify, "timeout", _timeout, obj);
1281 for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
1282 wd->buttons[i] = NULL;
1284 //TODO: To use scroller for description also
1289 elm_popup_content_text_wrap_type_set(Evas_Object *obj, Elm_Wrap_Type wrap)
1291 ELM_CHECK_WIDTYPE(obj, widtype);
1292 Evas_Object *content_text_obj;
1293 Widget_Data *wd = elm_widget_data_get(obj);
1296 if (wd->content_text_wrap_type == ELM_WRAP_NONE) return;
1297 //Need to wrap the content text, so not allowing ELM_WRAP_NONE
1298 wd->content_text_wrap_type = wrap;
1299 if (wd->content_text_obj)
1301 content_text_obj = elm_object_part_content_get(wd->content_area,
1302 "elm.swallow.content");
1303 elm_label_line_wrap_set(content_text_obj, wrap);
1308 elm_popup_content_text_wrap_type_get(const Evas_Object *obj)
1310 ELM_CHECK_WIDTYPE(obj, widtype) ELM_WRAP_LAST;
1311 Widget_Data *wd = elm_widget_data_get(obj);
1313 if (!wd) return ELM_WRAP_LAST;
1314 return wd->content_text_wrap_type;
1318 elm_popup_orient_set(Evas_Object *obj, Elm_Popup_Orient orient)
1320 ELM_CHECK_WIDTYPE(obj, widtype);
1321 Widget_Data *wd = elm_widget_data_get(obj);
1324 if (orient >= ELM_POPUP_ORIENT_LAST) return;
1325 elm_notify_orient_set(wd->notify, (Elm_Notify_Orient)orient);
1328 EAPI Elm_Popup_Orient
1329 elm_popup_orient_get(const Evas_Object *obj)
1331 ELM_CHECK_WIDTYPE(obj, widtype) -1;
1332 Widget_Data *wd = elm_widget_data_get(obj);
1334 if (!wd) return ELM_POPUP_ORIENT_LAST;
1335 return (Elm_Popup_Orient)elm_notify_orient_get(wd->notify);
1339 elm_popup_timeout_set(Evas_Object *obj, double timeout)
1341 ELM_CHECK_WIDTYPE(obj, widtype);
1342 Widget_Data *wd = elm_widget_data_get(obj);
1345 elm_notify_timeout_set(wd->notify, timeout);
1349 elm_popup_timeout_get(const Evas_Object *obj)
1351 ELM_CHECK_WIDTYPE(obj, widtype) 0.0;
1352 Widget_Data *wd = elm_widget_data_get(obj);
1354 if (!wd) return 0.0;
1355 return elm_notify_timeout_get(wd->notify);
1359 elm_popup_allow_events_set(Evas_Object *obj, Eina_Bool allow)
1361 ELM_CHECK_WIDTYPE(obj, widtype);
1362 Eina_Bool allow_events = !!allow;
1363 Widget_Data *wd = elm_widget_data_get(obj);
1366 elm_notify_allow_events_set(wd->notify, allow_events);
1370 elm_popup_allow_events_get(const Evas_Object *obj)
1372 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1373 Widget_Data *wd = elm_widget_data_get(obj);
1375 if (!wd) return EINA_FALSE;
1376 return elm_notify_allow_events_get(wd->notify);
1379 EAPI Elm_Object_Item *
1380 elm_popup_item_append(Evas_Object *obj, const char *label,
1381 Evas_Object *icon, Evas_Smart_Cb func,
1384 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1385 Evas_Object *prev_content;
1386 Elm_Popup_Content_Item *item;
1387 Widget_Data *wd = elm_widget_data_get(obj);
1389 if (!wd) return NULL;
1390 item = elm_widget_item_new(obj, Elm_Popup_Content_Item);
1391 if (!item) return NULL;
1392 if (wd->content || wd->content_text_obj)
1394 prev_content = elm_object_part_content_get(wd->content_area,
1395 "elm.swallow.content");
1397 evas_object_del(prev_content);
1400 //The first item is appended.
1405 item->base.data = data;
1408 _item_icon_set(item, icon);
1409 _item_text_set(item, label);
1410 elm_box_pack_end(wd->box, VIEW(item));
1411 wd->items = eina_list_append(wd->items, item);
1413 _scroller_size_calc(obj);
1415 return (Elm_Object_Item *)item;