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