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