1 #ifdef HAVE_CONFIG_H
2 # include "elementary_config.h"
3 #endif
4
5 #define EFL_PART_PROTECTED
6 #define EFL_UI_POPUP_PROTECTED
7 #define EFL_PART_PROTECTED
8 #define EFL_UI_WIDGET_SCROLLABLE_CONTENT_PROTECTED
9 #include <Elementary.h>
10
11 #include "elm_priv.h"
12 #include "efl_ui_popup_private.h"
13 #include "efl_ui_popup_part_backwall.eo.h"
14 #include "elm_part_helper.h"
15
16 #define MY_CLASS EFL_UI_POPUP_CLASS
17 #define MY_CLASS_NAME "Efl.Ui.Popup"
18
19 static const char PART_NAME_BACKWALL[] = "backwall";
20
21 static void
_calc_align(Eo * obj)22 _calc_align(Eo *obj)
23 {
24 Efl_Ui_Popup_Data *pd = efl_data_scope_get(obj, MY_CLASS);
25
26 Eina_Rect p_geom = efl_gfx_entity_geometry_get(pd->win_parent);
27
28 Eina_Rect o_geom = efl_gfx_entity_geometry_get(obj);
29
30 Evas_Coord pw, ph;
31 pw = p_geom.w;
32 ph = p_geom.h;
33
34 Evas_Coord ow, oh;
35 ow = o_geom.w;
36 oh = o_geom.h;
37
38 switch (pd->align)
39 {
40 case EFL_UI_POPUP_ALIGN_CENTER:
41 efl_gfx_entity_position_set(efl_super(obj, MY_CLASS), EINA_POSITION2D((pw - ow ) / 2, (ph - oh) / 2));
42 break;
43 case EFL_UI_POPUP_ALIGN_LEFT:
44 efl_gfx_entity_position_set(efl_super(obj, MY_CLASS), EINA_POSITION2D(0, (ph - oh) / 2));
45 break;
46 case EFL_UI_POPUP_ALIGN_RIGHT:
47 efl_gfx_entity_position_set(efl_super(obj, MY_CLASS), EINA_POSITION2D(pw - ow, (ph - oh) / 2));
48 break;
49 case EFL_UI_POPUP_ALIGN_TOP:
50 efl_gfx_entity_position_set(efl_super(obj, MY_CLASS), EINA_POSITION2D((pw - ow) / 2, 0));
51 break;
52 case EFL_UI_POPUP_ALIGN_BOTTOM:
53 efl_gfx_entity_position_set(efl_super(obj, MY_CLASS), EINA_POSITION2D((pw - ow) / 2, ph - oh));
54 break;
55 default:
56 break;
57 }
58 }
59
60 static void
_anchor_calc(Eo * obj)61 _anchor_calc(Eo *obj)
62 {
63 ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
64 EFL_UI_POPUP_DATA_GET_OR_RETURN(obj, pd);
65
66 if (!pd->anchor) return;
67
68 Eina_Position2D pos = {0, 0};
69
70 Eina_Rect a_geom = efl_gfx_entity_geometry_get(pd->anchor);
71 Eina_Rect o_geom = efl_gfx_entity_geometry_get(obj);
72 Eina_Rect p_geom = efl_gfx_entity_geometry_get(pd->win_parent);
73
74 pd->used_align = EFL_UI_POPUP_ALIGN_NONE;
75
76 /* 1. Find align which display popup.
77 It enables to shifting popup from exact position.
78 LEFT, RIGHT - shift only y position within anchor object's height
79 TOP, BOTTOM - shift only x position within anchor object's width
80 CENTER - shift both x, y position within anchor object's area
81 */
82
83 for (int idx = 0; idx < 6; idx++)
84 {
85 Efl_Ui_Popup_Align cur_align;
86
87 if (idx == 0)
88 cur_align = pd->align;
89 else
90 cur_align = pd->priority[idx - 1];
91
92 if (cur_align == EFL_UI_POPUP_ALIGN_NONE)
93 continue;
94
95 switch(cur_align)
96 {
97 case EFL_UI_POPUP_ALIGN_TOP:
98 pos.x = a_geom.x + ((a_geom.w - o_geom.w) / 2);
99 pos.y = (a_geom.y - o_geom.h);
100
101 if ((pos.y < 0) ||
102 ((pos.y + o_geom.h) > p_geom.h) ||
103 (o_geom.w > p_geom.w))
104 continue;
105 break;
106
107 case EFL_UI_POPUP_ALIGN_LEFT:
108 pos.x = (a_geom.x - o_geom.w);
109 pos.y = a_geom.y + ((a_geom.h - o_geom.h) / 2);
110
111 if ((pos.x < 0) ||
112 ((pos.x + o_geom.w) > p_geom.w) ||
113 (o_geom.h > p_geom.h))
114 continue;
115 break;
116
117 case EFL_UI_POPUP_ALIGN_RIGHT:
118 pos.x = (a_geom.x + a_geom.w);
119 pos.y = a_geom.y + ((a_geom.h - o_geom.h) / 2);
120
121 if ((pos.x < 0) ||
122 ((pos.x + o_geom.w) > p_geom.w) ||
123 (o_geom.h > p_geom.h))
124 continue;
125 break;
126
127 case EFL_UI_POPUP_ALIGN_BOTTOM:
128 pos.x = a_geom.x + ((a_geom.w - o_geom.w) / 2);
129 pos.y = (a_geom.y + a_geom.h);
130
131 if ((pos.y < 0) ||
132 ((pos.y + o_geom.h) > p_geom.h) ||
133 (o_geom.w > p_geom.w))
134 continue;
135 break;
136
137 case EFL_UI_POPUP_ALIGN_CENTER:
138 pos.x = a_geom.x + ((a_geom.w - o_geom.w) / 2);
139 pos.y = a_geom.y + ((a_geom.h - o_geom.h) / 2);
140
141 if ((o_geom.w > p_geom.w) || (o_geom.h > p_geom.h))
142 continue;
143 break;
144
145 default:
146 continue;
147 }
148
149 if ((cur_align == EFL_UI_POPUP_ALIGN_TOP) ||
150 (cur_align == EFL_UI_POPUP_ALIGN_BOTTOM) ||
151 (cur_align == EFL_UI_POPUP_ALIGN_CENTER))
152 {
153 if (pos.x < 0)
154 pos.x = 0;
155 if ((pos.x + o_geom.w) > p_geom.w)
156 pos.x = p_geom.w - o_geom.w;
157
158 if ((pos.x > (a_geom.x + a_geom.w)) ||
159 ((pos.x + o_geom.w) < a_geom.x))
160 continue;
161 }
162
163 if ((cur_align == EFL_UI_POPUP_ALIGN_LEFT) ||
164 (cur_align == EFL_UI_POPUP_ALIGN_RIGHT) ||
165 (cur_align == EFL_UI_POPUP_ALIGN_CENTER))
166 {
167 if (pos.y < 0)
168 pos.y = 0;
169 if ((pos.y + o_geom.h) > p_geom.h)
170 pos.y = p_geom.h - o_geom.h;
171
172 if ((pos.y > (a_geom.y + a_geom.h)) ||
173 ((pos.y + o_geom.h) < a_geom.y))
174 continue;
175 }
176
177 pd->used_align = cur_align;
178 goto end;
179 }
180
181 /* 2. Move popup to fit first valid align although entire popup can't display */
182
183 for (int idx = 0; idx < 6; idx++)
184 {
185 Efl_Ui_Popup_Align cur_align;
186
187 if (idx == 0)
188 cur_align = pd->align;
189 else
190 cur_align = pd->priority[idx - 1];
191
192 if (cur_align == EFL_UI_POPUP_ALIGN_NONE)
193 continue;
194
195 switch(cur_align)
196 {
197 case EFL_UI_POPUP_ALIGN_TOP:
198 pos.x = a_geom.x + ((a_geom.w - o_geom.w) / 2);
199 pos.y = (a_geom.y - o_geom.h);
200 pd->used_align = cur_align;
201 goto end;
202 break;
203
204 case EFL_UI_POPUP_ALIGN_LEFT:
205 pos.x = (a_geom.x - o_geom.w);
206 pos.y = a_geom.y + ((a_geom.h - o_geom.h) / 2);
207 pd->used_align = cur_align;
208 goto end;
209 break;
210
211 case EFL_UI_POPUP_ALIGN_RIGHT:
212 pos.x = (a_geom.x + a_geom.w);
213 pos.y = a_geom.y + ((a_geom.h - o_geom.h) / 2);
214 pd->used_align = cur_align;
215 goto end;
216 break;
217
218 case EFL_UI_POPUP_ALIGN_BOTTOM:
219 pos.x = a_geom.x + ((a_geom.w - o_geom.w) / 2);
220 pos.y = (a_geom.y + a_geom.h);
221 pd->used_align = cur_align;
222 goto end;
223 break;
224
225 case EFL_UI_POPUP_ALIGN_CENTER:
226 pos.x = a_geom.x + ((a_geom.w - o_geom.w) / 2);
227 pos.y = a_geom.y + ((a_geom.h - o_geom.h) / 2);
228 pd->used_align = cur_align;
229 goto end;
230 break;
231
232 default:
233 break;
234 }
235 }
236
237 end:
238 if (pd->used_align != EFL_UI_POPUP_ALIGN_NONE)
239 efl_gfx_entity_position_set(efl_super(obj, MY_CLASS), pos);
240 }
241
242 static void
_anchor_geom_cb(void * data,const Efl_Event * ev EINA_UNUSED)243 _anchor_geom_cb(void *data, const Efl_Event *ev EINA_UNUSED)
244 {
245 _anchor_calc(data);
246 }
247
248 static void
_anchor_del_cb(void * data,const Efl_Event * ev EINA_UNUSED)249 _anchor_del_cb(void *data, const Efl_Event *ev EINA_UNUSED)
250 {
251 EFL_UI_POPUP_DATA_GET_OR_RETURN(data, pd);
252
253 efl_event_callback_del(pd->win_parent, EFL_GFX_ENTITY_EVENT_SIZE_CHANGED, _anchor_geom_cb, data);
254
255 pd->anchor = NULL;
256 _anchor_calc(data);
257 }
258
259 static void
_anchor_detach(Eo * obj,Efl_Ui_Popup_Data * pd)260 _anchor_detach(Eo *obj, Efl_Ui_Popup_Data *pd)
261 {
262 if (!pd->anchor) return;
263
264 efl_event_callback_del(pd->win_parent, EFL_GFX_ENTITY_EVENT_SIZE_CHANGED, _anchor_geom_cb, obj);
265 efl_event_callback_del(pd->anchor, EFL_GFX_ENTITY_EVENT_SIZE_CHANGED, _anchor_geom_cb, obj);
266 efl_event_callback_del(pd->anchor, EFL_GFX_ENTITY_EVENT_POSITION_CHANGED, _anchor_geom_cb, obj);
267 efl_event_callback_del(pd->anchor, EFL_EVENT_DEL, _anchor_del_cb, obj);
268 }
269
270 EOLIAN static void
_efl_ui_popup_anchor_set(Eo * obj,Efl_Ui_Popup_Data * pd,Eo * anchor)271 _efl_ui_popup_anchor_set(Eo *obj, Efl_Ui_Popup_Data *pd, Eo *anchor)
272 {
273 _anchor_detach(obj, pd);
274 pd->anchor = anchor;
275
276 if (anchor)
277 {
278 efl_event_callback_add(pd->win_parent, EFL_GFX_ENTITY_EVENT_SIZE_CHANGED, _anchor_geom_cb, obj);
279 efl_event_callback_add(anchor, EFL_GFX_ENTITY_EVENT_SIZE_CHANGED, _anchor_geom_cb, obj);
280 efl_event_callback_add(anchor, EFL_GFX_ENTITY_EVENT_POSITION_CHANGED, _anchor_geom_cb, obj);
281 efl_event_callback_add(anchor, EFL_EVENT_DEL, _anchor_del_cb, obj);
282 _anchor_calc(obj);
283 }
284 else
285 _calc_align(obj);
286 }
287
288 EOLIAN static Efl_Object *
_efl_ui_popup_anchor_get(const Eo * obj EINA_UNUSED,Efl_Ui_Popup_Data * pd)289 _efl_ui_popup_anchor_get(const Eo *obj EINA_UNUSED, Efl_Ui_Popup_Data *pd)
290 {
291 return pd->anchor;
292 }
293
294 EOLIAN static void
_efl_ui_popup_align_priority_set(Eo * obj EINA_UNUSED,Efl_Ui_Popup_Data * pd,Efl_Ui_Popup_Align first,Efl_Ui_Popup_Align second,Efl_Ui_Popup_Align third,Efl_Ui_Popup_Align fourth,Efl_Ui_Popup_Align fifth)295 _efl_ui_popup_align_priority_set(Eo *obj EINA_UNUSED,
296 Efl_Ui_Popup_Data *pd,
297 Efl_Ui_Popup_Align first,
298 Efl_Ui_Popup_Align second,
299 Efl_Ui_Popup_Align third,
300 Efl_Ui_Popup_Align fourth,
301 Efl_Ui_Popup_Align fifth)
302 {
303 pd->priority[0] = first;
304 pd->priority[1] = second;
305 pd->priority[2] = third;
306 pd->priority[3] = fourth;
307 pd->priority[4] = fifth;
308 }
309
310 EOLIAN static void
_efl_ui_popup_align_priority_get(const Eo * obj EINA_UNUSED,Efl_Ui_Popup_Data * pd,Efl_Ui_Popup_Align * first,Efl_Ui_Popup_Align * second,Efl_Ui_Popup_Align * third,Efl_Ui_Popup_Align * fourth,Efl_Ui_Popup_Align * fifth)311 _efl_ui_popup_align_priority_get(const Eo *obj EINA_UNUSED,
312 Efl_Ui_Popup_Data *pd,
313 Efl_Ui_Popup_Align *first,
314 Efl_Ui_Popup_Align *second,
315 Efl_Ui_Popup_Align *third,
316 Efl_Ui_Popup_Align *fourth,
317 Efl_Ui_Popup_Align *fifth)
318 {
319 if (first) *first = pd->priority[0];
320 if (second) *second = pd->priority[1];
321 if (third) *third = pd->priority[2];
322 if (fourth) *fourth = pd->priority[3];
323 if (fifth) *fifth = pd->priority[4];
324 }
325
326
327 static void
_backwall_clicked_cb(void * data,Eo * o EINA_UNUSED,const char * emission EINA_UNUSED,const char * source EINA_UNUSED)328 _backwall_clicked_cb(void *data,
329 Eo *o EINA_UNUSED,
330 const char *emission EINA_UNUSED,
331 const char *source EINA_UNUSED)
332 {
333 Eo *obj = data;
334 efl_event_callback_call(obj, EFL_UI_POPUP_EVENT_BACKWALL_CLICKED, NULL);
335 }
336
337 EOLIAN static void
_efl_ui_popup_efl_gfx_entity_position_set(Eo * obj,Efl_Ui_Popup_Data * pd,Eina_Position2D pos)338 _efl_ui_popup_efl_gfx_entity_position_set(Eo *obj, Efl_Ui_Popup_Data *pd, Eina_Position2D pos)
339 {
340 pd->align = EFL_UI_POPUP_ALIGN_NONE;
341 _anchor_detach(obj, pd);
342
343 pd->anchor = NULL;
344 efl_gfx_entity_position_set(efl_super(obj, MY_CLASS), pos);
345 }
346
347 EOLIAN static void
_efl_ui_popup_efl_gfx_entity_size_set(Eo * obj,Efl_Ui_Popup_Data * pd,Eina_Size2D size)348 _efl_ui_popup_efl_gfx_entity_size_set(Eo *obj, Efl_Ui_Popup_Data *pd, Eina_Size2D size)
349 {
350 efl_gfx_entity_size_set(efl_super(obj, MY_CLASS), size);
351
352 if (!pd->in_calc)
353 efl_canvas_group_change(obj);
354 }
355
356 static void
_parent_geom_cb(void * data,const Efl_Event * ev EINA_UNUSED)357 _parent_geom_cb(void *data, const Efl_Event *ev EINA_UNUSED)
358 {
359 Eo *obj = data;
360
361 EFL_UI_POPUP_DATA_GET_OR_RETURN(obj, pd);
362
363 efl_canvas_group_change(obj);
364 }
365
366 static void
_hints_changed_cb(void * data,const Efl_Event * ev EINA_UNUSED)367 _hints_changed_cb(void *data, const Efl_Event *ev EINA_UNUSED)
368 {
369 Efl_Ui_Popup_Data *pd = data;
370
371 if (!pd->in_calc)
372 efl_canvas_group_change(ev->object);
373 }
374
375 EOLIAN static void
_efl_ui_popup_efl_ui_widget_widget_parent_set(Eo * obj,Efl_Ui_Popup_Data * pd,Eo * parent)376 _efl_ui_popup_efl_ui_widget_widget_parent_set(Eo *obj, Efl_Ui_Popup_Data *pd, Eo *parent)
377 {
378 if (!parent)
379 {
380 /* unsetting parent, probably before deletion */
381 if (pd->win_parent)
382 {
383 efl_event_callback_del(pd->win_parent, EFL_GFX_ENTITY_EVENT_SIZE_CHANGED, _parent_geom_cb, obj);
384 efl_event_callback_del(pd->win_parent, EFL_GFX_ENTITY_EVENT_POSITION_CHANGED, _parent_geom_cb, obj);
385 }
386 goto end;
387 }
388 pd->win_parent = efl_provider_find(obj, EFL_UI_WIN_CLASS);
389 if (!pd->win_parent)
390 {
391 ERR("Cannot find window parent");
392 return;
393 }
394
395 Eina_Rect p_geom = efl_gfx_entity_geometry_get(pd->win_parent);
396
397 efl_gfx_entity_position_set(pd->backwall, EINA_POSITION2D(p_geom.x, p_geom.y));
398 efl_gfx_entity_size_set(pd->backwall, EINA_SIZE2D(p_geom.w, p_geom.h));
399
400 efl_event_callback_add(pd->win_parent, EFL_GFX_ENTITY_EVENT_SIZE_CHANGED, _parent_geom_cb, obj);
401 efl_event_callback_add(pd->win_parent, EFL_GFX_ENTITY_EVENT_POSITION_CHANGED, _parent_geom_cb, obj);
402 end:
403 efl_ui_widget_parent_set(efl_super(obj, MY_CLASS), parent);
404 }
405
406 EOLIAN static void
_efl_ui_popup_align_set(Eo * obj EINA_UNUSED,Efl_Ui_Popup_Data * pd,Efl_Ui_Popup_Align type)407 _efl_ui_popup_align_set(Eo *obj EINA_UNUSED, Efl_Ui_Popup_Data *pd, Efl_Ui_Popup_Align type)
408 {
409 pd->align = type;
410
411 efl_canvas_group_change(obj);
412 }
413
414 EOLIAN static Efl_Ui_Popup_Align
_efl_ui_popup_align_get(const Eo * obj EINA_UNUSED,Efl_Ui_Popup_Data * pd)415 _efl_ui_popup_align_get(const Eo *obj EINA_UNUSED, Efl_Ui_Popup_Data *pd)
416 {
417 return pd->align;
418 }
419
420 static Eina_Bool
_timer_cb(void * data)421 _timer_cb(void *data)
422 {
423 Eo *popup = data;
424 efl_event_callback_call(popup, EFL_UI_POPUP_EVENT_TIMEOUT, NULL);
425 efl_del(popup);
426
427 return ECORE_CALLBACK_CANCEL;
428 }
429
430 static void
_timer_del(Efl_Ui_Popup_Data * pd)431 _timer_del(Efl_Ui_Popup_Data *pd)
432 {
433 if (pd->timer)
434 {
435 ecore_timer_del(pd->timer);
436 pd->timer = NULL;
437 }
438 }
439
440 static void
_timer_init(Eo * obj,Efl_Ui_Popup_Data * pd)441 _timer_init(Eo *obj, Efl_Ui_Popup_Data *pd)
442 {
443 if (pd->timeout > 0.0)
444 pd->timer = ecore_timer_add(pd->timeout, _timer_cb, obj);
445 }
446
447 EOLIAN static void
_efl_ui_popup_efl_gfx_entity_visible_set(Eo * obj,Efl_Ui_Popup_Data * pd,Eina_Bool v)448 _efl_ui_popup_efl_gfx_entity_visible_set(Eo *obj, Efl_Ui_Popup_Data *pd, Eina_Bool v)
449 {
450 if (_evas_object_intercept_call(obj, EVAS_OBJECT_INTERCEPT_CB_VISIBLE, 0, v))
451 return;
452
453 efl_gfx_entity_visible_set(efl_super(obj, MY_CLASS), v);
454
455 if (v)
456 {
457 _timer_del(pd);
458 _timer_init(obj, pd);
459 }
460 }
461
462 EOLIAN static void
_efl_ui_popup_closing_timeout_set(Eo * obj,Efl_Ui_Popup_Data * pd,double time)463 _efl_ui_popup_closing_timeout_set(Eo *obj, Efl_Ui_Popup_Data *pd, double time)
464 {
465 if (time < 0.0)
466 time = 0.0;
467
468 pd->timeout = time;
469
470 _timer_del(pd);
471
472 if (efl_gfx_entity_visible_get(obj))
473 _timer_init(obj, pd);
474 }
475
476 EOLIAN static double
_efl_ui_popup_closing_timeout_get(const Eo * obj EINA_UNUSED,Efl_Ui_Popup_Data * pd)477 _efl_ui_popup_closing_timeout_get(const Eo *obj EINA_UNUSED, Efl_Ui_Popup_Data *pd)
478 {
479 return pd->timeout;
480 }
481
482 /* this will ONLY be called during _sizing_eval() */
483 static void
_scrollable_content_size_cb(void * data EINA_UNUSED,const Efl_Event * ev)484 _scrollable_content_size_cb(void *data EINA_UNUSED, const Efl_Event *ev)
485 {
486 Eina_Size2D *size = ev->info;
487
488 efl_gfx_entity_size_set(ev->object, *size);
489 /* finish group calc chain */
490 efl_canvas_group_calculate(efl_super(ev->object, EFL_UI_WIDGET_SCROLLABLE_CONTENT_MIXIN));
491 }
492
493 static void
_sizing_eval(Eo * obj)494 _sizing_eval(Eo *obj)
495 {
496 Eina_Size2D min;
497
498 /* trigger layout calc */
499 efl_canvas_group_calculate(efl_super(obj, MY_CLASS));
500 if (efl_ui_widget_scrollable_content_did_group_calc_get(obj)) return;
501 min = efl_gfx_hint_size_combined_min_get(obj);
502
503 Eina_Size2D size = efl_gfx_entity_size_get(obj);
504
505 Eina_Size2D new_size;
506 new_size.w = (min.w > size.w ? min.w : size.w);
507 new_size.h = (min.h > size.h ? min.h : size.h);
508 efl_gfx_entity_size_set(obj, new_size);
509 }
510
511 EOLIAN static void
_efl_ui_popup_efl_canvas_group_group_calculate(Eo * obj,Efl_Ui_Popup_Data * pd)512 _efl_ui_popup_efl_canvas_group_group_calculate(Eo *obj, Efl_Ui_Popup_Data *pd)
513 {
514 /* When efl_canvas_group_change() is called, just flag is set instead of size
515 * calculation.
516 * The actual size calculation is done here when the object is rendered to
517 * avoid duplicate size calculations. */
518 efl_canvas_group_need_recalculate_set(obj, EINA_FALSE);
519 pd->in_calc = EINA_TRUE;
520 _sizing_eval(obj);
521 pd->in_calc = EINA_FALSE;
522 if (pd->anchor)
523 _anchor_calc(obj);
524 else
525 _calc_align(obj);
526
527 Eina_Rect p_geom = efl_gfx_entity_geometry_get(pd->win_parent);
528
529 efl_gfx_entity_position_set(pd->backwall, EINA_POSITION2D(0, 0));
530 efl_gfx_entity_size_set(pd->backwall, EINA_SIZE2D(p_geom.w, p_geom.h));
531 }
532
533 EOLIAN static Eo *
_efl_ui_popup_efl_object_constructor(Eo * obj,Efl_Ui_Popup_Data * pd)534 _efl_ui_popup_efl_object_constructor(Eo *obj, Efl_Ui_Popup_Data *pd)
535 {
536 ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, NULL);
537
538 if (!elm_widget_theme_klass_get(obj))
539 elm_widget_theme_klass_set(obj, "popup");
540 obj = efl_constructor(efl_super(obj, MY_CLASS));
541 efl_canvas_object_type_set(obj, MY_CLASS_NAME);
542 efl_event_callback_add(obj, EFL_GFX_ENTITY_EVENT_HINTS_CHANGED, _hints_changed_cb, pd);
543 efl_event_callback_add(obj, EFL_UI_WIDGET_SCROLLABLE_CONTENT_EVENT_OPTIMAL_SIZE_CALC, _scrollable_content_size_cb, pd);
544
545 elm_widget_can_focus_set(obj, EINA_TRUE);
546 if (elm_widget_theme_object_set(obj, wd->resize_obj,
547 elm_widget_theme_klass_get(obj),
548 elm_widget_theme_element_get(obj),
549 elm_widget_theme_style_get(obj)) == EFL_UI_THEME_APPLY_ERROR_GENERIC)
550 CRI("Failed to set layout!");
551
552 pd->backwall = edje_object_add(evas_object_evas_get(obj));
553 elm_widget_element_update(obj, pd->backwall, PART_NAME_BACKWALL);
554 evas_object_smart_member_add(pd->backwall, obj);
555 evas_object_stack_below(pd->backwall, wd->resize_obj);
556
557 edje_object_signal_callback_add(pd->backwall, "efl,action,click", "*",
558 _backwall_clicked_cb, obj);
559
560 pd->align = EFL_UI_POPUP_ALIGN_CENTER;
561
562 pd->priority[0] = EFL_UI_POPUP_ALIGN_TOP;
563 pd->priority[1] = EFL_UI_POPUP_ALIGN_LEFT;
564 pd->priority[2] = EFL_UI_POPUP_ALIGN_RIGHT;
565 pd->priority[3] = EFL_UI_POPUP_ALIGN_BOTTOM;
566 pd->priority[4] = EFL_UI_POPUP_ALIGN_CENTER;
567 return obj;
568 }
569
570 EOLIAN static void
_efl_ui_popup_efl_object_invalidate(Eo * obj,Efl_Ui_Popup_Data * pd)571 _efl_ui_popup_efl_object_invalidate(Eo *obj, Efl_Ui_Popup_Data *pd)
572 {
573 ELM_SAFE_DEL(pd->backwall);
574 efl_invalidate(efl_super(obj, MY_CLASS));
575 }
576
577 EOLIAN static void
_efl_ui_popup_efl_object_destructor(Eo * obj,Efl_Ui_Popup_Data * pd)578 _efl_ui_popup_efl_object_destructor(Eo *obj, Efl_Ui_Popup_Data *pd)
579 {
580 _anchor_detach(obj, pd);
581
582 efl_event_callback_del(pd->win_parent, EFL_GFX_ENTITY_EVENT_SIZE_CHANGED, _parent_geom_cb,
583 obj);
584 efl_event_callback_del(pd->win_parent, EFL_GFX_ENTITY_EVENT_POSITION_CHANGED, _parent_geom_cb,
585 obj);
586
587 efl_destructor(efl_super(obj, MY_CLASS));
588 }
589
590 /* Standard widget overrides */
591
ELM_PART_CONTENT_DEFAULT_IMPLEMENT(efl_ui_popup,Efl_Ui_Popup_Data)592 ELM_PART_CONTENT_DEFAULT_IMPLEMENT(efl_ui_popup, Efl_Ui_Popup_Data)
593
594 EOLIAN static Eo *
595 _efl_ui_popup_efl_part_part_get(const Eo *obj, Efl_Ui_Popup_Data *_pd EINA_UNUSED, const char *part)
596 {
597 EINA_SAFETY_ON_NULL_RETURN_VAL(part, NULL);
598
599 if (eina_streq(part, PART_NAME_BACKWALL))
600 return ELM_PART_IMPLEMENT(EFL_UI_POPUP_PART_BACKWALL_CLASS, obj, part);
601
602 return efl_part_get(efl_super(obj, MY_CLASS), part);
603 }
604
605 EOLIAN static void
_efl_ui_popup_part_backwall_repeat_events_set(Eo * obj,void * _pd EINA_UNUSED,Eina_Bool repeat)606 _efl_ui_popup_part_backwall_repeat_events_set(Eo *obj, void *_pd EINA_UNUSED, Eina_Bool repeat)
607 {
608 Elm_Part_Data *pd = efl_data_scope_get(obj, EFL_UI_WIDGET_PART_CLASS);
609 Efl_Ui_Popup_Data *sd = efl_data_scope_get(pd->obj, EFL_UI_POPUP_CLASS);
610
611 efl_canvas_object_repeat_events_set(sd->backwall, repeat);
612 }
613
614 EOLIAN static Eina_Bool
_efl_ui_popup_part_backwall_repeat_events_get(const Eo * obj,void * _pd EINA_UNUSED)615 _efl_ui_popup_part_backwall_repeat_events_get(const Eo *obj, void *_pd EINA_UNUSED)
616 {
617 Elm_Part_Data *pd = efl_data_scope_get(obj, EFL_UI_WIDGET_PART_CLASS);
618 Efl_Ui_Popup_Data *sd = efl_data_scope_get(pd->obj, EFL_UI_POPUP_CLASS);
619
620 return efl_canvas_object_repeat_events_get(sd->backwall);
621 }
622
623 EOLIAN static Eina_Stringshare *
_efl_ui_popup_part_backwall_efl_file_file_get(const Eo * obj,void * _pd EINA_UNUSED)624 _efl_ui_popup_part_backwall_efl_file_file_get(const Eo *obj, void *_pd EINA_UNUSED)
625 {
626 Elm_Part_Data *pd = efl_data_scope_get(obj, EFL_UI_WIDGET_PART_CLASS);
627 Efl_Ui_Popup_Data *sd = efl_data_scope_get(pd->obj, EFL_UI_POPUP_CLASS);
628
629 Eo *content = edje_object_part_swallow_get(sd->backwall, "efl.content");
630 return content ? efl_file_get(content) : NULL;
631 }
632
633 EOLIAN static Eina_Stringshare *
_efl_ui_popup_part_backwall_efl_file_key_get(const Eo * obj,void * _pd EINA_UNUSED)634 _efl_ui_popup_part_backwall_efl_file_key_get(const Eo *obj, void *_pd EINA_UNUSED)
635 {
636 Elm_Part_Data *pd = efl_data_scope_get(obj, EFL_UI_WIDGET_PART_CLASS);
637 Efl_Ui_Popup_Data *sd = efl_data_scope_get(pd->obj, EFL_UI_POPUP_CLASS);
638
639 Eo *content = edje_object_part_swallow_get(sd->backwall, "efl.content");
640 return content ? efl_file_key_get(content) : NULL;
641 }
642
643 EOLIAN static void
_efl_ui_popup_part_backwall_efl_file_unload(Eo * obj,void * _pd EINA_UNUSED)644 _efl_ui_popup_part_backwall_efl_file_unload(Eo *obj, void *_pd EINA_UNUSED)
645 {
646 Elm_Part_Data *pd = efl_data_scope_get(obj, EFL_UI_WIDGET_PART_CLASS);
647 Efl_Ui_Popup_Data *sd = efl_data_scope_get(pd->obj, EFL_UI_POPUP_CLASS);
648
649 efl_file_unload(efl_super(obj, EFL_UI_POPUP_PART_BACKWALL_CLASS));
650 Eo *prev_obj = edje_object_part_swallow_get(sd->backwall, "efl.content");
651 if (prev_obj)
652 {
653 edje_object_signal_emit(sd->backwall, "efl,state,content,unset", "efl");
654 edje_object_part_unswallow(sd->backwall, prev_obj);
655 efl_del(prev_obj);
656 }
657 }
658
659 EOLIAN static Eina_Error
_efl_ui_popup_part_backwall_efl_file_load(Eo * obj,void * _pd EINA_UNUSED)660 _efl_ui_popup_part_backwall_efl_file_load(Eo *obj, void *_pd EINA_UNUSED)
661 {
662 Elm_Part_Data *pd = efl_data_scope_get(obj, EFL_UI_WIDGET_PART_CLASS);
663 Efl_Ui_Popup_Data *sd = efl_data_scope_get(pd->obj, EFL_UI_POPUP_CLASS);
664
665 Eina_Error err;
666
667 if (efl_file_loaded_get(obj)) return 0;
668
669 err = efl_file_load(efl_super(obj, EFL_UI_POPUP_PART_BACKWALL_CLASS));
670 if (err) return err;
671
672 Eo *prev_obj = edje_object_part_swallow_get(sd->backwall, "efl.content");
673 if (prev_obj)
674 {
675 edje_object_signal_emit(sd->backwall, "efl,state,content,unset", "efl");
676 edje_object_part_unswallow(sd->backwall, prev_obj);
677 efl_del(prev_obj);
678 }
679
680 Eo *image = efl_add(EFL_UI_IMAGE_CLASS, pd->obj);
681 Eina_Bool ret;
682 const Eina_File *f;
683
684 f = efl_file_mmap_get(obj);
685 if (f)
686 ret = efl_file_simple_mmap_load(image, f, efl_file_key_get(obj));
687 else
688 ret = efl_file_simple_load(image, efl_file_get(obj), efl_file_key_get(obj));
689 if (!ret)
690 {
691 efl_del(image);
692 return EFL_GFX_IMAGE_LOAD_ERROR_GENERIC;
693 }
694 edje_object_part_swallow(sd->backwall, "efl.content", image);
695 edje_object_signal_emit(sd->backwall, "efl,state,content,set", "efl");
696
697 return 0;
698 }
699
700 #include "efl_ui_popup_part_backwall.eo.c"
701
702 /* Efl.Part end */
703
704 #include "efl_ui_popup.eo.c"
705