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