1 #ifdef HAVE_CONFIG_H
2 #include "elementary_config.h"
3 #endif
4 #define EFL_UI_SCROLL_MANAGER_PROTECTED
5 #define EFL_UI_SCROLLBAR_PROTECTED
6 
7 #include <Elementary.h>
8 #include <Efl_Ui.h>
9 #include "elm_priv.h"
10 
11 typedef struct {
12    Eo *obj;
13    Eo *smanager;
14    int freeze_want;
15    Eina_Bool scroll_count : 1;
16    Eina_Bool need_scroll : 1;
17 } Scroll_Connector_Context;
18 
19 static void
_scroll_connector_bar_read_and_update(Scroll_Connector_Context * ctx)20 _scroll_connector_bar_read_and_update(Scroll_Connector_Context *ctx)
21 {
22    ELM_WIDGET_DATA_GET_OR_RETURN(ctx->obj, wd);
23    double vx = 0.0, vy = 0.0;
24 
25    edje_object_part_drag_value_get
26      (wd->resize_obj, "efl.draggable.vertical_bar", NULL, &vy);
27 
28    edje_object_part_drag_value_get
29      (wd->resize_obj, "efl.draggable.horizontal_bar", &vx, NULL);
30 
31    efl_ui_scrollbar_bar_position_set(ctx->smanager, vx, vy);
32 }
33 
34 static void
_scroll_connector_reload_cb(void * data,Evas_Object * obj EINA_UNUSED,const char * emission EINA_UNUSED,const char * source EINA_UNUSED)35 _scroll_connector_reload_cb(void *data,
36                        Evas_Object *obj EINA_UNUSED,
37                        const char *emission EINA_UNUSED,
38                        const char *source EINA_UNUSED)
39 {
40    Scroll_Connector_Context *ctx = data;
41    ELM_WIDGET_DATA_GET_OR_RETURN(ctx->obj, wd);
42    Eina_Bool hbar_visible = EINA_FALSE, vbar_visible = EINA_FALSE;
43 
44    efl_ui_scrollbar_bar_visibility_get(ctx->smanager, &hbar_visible, &vbar_visible);
45 
46    if (hbar_visible)
47      efl_layout_signal_emit(wd->resize_obj, "efl,horizontal_bar,visible,on", "efl");
48    else
49      efl_layout_signal_emit(wd->resize_obj, "efl,horizontal_bar,visible,off", "efl");
50 
51    if (vbar_visible)
52      efl_layout_signal_emit(wd->resize_obj, "efl,vertical_bar,visible,on", "efl");
53    else
54      efl_layout_signal_emit(wd->resize_obj, "efl,vertical_bar,visible,off", "efl");
55 
56    efl_ui_scrollbar_bar_visibility_update(ctx->smanager);
57 }
58 
59 
60 static void
_scroll_connector_edje_drag_cb(void * data,Evas_Object * obj EINA_UNUSED,const char * emission EINA_UNUSED,const char * source EINA_UNUSED)61 _scroll_connector_edje_drag_cb(void *data,
62                           Evas_Object *obj EINA_UNUSED,
63                           const char *emission EINA_UNUSED,
64                           const char *source EINA_UNUSED)
65 {
66    Scroll_Connector_Context *ctx = data;
67 
68    _scroll_connector_bar_read_and_update(ctx);
69 }
70 
71 
72 static void
_scroll(void * data,Evas_Object * obj,const char * emission EINA_UNUSED,const char * source EINA_UNUSED)73 _scroll(void *data,
74                           Evas_Object *obj,
75                           const char *emission EINA_UNUSED,
76                           const char *source EINA_UNUSED)
77 {
78    Scroll_Connector_Context *ctx = data;
79 
80    ctx->scroll_count = EINA_FALSE;
81    if (!ctx->need_scroll) return;
82    ctx->need_scroll = EINA_FALSE;
83    efl_layout_signal_emit(obj, "efl,action,scroll", "efl");
84 }
85 
86 static void
_scroll_connector_edje_drag_start_cb(void * data,Evas_Object * obj EINA_UNUSED,const char * emission EINA_UNUSED,const char * source EINA_UNUSED)87 _scroll_connector_edje_drag_start_cb(void *data,
88                                 Evas_Object *obj EINA_UNUSED,
89                                 const char *emission EINA_UNUSED,
90                                 const char *source EINA_UNUSED)
91 {
92    Scroll_Connector_Context *ctx = data;
93 
94    _scroll_connector_bar_read_and_update(ctx);
95 
96    ctx->freeze_want = efl_ui_scrollable_scroll_freeze_get(ctx->smanager);
97    efl_ui_scrollable_scroll_freeze_set(ctx->smanager, EINA_TRUE);
98    efl_event_callback_call(ctx->obj, EFL_UI_EVENT_SCROLL_DRAG_STARTED, NULL);
99 }
100 
101 static void
_scroll_connector_edje_drag_stop_cb(void * data,Evas_Object * obj EINA_UNUSED,const char * emission EINA_UNUSED,const char * source EINA_UNUSED)102 _scroll_connector_edje_drag_stop_cb(void *data,
103                                Evas_Object *obj EINA_UNUSED,
104                                const char *emission EINA_UNUSED,
105                                const char *source EINA_UNUSED)
106 {
107    Scroll_Connector_Context *ctx = data;
108 
109    _scroll_connector_bar_read_and_update(ctx);
110    EINA_SAFETY_ON_TRUE_RETURN(ctx->freeze_want == -1);
111    efl_ui_scrollable_scroll_freeze_set(ctx->smanager, ctx->freeze_want);
112    ctx->freeze_want = -1;
113    efl_event_callback_call(ctx->obj, EFL_UI_EVENT_SCROLL_DRAG_FINISHED, NULL);
114 }
115 
116 static void
_scroll_connector_vbar_drag_cb(void * data,Evas_Object * obj EINA_UNUSED,const char * emission EINA_UNUSED,const char * source EINA_UNUSED)117 _scroll_connector_vbar_drag_cb(void *data,
118                           Evas_Object *obj EINA_UNUSED,
119                           const char *emission EINA_UNUSED,
120                           const char *source EINA_UNUSED)
121 {
122    Scroll_Connector_Context *ctx = data;
123    Efl_Ui_Layout_Orientation type;
124 
125    _scroll_connector_bar_read_and_update(ctx);
126 
127    type = EFL_UI_LAYOUT_ORIENTATION_VERTICAL;
128    efl_event_callback_call(ctx->obj, EFL_UI_SCROLLBAR_EVENT_BAR_DRAGGED, &type);
129 }
130 
131 static void
_scroll_connector_vbar_press_cb(void * data,Evas_Object * obj EINA_UNUSED,const char * emission EINA_UNUSED,const char * source EINA_UNUSED)132 _scroll_connector_vbar_press_cb(void *data,
133                            Evas_Object *obj EINA_UNUSED,
134                            const char *emission EINA_UNUSED,
135                            const char *source EINA_UNUSED)
136 {
137    Scroll_Connector_Context *ctx = data;
138    Efl_Ui_Layout_Orientation type = EFL_UI_LAYOUT_ORIENTATION_VERTICAL;
139 
140    efl_event_callback_call(ctx->obj, EFL_UI_SCROLLBAR_EVENT_BAR_PRESSED, &type);
141 }
142 
143 static void
_scroll_connector_vbar_unpress_cb(void * data,Evas_Object * obj EINA_UNUSED,const char * emission EINA_UNUSED,const char * source EINA_UNUSED)144 _scroll_connector_vbar_unpress_cb(void *data,
145                              Evas_Object *obj EINA_UNUSED,
146                              const char *emission EINA_UNUSED,
147                              const char *source EINA_UNUSED)
148 {
149    Scroll_Connector_Context *ctx = data;
150    Efl_Ui_Layout_Orientation type = EFL_UI_LAYOUT_ORIENTATION_VERTICAL;
151 
152    efl_event_callback_call(ctx->obj, EFL_UI_SCROLLBAR_EVENT_BAR_UNPRESSED, &type);
153 }
154 
155 static void
_scroll_connector_hbar_drag_cb(void * data,Evas_Object * obj EINA_UNUSED,const char * emission EINA_UNUSED,const char * source EINA_UNUSED)156 _scroll_connector_hbar_drag_cb(void *data,
157                           Evas_Object *obj EINA_UNUSED,
158                           const char *emission EINA_UNUSED,
159                           const char *source EINA_UNUSED)
160 {
161    Scroll_Connector_Context *ctx = data;
162    Efl_Ui_Layout_Orientation type = EFL_UI_LAYOUT_ORIENTATION_HORIZONTAL;
163 
164    _scroll_connector_bar_read_and_update(ctx);
165    efl_event_callback_call(ctx->obj, EFL_UI_SCROLLBAR_EVENT_BAR_DRAGGED, &type);
166 }
167 
168 static void
_scroll_connector_hbar_press_cb(void * data,Evas_Object * obj EINA_UNUSED,const char * emission EINA_UNUSED,const char * source EINA_UNUSED)169 _scroll_connector_hbar_press_cb(void *data,
170                            Evas_Object *obj EINA_UNUSED,
171                            const char *emission EINA_UNUSED,
172                            const char *source EINA_UNUSED)
173 {
174    Scroll_Connector_Context *ctx = data;
175    Efl_Ui_Layout_Orientation type = EFL_UI_LAYOUT_ORIENTATION_HORIZONTAL;
176 
177    efl_event_callback_call(ctx->obj, EFL_UI_SCROLLBAR_EVENT_BAR_PRESSED, &type);
178 }
179 
180 static void
_scroll_connector_hbar_unpress_cb(void * data,Evas_Object * obj EINA_UNUSED,const char * emission EINA_UNUSED,const char * source EINA_UNUSED)181 _scroll_connector_hbar_unpress_cb(void *data,
182                              Evas_Object *obj EINA_UNUSED,
183                              const char *emission EINA_UNUSED,
184                              const char *source EINA_UNUSED)
185 {
186    Scroll_Connector_Context *ctx = data;
187    Efl_Ui_Layout_Orientation type = EFL_UI_LAYOUT_ORIENTATION_HORIZONTAL;
188 
189    efl_event_callback_call(ctx->obj, EFL_UI_SCROLLBAR_EVENT_BAR_UNPRESSED, &type);
190 }
191 
192 static void
_scroll_connector_bar_size_changed_cb(void * data,const Efl_Event * event EINA_UNUSED)193 _scroll_connector_bar_size_changed_cb(void *data, const Efl_Event *event EINA_UNUSED)
194 {
195    Scroll_Connector_Context *ctx = data;
196    ELM_WIDGET_DATA_GET_OR_RETURN(ctx->obj, wd);
197 
198    double width = 0.0, height = 0.0;
199 
200    edje_object_calc_force(wd->resize_obj);
201    efl_ui_scrollbar_bar_size_get(ctx->smanager, &width, &height);
202    edje_object_part_drag_size_set(wd->resize_obj, "efl.draggable.horizontal_bar", width, 1.0);
203    edje_object_part_drag_size_set(wd->resize_obj, "efl.draggable.vertical_bar", 1.0, height);
204 }
205 
206 static void
_scroll_connector_bar_pos_changed_cb(void * data,const Efl_Event * event EINA_UNUSED)207 _scroll_connector_bar_pos_changed_cb(void *data, const Efl_Event *event EINA_UNUSED)
208 {
209    Scroll_Connector_Context *ctx = data;
210    ELM_WIDGET_DATA_GET_OR_RETURN(ctx->obj, wd);
211 
212    double posx = 0.0, posy = 0.0;
213    Eina_Size2D cs;
214    Eina_Position2D step;
215 
216    step = efl_ui_scrollable_step_size_get(ctx->smanager);
217    cs = efl_ui_scrollable_content_size_get(ctx->smanager);
218 
219    edje_object_part_drag_step_set(wd->resize_obj, "efl.draggable.horizontal_bar",
220                                   (double)step.x / cs.w, 0.0);
221    edje_object_part_drag_step_set(wd->resize_obj, "efl.draggable.vertical_bar",
222                                   0.0, (double)step.y / cs.h);
223 
224    efl_ui_scrollbar_bar_position_get(ctx->smanager, &posx, &posy);
225    edje_object_part_drag_value_set(wd->resize_obj, "efl.draggable.horizontal_bar", posx, 0.0);
226    edje_object_part_drag_value_set(wd->resize_obj, "efl.draggable.vertical_bar", 0.0, posy);
227    if (ctx->scroll_count)
228      ctx->need_scroll = EINA_TRUE;
229    else
230      {
231         efl_layout_signal_emit(wd->resize_obj, "efl,action,scroll", "efl");
232         ctx->scroll_count = EINA_TRUE;
233      }
234 }
235 
236 static void
_scroll_connector_bar_show_cb(void * data,const Efl_Event * event)237 _scroll_connector_bar_show_cb(void *data, const Efl_Event *event)
238 {
239    Scroll_Connector_Context *ctx = data;
240    ELM_WIDGET_DATA_GET_OR_RETURN(ctx->obj, wd);
241    Efl_Ui_Layout_Orientation type = *(Efl_Ui_Layout_Orientation *)(event->info);
242 
243    if (type == EFL_UI_LAYOUT_ORIENTATION_HORIZONTAL)
244      efl_layout_signal_emit(wd->resize_obj, "efl,horizontal_bar,visible,on", "efl");
245    else if (type == EFL_UI_LAYOUT_ORIENTATION_VERTICAL)
246      efl_layout_signal_emit(wd->resize_obj, "efl,vertical_bar,visible,on", "efl");
247 }
248 
249 static void
_scroll_connector_bar_hide_cb(void * data,const Efl_Event * event)250 _scroll_connector_bar_hide_cb(void *data, const Efl_Event *event)
251 {
252    Scroll_Connector_Context *ctx = data;
253    ELM_WIDGET_DATA_GET_OR_RETURN(ctx->obj, wd);
254    Efl_Ui_Layout_Orientation type = *(Efl_Ui_Layout_Orientation *)(event->info);
255 
256    if (type == EFL_UI_LAYOUT_ORIENTATION_HORIZONTAL)
257      efl_layout_signal_emit(wd->resize_obj, "efl,horizontal_bar,visible,off", "efl");
258    else if (type == EFL_UI_LAYOUT_ORIENTATION_VERTICAL)
259      efl_layout_signal_emit(wd->resize_obj, "efl,vertical_bar,visible,off", "efl");
260 }
261 
262 void
efl_ui_scroll_connector_bind(Eo * obj,Eo * manager)263 efl_ui_scroll_connector_bind(Eo *obj, Eo *manager)
264 {
265    Scroll_Connector_Context *ctx = calloc(1, sizeof(Scroll_Connector_Context));
266    if (!ctx) return;
267    ctx->obj = obj;
268    ctx->smanager = manager;
269    efl_key_data_set(obj, "__context", ctx);
270 
271    //from the theme to the object
272    efl_layout_signal_callback_add(obj, "reload", "efl",
273                                   ctx, _scroll_connector_reload_cb, NULL);
274    efl_layout_signal_callback_add(obj, "drag", "efl.draggable.vertical_bar",
275                                   ctx, _scroll_connector_vbar_drag_cb, NULL);
276    efl_layout_signal_callback_add(obj, "drag,set", "efl.draggable.vertical_bar",
277                                   ctx, _scroll_connector_edje_drag_cb, NULL);
278    efl_layout_signal_callback_add(obj, "drag,start", "efl.draggable.vertical_bar",
279                                   ctx, _scroll_connector_edje_drag_start_cb, NULL);
280    efl_layout_signal_callback_add(obj, "drag,stop", "efl.draggable.vertical_bar",
281                                   ctx, _scroll_connector_edje_drag_stop_cb, NULL);
282    efl_layout_signal_callback_add(obj, "drag,step", "efl.draggable.vertical_bar",
283                                   ctx, _scroll_connector_edje_drag_cb, NULL);
284    efl_layout_signal_callback_add(obj, "drag,page", "efl.draggable.vertical_bar",
285                                   ctx, _scroll_connector_edje_drag_cb, NULL);
286    efl_layout_signal_callback_add(obj, "efl,vertical_bar,press", "efl",
287                                   ctx, _scroll_connector_vbar_press_cb, NULL);
288    efl_layout_signal_callback_add(obj, "efl,vbar,unpress", "efl",
289                                   ctx, _scroll_connector_vbar_unpress_cb, NULL);
290    efl_layout_signal_callback_add(obj, "drag", "efl.draggable.horizontal_bar",
291                                   ctx, _scroll_connector_hbar_drag_cb, NULL);
292    efl_layout_signal_callback_add(obj, "drag,set", "efl.draggable.horizontal_bar",
293                                   ctx, _scroll_connector_edje_drag_cb, NULL);
294    efl_layout_signal_callback_add(obj, "drag,start", "efl.draggable.horizontal_bar",
295                                   ctx, _scroll_connector_edje_drag_start_cb, NULL);
296    efl_layout_signal_callback_add(obj, "drag,stop", "efl.draggable.horizontal_bar",
297                                   ctx, _scroll_connector_edje_drag_stop_cb, NULL);
298    efl_layout_signal_callback_add(obj, "drag,step", "efl.draggable.horizontal_bar",
299                                   ctx, _scroll_connector_edje_drag_cb, NULL);
300    efl_layout_signal_callback_add(obj, "drag,page", "efl.draggable.horizontal_bar",
301                                   ctx, _scroll_connector_edje_drag_cb, NULL);
302    efl_layout_signal_callback_add(obj, "efl,horizontal_bar,press", "efl",
303                                   ctx, _scroll_connector_hbar_press_cb, NULL);
304    efl_layout_signal_callback_add(obj, "efl,hbar,unpress", "efl",
305                                   ctx, _scroll_connector_hbar_unpress_cb, NULL);
306    efl_layout_signal_callback_add(obj, "efl,action,scroll", "efl",
307                                   ctx, _scroll, NULL);
308 
309    //from the object to the theme
310    efl_event_callback_add(obj, EFL_UI_SCROLLBAR_EVENT_BAR_SIZE_CHANGED,
311                           _scroll_connector_bar_size_changed_cb, ctx);
312    efl_event_callback_add(obj, EFL_UI_SCROLLBAR_EVENT_BAR_POS_CHANGED,
313                           _scroll_connector_bar_pos_changed_cb, ctx);
314    efl_event_callback_add(obj, EFL_UI_SCROLLBAR_EVENT_BAR_SHOW,
315                           _scroll_connector_bar_show_cb, ctx);
316    efl_event_callback_add(obj, EFL_UI_SCROLLBAR_EVENT_BAR_HIDE,
317                           _scroll_connector_bar_hide_cb, ctx);
318 }
319 
320 void
efl_ui_scroll_connector_unbind(Eo * obj)321 efl_ui_scroll_connector_unbind(Eo *obj)
322 {
323    Scroll_Connector_Context *ctx;
324 
325    ctx = efl_key_data_get(obj, "__context");
326    EINA_SAFETY_ON_NULL_RETURN(ctx);
327 
328    efl_layout_signal_callback_del(obj, "reload", "efl",
329                                   ctx, _scroll_connector_reload_cb, NULL);
330    efl_layout_signal_callback_del(obj, "drag", "efl.draggable.vertical_bar",
331                                   ctx, _scroll_connector_vbar_drag_cb, NULL);
332    efl_layout_signal_callback_del(obj, "drag,set", "efl.draggable.vertical_bar",
333                                   ctx, _scroll_connector_edje_drag_cb, NULL);
334    efl_layout_signal_callback_del(obj, "drag,start", "efl.draggable.vertical_bar",
335                                   ctx, _scroll_connector_edje_drag_start_cb, NULL);
336    efl_layout_signal_callback_del(obj, "drag,stop", "efl.draggable.vertical_bar",
337                                   ctx, _scroll_connector_edje_drag_stop_cb, NULL);
338    efl_layout_signal_callback_del(obj, "drag,step", "efl.draggable.vertical_bar",
339                                   ctx, _scroll_connector_edje_drag_cb, NULL);
340    efl_layout_signal_callback_del(obj, "drag,page", "efl.draggable.vertical_bar",
341                                   ctx, _scroll_connector_edje_drag_cb, NULL);
342    efl_layout_signal_callback_del(obj, "efl,vertical_bar,press", "efl",
343                                   ctx, _scroll_connector_vbar_press_cb, NULL);
344    efl_layout_signal_callback_del(obj, "efl,vbar,unpress", "efl",
345                                   ctx, _scroll_connector_vbar_unpress_cb, NULL);
346 
347    efl_layout_signal_callback_del(obj, "drag", "efl.draggable.horizontal_bar",
348                                   ctx, _scroll_connector_hbar_drag_cb, NULL);
349    efl_layout_signal_callback_del(obj, "drag,set", "efl.draggable.horizontal_bar",
350                                   ctx, _scroll_connector_edje_drag_cb, NULL);
351    efl_layout_signal_callback_del(obj, "drag,start", "efl.draggable.horizontal_bar",
352                                   ctx, _scroll_connector_edje_drag_start_cb, NULL);
353    efl_layout_signal_callback_del(obj, "drag,stop", "efl.draggable.horizontal_bar",
354                                   ctx, _scroll_connector_edje_drag_stop_cb, NULL);
355    efl_layout_signal_callback_del(obj, "drag,step", "efl.draggable.horizontal_bar",
356                                   ctx, _scroll_connector_edje_drag_cb, NULL);
357    efl_layout_signal_callback_del(obj, "drag,page", "efl.draggable.horizontal_bar",
358                                   ctx, _scroll_connector_edje_drag_cb, NULL);
359    efl_layout_signal_callback_del(obj, "efl,horizontal_bar,press", "efl",
360                                   ctx, _scroll_connector_hbar_press_cb, NULL);
361    efl_layout_signal_callback_del(obj, "efl,hbar,unpress", "efl",
362                                   ctx, _scroll_connector_hbar_unpress_cb, NULL);
363    free(ctx);
364 }
365