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