Elementary migration revision 69922
[framework/uifw/elementary.git] / src / lib / elc_popup.c
1 #include <Elementary.h>
2 #include "elm_priv.h"
3
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;
8
9 struct _Widget_Data
10 {
11    Evas_Object *base;
12    Evas_Object *notify;
13    Evas_Object *title_icon;
14    Evas_Object *content_area;
15    Evas_Object *content_text_obj;
16    Evas_Object *action_area;
17    Evas_Object *box;
18    Evas_Object *scr;
19    Evas_Object *content;
20    Eina_List *items;
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;
25    Evas_Coord max_sc_w;
26    Evas_Coord max_sc_h;
27    Eina_Bool scr_size_recalc:1;
28 };
29
30 struct _Elm_Popup_Content_Item
31 {
32    Elm_Widget_Item base;
33    const char *label;
34    Evas_Object *icon;
35    Evas_Smart_Cb func;
36    Eina_Bool disabled:1;
37 };
38
39 struct _Action_Area_Data
40 {
41    Evas_Object *obj;
42    Evas_Object *btn;
43    Eina_Bool delete_me;
44 };
45
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,
50                                           const char *label);
51 static const char *_text_get_hook(const Evas_Object *obj,
52                                                  const char *part);
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,
56                                                      const char *part);
57 static Evas_Object *_content_unset_hook(Evas_Object *obj,
58                                                        const char *part);
59 static void _item_text_set_hook(Elm_Object_Item *it, const char *part,
60                                 const char *label);
61 static const char *_item_text_get_hook(const Elm_Object_Item *it,
62                                        const char *part);
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,
66                                              const char *part);
67 static Evas_Object *_item_content_get_hook(const Elm_Object_Item *it,
68                                            const char *part);
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,
72                                    const char *source);
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,
76                            void *event_info);
77 static void _scroller_resize(void *data, Evas *e, Evas_Object *obj,
78                              void *event_info);
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,
96                                unsigned int idx);
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,
100                            Eina_Bool delete);
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, ""},
105        {SIG_TIMEOUT, ""},
106        {NULL, NULL}
107 };
108
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__;
112
113 static void
114 _layout_set(Evas_Object *obj)
115 {
116    Widget_Data *wd = elm_widget_data_get(obj);
117
118    if (!wd) return;
119    if ((!(wd->title_text)) && (!(wd->title_icon)))
120      elm_object_signal_emit(wd->base, "elm,state,title_area,hidden", "elm");
121    else
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");
125    else
126      elm_object_signal_emit(wd->base, "elm,state,action_area,hidden", "elm");
127 }
128
129 static void
130 _del_hook(Evas_Object *obj)
131 {
132    Widget_Data *wd = elm_widget_data_get(obj);
133
134    if (!wd) return;
135    free(wd);
136 }
137
138 static void
139 _del_pre_hook(Evas_Object *obj)
140 {
141    unsigned int i;
142    Widget_Data *wd = elm_widget_data_get(obj);
143
144    if (!wd) return;
145    evas_object_smart_callback_del(wd->notify, "block,clicked",
146                                   _block_clicked_cb);
147    evas_object_smart_callback_del(wd->notify, "timeout", _timeout);
148    evas_object_event_callback_del(wd->notify, EVAS_CALLBACK_RESIZE,
149                                   _notify_resize);
150    wd->button_count = 0;
151    for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
152      if (wd->buttons[i])
153        {
154           evas_object_del(wd->buttons[i]->btn);
155           free(wd->buttons[i]);
156           wd->buttons[i] = NULL;
157        }
158    if (wd->items)
159      {
160         _remove_items(wd);
161         _list_del(wd);
162      }
163 }
164
165 static void
166 _theme_hook(Evas_Object *obj)
167 {
168    Eina_List *elist;
169    Elm_Popup_Content_Item *item;
170    char buf[128];
171    unsigned int i = 0;
172    Widget_Data *wd = elm_widget_data_get(obj);
173
174    if (!wd) return;
175    elm_layout_theme_set(wd->base, "popup", "base", elm_widget_style_get(obj));
176    _elm_widget_mirrored_reload(obj);
177    _mirrored_set(obj, elm_widget_mirrored_get(obj));
178    if (wd->button_count)
179      {
180         snprintf(buf, sizeof(buf), "buttons%u", wd->button_count);
181         elm_layout_theme_set(wd->action_area, "popup", buf,
182                              elm_widget_style_get(obj));
183         for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
184           {
185              if (!wd->buttons[i]) continue;
186              elm_object_style_set(wd->buttons[i]->btn, buf);
187           }
188      }
189    elm_layout_theme_set(wd->content_area, "popup", "content",
190                         elm_widget_style_get(obj));
191    if (wd->content_text_obj)
192      {
193         snprintf(buf, sizeof(buf), "popup/%s", elm_widget_style_get(obj));
194         elm_object_style_set(wd->content_text_obj, buf);
195      }
196    else if (wd->items)
197      {
198         EINA_LIST_FOREACH(wd->items, elist, item)
199           {
200              _elm_theme_object_set(obj, VIEW(item), "popup",
201                                    "item", elm_widget_style_get(obj));
202              if (item->label)
203                {
204                   edje_object_part_text_set(VIEW(item), "elm.text",
205                                             item->label);
206                   edje_object_signal_emit(VIEW(item),
207                                           "elm,state,item,text,visible", "elm");
208                }
209              if (item->icon)
210                edje_object_signal_emit(VIEW(item),
211                                        "elm,state,item,icon,visible", "elm");
212              if (item->disabled)
213                edje_object_signal_emit(VIEW(item),
214                                        "elm,state,item,disabled", "elm");
215              evas_object_show(VIEW(item));
216              edje_object_message_signal_process(VIEW(item));
217           }
218         _scroller_size_calc(obj);
219      }
220    if (wd->title_text)
221      {
222         elm_object_part_text_set(wd->base, "elm.text.title", wd->title_text);
223         elm_object_signal_emit(wd->base, "elm,state,title,text,visible", "elm");
224      }
225    if (wd->title_icon)
226      elm_object_signal_emit(wd->base, "elm,state,title,icon,visible", "elm");
227    _layout_set(obj);
228    edje_object_message_signal_process(elm_layout_edje_get(wd->base));
229    _sizing_eval(obj);
230 }
231
232 static void
233 _item_sizing_eval(Elm_Popup_Content_Item *item)
234 {
235    Evas_Coord min_w = -1, min_h = -1, max_w = -1, max_h = -1;
236
237    edje_object_size_min_restricted_calc(VIEW(item), &min_w, &min_h, min_w,
238                                         min_h);
239    evas_object_size_hint_min_set(VIEW(item), min_w, min_h);
240    evas_object_size_hint_max_set(VIEW(item), max_w, max_h);
241 }
242
243 static void
244 _sizing_eval(Evas_Object *obj)
245 {
246    Eina_List *elist;
247    Elm_Popup_Content_Item *item;
248    Evas_Coord w_box = 0, h_box = 0;
249    Evas_Coord minw_box = 0, minh_box = 0;
250    Evas_Coord minw = -1, minh = -1, maxw = -1, maxh = -1;
251    Widget_Data *wd = elm_widget_data_get(obj);
252
253    if (!wd) return;
254    if (wd->items)
255      {
256         EINA_LIST_FOREACH(wd->items, elist, item)
257           {
258              _item_sizing_eval(item);
259              evas_object_size_hint_min_get(VIEW(item), &minw_box,
260                                            &minh_box);
261              if (minw_box > w_box)
262                w_box = minw_box;
263              if (minh_box != -1)
264                h_box += minh_box;
265           }
266         evas_object_size_hint_min_set(wd->box, w_box, h_box);
267         evas_object_size_hint_min_set(wd->scr, w_box, MIN(h_box, wd->max_sc_h));
268         evas_object_size_hint_max_set(wd->scr, w_box, wd->max_sc_h);
269         evas_object_smart_calculate(wd->scr);
270      }
271    edje_object_size_min_calc(elm_layout_edje_get(wd->base), &minw, &minh);
272    evas_object_size_hint_min_set(wd->base, minw, minh);
273    evas_object_size_hint_max_set(wd->base, maxw, maxh);
274    evas_object_size_hint_min_set(obj, minw, minh);
275    evas_object_size_hint_max_set(obj, maxw, maxh);
276    elm_layout_sizing_eval(wd->base);
277 }
278
279 static void
280 _changed_size_hints(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__,
281                     void *event_info __UNUSED__)
282 {
283    _sizing_eval(data);
284 }
285
286 static void
287 _sub_del(void *data, Evas_Object *obj, void *event_info)
288 {
289    Elm_Popup_Content_Item *item;
290    unsigned int i;
291    Evas_Object *sub = event_info;
292    Widget_Data *wd = elm_widget_data_get(data);
293
294    if (!wd) return;
295    if (obj == data)
296      {
297         if ((item = evas_object_data_get(sub, "_popup_content_item")) != NULL)
298           {
299              if (sub == item->icon)
300                {
301                   edje_object_part_unswallow(VIEW(item), sub);
302                   edje_object_signal_emit(VIEW(item),
303                                           "elm,state,item,icon,hidden", "elm");
304                   item->icon = NULL;
305                }
306           }
307      }
308    else if (obj == wd->content_area)
309      {
310         if (sub == wd->content)
311           {
312              wd->content = NULL;
313              elm_object_part_content_unset(wd->base, "elm.swallow.content");
314              _sizing_eval(data);
315           }
316         else if (sub == wd->content_text_obj)
317           {
318              wd->content_text_obj = NULL;
319              elm_object_part_content_unset(wd->base, "elm.swallow.content");
320              _sizing_eval(data);
321           }
322         else if (sub == wd->scr)
323           {
324              wd->scr = NULL;
325              wd->box = NULL;
326              elm_object_part_content_unset(wd->base, "elm.swallow.content");
327              _sizing_eval(data);
328           }
329      }
330    else if (obj == wd->action_area)
331      {
332         for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
333           {
334              if (wd->buttons[i] && sub == wd->buttons[i]->btn &&
335                       wd->buttons[i]->delete_me == EINA_TRUE)
336                {
337                   _button_remove(data, sub, EINA_FALSE);
338                   break;
339                }
340           }
341      }
342    else if (obj == wd->base)
343      {
344         if (sub == wd->title_icon)
345           {
346              elm_object_signal_emit(wd->base, "elm,state,title,icon,hidden",
347                                     "elm");
348              edje_object_message_signal_process(wd->base);
349              wd->title_icon = NULL;
350           }
351      }
352 }
353
354 static void
355 _block_clicked_cb(void *data, Evas_Object *obj __UNUSED__,
356                   void *event_info __UNUSED__)
357 {
358    Widget_Data *wd = elm_widget_data_get(data);
359
360    if (!wd) return;
361    evas_object_smart_callback_call(data, SIG_BLOCK_CLICKED, NULL);
362 }
363
364 static void
365 _timeout(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
366 {
367    evas_object_hide(data);
368    evas_object_smart_callback_call(data, SIG_TIMEOUT, NULL);
369 }
370
371 static void
372 _mirrored_set(Evas_Object *obj, Eina_Bool rtl)
373 {
374    Eina_List *elist;
375    Elm_Popup_Content_Item *item;
376    Widget_Data *wd = elm_widget_data_get(obj);
377
378    if (!wd) return;
379    elm_object_mirrored_set(wd->notify, rtl);
380    if (wd->items)
381      EINA_LIST_FOREACH(wd->items, elist, item)
382        edje_object_mirrored_set(VIEW(item), rtl);
383 }
384
385 static void
386 _layout_change_cb(void *data, Evas_Object *obj __UNUSED__,
387                   const char *emission __UNUSED__,
388                   const char *source __UNUSED__)
389 {
390    Widget_Data *wd = elm_widget_data_get((Evas_Object*)data);
391
392    if (!wd) return;
393    if (wd->base)
394      elm_layout_sizing_eval(wd->base);
395 }
396
397 static void
398 _restack(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj,
399          void *event_info __UNUSED__)
400 {
401    Widget_Data *wd = elm_widget_data_get(obj);
402
403    if (!wd) return;
404    evas_object_layer_set(wd->notify, evas_object_layer_get(obj));
405 }
406
407 static void
408 _scroller_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj,
409                  void *event_info __UNUSED__)
410 {
411    Evas_Coord w, h;
412    Widget_Data *wd = elm_widget_data_get(data);
413
414    if (!wd || wd->scr_size_recalc) return;
415    evas_object_geometry_get(obj, NULL, NULL, &w, &h);
416    if (w && h)
417      {
418         if ((w <= wd->max_sc_w) && (h <= wd->max_sc_h))
419           {
420              _sizing_eval(data);
421              wd->scr_size_recalc = EINA_TRUE;
422              return;
423           }
424      }
425    if (wd->max_sc_w < w)
426      wd->max_sc_w = w;
427    if (wd->max_sc_h < h)
428      wd->max_sc_h = h;
429    _sizing_eval(data);
430 }
431
432 static void
433 _list_new(Evas_Object *obj)
434 {
435    Widget_Data *wd = elm_widget_data_get(obj);
436
437    if (!wd) return;
438    //Scroller
439    wd->scr = elm_scroller_add(obj);
440    elm_scroller_bounce_set(wd->scr, EINA_FALSE, EINA_TRUE);
441    elm_object_content_set(wd->scr, wd->box);
442    evas_object_size_hint_weight_set(wd->scr, EVAS_HINT_EXPAND,
443                                     EVAS_HINT_EXPAND);
444    evas_object_size_hint_align_set(wd->scr, EVAS_HINT_FILL, EVAS_HINT_FILL);
445    evas_object_event_callback_add(wd->scr, EVAS_CALLBACK_RESIZE,
446                                   _scroller_resize, obj);
447    evas_object_event_callback_add(wd->scr,
448                                   EVAS_CALLBACK_CHANGED_SIZE_HINTS,
449                                   _changed_size_hints, obj);
450    elm_object_part_content_set(wd->base, "elm.swallow.content", wd->scr);
451
452    //Box
453    wd->box = elm_box_add(obj);
454    evas_object_size_hint_weight_set(wd->box, EVAS_HINT_EXPAND,
455                                     EVAS_HINT_EXPAND);
456    evas_object_size_hint_align_set(wd->box, EVAS_HINT_FILL, EVAS_HINT_FILL);
457
458    elm_object_content_set(wd->scr, wd->box);
459 }
460
461 static void
462 _list_del(Widget_Data *wd)
463 {
464    if (!wd->scr) return;
465    elm_object_part_content_unset(wd->base, "elm.swallow.content");
466    evas_object_event_callback_del(wd->scr, EVAS_CALLBACK_RESIZE,
467                                   _scroller_resize);
468    evas_object_event_callback_del(wd->scr, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
469                                   _changed_size_hints);
470    evas_object_del(wd->scr);
471    wd->scr = NULL;
472    wd->box = NULL;
473 }
474
475 static void
476 _scroller_size_calc(Evas_Object *obj)
477 {
478    Evas_Coord h;
479    Evas_Coord h_title = 0;
480    Evas_Coord h_action_area = 0;
481    Evas_Coord h_content = 0;
482    const char *action_area_height;
483    Widget_Data *wd = elm_widget_data_get(obj);
484
485    if (!wd || !wd->items) return;
486    wd->scr_size_recalc = EINA_FALSE;
487    wd->max_sc_h = -1;
488    wd->max_sc_w = -1;
489    evas_object_geometry_get(wd->notify, NULL, NULL, NULL, &h);
490    if (wd->title_text || wd->title_icon)
491      edje_object_part_geometry_get(elm_layout_edje_get(wd->base),
492                                    "elm.bg.title", NULL, NULL, NULL, &h_title);
493    if (wd->button_count)
494      {
495         action_area_height = edje_object_data_get(
496                  elm_layout_edje_get(wd->action_area), "action_area_height");
497         if (action_area_height) h_action_area = (int)(atoi(action_area_height)
498                  * _elm_config->scale * elm_object_scale_get(obj));
499      }
500    h_content = h - (h_title + h_action_area);
501    wd->max_sc_h = h_content;
502 }
503
504 static void
505 _item_select_cb(void *data, Evas_Object *obj __UNUSED__,
506                 const char *emission __UNUSED__, const char *source __UNUSED__)
507 {
508    Elm_Popup_Content_Item *item = data;
509
510    if (!item || item->disabled) return;
511    if (item->func)
512      item->func((void*)item->base.data, WIDGET(item), data);
513 }
514
515 static void
516 _item_new(Elm_Popup_Content_Item *item)
517 {
518    Widget_Data *wd = elm_widget_data_get(WIDGET(item));
519
520    if (!wd) return;
521    elm_widget_item_text_set_hook_set(item, _item_text_set_hook);
522    elm_widget_item_text_get_hook_set(item, _item_text_get_hook);
523    elm_widget_item_content_set_hook_set(item, _item_content_set_hook);
524    elm_widget_item_content_get_hook_set(item, _item_content_get_hook);
525    elm_widget_item_content_unset_hook_set(item, _item_content_unset_hook);
526    elm_widget_item_disable_hook_set(item, _item_disable_hook);
527    elm_widget_item_del_pre_hook_set(item, _item_del_pre_hook);
528    elm_widget_item_signal_emit_hook_set(item, _item_signal_emit_hook);
529    VIEW(item) = edje_object_add(evas_object_evas_get(wd->base));
530    _elm_theme_object_set(WIDGET(item), VIEW(item), "popup", "item",
531                          elm_widget_style_get(WIDGET(item)));
532    edje_object_mirrored_set(VIEW(item), elm_widget_mirrored_get(WIDGET(item)));
533    edje_object_signal_callback_add(VIEW(item), "elm,action,click", "",
534                                    _item_select_cb, item);
535    evas_object_size_hint_align_set(VIEW(item), EVAS_HINT_FILL,
536                                    EVAS_HINT_FILL);
537    evas_object_show(VIEW(item));
538 }
539
540 static void
541 _remove_items(Widget_Data *wd)
542 {
543    Eina_List *elist;
544    Elm_Popup_Content_Item *item;
545
546    if (!wd->items) return;
547    EINA_LIST_FOREACH(wd->items, elist, item)
548      {
549         if (item->label)
550           eina_stringshare_del(item->label);
551         if (item->icon)
552           {
553              evas_object_del(item->icon);
554              item->icon = NULL;
555           }
556         evas_object_del(VIEW(item));
557         wd->items = eina_list_remove(wd->items, item);
558         free(item);
559      }
560    wd->items = NULL;
561 }
562
563 static void
564 _notify_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__,
565                void *event_info __UNUSED__)
566 {
567    Widget_Data *wd = elm_widget_data_get(data);
568
569    if (wd->items)
570      _scroller_size_calc(data);
571    _sizing_eval(data);
572 }
573
574 static void
575 _title_text_set(Evas_Object *obj, const char *text)
576 {
577    ELM_CHECK_WIDTYPE(obj, widtype);
578    Eina_Bool title_visibility_old, title_visibility_current;
579    Widget_Data *wd = elm_widget_data_get(obj);
580
581    if (!wd) return;
582    if (wd->title_text == text) return;
583    title_visibility_old = (wd->title_text) || (wd->title_icon);
584    eina_stringshare_replace(&wd->title_text, text);
585    elm_object_part_text_set(wd->base, "elm.text.title", text);
586    if (wd->title_text)
587      elm_object_signal_emit(wd->base, "elm,state,title,text,visible", "elm");
588    else
589      elm_object_signal_emit(wd->base, "elm,state,title,text,hidden", "elm");
590    title_visibility_current = (wd->title_text) || (wd->title_icon);
591    if (title_visibility_old != title_visibility_current)
592      _layout_set(obj);
593    edje_object_message_signal_process(wd->base);
594    _sizing_eval(obj);
595 }
596
597 static void
598 _content_text_set(Evas_Object *obj, const char *text)
599 {
600    ELM_CHECK_WIDTYPE(obj, widtype);
601    Evas_Object *prev_content;
602    char buf[128];
603    Widget_Data *wd = elm_widget_data_get(obj);
604
605    if (!wd) return;
606    if (wd->items)
607      {
608         _remove_items(wd);
609         _list_del(wd);
610      }
611    prev_content = elm_object_part_content_get(wd->content_area,
612                                               "elm.swallow.content");
613    if (prev_content)
614      evas_object_del(prev_content);
615    if (text)
616      {
617         elm_object_part_content_set(wd->base, "elm.swallow.content",
618                                     wd->content_area);
619         wd->content_text_obj = elm_label_add(obj);
620         snprintf(buf, sizeof(buf), "popup/%s",
621                  elm_widget_style_get(obj));
622         elm_object_style_set(wd->content_text_obj, buf);
623         elm_label_line_wrap_set(wd->content_text_obj,
624                                 wd->content_text_wrap_type);
625         elm_object_text_set(wd->content_text_obj, text);
626         evas_object_size_hint_weight_set(wd->content_text_obj, EVAS_HINT_EXPAND,
627                                          0.0);
628         evas_object_size_hint_align_set(wd->content_text_obj, EVAS_HINT_FILL,
629                                         EVAS_HINT_FILL);
630         elm_object_part_content_set(wd->content_area, "elm.swallow.content",
631                                     wd->content_text_obj);
632      }
633    _sizing_eval(obj);
634 }
635
636 static void
637 _text_set_hook(Evas_Object *obj, const char *part,
638                               const char *label)
639 {
640    ELM_CHECK_WIDTYPE(obj, widtype);
641    Widget_Data *wd = elm_widget_data_get(obj);
642
643    if (!wd) return;
644    if (!part || !strcmp(part, "default"))
645      _content_text_set(obj, label);
646    else if (!strcmp(part, "title,text"))
647      _title_text_set(obj, label);
648    else
649      WRN("The part name is invalid! : popup=%p", obj);
650 }
651
652 static const char*
653 _title_text_get(const Evas_Object *obj)
654 {
655    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
656    Widget_Data *wd = elm_widget_data_get(obj);
657
658    if (!wd) return NULL;
659    return wd->title_text;
660 }
661
662 static const char*
663 _content_text_get(const Evas_Object *obj)
664 {
665    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
666    const char *str = NULL;
667    Widget_Data *wd = elm_widget_data_get(obj);
668
669    if (!wd) return NULL;
670    if (wd->content_text_obj)
671      str = elm_object_text_get(wd->content_text_obj);
672    return str;
673 }
674
675 static const char *
676 _text_get_hook(const Evas_Object *obj, const char *part)
677 {
678    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
679    const char *str = NULL;
680    Widget_Data *wd = elm_widget_data_get(obj);
681
682    if (!wd) return NULL;
683    if (!part || !strcmp(part, "default"))
684      str = _content_text_get(obj);
685    else if (!strcmp(part, "title,text"))
686      str = _title_text_get(obj);
687    else
688      WRN("The part name is invalid! : popup=%p", obj);
689    return str;
690 }
691
692 static void
693 _title_icon_set(Evas_Object *obj, Evas_Object *icon)
694 {
695    ELM_CHECK_WIDTYPE(obj, widtype);
696    Eina_Bool title_visibility_old, title_visibility_current;
697    Widget_Data *wd = elm_widget_data_get(obj);
698
699    if (!wd) return;
700    if (wd->title_icon == icon) return;
701    title_visibility_old = (wd->title_text) || (wd->title_icon);
702    if (wd->title_icon) evas_object_del(wd->title_icon);
703
704    wd->title_icon = icon;
705    title_visibility_current = (wd->title_text) || (wd->title_icon);
706    elm_object_part_content_set(wd->base, "elm.swallow.title.icon",
707                                wd->title_icon);
708    if (wd->title_icon)
709      elm_object_signal_emit(wd->base, "elm,state,title,icon,visible", "elm");
710    if (title_visibility_old != title_visibility_current) _layout_set(obj);
711    edje_object_message_signal_process(wd->base);
712    _sizing_eval(obj);
713 }
714
715 static void
716 _content_set(Evas_Object *obj, Evas_Object *content)
717 {
718    ELM_CHECK_WIDTYPE(obj, widtype);
719    Evas_Object *prev_content;
720    Widget_Data *wd = elm_widget_data_get(obj);
721
722    if (!wd) return;
723    if (wd->content && wd->content == content) return;
724    if (wd->items)
725      {
726         _remove_items(wd);
727         _list_del(wd);
728      }
729    prev_content = elm_object_part_content_get(wd->content_area,
730                                               "elm.swallow.content");
731    if (prev_content)
732      evas_object_del(prev_content);
733    wd->content = content;
734    if (content)
735      {
736         elm_object_part_content_set(wd->base, "elm.swallow.content",
737                                     wd->content_area);
738         elm_object_part_content_set(wd->content_area, "elm.swallow.content",
739                                     content);
740      }
741    _sizing_eval(obj);
742 }
743
744 static void
745 _button_remove(Evas_Object *obj, Evas_Object *content, Eina_Bool delete)
746 {
747    unsigned int i = 0, position = 0;
748    char buf[128];
749    Widget_Data *wd = elm_widget_data_get(obj);
750
751    if (!wd->button_count) return;
752    for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
753     {
754        if (wd->buttons[i])
755          {
756             position++;
757             wd->buttons[i]->delete_me = EINA_FALSE;
758             if (wd->buttons[i]->btn == content)
759               {
760                  snprintf(buf, sizeof(buf), "actionbtn%u", position);
761                  elm_object_part_content_unset(wd->action_area, buf);
762                  evas_object_hide(content);
763                  if (delete) evas_object_del(content);
764                  free(wd->buttons[i]);
765                  wd->buttons[i] = NULL;
766                  wd->button_count -= 1;
767                }
768          }
769     }
770    position = 0;
771    for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
772     {
773        if (!wd->buttons[i]) continue;
774        position++;
775        snprintf(buf, sizeof(buf), "actionbtn%u", position);
776        elm_object_part_content_unset(wd->action_area, buf);
777        elm_object_part_content_set(wd->action_area, buf,
778                                    wd->buttons[i]->btn);
779        wd->buttons[i]->delete_me = EINA_TRUE;
780     }
781    if (!wd->button_count)
782     {
783        _layout_set(obj);
784        edje_object_message_signal_process(elm_layout_edje_get(wd->base));
785     }
786    else
787     {
788        snprintf(buf, sizeof(buf), "buttons%u", wd->button_count);
789        elm_layout_theme_set(wd->action_area, "popup", buf,
790                             elm_widget_style_get(obj));
791     }
792 }
793
794 static void
795 _action_button_set(Evas_Object *obj, Evas_Object *btn, unsigned int idx)
796 {
797    Action_Area_Data *adata;
798    char buf[128];
799    unsigned int num = idx - 1, i = 0, position = 0;
800    Widget_Data *wd = elm_widget_data_get(obj);
801
802    if (!wd) return;
803    if (num >= ELM_POPUP_ACTION_BUTTON_MAX) return;
804    if (wd->buttons[num])
805      _button_remove(obj, wd->buttons[num]->btn, EINA_TRUE);
806    if (btn)
807      {
808         wd->button_count++;
809         snprintf(buf, sizeof(buf), "buttons%u", wd->button_count);
810         elm_layout_theme_set(wd->action_area, "popup", buf,
811                              elm_widget_style_get(obj));
812         adata = ELM_NEW(Action_Area_Data);
813         adata->obj = obj;
814         adata->btn = btn;
815         wd->buttons[num] = adata;
816         /* Adding delete_me state inside action data as unset calls _sub_del
817            too and before setting a new content, the previous one needs to
818            be unset in order to avoid unwanted deletion. This way rearrangement
819             of buttons can be achieved in action area.
820          */
821         for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
822           if (wd->buttons[i])
823             wd->buttons[i]->delete_me = EINA_FALSE;
824         for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
825           {
826              if (!wd->buttons[i]) continue;
827              position++;
828              snprintf(buf, sizeof(buf), "actionbtn%u", position);
829              elm_object_part_content_unset(wd->action_area, buf);
830              elm_object_part_content_set(wd->action_area, buf,
831                                          wd->buttons[i]->btn);
832              /* Setting delete_me to TRUE in order to let _sub_del handle it
833                 if deleted externally and update the buttons array after freeing
834                 action data allocated earlier.
835               */
836              wd->buttons[i]->delete_me = EINA_TRUE;
837           }
838         elm_object_part_content_set(wd->base, "elm.swallow.action_area",
839                                     wd->action_area);
840         if (wd->button_count == 1)
841           _layout_set(obj);
842         edje_object_message_signal_process(wd->base);
843         if (wd->items)
844           _scroller_size_calc(obj);
845         _sizing_eval(obj);
846      }
847 }
848
849 static void
850 _content_set_hook(Evas_Object *obj, const char *part,
851                                  Evas_Object *content)
852 {
853    ELM_CHECK_WIDTYPE(obj, widtype);
854    char buff[3];
855    unsigned int i;
856    Widget_Data *wd = elm_widget_data_get(obj);
857
858    if (!wd) return;
859    if (!part || !strcmp(part, "default"))
860      _content_set(obj, content);
861    else if (!strcmp(part, "title,icon"))
862      _title_icon_set(obj, content);
863    else if (!strncmp(part, "button", 6))
864      {
865         part += 6;
866         for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
867           {
868              snprintf(buff, sizeof(buff), "%u", i+1);
869              if (!strncmp(part, buff, sizeof(buff)))
870                {
871                   _action_button_set(obj, content, i+1);
872                   break;
873                }
874           }
875       }
876    else
877      WRN("The part name is invalid! : popup=%p", obj);
878 }
879
880 static Evas_Object *
881 _title_icon_get(Evas_Object *obj)
882 {
883    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
884    Widget_Data *wd = elm_widget_data_get(obj);
885
886    if (!wd) return NULL;
887    return wd->title_icon;
888 }
889
890 static Evas_Object *
891 _content_get(Evas_Object *obj)
892 {
893    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
894    Widget_Data *wd = elm_widget_data_get(obj);
895
896    if (!wd) return NULL;
897    return wd->content;
898 }
899
900 static Evas_Object *
901 _action_button_get(Evas_Object *obj, unsigned int idx)
902 {
903    unsigned int num = idx - 1;
904    Evas_Object *button = NULL;
905    Widget_Data *wd = elm_widget_data_get(obj);
906
907    if (!wd || !wd->button_count) return NULL;
908    if (wd->buttons[num])
909      button = wd->buttons[num]->btn;
910    return button;
911 }
912
913 static Evas_Object *
914 _content_get_hook(Evas_Object *obj, const char *part)
915 {
916    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
917    Evas_Object *content = NULL;
918    char buff[3];
919    unsigned int i;
920    Widget_Data *wd = elm_widget_data_get(obj);
921
922    if (!wd) return NULL;
923    if (!part || !strcmp(part, "default"))
924      content = _content_get(obj);
925    else if (!strcmp(part, "title,text"))
926      content = _title_icon_get(obj);
927    else if (!strncmp(part, "button", 6))
928      {
929         part += 6;
930         for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
931           {
932              snprintf(buff, sizeof(buff), "%u", i+1);
933              if (!strncmp(part, buff, sizeof(buff)))
934                {
935                   content = _action_button_get(obj, i+1);
936                   break;
937                }
938           }
939       }
940    else
941      WRN("The part name is invalid! : popup=%p", obj);
942    return content;
943 }
944
945 static Evas_Object *
946 _content_unset(Evas_Object *obj)
947 {
948    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
949    Evas_Object *content;
950    Widget_Data *wd = elm_widget_data_get(obj);
951
952    if (!wd || !wd->content) return NULL;
953    content = elm_object_part_content_unset(wd->content_area,
954                                            "elm.swallow.content");
955    wd->content = NULL;
956    _sizing_eval(obj);
957    return content;
958 }
959
960 static Evas_Object *
961 _title_icon_unset(Evas_Object *obj)
962 {
963    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
964    Evas_Object *icon;
965    Widget_Data *wd = elm_widget_data_get(obj);
966
967    if (!wd || !wd->title_icon) return NULL;
968    icon = elm_object_part_content_unset(wd->base, "elm.swallow.title.icon");
969    wd->title_icon = NULL;
970    return icon;
971 }
972
973 static Evas_Object *
974 _action_button_unset(Evas_Object *obj, unsigned int idx)
975 {
976    unsigned int num = idx -1;
977    Evas_Object *button = NULL;
978    Widget_Data *wd = elm_widget_data_get(obj);
979
980    if (!wd) return NULL;
981    if ((!wd->button_count) || (num >= ELM_POPUP_ACTION_BUTTON_MAX))
982      return NULL;
983
984    if (wd->buttons[num])
985      {
986         button = wd->buttons[num]->btn;
987         _button_remove(obj, button, EINA_FALSE);
988       }
989    return button;
990 }
991
992 static Evas_Object *
993 _content_unset_hook(Evas_Object *obj, const char *part)
994 {
995    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
996    Evas_Object *content = NULL;
997    char buff[3];
998    unsigned int i;
999    Widget_Data *wd = elm_widget_data_get(obj);
1000
1001    if (!wd) return NULL;
1002    if (!part || !strcmp(part, "default"))
1003      content = _content_unset(obj);
1004    else if (!strcmp(part, "title,icon"))
1005      content = _title_icon_unset(obj);
1006    else if (!strncmp(part, "button", 6))
1007      {
1008         part += 6;
1009         for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
1010           {
1011              snprintf(buff, sizeof(buff), "%u", i+1);
1012              if (!strncmp(part, buff, sizeof(buff)))
1013                {
1014                   content = _action_button_unset(obj, i+1);
1015                   break;
1016                }
1017           }
1018       }
1019    else
1020      WRN("The part name is invalid! : popup=%p", obj);
1021    return content;
1022 }
1023
1024 static Eina_Bool
1025 _focus_next_hook(const Evas_Object *obj __UNUSED__,
1026                  Elm_Focus_Direction dir __UNUSED__,
1027                  Evas_Object **next __UNUSED__)
1028 {
1029    //TODO: Implement Focus chanin Handling in Popup for action area buttons
1030    return EINA_FALSE;
1031 }
1032
1033 static void
1034 _item_text_set(Elm_Popup_Content_Item *item, const char *label)
1035 {
1036    if (!eina_stringshare_replace(&item->label, label)) return;
1037    edje_object_part_text_set(VIEW(item), "elm.text", label);
1038    if (item->label)
1039      edje_object_signal_emit(VIEW(item),
1040                              "elm,state,item,text,visible", "elm");
1041    else
1042      edje_object_signal_emit(VIEW(item),
1043                              "elm,state,item,text,hidden", "elm");
1044    edje_object_message_signal_process(VIEW(item));
1045 }
1046
1047 static void
1048 _item_text_set_hook(Elm_Object_Item *it, const char *part, const char *label)
1049 {
1050    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1051    Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1052
1053    if ((!part) || (!strcmp(part, "default")))
1054      {
1055         _item_text_set(item, label);
1056         return;
1057      }
1058    WRN("The part name is invalid! : popup=%p", WIDGET(item));
1059 }
1060
1061 static const char *
1062 _item_text_get_hook(const Elm_Object_Item *it, const char *part)
1063 {
1064    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
1065    Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1066
1067    if ((!part) || (!strcmp(part, "default")))
1068      return item->label;
1069    WRN("The part name is invalid! : popup=%p", WIDGET(item));
1070    return NULL;
1071 }
1072
1073 static void
1074 _item_icon_set(Elm_Popup_Content_Item *item, Evas_Object *icon)
1075 {
1076    if (item->icon == icon) return;
1077    if (item->icon)
1078      {
1079         evas_object_data_del(item->icon, "_popup_content_item");
1080         evas_object_del(item->icon);
1081      }
1082    item->icon = icon;
1083    if (item->icon)
1084      {
1085         elm_widget_sub_object_add(WIDGET(item), item->icon);
1086         evas_object_data_set(item->icon, "_popup_content_item", item);
1087         edje_object_part_swallow(VIEW(item), "elm.swallow.content",
1088                                  item->icon);
1089         edje_object_signal_emit(VIEW(item),
1090                                 "elm,state,item,icon,visible", "elm");
1091      }
1092    else
1093      edje_object_signal_emit(VIEW(item),
1094                              "elm,state,item,icon,hidden", "elm");
1095    edje_object_message_signal_process(item->base.view);
1096 }
1097
1098 static void
1099 _item_content_set_hook(Elm_Object_Item *it, const char *part,
1100                        Evas_Object *content)
1101 {
1102    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1103    Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1104
1105    if ((!(part)) || (!strcmp(part, "default")))
1106      _item_icon_set(item, content);
1107    else
1108      WRN("The part name is invalid! : popup=%p", WIDGET(item));
1109 }
1110
1111 static Evas_Object *
1112 _item_content_get_hook(const Elm_Object_Item *it,
1113                        const char *part)
1114 {
1115    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
1116    Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1117
1118    if ((!(part)) || (!strcmp(part, "default")))
1119      return item->icon;
1120    WRN("The part name is invalid! : popup=%p", WIDGET(item));
1121    return NULL;
1122 }
1123
1124 static Evas_Object *
1125 _item_icon_unset(Elm_Popup_Content_Item *item)
1126 {
1127    Evas_Object *icon = item->icon;
1128
1129    if (!item->icon) return NULL;
1130    elm_widget_sub_object_del(WIDGET(item), icon);
1131    evas_object_data_del(icon, "_popup_content_item");
1132    edje_object_part_unswallow(item->base.view, icon);
1133    edje_object_signal_emit(VIEW(item),
1134                            "elm,state,item,icon,hidden", "elm");
1135    item->icon = NULL;
1136    return icon;
1137 }
1138
1139 static Evas_Object *
1140 _item_content_unset_hook(const Elm_Object_Item *it,
1141                          const char *part)
1142 {
1143    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
1144    Evas_Object *content = NULL;
1145    Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1146
1147    if ((!(part)) || (!strcmp(part, "default")))
1148      content = _item_icon_unset(item);
1149    else
1150      WRN("The part name is invalid! : popup=%p", WIDGET(item));
1151    return content;
1152 }
1153
1154 static void
1155 _item_disable_hook(Elm_Object_Item *it)
1156 {
1157    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1158    Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1159    Widget_Data *wd = elm_widget_data_get(WIDGET(item));
1160
1161    if (!wd) return;
1162    if (elm_widget_item_disabled_get(it))
1163      edje_object_signal_emit(VIEW(item), "elm,state,item,disabled", "elm");
1164    else
1165      edje_object_signal_emit(VIEW(item), "elm,state,item,enabled", "elm");
1166 }
1167
1168 static void
1169 _item_del_pre_hook(Elm_Object_Item *it)
1170 {
1171    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1172    Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1173    Widget_Data *wd = elm_widget_data_get(WIDGET(item));
1174
1175    if (!wd) return;
1176    if (item->icon)
1177      evas_object_del(item->icon);
1178    eina_stringshare_del(item->label);
1179    wd->items = eina_list_remove(wd->items, item);
1180    if (!eina_list_count(wd->items))
1181      {
1182         wd->items = NULL;
1183         _list_del(wd);
1184      }
1185 }
1186
1187 static void
1188 _item_signal_emit_hook(Elm_Object_Item *it, const char *emission,
1189                        const char *source)
1190 {
1191    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1192    Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1193
1194    edje_object_signal_emit(VIEW(item), emission, source);
1195 }
1196
1197 static void
1198 _popup_show(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj,
1199                void *event_info __UNUSED__)
1200 {
1201    Widget_Data *wd;
1202
1203    wd = elm_widget_data_get(obj);
1204    if (!wd) return;
1205
1206    evas_object_show(wd->notify);
1207 }
1208
1209 EAPI Evas_Object *
1210 elm_popup_add(Evas_Object *parent)
1211 {
1212    Evas_Object *obj;
1213    Evas *e;
1214    int i = 0;
1215    Widget_Data *wd;
1216
1217    ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
1218    ELM_SET_WIDTYPE(widtype, "popup");
1219    elm_widget_type_set(obj, widtype);
1220    elm_widget_sub_object_add(parent, obj);
1221    elm_widget_data_set(obj, wd);
1222    elm_widget_del_pre_hook_set(obj, _del_pre_hook);
1223    elm_widget_del_hook_set(obj, _del_hook);
1224    elm_widget_theme_hook_set(obj, _theme_hook);
1225    elm_widget_text_set_hook_set(obj, _text_set_hook);
1226    elm_widget_text_get_hook_set(obj, _text_get_hook);
1227    elm_widget_content_set_hook_set(obj, _content_set_hook);
1228    elm_widget_content_get_hook_set(obj, _content_get_hook);
1229    elm_widget_content_unset_hook_set(obj,_content_unset_hook);
1230    elm_widget_focus_next_hook_set(obj, _focus_next_hook);
1231    evas_object_smart_callbacks_descriptions_set(obj, _signals);
1232
1233    wd->notify = elm_notify_add(obj);
1234    elm_notify_parent_set(wd->notify, parent);
1235    elm_notify_orient_set(wd->notify, ELM_NOTIFY_ORIENT_CENTER);
1236    elm_notify_allow_events_set(wd->notify, EINA_FALSE);
1237    evas_object_size_hint_weight_set(wd->notify,
1238                                     EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
1239    evas_object_size_hint_align_set(wd->notify, EVAS_HINT_FILL, EVAS_HINT_FILL);
1240    elm_object_style_set(wd->notify, "popup");
1241
1242    evas_object_event_callback_add(wd->notify, EVAS_CALLBACK_RESIZE,
1243                                   _notify_resize, obj);
1244    evas_object_event_callback_add(obj, EVAS_CALLBACK_SHOW, _popup_show,
1245                                   NULL);
1246    evas_object_event_callback_add(obj, EVAS_CALLBACK_RESTACK, _restack, NULL);
1247    wd->base = elm_layout_add(obj);
1248    evas_object_size_hint_weight_set(wd->base, EVAS_HINT_EXPAND,
1249                                     EVAS_HINT_EXPAND);
1250    evas_object_size_hint_align_set(wd->base, EVAS_HINT_FILL, EVAS_HINT_FILL);
1251
1252    elm_layout_theme_set(wd->base, "popup", "base", elm_widget_style_get(obj));
1253    elm_object_content_set(wd->notify, wd->base);
1254
1255    elm_object_signal_callback_add(wd->base, "elm,state,title_area,visible",
1256                                   "elm", _layout_change_cb, obj);
1257    elm_object_signal_callback_add(wd->base, "elm,state,title_area,hidden",
1258                                   "elm", _layout_change_cb, obj);
1259    elm_object_signal_callback_add(wd->base, "elm,state,action_area,visible",
1260                                   "elm", _layout_change_cb, obj);
1261    elm_object_signal_callback_add(wd->base, "elm,state,action_area,hidden",
1262                                   "elm", _layout_change_cb, obj);
1263    wd->content_area = elm_layout_add(obj);
1264    elm_layout_theme_set(wd->content_area, "popup", "content",
1265                         elm_widget_style_get(obj));
1266    wd->action_area = elm_layout_add(obj);
1267    evas_object_size_hint_weight_set(wd->action_area, EVAS_HINT_EXPAND,
1268                                     EVAS_HINT_EXPAND);
1269    evas_object_size_hint_align_set(wd->action_area, EVAS_HINT_FILL,
1270                                    EVAS_HINT_FILL);
1271    evas_object_event_callback_add(wd->action_area,
1272                                   EVAS_CALLBACK_CHANGED_SIZE_HINTS,
1273                                   _changed_size_hints, obj);
1274    evas_object_event_callback_add(wd->content_area,
1275                                   EVAS_CALLBACK_CHANGED_SIZE_HINTS,
1276                                   _changed_size_hints, obj);
1277    evas_object_smart_callback_add(wd->base, "sub-object-del",
1278                                   _sub_del, obj);
1279    evas_object_smart_callback_add(wd->content_area, "sub-object-del",
1280                                   _sub_del, obj);
1281    evas_object_smart_callback_add(wd->action_area, "sub-object-del",
1282                                   _sub_del, obj);
1283    evas_object_smart_callback_add(obj, "sub-object-del",
1284                                   _sub_del, obj);
1285
1286    wd->content_text_wrap_type = ELM_WRAP_MIXED;
1287    evas_object_smart_callback_add(wd->notify, "block,clicked",
1288                                   _block_clicked_cb, obj);
1289    evas_object_smart_callback_add(wd->notify, "timeout", _timeout, obj);
1290    for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
1291      wd->buttons[i] = NULL;
1292    _layout_set(obj);
1293    //TODO: To use scroller for description also
1294    return obj;
1295 }
1296
1297 EAPI void
1298 elm_popup_content_text_wrap_type_set(Evas_Object *obj, Elm_Wrap_Type wrap)
1299 {
1300    ELM_CHECK_WIDTYPE(obj, widtype);
1301    Evas_Object *content_text_obj;
1302    Widget_Data *wd = elm_widget_data_get(obj);
1303
1304    if (!wd) return;
1305    if (wd->content_text_wrap_type == ELM_WRAP_NONE) return;
1306    //Need to wrap the content text, so not allowing ELM_WRAP_NONE
1307    wd->content_text_wrap_type = wrap;
1308    if (wd->content_text_obj)
1309      {
1310         content_text_obj = elm_object_part_content_get(wd->content_area,
1311                                                        "elm.swallow.content");
1312         elm_label_line_wrap_set(content_text_obj, wrap);
1313      }
1314 }
1315
1316 EAPI Elm_Wrap_Type
1317 elm_popup_content_text_wrap_type_get(const Evas_Object *obj)
1318 {
1319    ELM_CHECK_WIDTYPE(obj, widtype) ELM_WRAP_LAST;
1320    Widget_Data *wd = elm_widget_data_get(obj);
1321
1322    if (!wd) return ELM_WRAP_LAST;
1323    return wd->content_text_wrap_type;
1324 }
1325
1326 EAPI void
1327 elm_popup_orient_set(Evas_Object *obj, Elm_Popup_Orient orient)
1328 {
1329    ELM_CHECK_WIDTYPE(obj, widtype);
1330    Widget_Data *wd = elm_widget_data_get(obj);
1331
1332    if (!wd) return;
1333    if (orient >= ELM_POPUP_ORIENT_LAST) return;
1334    elm_notify_orient_set(wd->notify, (Elm_Notify_Orient)orient);
1335 }
1336
1337 EAPI Elm_Popup_Orient
1338 elm_popup_orient_get(const Evas_Object *obj)
1339 {
1340    ELM_CHECK_WIDTYPE(obj, widtype) -1;
1341    Widget_Data *wd = elm_widget_data_get(obj);
1342
1343    if (!wd) return ELM_POPUP_ORIENT_LAST;
1344    return (Elm_Popup_Orient)elm_notify_orient_get(wd->notify);
1345 }
1346
1347 EAPI void
1348 elm_popup_timeout_set(Evas_Object *obj, double timeout)
1349 {
1350    ELM_CHECK_WIDTYPE(obj, widtype);
1351    Widget_Data *wd = elm_widget_data_get(obj);
1352
1353    if (!wd) return;
1354    elm_notify_timeout_set(wd->notify, timeout);
1355 }
1356
1357 EAPI double
1358 elm_popup_timeout_get(const Evas_Object *obj)
1359 {
1360    ELM_CHECK_WIDTYPE(obj, widtype) 0.0;
1361    Widget_Data *wd = elm_widget_data_get(obj);
1362
1363    if (!wd) return 0.0;
1364    return elm_notify_timeout_get(wd->notify);
1365 }
1366
1367 EAPI void
1368 elm_popup_allow_events_set(Evas_Object *obj, Eina_Bool allow)
1369 {
1370    ELM_CHECK_WIDTYPE(obj, widtype);
1371    Eina_Bool allow_events = !!allow;
1372    Widget_Data *wd = elm_widget_data_get(obj);
1373
1374    if (!wd) return;
1375    elm_notify_allow_events_set(wd->notify, allow_events);
1376 }
1377
1378 EAPI Eina_Bool
1379 elm_popup_allow_events_get(const Evas_Object *obj)
1380 {
1381    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1382    Widget_Data *wd = elm_widget_data_get(obj);
1383
1384    if (!wd) return EINA_FALSE;
1385    return elm_notify_allow_events_get(wd->notify);
1386 }
1387
1388 EAPI Elm_Object_Item *
1389 elm_popup_item_append(Evas_Object *obj, const char *label,
1390                               Evas_Object *icon, Evas_Smart_Cb func,
1391                               const void *data)
1392 {
1393    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1394    Evas_Object *prev_content;
1395    Elm_Popup_Content_Item *item;
1396    Widget_Data *wd = elm_widget_data_get(obj);
1397
1398    if (!wd) return NULL;
1399    item = elm_widget_item_new(obj, Elm_Popup_Content_Item);
1400    if (!item) return NULL;
1401    if (wd->content || wd->content_text_obj)
1402      {
1403         prev_content = elm_object_part_content_get(wd->content_area,
1404                                                    "elm.swallow.content");
1405         if (prev_content)
1406           evas_object_del(prev_content);
1407      }
1408
1409    //The first item is appended.
1410    if (!wd->items)
1411      _list_new(obj);
1412
1413    item->func = func;
1414    item->base.data = data;
1415
1416    _item_new(item);
1417    _item_icon_set(item, icon);
1418    _item_text_set(item, label);
1419    elm_box_pack_end(wd->box, VIEW(item));
1420    wd->items = eina_list_append(wd->items, item);
1421
1422    _scroller_size_calc(obj);
1423    _sizing_eval(obj);
1424    return (Elm_Object_Item *)item;
1425 }