1 #ifdef HAVE_CONFIG_H
2 # include "elementary_config.h"
3 #endif
4
5 #define EFL_ACCESS_OBJECT_PROTECTED
6 #define EFL_ACCESS_WIDGET_ACTION_PROTECTED
7 #define EFL_UI_FOCUS_LAYER_PROTECTED
8 #define EFL_PART_PROTECTED
9 #define EFL_UI_SCROLL_MANAGER_PROTECTED
10
11 #include <Elementary.h>
12
13 #include "elm_priv.h"
14 #include "efl_ui_panel_private.h"
15
16 #include "els_box.h"
17
18 #include "elm_part_helper.h"
19
20 #define MY_CLASS EFL_UI_PANEL_CLASS
21
22 #define MY_CLASS_NAME "Efl.Ui.Panel"
23
24 static const char ACCESS_OUTLINE_PART[] = "access.outline";
25 static const char SIG_TOGGLED[] = "toggled";
26 static const char SIG_SCROLL[] = "scroll";
27
28 static const Evas_Smart_Cb_Description _smart_callbacks[] = {
29 {SIG_TOGGLED, ""},
30 {SIG_SCROLL, ""},
31 {SIG_LAYOUT_FOCUSED, ""}, /**< handled by elm_layout */
32 {SIG_LAYOUT_UNFOCUSED, ""}, /**< handled by elm_layout */
33 {NULL, NULL}
34 };
35 static void _panel_toggle(void *, Evas_Object *, const char *,const char *);
36 static Eina_Bool _key_action_toggle(Evas_Object *obj, const char *params);
37 static void _drawer_open(Evas_Object *, Evas_Coord , Evas_Coord , Eina_Bool );
38 static void _drawer_close(Evas_Object *, Evas_Coord , Evas_Coord , Eina_Bool);
39
40 static const Elm_Action key_actions[] = {
41 {"toggle", _key_action_toggle},
42 {NULL, NULL}
43 };
44
45 static void
_mirrored_set(Evas_Object * obj,Eina_Bool rtl)46 _mirrored_set(Evas_Object *obj,
47 Eina_Bool rtl)
48 {
49 EFL_UI_PANEL_DATA_GET(obj, sd);
50
51 if ((sd->content) && (efl_isa(sd->content, EFL_UI_WIDGET_CLASS)))
52 efl_ui_mirrored_set(sd->content, rtl);
53 efl_ui_panel_orient_set(obj, efl_ui_panel_orient_get(obj));
54 }
55
56 EOLIAN static void
_efl_ui_panel_efl_canvas_group_group_calculate(Eo * obj,Efl_Ui_Panel_Data * sd)57 _efl_ui_panel_efl_canvas_group_group_calculate(Eo *obj, Efl_Ui_Panel_Data *sd)
58 {
59 if (sd->delete_me) return;
60
61 if (sd->scrollable)
62 {
63 Eina_Size2D size = efl_gfx_entity_size_get(obj);
64 if (sd->hidden) _drawer_close(obj, size.w, size.h, EINA_FALSE);
65 else _drawer_open(obj, size.w, size.h, EINA_FALSE);
66 }
67
68 efl_canvas_group_calculate(efl_super(obj, MY_CLASS));
69 }
70
71 static char *
_access_state_cb(void * data,Evas_Object * obj EINA_UNUSED)72 _access_state_cb(void *data, Evas_Object *obj EINA_UNUSED)
73 {
74 EFL_UI_PANEL_DATA_GET(data, sd);
75
76 if (!sd->hidden) return strdup(E_("state: opened"));
77 else return strdup(E_("state: closed"));
78
79 return NULL;
80 }
81
82 static Evas_Object *
_access_object_get(const Evas_Object * obj,const char * part)83 _access_object_get(const Evas_Object *obj, const char *part)
84 {
85 Evas_Object *po, *ao, *o;
86 EFL_UI_PANEL_DATA_GET(obj, sd);
87
88 o = elm_layout_edje_get(sd->scr_ly);
89 edje_object_freeze(o);
90 po = (Evas_Object *)edje_object_part_object_get(o, part);
91 edje_object_thaw(o);
92 ao = evas_object_data_get(po, "_part_access_obj");
93
94 return ao;
95 }
96
97 static void
_access_activate_cb(void * data,Evas_Object * part_obj EINA_UNUSED,Elm_Object_Item * item EINA_UNUSED)98 _access_activate_cb(void *data,
99 Evas_Object *part_obj EINA_UNUSED,
100 Elm_Object_Item *item EINA_UNUSED)
101 {
102 efl_ui_panel_hidden_set(data, EINA_TRUE);
103 }
104
105 static void
_access_obj_process(Evas_Object * obj,Eina_Bool is_access)106 _access_obj_process(Evas_Object *obj, Eina_Bool is_access)
107 {
108 Evas_Object *ao;
109 EFL_UI_PANEL_DATA_GET(obj, sd);
110
111 if (is_access)
112 {
113 ao = _access_object_get(obj, ACCESS_OUTLINE_PART);
114 if (!ao)
115 {
116 ao = _elm_access_edje_object_part_object_register
117 (obj, elm_layout_edje_get(sd->scr_ly), ACCESS_OUTLINE_PART);
118 _elm_access_text_set(_elm_access_info_get(ao),
119 ELM_ACCESS_TYPE, E_("A panel is open"));
120 _elm_access_text_set(_elm_access_info_get(ao),
121 ELM_ACCESS_CONTEXT_INFO, E_("Double tap to close panel menu"));
122 _elm_access_activate_callback_set
123 (_elm_access_info_get(ao), _access_activate_cb, obj);
124 }
125 }
126 else
127 {
128 _elm_access_edje_object_part_object_unregister
129 (obj, elm_layout_edje_get(sd->scr_ly), ACCESS_OUTLINE_PART);
130 }
131 }
132
133 static void
_orient_set_do(Evas_Object * obj)134 _orient_set_do(Evas_Object *obj)
135 {
136 EFL_UI_PANEL_DATA_GET(obj, sd);
137 ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
138
139 switch (sd->orient)
140 {
141 case EFL_UI_PANEL_ORIENT_TOP:
142 elm_widget_theme_element_set(obj, "top");
143 break;
144 case EFL_UI_PANEL_ORIENT_BOTTOM:
145 elm_widget_theme_element_set(obj, "bottom");
146 break;
147 case EFL_UI_PANEL_ORIENT_LEFT:
148 elm_widget_theme_element_set(obj, "left");
149 break;
150 case EFL_UI_PANEL_ORIENT_RIGHT:
151 elm_widget_theme_element_set(obj, "right");
152 break;
153 }
154
155 efl_ui_widget_theme_apply(obj);
156
157 /* access */
158 if (_elm_config->access_mode == ELM_ACCESS_MODE_ON)
159 {
160 Evas_Object *ao;
161 ao = _elm_access_edje_object_part_object_register
162 (obj, wd->resize_obj, "btn_icon");
163 _elm_access_text_set(_elm_access_info_get(ao),
164 ELM_ACCESS_TYPE, E_("panel button"));
165 _elm_access_callback_set
166 (_elm_access_info_get(ao), ELM_ACCESS_STATE, _access_state_cb, obj);
167 }
168 }
169
170 static void
_scrollable_layout_theme_set(Eo * obj,Efl_Ui_Panel_Data * sd)171 _scrollable_layout_theme_set(Eo *obj, Efl_Ui_Panel_Data *sd)
172 {
173 switch (sd->orient)
174 {
175 case EFL_UI_PANEL_ORIENT_TOP:
176 elm_widget_theme_element_set(sd->scr_ly, "scrollable/top");
177 break;
178 case EFL_UI_PANEL_ORIENT_BOTTOM:
179 elm_widget_theme_element_set(sd->scr_ly, "scrollable/bottom");
180 break;
181 case EFL_UI_PANEL_ORIENT_LEFT:
182 elm_widget_theme_element_set(sd->scr_ly, "scrollable/left");
183 break;
184 case EFL_UI_PANEL_ORIENT_RIGHT:
185 elm_widget_theme_element_set(sd->scr_ly, "scrollable/right");
186 break;
187 }
188
189 efl_ui_widget_theme_apply(sd->scr_ly);
190
191 /* access */
192 if (_elm_config->access_mode == ELM_ACCESS_MODE_ON)
193 _access_obj_process(obj, EINA_TRUE);
194 }
195
196 EOLIAN static Eina_Error
_efl_ui_panel_efl_ui_widget_theme_apply(Eo * obj,Efl_Ui_Panel_Data * sd)197 _efl_ui_panel_efl_ui_widget_theme_apply(Eo *obj, Efl_Ui_Panel_Data *sd)
198 {
199 const char *str;
200 Evas_Coord minw = 0, minh = 0;
201
202 Eina_Error int_ret = EFL_UI_THEME_APPLY_ERROR_GENERIC;
203
204 ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, EFL_UI_THEME_APPLY_ERROR_GENERIC);
205
206 int_ret = efl_ui_widget_theme_apply(efl_super(obj, MY_CLASS));
207 if (int_ret == EFL_UI_THEME_APPLY_ERROR_GENERIC) return int_ret;
208
209 _mirrored_set(obj, efl_ui_mirrored_get(obj));
210
211 if (sd->scrollable)
212 {
213 const char *handler_size;
214 elm_widget_theme_object_set(obj, sd->scr_edje, "panel", NULL,
215 elm_widget_style_get(obj));
216 handler_size = edje_object_data_get(sd->scr_edje, "handler_size");
217 if (handler_size)
218 sd->handler_size = (int) (elm_object_scale_get(obj)) * (atoi(handler_size));
219 }
220 else
221 {
222 str = edje_object_data_get
223 (wd->resize_obj, "focus_highlight");
224 if ((str) && (!strcmp(str, "on")))
225 elm_widget_highlight_in_theme_set(obj, EINA_TRUE);
226 else
227 elm_widget_highlight_in_theme_set(obj, EINA_FALSE);
228
229 evas_object_hide(sd->event);
230 elm_coords_finger_size_adjust(1, &minw, 1, &minh);
231 efl_gfx_hint_size_min_set(sd->event, EINA_SIZE2D(minw, minh));
232
233 if (edje_object_part_exists(wd->resize_obj, "efl.swallow.event"))
234 efl_content_set(efl_part(efl_super(obj, MY_CLASS), "efl.swallow.event"), sd->event);
235 }
236
237 return int_ret;
238 }
239
240 static void
_box_layout_cb(Evas_Object * o,Evas_Object_Box_Data * _pd,void * data EINA_UNUSED)241 _box_layout_cb(Evas_Object *o,
242 Evas_Object_Box_Data *_pd,
243 void *data EINA_UNUSED)
244 {
245 _els_box_layout(o, _pd, EINA_TRUE, EINA_FALSE, EINA_FALSE);
246 }
247
248 static void
_handler_open(Evas_Object * obj,Evas_Coord w,Evas_Coord h)249 _handler_open(Evas_Object *obj, Evas_Coord w, Evas_Coord h)
250 {
251 EFL_UI_PANEL_DATA_GET(obj, sd);
252
253 if (sd->handler_size == 0) return;
254
255 switch (sd->orient)
256 {
257 case EFL_UI_PANEL_ORIENT_TOP:
258 efl_ui_scrollable_scroll
259 (obj, EINA_RECT(0, (h * sd->content_size_ratio) - sd->handler_size, w, h), EINA_TRUE);
260 break;
261 case EFL_UI_PANEL_ORIENT_BOTTOM:
262 efl_ui_scrollable_scroll
263 (obj, EINA_RECT(0, sd->handler_size, w, h), EINA_TRUE);
264 break;
265 case EFL_UI_PANEL_ORIENT_LEFT:
266 efl_ui_scrollable_scroll
267 (obj, EINA_RECT((w * sd->content_size_ratio) - sd->handler_size, 0, w, h), EINA_TRUE);
268 break;
269 case EFL_UI_PANEL_ORIENT_RIGHT:
270 efl_ui_scrollable_scroll
271 (obj, EINA_RECT(sd->handler_size, 0, w, h), EINA_TRUE);
272 break;
273 }
274 }
275
276 static void
_drawer_open(Evas_Object * obj,Evas_Coord w,Evas_Coord h,Eina_Bool anim)277 _drawer_open(Evas_Object *obj, Evas_Coord w, Evas_Coord h, Eina_Bool anim)
278 {
279 EFL_UI_PANEL_DATA_GET(obj, sd);
280 int x = 0, y = 0;
281
282 if (sd->freeze)
283 {
284 efl_ui_scrollable_movement_block_set(obj, EFL_UI_LAYOUT_ORIENTATION_DEFAULT);
285 sd->freeze = EINA_FALSE;
286 elm_layout_signal_emit(sd->scr_ly, "efl,state,content,visible", "efl");
287 }
288
289 switch (sd->orient)
290 {
291 case EFL_UI_PANEL_ORIENT_TOP:
292 break;
293 case EFL_UI_PANEL_ORIENT_LEFT:
294 if (efl_ui_mirrored_get(obj))
295 x = w * sd->content_size_ratio;
296 break;
297
298 case EFL_UI_PANEL_ORIENT_BOTTOM:
299 y = h * sd->content_size_ratio;
300 break;
301
302 case EFL_UI_PANEL_ORIENT_RIGHT:
303 if (!efl_ui_mirrored_get(obj))
304 x = w * sd->content_size_ratio;
305 break;
306 }
307 efl_ui_scrollable_scroll(obj, EINA_RECT(x, y, w, h), anim);
308 }
309
310 static void
_drawer_close(Evas_Object * obj,Evas_Coord w,Evas_Coord h,Eina_Bool anim)311 _drawer_close(Evas_Object *obj, Evas_Coord w, Evas_Coord h, Eina_Bool anim)
312 {
313 EFL_UI_PANEL_DATA_GET(obj, sd);
314 int x = 0, y = 0;
315 Eina_Bool horizontal = EINA_FALSE;
316 Eina_Position2D c;
317
318 elm_widget_tree_unfocusable_set(obj, EINA_TRUE);
319 switch (sd->orient)
320 {
321 case EFL_UI_PANEL_ORIENT_TOP:
322 y = h * sd->content_size_ratio;
323 break;
324
325 case EFL_UI_PANEL_ORIENT_LEFT:
326 if (!efl_ui_mirrored_get(obj))
327 x = w * sd->content_size_ratio;
328 horizontal = EINA_TRUE;
329 break;
330
331 case EFL_UI_PANEL_ORIENT_BOTTOM:
332 break;
333
334 case EFL_UI_PANEL_ORIENT_RIGHT:
335 if (efl_ui_mirrored_get(obj))
336 x = w * sd->content_size_ratio;
337 horizontal = EINA_TRUE;
338 break;
339 }
340
341 c = efl_ui_scrollable_content_pos_get(obj);
342
343 if ((x == c.x) && (y == c.y))
344 {
345 if (!sd->freeze)
346 {
347 if (horizontal)
348 efl_ui_scrollable_movement_block_set
349 (obj, EFL_UI_LAYOUT_ORIENTATION_HORIZONTAL);
350 else
351 efl_ui_scrollable_movement_block_set
352 (obj, EFL_UI_LAYOUT_ORIENTATION_VERTICAL);
353 sd->freeze = EINA_TRUE;
354 elm_layout_signal_emit(sd->scr_ly, "efl,state,content,hidden", "efl");
355 }
356
357 return;
358 }
359
360 if (anim)
361 {
362 if (sd->freeze)
363 {
364 efl_ui_scrollable_movement_block_set
365 (obj, EFL_UI_LAYOUT_ORIENTATION_DEFAULT);
366 sd->freeze = EINA_FALSE;
367 elm_layout_signal_emit(sd->scr_ly, "efl,state,content,visible", "efl");
368 }
369 efl_ui_scrollable_scroll(obj, EINA_RECT(x, y, w, h), anim);
370 }
371 else
372 {
373 efl_ui_scrollable_scroll(obj, EINA_RECT(x, y, w, h), anim);
374 if (!sd->freeze)
375 {
376 if (horizontal)
377 efl_ui_scrollable_movement_block_set
378 (obj, EFL_UI_LAYOUT_ORIENTATION_HORIZONTAL);
379 else
380 efl_ui_scrollable_movement_block_set
381 (obj, EFL_UI_LAYOUT_ORIENTATION_VERTICAL);
382 sd->freeze = EINA_TRUE;
383 elm_layout_signal_emit(sd->scr_ly, "efl,state,content,hidden", "efl");
384 }
385 }
386 }
387
388 static void
_panel_toggle(void * data EINA_UNUSED,Evas_Object * obj,const char * emission EINA_UNUSED,const char * source EINA_UNUSED)389 _panel_toggle(void *data EINA_UNUSED,
390 Evas_Object *obj,
391 const char *emission EINA_UNUSED,
392 const char *source EINA_UNUSED)
393 {
394 EFL_UI_PANEL_DATA_GET(obj, sd);
395 ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
396 int w, h;
397
398 if (sd->scrollable)
399 {
400 if (elm_widget_disabled_get(obj)) return;
401
402 evas_object_geometry_get(obj, NULL, NULL, &w, &h);
403 if (sd->hidden)
404 {
405 sd->hidden = EINA_FALSE;
406 _drawer_open(obj, w, h, EINA_TRUE);
407 }
408 else
409 {
410 sd->hidden = EINA_TRUE;
411 _drawer_close(obj, w, h, EINA_TRUE);
412 }
413 }
414 else
415 {
416 if (sd->hidden)
417 {
418 elm_layout_signal_emit(obj, "efl,action,show", "efl");
419 sd->hidden = EINA_FALSE;
420 evas_object_repeat_events_set(obj, EINA_FALSE);
421 }
422 else
423 {
424 elm_layout_signal_emit(obj, "efl,action,hide", "efl");
425 sd->hidden = EINA_TRUE;
426 evas_object_repeat_events_set(obj, EINA_TRUE);
427 }
428
429 //if the panel is hidden, make this thing unfocusable
430 elm_widget_tree_unfocusable_set(obj, sd->hidden);
431 edje_object_message_signal_process(wd->resize_obj);
432 }
433
434 efl_ui_focus_layer_enable_set(obj, !sd->hidden);
435 efl_event_callback_call(obj, EFL_UI_PANEL_EVENT_TOGGLED, NULL);
436 }
437
438 static Eina_Bool
_state_sync(Evas_Object * obj)439 _state_sync(Evas_Object *obj)
440 {
441 EFL_UI_PANEL_DATA_GET(obj, sd);
442 Evas_Coord pos, panel_size, w, h, threshold;
443 Eina_Bool horizontal = EINA_FALSE, reverse = EINA_FALSE;
444 Eina_Position2D c;
445
446 evas_object_geometry_get(obj, NULL, NULL, &w, &h);
447
448 if (!evas_object_visible_get(sd->bx)) return EINA_TRUE;
449
450 switch (sd->orient)
451 {
452 case EFL_UI_PANEL_ORIENT_BOTTOM:
453 reverse = EINA_TRUE;
454 case EFL_UI_PANEL_ORIENT_TOP:
455 break;
456
457 case EFL_UI_PANEL_ORIENT_RIGHT:
458 reverse = EINA_TRUE;
459 EINA_FALLTHROUGH;
460 case EFL_UI_PANEL_ORIENT_LEFT:
461 horizontal = EINA_TRUE;
462 break;
463 }
464
465 c = efl_ui_scrollable_content_pos_get(obj);
466 if (horizontal)
467 {
468 if (w <= 0) return EINA_TRUE;
469
470 panel_size = w * sd->content_size_ratio;
471 pos = c.x;
472 reverse ^= efl_ui_mirrored_get(obj);
473 }
474 else
475 {
476 if (h <= 0) return EINA_TRUE;
477
478 panel_size = h * sd->content_size_ratio;
479 pos = c.y;
480 }
481 threshold = (sd->hidden) ? panel_size - (panel_size / 4) : (panel_size / 4);
482
483 if (reverse)
484 {
485 if (pos > panel_size - threshold) sd->hidden = EINA_FALSE;
486 else sd->hidden = EINA_TRUE;
487 }
488 else
489 {
490 if (pos < threshold) sd->hidden = EINA_FALSE;
491 else sd->hidden = EINA_TRUE;
492 }
493
494 return EINA_FALSE;
495 }
496
497 static Eina_Bool
_timer_cb(void * data)498 _timer_cb(void *data)
499 {
500 EFL_UI_PANEL_DATA_GET(data, sd);
501 Evas_Object *obj = data;
502 Evas_Coord w, h;
503
504 sd->timer = NULL;
505
506 if (sd->freeze)
507 {
508 efl_ui_scrollable_movement_block_set
509 (obj, EFL_UI_LAYOUT_ORIENTATION_DEFAULT);
510 sd->freeze = EINA_FALSE;
511 elm_layout_signal_emit(sd->scr_ly, "efl,state,content,visible", "efl");
512 evas_object_geometry_get(obj, NULL, NULL, &w, &h);
513 _handler_open(obj, w, h);
514 }
515
516 return ECORE_CALLBACK_CANCEL;
517 }
518
519 static void
_event_mouse_up(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info)520 _event_mouse_up(void *data,
521 Evas *e EINA_UNUSED,
522 Evas_Object *obj EINA_UNUSED,
523 void *event_info)
524 {
525 EFL_UI_PANEL_DATA_GET(data, sd);
526 Evas_Event_Mouse_Up *ev = event_info;
527 Evas_Coord x, y, up_x, up_y, minw = 0, minh = 0;
528 evas_object_geometry_get(data, &x, &y, NULL, NULL);
529
530 up_x = ev->canvas.x - x;
531 up_y = ev->canvas.y - y;
532
533 elm_coords_finger_size_adjust(1, &minw, 1, &minh);
534
535 if ((!sd->hidden) && (up_x == sd->down_x) && (up_y == sd->down_y))
536 efl_ui_panel_hidden_set(data, EINA_TRUE);
537 }
538
539 static void
_on_mouse_down(void * data,Evas * e EINA_UNUSED,Evas_Object * obj,void * event_info)540 _on_mouse_down(void *data,
541 Evas *e EINA_UNUSED,
542 Evas_Object *obj,
543 void *event_info)
544 {
545 Efl_Ui_Panel_Data *sd = data;
546 Evas_Event_Mouse_Down *ev = event_info;
547 Evas_Coord finger_size = elm_config_finger_size_get();
548 Evas_Coord x, y, w, h;
549 evas_object_geometry_get(obj, &x, &y, &w, &h);
550 Eina_Bool is_mirrored = efl_ui_mirrored_get(obj);
551
552 sd->down_x = ev->canvas.x - x;
553 sd->down_y = ev->canvas.y - y;
554
555 // if freeze state & mouse down on the edge
556 // then set timer for un-freeze
557 switch (sd->orient)
558 {
559 case EFL_UI_PANEL_ORIENT_TOP:
560 if ((sd->freeze) && (sd->down_y >= 0) && (sd->down_y < finger_size))
561 {
562 ecore_timer_del(sd->timer);
563 sd->timer = ecore_timer_add(0.2, _timer_cb, obj);
564 }
565 break;
566 case EFL_UI_PANEL_ORIENT_BOTTOM:
567 if ((sd->freeze) && (sd->down_y <= h) && (sd->down_y > (h - finger_size)))
568 {
569 ecore_timer_del(sd->timer);
570 sd->timer = ecore_timer_add(0.2, _timer_cb, obj);
571 }
572 break;
573 case EFL_UI_PANEL_ORIENT_LEFT:
574 if ((!is_mirrored && (sd->freeze) && (sd->down_x >= 0) && (sd->down_x < finger_size)) ||
575 ((is_mirrored && (sd->freeze) && (sd->down_x <= w) && (sd->down_x > (w - finger_size)))))
576 {
577 ecore_timer_del(sd->timer);
578 sd->timer = ecore_timer_add(0.2, _timer_cb, obj);
579 }
580 break;
581 case EFL_UI_PANEL_ORIENT_RIGHT:
582 if ((is_mirrored && (sd->freeze) && (sd->down_x >= 0) && (sd->down_x < finger_size)) ||
583 (!is_mirrored && (sd->freeze) && (sd->down_x <= w) && (sd->down_x > (w - finger_size))))
584 {
585 ecore_timer_del(sd->timer);
586 sd->timer = ecore_timer_add(0.2, _timer_cb, obj);
587 }
588 break;
589 }
590 }
591
592 static void
_on_mouse_move(void * data,Evas * e EINA_UNUSED,Evas_Object * obj,void * event_info)593 _on_mouse_move(void *data,
594 Evas *e EINA_UNUSED,
595 Evas_Object *obj,
596 void *event_info)
597 {
598 Efl_Ui_Panel_Data *sd = data;
599 Evas_Event_Mouse_Move *ev = event_info;
600 Evas_Coord x, y, w, h, cur_x, cur_y, finger_size;
601 evas_object_geometry_get(obj, &x, &y, &w, &h);
602 finger_size = elm_config_finger_size_get();
603 Eina_Bool is_mirrored = efl_ui_mirrored_get(obj);
604
605 cur_x = ev->cur.canvas.x - x;
606 cur_y = ev->cur.canvas.y - y;
607
608 // if mouse down on the edge (it means sd->timer is not null)
609 // and move more than finger size
610 // then un-freeze
611 switch (sd->orient)
612 {
613 case EFL_UI_PANEL_ORIENT_TOP:
614 if (sd->timer && ((cur_y - sd->down_y) > finger_size))
615 {
616 efl_ui_scrollable_movement_block_set
617 (obj, EFL_UI_LAYOUT_ORIENTATION_DEFAULT);
618 sd->freeze = EINA_FALSE;
619 elm_layout_signal_emit(sd->scr_ly, "efl,state,content,visible", "efl");
620 }
621 break;
622 case EFL_UI_PANEL_ORIENT_BOTTOM:
623 if (sd->timer && ((sd->down_y - cur_y) > finger_size))
624 {
625 efl_ui_scrollable_movement_block_set
626 (obj, EFL_UI_LAYOUT_ORIENTATION_DEFAULT);
627 sd->freeze = EINA_FALSE;
628 elm_layout_signal_emit(sd->scr_ly, "efl,state,content,visible", "efl");
629 }
630 break;
631 case EFL_UI_PANEL_ORIENT_LEFT:
632 if ((!is_mirrored && (sd->timer) && ((cur_x - sd->down_x) > finger_size)) ||
633 ((is_mirrored) && (sd->timer) && ((sd->down_x - cur_x) > finger_size)))
634 {
635 efl_ui_scrollable_movement_block_set
636 (obj, EFL_UI_LAYOUT_ORIENTATION_DEFAULT);
637 sd->freeze = EINA_FALSE;
638 elm_layout_signal_emit(sd->scr_ly, "efl,state,content,visible", "efl");
639 }
640 break;
641 case EFL_UI_PANEL_ORIENT_RIGHT:
642 if ((is_mirrored && (sd->timer) && ((cur_x - sd->down_x) > finger_size)) ||
643 (!is_mirrored && (sd->timer) && ((sd->down_x - cur_x) > finger_size)))
644 {
645 efl_ui_scrollable_movement_block_set
646 (obj, EFL_UI_LAYOUT_ORIENTATION_DEFAULT);
647 sd->freeze = EINA_FALSE;
648 elm_layout_signal_emit(sd->scr_ly, "efl,state,content,visible", "efl");
649 }
650 break;
651 }
652
653 if (!sd->freeze && sd->hidden)
654 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
655 }
656
657 static void
_on_mouse_up(void * data,Evas * e EINA_UNUSED,Evas_Object * obj,void * event_info)658 _on_mouse_up(void *data,
659 Evas *e EINA_UNUSED,
660 Evas_Object *obj,
661 void *event_info)
662 {
663 Efl_Ui_Panel_Data *sd = data;
664 Evas_Event_Mouse_Up *ev = event_info;
665 Evas_Coord w, h;
666 Eina_Bool hidden;
667
668 hidden = sd->hidden;
669 evas_object_geometry_get(obj, NULL, NULL, &w, &h);
670
671 ELM_SAFE_FREE(sd->timer, ecore_timer_del);
672
673 if (_state_sync(obj)) return;
674
675 if (sd->hidden) _drawer_close(obj, w, h, EINA_TRUE);
676 else _drawer_open(obj, w, h, EINA_TRUE);
677
678 if (sd->hidden != hidden)
679 efl_event_callback_legacy_call(obj, EFL_UI_PANEL_EVENT_TOGGLED, NULL);
680
681 if (!sd->freeze && sd->hidden)
682 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
683 }
684
685 static Eina_Bool
_key_action_toggle(Evas_Object * obj,const char * params EINA_UNUSED)686 _key_action_toggle(Evas_Object *obj, const char *params EINA_UNUSED)
687 {
688 _panel_toggle(NULL, obj, NULL, NULL);
689 return EINA_TRUE;
690 }
691
692 // _panel_elm_widget_widget_event
ELM_WIDGET_KEY_DOWN_DEFAULT_IMPLEMENT(panel,Efl_Ui_Panel_Data)693 ELM_WIDGET_KEY_DOWN_DEFAULT_IMPLEMENT(panel, Efl_Ui_Panel_Data)
694
695 EOLIAN static Eina_Bool
696 _efl_ui_panel_efl_ui_widget_widget_input_event_handler(Eo *obj, Efl_Ui_Panel_Data *pd, const Efl_Event *eo_event, Evas_Object *src)
697 {
698 if (src != obj) return EINA_FALSE;
699 return _panel_efl_ui_widget_widget_input_event_handler(obj, pd, eo_event, src);
700 }
701
702
703 static void
_invalidate_cb(void * data,const Efl_Event * ev EINA_UNUSED)704 _invalidate_cb(void *data, const Efl_Event *ev EINA_UNUSED)
705 {
706 efl_content_unset(data);
707 }
708
709 static void
_content_unset(Eo * obj EINA_UNUSED,Efl_Ui_Panel_Data * sd EINA_UNUSED)710 _content_unset(Eo *obj EINA_UNUSED, Efl_Ui_Panel_Data *sd EINA_UNUSED)
711 {
712 if (sd->content)
713 {
714 efl_event_callback_del(sd->content, EFL_EVENT_INVALIDATE, _invalidate_cb, obj);
715 evas_object_box_remove(sd->bx, sd->content);
716 if (!sd->scrollable)
717 efl_ui_widget_sub_object_del(obj, sd->content);
718 else
719 efl_ui_widget_sub_object_del(sd->scr_ly, sd->content);
720 sd->content = NULL;
721 }
722 }
723
724 static Eina_Bool
_efl_ui_panel_efl_content_content_set(Eo * obj,Efl_Ui_Panel_Data * sd,Efl_Gfx_Entity * content)725 _efl_ui_panel_efl_content_content_set(Eo *obj, Efl_Ui_Panel_Data *sd, Efl_Gfx_Entity *content)
726 {
727 if (sd->content == content) return EINA_TRUE;
728
729 if (sd->content)
730 {
731 Eo *c = sd->content;
732 _content_unset(obj, sd);
733 if (efl_alive_get(obj))
734 efl_del(c);
735 }
736 if (content && !elm_widget_sub_object_add(obj, content)) return EINA_FALSE;
737 sd->content = content;
738 if (sd->content)
739 {
740 efl_event_callback_add(sd->content, EFL_EVENT_INVALIDATE, _invalidate_cb, obj);
741 evas_object_box_append(sd->bx, sd->content);
742 evas_object_show(sd->content);
743 if (sd->scrollable)
744 elm_widget_sub_object_add(sd->scr_ly, sd->content);
745 }
746 efl_event_callback_call(obj, EFL_CONTENT_EVENT_CONTENT_CHANGED, content);
747 efl_canvas_group_change(obj);
748
749 return EINA_TRUE;
750 }
751
752 static Efl_Gfx_Entity*
_efl_ui_panel_efl_content_content_get(const Eo * obj EINA_UNUSED,Efl_Ui_Panel_Data * sd)753 _efl_ui_panel_efl_content_content_get(const Eo *obj EINA_UNUSED, Efl_Ui_Panel_Data *sd)
754 {
755 return sd->content;
756 }
757
758 static Efl_Gfx_Entity*
_efl_ui_panel_efl_content_content_unset(Eo * obj,Efl_Ui_Panel_Data * sd EINA_UNUSED)759 _efl_ui_panel_efl_content_content_unset(Eo *obj, Efl_Ui_Panel_Data *sd EINA_UNUSED)
760 {
761 Eo *o = sd->content;
762 _content_unset(obj, sd);
763 efl_event_callback_call(obj, EFL_CONTENT_EVENT_CONTENT_CHANGED, NULL);
764 return o;
765 }
766
767 static void
_scrollable_layout_resize(Eo * obj,Efl_Ui_Panel_Data * sd,Evas_Coord w,Evas_Coord h)768 _scrollable_layout_resize(Eo *obj, Efl_Ui_Panel_Data *sd, Evas_Coord w, Evas_Coord h)
769 {
770 switch (sd->orient)
771 {
772 case EFL_UI_PANEL_ORIENT_TOP:
773 case EFL_UI_PANEL_ORIENT_BOTTOM:
774 // vertical
775 evas_object_resize(sd->scr_ly, w, (1 + sd->content_size_ratio) * h);
776 efl_gfx_hint_size_min_set(sd->scr_panel, EINA_SIZE2D(w, (sd->content_size_ratio * h)));
777 efl_gfx_hint_size_min_set(sd->scr_event, EINA_SIZE2D(w, h));
778 break;
779 case EFL_UI_PANEL_ORIENT_LEFT:
780 case EFL_UI_PANEL_ORIENT_RIGHT:
781 // horizontal
782 evas_object_resize(sd->scr_ly, (1 + sd->content_size_ratio) * w, h);
783 efl_gfx_hint_size_min_set(sd->scr_panel, EINA_SIZE2D((sd->content_size_ratio * w), h));
784 efl_gfx_hint_size_min_set(sd->scr_event, EINA_SIZE2D(w, h));
785 break;
786 }
787 efl_canvas_group_change(obj);
788 }
789
790 EOLIAN static void
_efl_ui_panel_efl_gfx_entity_size_set(Eo * obj,Efl_Ui_Panel_Data * sd,Eina_Size2D sz)791 _efl_ui_panel_efl_gfx_entity_size_set(Eo *obj, Efl_Ui_Panel_Data *sd, Eina_Size2D sz)
792 {
793 if (_evas_object_intercept_call(obj, EVAS_OBJECT_INTERCEPT_CB_RESIZE, 0, sz.w, sz.h))
794 return;
795
796 efl_gfx_entity_size_set(efl_super(obj, MY_CLASS), sz);
797
798 if (!sd->scrollable) return;
799
800 _scrollable_layout_resize(obj, sd, sz.w, sz.h);
801 }
802
803 EOLIAN static void
_efl_ui_panel_efl_canvas_group_group_member_add(Eo * obj,Efl_Ui_Panel_Data * sd,Evas_Object * member)804 _efl_ui_panel_efl_canvas_group_group_member_add(Eo *obj, Efl_Ui_Panel_Data *sd, Evas_Object *member)
805 {
806 efl_canvas_group_member_add(efl_super(obj, MY_CLASS), member);
807
808 if (sd->scr_event) evas_object_raise(sd->scr_event);
809 }
810
811 EOLIAN static void
_efl_ui_panel_efl_ui_widget_on_access_update(Eo * obj,Efl_Ui_Panel_Data * _pd,Eina_Bool is_access)812 _efl_ui_panel_efl_ui_widget_on_access_update(Eo *obj, Efl_Ui_Panel_Data *_pd, Eina_Bool is_access)
813 {
814 ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
815 Efl_Ui_Panel_Data *sd = _pd;
816
817 if (sd->scrollable)
818 {
819 _access_obj_process(obj, is_access);
820 return;
821 }
822
823 if (is_access)
824 _elm_access_edje_object_part_object_register
825 (obj, wd->resize_obj, "btn_icon");
826 else
827 _elm_access_edje_object_part_object_unregister
828 (obj, wd->resize_obj, "btn_icon");
829 }
830
831 EOLIAN static Eo *
_efl_ui_panel_efl_object_constructor(Eo * obj,Efl_Ui_Panel_Data * _pd)832 _efl_ui_panel_efl_object_constructor(Eo *obj, Efl_Ui_Panel_Data *_pd)
833 {
834 ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, NULL);
835
836 obj = efl_constructor(efl_super(obj, MY_CLASS));
837 elm_widget_can_focus_set(obj, EINA_TRUE);
838
839 _pd->panel_edje = wd->resize_obj;
840
841 efl_ui_widget_theme_apply(obj);
842
843 _pd->bx = evas_object_box_add(evas_object_evas_get(obj));
844 evas_object_box_layout_set(_pd->bx, _box_layout_cb, _pd, NULL);
845 evas_object_show(_pd->bx);
846
847 elm_layout_signal_callback_add
848 (obj, "efl,action,panel,toggle", "*", _panel_toggle, obj);
849
850 _mirrored_set(obj, efl_ui_mirrored_get(obj));
851
852 _pd->event = evas_object_rectangle_add(evas_object_evas_get(obj));
853 evas_object_color_set(_pd->event, 0, 0, 0, 0);
854 evas_object_pass_events_set(_pd->event, EINA_TRUE);
855 elm_widget_sub_object_add(obj, _pd->event);
856
857 /* just to bootstrap and have theme hook to work */
858 if (!elm_layout_theme_set(obj, "panel", "top", elm_widget_style_get(obj)))
859 CRI("Failed to set layout!");
860 else
861 {
862 elm_layout_content_set(obj, "efl.content", _pd->bx);
863 /* trigger box recalc on manual panel calc */
864 _efl_ui_layout_subobjs_calc_set(obj, EINA_TRUE);
865 efl_ui_layout_finger_size_multiplier_set(obj, 0, 0);
866
867 if (edje_object_part_exists
868 (wd->resize_obj, "efl.swallow.event"))
869 {
870 Evas_Coord minw = 0, minh = 0;
871
872 elm_coords_finger_size_adjust(1, &minw, 1, &minh);
873 efl_gfx_hint_size_min_set(_pd->event, EINA_SIZE2D(minw, minh));
874 efl_content_set(efl_part(efl_super(obj, MY_CLASS), "efl.swallow.event"), _pd->event);
875 }
876 }
877
878 evas_object_smart_callbacks_descriptions_set(obj, _smart_callbacks);
879 efl_access_object_role_set(obj, EFL_ACCESS_ROLE_PANEL);
880
881 efl_ui_focus_layer_behaviour_set(obj, EINA_FALSE, EINA_FALSE);
882
883 return obj;
884 }
885
886 EOLIAN static void
_efl_ui_panel_efl_object_destructor(Eo * obj,Efl_Ui_Panel_Data * sd)887 _efl_ui_panel_efl_object_destructor(Eo *obj, Efl_Ui_Panel_Data *sd)
888 {
889 ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
890
891 sd->delete_me = EINA_TRUE;
892
893 ELM_SAFE_FREE(sd->timer, ecore_timer_del);
894
895 /* let's make our panel object the *last* to be processed, since it
896 * may (smart) parent other sub objects here */
897 {
898 unsigned int resize_id = 0;
899 if (eina_array_find(wd->children, wd->resize_obj, &resize_id))
900 {
901 //exchange with last
902 eina_array_data_set(wd->children, resize_id, eina_array_data_get(wd->children, eina_array_count(wd->children) - 1));
903 eina_array_data_set(wd->children, eina_array_count(wd->children) - 1, wd->resize_obj);
904 }
905 }
906
907 efl_destructor(efl_super(obj, MY_CLASS));
908 }
909
910 EOLIAN static void
_efl_ui_panel_orient_set(Eo * obj,Efl_Ui_Panel_Data * sd,Efl_Ui_Panel_Orient orient)911 _efl_ui_panel_orient_set(Eo *obj, Efl_Ui_Panel_Data *sd, Efl_Ui_Panel_Orient orient)
912 {
913 if (sd->orient == orient) return;
914 sd->orient = orient;
915
916 if (sd->scrollable)
917 {
918 _scrollable_layout_theme_set(obj, sd);
919
920 if (!sd->freeze)
921 {
922 switch (sd->orient)
923 {
924 case EFL_UI_PANEL_ORIENT_TOP:
925 case EFL_UI_PANEL_ORIENT_BOTTOM:
926 efl_ui_scrollable_movement_block_set
927 (obj, EFL_UI_LAYOUT_ORIENTATION_VERTICAL);
928 break;
929 case EFL_UI_PANEL_ORIENT_LEFT:
930 case EFL_UI_PANEL_ORIENT_RIGHT:
931 efl_ui_scrollable_movement_block_set
932 (obj, EFL_UI_LAYOUT_ORIENTATION_HORIZONTAL);
933 break;
934 }
935
936 sd->freeze = EINA_TRUE;
937 elm_layout_signal_emit(sd->scr_ly, "efl,state,content,hidden", "efl");
938 }
939
940 efl_ui_panel_scrollable_content_size_set(obj, sd->content_size_ratio);
941 }
942 else
943 _orient_set_do(obj);
944
945 efl_canvas_group_change(obj);
946 }
947
948 EOLIAN static Efl_Ui_Panel_Orient
_efl_ui_panel_orient_get(const Eo * obj EINA_UNUSED,Efl_Ui_Panel_Data * sd)949 _efl_ui_panel_orient_get(const Eo *obj EINA_UNUSED, Efl_Ui_Panel_Data *sd)
950 {
951 return sd->orient;
952 }
953
954 EOLIAN static void
_efl_ui_panel_hidden_set(Eo * obj,Efl_Ui_Panel_Data * sd,Eina_Bool hidden)955 _efl_ui_panel_hidden_set(Eo *obj, Efl_Ui_Panel_Data *sd, Eina_Bool hidden)
956 {
957 if (sd->hidden == !!hidden)
958 {
959 if (sd->scrollable && sd->hidden && !sd->freeze)
960 {
961 Evas_Coord w, h;
962 evas_object_geometry_get(obj, NULL, NULL, &w, &h);
963 _drawer_close(obj, w, h, EINA_TRUE);
964 }
965 return;
966 }
967
968 _panel_toggle(NULL, obj, NULL, NULL);
969 }
970
971 EOLIAN static Eina_Bool
_efl_ui_panel_hidden_get(const Eo * obj EINA_UNUSED,Efl_Ui_Panel_Data * sd)972 _efl_ui_panel_hidden_get(const Eo *obj EINA_UNUSED, Efl_Ui_Panel_Data *sd)
973 {
974 return sd->hidden;
975 }
976
977 EOLIAN static void
_efl_ui_panel_toggle(Eo * obj,Efl_Ui_Panel_Data * _pd EINA_UNUSED)978 _efl_ui_panel_toggle(Eo *obj, Efl_Ui_Panel_Data *_pd EINA_UNUSED)
979 {
980 _panel_toggle(NULL, obj, NULL, NULL);
981 }
982
983 EOLIAN static Eina_Rect
_efl_ui_panel_efl_ui_widget_interest_region_get(const Eo * obj,Efl_Ui_Panel_Data * sd)984 _efl_ui_panel_efl_ui_widget_interest_region_get(const Eo *obj, Efl_Ui_Panel_Data *sd)
985 {
986 Eina_Rect r = {};
987 Eina_Position2D p;
988
989 p = efl_ui_scrollable_content_pos_get(obj);
990 evas_object_geometry_get(obj, NULL, NULL, &r.w, &r.h);
991 switch (sd->orient)
992 {
993 case EFL_UI_PANEL_ORIENT_TOP:
994 case EFL_UI_PANEL_ORIENT_BOTTOM:
995 r.h *= sd->content_size_ratio;
996 break;
997 case EFL_UI_PANEL_ORIENT_LEFT:
998 case EFL_UI_PANEL_ORIENT_RIGHT:
999 r.w *= sd->content_size_ratio;
1000 break;
1001 }
1002 if (r.w < 1) r.w = 1;
1003 if (r.h < 1) r.h = 1;
1004 r.x = p.x;
1005 r.y = p.y;
1006
1007 return r;
1008 }
1009
1010 static void
_anim_stop_cb(void * data EINA_UNUSED,const Efl_Event * event)1011 _anim_stop_cb(void *data EINA_UNUSED, const Efl_Event *event)
1012 {
1013 Eo *obj = event->object;
1014 EFL_UI_PANEL_DATA_GET(obj, sd);
1015 Evas_Object *ao;
1016 Evas_Coord pos, w, h, panel_size = 0;
1017 Eina_Bool open = EINA_FALSE, horizontal = EINA_FALSE, reverse = EINA_FALSE;
1018 Eina_Position2D c;
1019
1020 if (elm_widget_disabled_get(obj)) return;
1021
1022 switch (sd->orient)
1023 {
1024 case EFL_UI_PANEL_ORIENT_BOTTOM:
1025 reverse = EINA_TRUE;
1026 case EFL_UI_PANEL_ORIENT_TOP:
1027 break;
1028
1029 case EFL_UI_PANEL_ORIENT_RIGHT:
1030 reverse = EINA_TRUE;
1031 EINA_FALLTHROUGH;
1032 case EFL_UI_PANEL_ORIENT_LEFT:
1033 horizontal = EINA_TRUE;
1034 break;
1035 }
1036
1037 c = efl_ui_scrollable_content_pos_get(obj);
1038 evas_object_geometry_get(obj, NULL, NULL, &w, &h);
1039 if (horizontal)
1040 {
1041 if (w <= 0) return;
1042
1043 panel_size = w * sd->content_size_ratio;
1044 pos = c.x;
1045 reverse ^= efl_ui_mirrored_get(obj);
1046 }
1047 else
1048 {
1049 if (h <= 0) return;
1050
1051 panel_size = h * sd->content_size_ratio;
1052 pos = c.y;
1053 }
1054
1055 if (pos == 0) open = !reverse;
1056 else if (pos == panel_size) open = reverse;
1057 else return;
1058
1059 if (open)
1060 {
1061 //focus & access
1062 elm_object_tree_focus_allow_set(obj, EINA_TRUE);
1063 if (_elm_config->access_mode == ELM_ACCESS_MODE_ON)
1064 {
1065 ao = _access_object_get(obj, ACCESS_OUTLINE_PART);
1066 evas_object_show(ao);
1067 _elm_access_highlight_set(ao);
1068 }
1069 else
1070 elm_object_focus_set(obj, EINA_TRUE);
1071 }
1072 else
1073 {
1074 if (horizontal)
1075 efl_ui_scrollable_movement_block_set
1076 (obj, EFL_UI_LAYOUT_ORIENTATION_HORIZONTAL);
1077 else
1078 efl_ui_scrollable_movement_block_set
1079 (obj, EFL_UI_LAYOUT_ORIENTATION_VERTICAL);
1080 sd->freeze = EINA_TRUE;
1081 elm_layout_signal_emit(sd->scr_ly, "efl,state,content,hidden", "efl");
1082
1083 //focus & access
1084 elm_object_tree_focus_allow_set(obj, EINA_FALSE);
1085 if (_elm_config->access_mode == ELM_ACCESS_MODE_ON)
1086 {
1087 ao = _access_object_get(obj, ACCESS_OUTLINE_PART);
1088 evas_object_hide(ao);
1089 }
1090 }
1091 }
1092
1093 static void
_scroll_cb(void * data EINA_UNUSED,const Efl_Event * event_info EINA_UNUSED)1094 _scroll_cb(void *data EINA_UNUSED, const Efl_Event *event_info EINA_UNUSED)
1095 {
1096 Eo *obj = event_info->object;
1097 EFL_UI_PANEL_DATA_GET(obj, sd);
1098
1099 if (elm_widget_disabled_get(obj)) return;
1100 // in the case of
1101 // freeze_set(FALSE) -> mouse_up -> freeze_set(TRUE) -> scroll
1102 if (sd->freeze)
1103 {
1104 efl_ui_scrollable_movement_block_set
1105 (obj, EFL_UI_LAYOUT_ORIENTATION_DEFAULT);
1106 sd->freeze = EINA_FALSE;
1107 elm_layout_signal_emit(sd->scr_ly, "efl,state,content,visible", "efl");
1108 }
1109 }
1110
1111 EOLIAN static void
_efl_ui_panel_efl_ui_widget_disabled_set(Eo * obj,Efl_Ui_Panel_Data * sd,Eina_Bool disabled)1112 _efl_ui_panel_efl_ui_widget_disabled_set(Eo *obj, Efl_Ui_Panel_Data *sd, Eina_Bool disabled)
1113 {
1114 efl_ui_widget_disabled_set(efl_super(obj, MY_CLASS), disabled);
1115
1116 if (sd->scrollable)
1117 {
1118 if (disabled && sd->callback_added)
1119 {
1120 switch (sd->orient)
1121 {
1122 case ELM_PANEL_ORIENT_BOTTOM:
1123 case ELM_PANEL_ORIENT_TOP:
1124 efl_ui_scrollable_movement_block_set
1125 (obj, EFL_UI_LAYOUT_ORIENTATION_VERTICAL);
1126 break;
1127
1128 case ELM_PANEL_ORIENT_RIGHT:
1129 case ELM_PANEL_ORIENT_LEFT:
1130 efl_ui_scrollable_movement_block_set
1131 (obj, EFL_UI_LAYOUT_ORIENTATION_HORIZONTAL);
1132 break;
1133 }
1134
1135 evas_object_event_callback_del(obj, EVAS_CALLBACK_MOUSE_DOWN,
1136 _on_mouse_down);
1137 evas_object_event_callback_del(obj, EVAS_CALLBACK_MOUSE_MOVE,
1138 _on_mouse_move);
1139 evas_object_event_callback_del(obj, EVAS_CALLBACK_MOUSE_UP,
1140 _on_mouse_up);
1141 evas_object_event_callback_del(sd->scr_event, EVAS_CALLBACK_MOUSE_UP,
1142 _event_mouse_up);
1143
1144 sd->callback_added = EINA_FALSE;
1145 }
1146 else if (!disabled && !sd->callback_added)
1147 {
1148 switch (sd->orient)
1149 {
1150 case ELM_PANEL_ORIENT_BOTTOM:
1151 case ELM_PANEL_ORIENT_TOP:
1152 efl_ui_scrollable_movement_block_set
1153 (obj, EFL_UI_LAYOUT_ORIENTATION_HORIZONTAL);
1154 break;
1155
1156 case ELM_PANEL_ORIENT_RIGHT:
1157 case ELM_PANEL_ORIENT_LEFT:
1158 efl_ui_scrollable_movement_block_set
1159 (obj, EFL_UI_LAYOUT_ORIENTATION_VERTICAL);
1160 break;
1161 }
1162
1163 evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_DOWN,
1164 _on_mouse_down, sd);
1165 evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_MOVE,
1166 _on_mouse_move, sd);
1167 evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_UP,
1168 _on_mouse_up, sd);
1169 evas_object_event_callback_add(sd->scr_event, EVAS_CALLBACK_MOUSE_UP,
1170 _event_mouse_up, obj);
1171
1172 sd->callback_added = EINA_TRUE;
1173 }
1174 }
1175 }
1176
1177 EOLIAN static double
_efl_ui_panel_scrollable_content_size_get(const Eo * obj EINA_UNUSED,Efl_Ui_Panel_Data * sd)1178 _efl_ui_panel_scrollable_content_size_get(const Eo *obj EINA_UNUSED, Efl_Ui_Panel_Data *sd)
1179 {
1180 return sd->content_size_ratio;
1181 }
1182
1183 EOLIAN static void
_efl_ui_panel_scrollable_content_size_set(Eo * obj,Efl_Ui_Panel_Data * sd,double ratio)1184 _efl_ui_panel_scrollable_content_size_set(Eo *obj, Efl_Ui_Panel_Data *sd, double ratio)
1185 {
1186 if (ratio < 0) ratio = 0;
1187 else if (ratio > 1.0) ratio = 1.0;
1188
1189 sd->content_size_ratio = ratio;
1190
1191 if (sd->scrollable)
1192 {
1193 Evas_Coord w, h;
1194 evas_object_geometry_get(obj, NULL, NULL, &w, &h);
1195
1196 _scrollable_layout_resize(obj, sd, w, h);
1197 }
1198 }
1199
1200 EOLIAN static Eina_Bool
_efl_ui_panel_scrollable_get(const Eo * obj EINA_UNUSED,Efl_Ui_Panel_Data * sd)1201 _efl_ui_panel_scrollable_get(const Eo *obj EINA_UNUSED, Efl_Ui_Panel_Data *sd)
1202 {
1203 return sd->scrollable;
1204 }
1205
1206 EOLIAN static void
_efl_ui_panel_scrollable_set(Eo * obj,Efl_Ui_Panel_Data * sd,Eina_Bool scrollable)1207 _efl_ui_panel_scrollable_set(Eo *obj, Efl_Ui_Panel_Data *sd, Eina_Bool scrollable)
1208 {
1209 scrollable = !!scrollable;
1210 if (sd->scrollable == scrollable) return;
1211 sd->scrollable = scrollable;
1212
1213 if (scrollable)
1214 {
1215 elm_layout_content_unset(obj, "efl.content");
1216
1217 elm_widget_resize_object_set(obj, NULL);
1218 elm_widget_sub_object_add(obj, sd->panel_edje);
1219
1220 if (!sd->scr_edje)
1221 {
1222 const char *handler_size;
1223
1224 sd->scr_edje = edje_object_add(evas_object_evas_get(obj));
1225 elm_widget_theme_object_set(obj, sd->scr_edje, "panel", NULL,
1226 elm_widget_style_get(obj));
1227 evas_object_size_hint_weight_set
1228 (sd->scr_edje, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
1229 evas_object_size_hint_align_set
1230 (sd->scr_edje, EVAS_HINT_FILL, EVAS_HINT_FILL);
1231
1232 handler_size = edje_object_data_get(sd->scr_edje, "handler_size");
1233 if (handler_size)
1234 sd->handler_size = (int) (elm_object_scale_get(obj)) * (atoi(handler_size));
1235 }
1236
1237 elm_widget_resize_object_set(obj, sd->scr_edje);
1238
1239 if (!sd->smanager)
1240 {
1241 sd->smanager = efl_add(EFL_UI_SCROLL_MANAGER_CLASS, obj);
1242 efl_ui_mirrored_set(sd->smanager, efl_ui_mirrored_get(obj));
1243
1244 efl_event_callback_add(obj, EFL_UI_EVENT_SCROLL_ANIM_FINISHED, _anim_stop_cb, NULL);
1245 efl_event_callback_add(obj, EFL_UI_EVENT_SCROLL_CHANGED, _scroll_cb, NULL);
1246 }
1247
1248 efl_composite_attach(obj, sd->smanager);
1249 efl_ui_scroll_connector_bind(obj, sd->smanager);
1250
1251 if (!sd->pan_obj)
1252 {
1253 sd->pan_obj = efl_add(EFL_UI_PAN_CLASS, obj);
1254 efl_ui_scroll_manager_pan_set(sd->smanager, sd->pan_obj);
1255 efl_content_set(efl_part(sd->scr_edje, "efl.content"), sd->pan_obj);
1256 }
1257
1258 if (!sd->scr_ly)
1259 {
1260 sd->scr_ly = efl_add(EFL_UI_LAYOUT_CLASS, obj,
1261 efl_ui_layout_theme_set(efl_added,
1262 "panel", "scrollable/left",
1263 efl_ui_widget_style_get(obj)));
1264
1265 efl_canvas_group_member_add(obj, sd->scr_ly);
1266 elm_widget_sub_object_add(obj, sd->scr_ly);
1267 _scrollable_layout_theme_set(obj, sd);
1268
1269 sd->scr_panel = evas_object_rectangle_add(evas_object_evas_get(obj));
1270 evas_object_color_set(sd->scr_panel, 0, 0, 0, 0);
1271 elm_widget_sub_object_add(obj, sd->scr_panel);
1272 if (!elm_layout_content_set(sd->scr_ly, "efl.panel_area", sd->scr_panel))
1273 elm_layout_content_set(sd->scr_ly, "panel_area", sd->scr_panel);
1274
1275 sd->scr_event = evas_object_rectangle_add(evas_object_evas_get(obj));
1276 evas_object_color_set(sd->scr_event, 0, 0, 0, 0);
1277 elm_widget_sub_object_add(obj, sd->scr_event);
1278 if (!elm_layout_content_set(sd->scr_ly, "efl.event_area", sd->scr_event))
1279 elm_layout_content_set(sd->scr_ly, "event_area", sd->scr_event);
1280 }
1281
1282 efl_content_set(sd->pan_obj, sd->scr_ly);
1283 sd->freeze = EINA_TRUE;
1284 efl_content_set(efl_part(sd->scr_ly, "efl.content"), sd->bx);
1285 if (sd->content) elm_widget_sub_object_add(sd->scr_ly, sd->content);
1286
1287 switch (sd->orient)
1288 {
1289 case EFL_UI_PANEL_ORIENT_TOP:
1290 case EFL_UI_PANEL_ORIENT_BOTTOM:
1291 efl_ui_scrollable_movement_block_set
1292 (obj, EFL_UI_LAYOUT_ORIENTATION_VERTICAL);
1293 break;
1294 case EFL_UI_PANEL_ORIENT_LEFT:
1295 case EFL_UI_PANEL_ORIENT_RIGHT:
1296 efl_ui_scrollable_movement_block_set
1297 (obj, EFL_UI_LAYOUT_ORIENTATION_HORIZONTAL);
1298 break;
1299 }
1300
1301 if (!elm_widget_disabled_get(obj) && !sd->callback_added)
1302 {
1303 evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_DOWN,
1304 _on_mouse_down, sd);
1305 evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_MOVE,
1306 _on_mouse_move, sd);
1307 evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_UP,
1308 _on_mouse_up, sd);
1309 evas_object_event_callback_add(sd->scr_event, EVAS_CALLBACK_MOUSE_UP,
1310 _event_mouse_up, obj);
1311
1312 sd->callback_added = EINA_TRUE;
1313 }
1314
1315 }
1316 else
1317 {
1318 efl_ui_scroll_connector_unbind(obj);
1319 efl_composite_detach(obj, sd->smanager);
1320
1321 if (sd->callback_added)
1322 {
1323 evas_object_event_callback_del(obj, EVAS_CALLBACK_MOUSE_DOWN, _on_mouse_down);
1324 evas_object_event_callback_del(obj, EVAS_CALLBACK_MOUSE_MOVE, _on_mouse_move);
1325 evas_object_event_callback_del(obj, EVAS_CALLBACK_MOUSE_UP, _on_mouse_up);
1326 evas_object_event_callback_del(sd->scr_event, EVAS_CALLBACK_MOUSE_UP,
1327 _event_mouse_up);
1328
1329 sd->callback_added = EINA_FALSE;
1330 }
1331
1332 elm_widget_resize_object_set(obj, NULL);
1333 elm_widget_sub_object_add(obj, sd->scr_edje);
1334
1335 elm_widget_resize_object_set(obj, sd->panel_edje);
1336
1337 elm_layout_content_unset(sd->scr_ly, "efl.content");
1338 elm_layout_content_set(obj, "efl.content", sd->bx);
1339 if (sd->content) elm_widget_sub_object_add(obj, sd->content);
1340 }
1341 }
1342
1343 EOLIAN static void
_efl_ui_panel_efl_ui_i18n_mirrored_set(Eo * obj,Efl_Ui_Panel_Data * sd,Eina_Bool mirrored)1344 _efl_ui_panel_efl_ui_i18n_mirrored_set(Eo *obj, Efl_Ui_Panel_Data *sd, Eina_Bool mirrored)
1345 {
1346 if (sd->scrollable)
1347 efl_ui_mirrored_set(efl_cast(obj, ELM_INTERFACE_SCROLLABLE_MIXIN), mirrored);
1348 else
1349 efl_ui_mirrored_set(efl_cast(obj, EFL_UI_WIDGET_CLASS), mirrored);
1350 }
1351
1352 EOLIAN const Efl_Access_Action_Data *
_efl_ui_panel_efl_access_widget_action_elm_actions_get(const Eo * obj EINA_UNUSED,Efl_Ui_Panel_Data * pd EINA_UNUSED)1353 _efl_ui_panel_efl_access_widget_action_elm_actions_get(const Eo *obj EINA_UNUSED, Efl_Ui_Panel_Data *pd EINA_UNUSED)
1354 {
1355 static Efl_Access_Action_Data atspi_actions[] = {
1356 { "toggle", "toggle", NULL, _key_action_toggle},
1357 { NULL, NULL, NULL, NULL }
1358 };
1359 return &atspi_actions[0];
1360 }
1361
1362 /* Internal EO APIs and hidden overrides */
1363
1364 #include "efl_ui_panel.eo.c"
1365