summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGustavo Lima Chaves <glima@profusion.mobi>2012-12-05 13:45:35 +0000
committerGustavo Lima Chaves <glima@profusion.mobi>2012-12-05 13:45:35 +0000
commit06021fe228d97464e2af4ad49c25c29299d5ae03 (patch)
treeb1a7714166b07cf462c051dd8b6e33c96cf2b58f
parentde0eb98ac9d5feaec8871c4756ee1547895bb769 (diff)
[elm] Actually remove those files.
Stupid conflict before, sorry. SVN revision: 80247
-rw-r--r--src/lib/els_scroller.c3233
-rw-r--r--src/lib/els_scroller.h48
2 files changed, 0 insertions, 3281 deletions
diff --git a/src/lib/els_scroller.c b/src/lib/els_scroller.c
deleted file mode 100644
index 70065dc45..000000000
--- a/src/lib/els_scroller.c
+++ /dev/null
@@ -1,3233 +0,0 @@
1#include <Elementary.h>
2#include "elm_priv.h"
3#include "els_scroller.h"
4#include "els_pan.h"
5
6#define SMART_NAME "els_scroller"
7#define API_ENTRY Smart_Data *sd = NULL; if ((!obj) || (!(sd = evas_object_smart_data_get(obj))) || (evas_object_type_get(obj) && strcmp(evas_object_type_get(obj), SMART_NAME)))
8#define INTERNAL_ENTRY Smart_Data *sd; sd = evas_object_smart_data_get(obj); if (!sd) return;
9typedef struct _Smart_Data Smart_Data;
10
11#define EVTIME 1
12//#define SCROLLDBG 1
13
14/* smoothness debug calls - for debugging how much smooth your app is */
15#define SMOOTHDBG 1
16
17#ifdef SMOOTHDBG
18#define SMOOTH_DEBUG_COUNT 100
19#define FPS 1/60
20typedef struct _smooth_debug_info smooth_debug_info;
21struct _smooth_debug_info
22{
23 double t;
24 double dt;
25 Evas_Coord pos;
26 Evas_Coord dpos;
27 double vpos;
28};
29
30static smooth_debug_info smooth_x_history[SMOOTH_DEBUG_COUNT];
31static smooth_debug_info smooth_y_history[SMOOTH_DEBUG_COUNT];
32static int smooth_info_x_count = 0;
33static int smooth_info_y_count = 0;
34static double start_time = 0;
35static int _els_scroller_smooth_debug = 0;
36
37void
38_els_scroller_smooth_debug_init(void)
39{
40 start_time = ecore_time_get();
41 smooth_info_x_count = 0;
42 smooth_info_y_count = 0;
43
44 memset(&(smooth_x_history[0]), 0, sizeof(smooth_x_history[0]) * SMOOTH_DEBUG_COUNT);
45 memset(&(smooth_y_history[0]), 0, sizeof(smooth_y_history[0]) * SMOOTH_DEBUG_COUNT);
46
47 return;
48}
49
50void
51_els_scroller_smooth_debug_shutdown(void)
52{
53 int i = 0;
54 int info_x_count = 0;
55 int info_y_count = 0;
56 double x_ave = 0, y_ave = 0;
57 double x_sum = 0, y_sum = 0;
58 double x_dev = 0, y_dev = 0;
59 double x_dev_sum = 0, y_dev_sum = 0;
60
61 if (smooth_info_x_count >= SMOOTH_DEBUG_COUNT)
62 info_x_count = SMOOTH_DEBUG_COUNT;
63 else
64 info_x_count = smooth_info_x_count;
65
66 if (smooth_info_y_count >= SMOOTH_DEBUG_COUNT)
67 info_y_count = SMOOTH_DEBUG_COUNT;
68 else
69 info_y_count = smooth_info_y_count;
70
71 printf("\n\n<<< X-axis Smoothness >>>\n");
72 printf("| Num | t(time) | dt | x | dx |vx(dx/1fps) |\n");
73
74 for (i = info_x_count -1; i >= 0; i--)
75 {
76 printf("| %4d | %1.6f | %1.6f | %4d | %4d | %9.3f |\n",info_x_count - i,
77 smooth_x_history[i].t,
78 smooth_x_history[i].dt,
79 smooth_x_history[i].pos,
80 smooth_x_history[i].dpos,
81 smooth_x_history[i].vpos);
82 if (i == info_x_count -1) continue;
83 x_sum += smooth_x_history[i].vpos;
84 }
85 x_ave = x_sum / (info_x_count - 1);
86 for (i = 0; i < info_x_count -1; i++)
87 {
88 x_dev_sum += (smooth_x_history[i].vpos - x_ave) * (smooth_x_history[i].vpos - x_ave);
89 }
90 x_dev = x_dev_sum / (info_x_count -1);
91 printf(" Standard deviation of X-axis velocity: %9.3f\n", sqrt(x_dev));
92
93 printf("\n\n<<< Y-axis Smoothness >>>\n");
94 printf("| Num | t(time) | dt | y | dy |vy(dy/1fps) |\n");
95 for (i = info_y_count -1; i >= 0; i--)
96 {
97 printf("| %4d | %1.6f | %1.6f | %4d | %4d | %9.3f |\n", info_y_count - i,
98 smooth_y_history[i].t,
99 smooth_y_history[i].dt,
100 smooth_y_history[i].pos,
101 smooth_y_history[i].dpos,
102 smooth_y_history[i].vpos);
103 if (i == info_y_count -1) continue;
104 y_sum += smooth_y_history[i].vpos;
105 }
106 y_ave = y_sum / (info_y_count - 1);
107 for (i = 0; i < info_y_count -1; i++)
108 {
109 y_dev_sum += (smooth_y_history[i].vpos - y_ave) * (smooth_y_history[i].vpos - y_ave);
110 }
111 y_dev = y_dev_sum / (info_y_count -1);
112 printf(" Standard deviation of Y-axis velocity: %9.3f\n", sqrt(y_dev));
113}
114
115void
116_els_scroller_smooth_debug_movetime_add(int x, int y)
117{
118 double tim = 0;
119 static int bx = 0;
120 static int by = 0;
121
122 tim = ecore_time_get();
123
124 if (bx != x)
125 {
126 smooth_info_x_count++;
127 memmove(&(smooth_x_history[1]), &(smooth_x_history[0]), sizeof(smooth_x_history[0]) * (SMOOTH_DEBUG_COUNT - 1));
128 smooth_x_history[0].t = tim - start_time;
129 smooth_x_history[0].dt = smooth_x_history[0].t - smooth_x_history[1].t;
130 smooth_x_history[0].pos = x;
131 smooth_x_history[0].dpos = smooth_x_history[0].pos - smooth_x_history[1].pos;
132
133 if (smooth_x_history[0].dpos >= 0)
134 smooth_x_history[0].vpos = (double)(smooth_x_history[0].dpos) / smooth_x_history[0].dt * FPS;
135 else
136 smooth_x_history[0].vpos = -((double)(smooth_x_history[0].dpos) / smooth_x_history[0].dt * FPS);
137 }
138
139 if (by != y)
140 {
141 smooth_info_y_count++;
142 memmove(&(smooth_y_history[1]), &(smooth_y_history[0]), sizeof(smooth_y_history[0]) * (SMOOTH_DEBUG_COUNT - 1));
143 smooth_y_history[0].t = tim - start_time;
144 smooth_y_history[0].dt = smooth_y_history[0].t - smooth_y_history[1].t;
145 smooth_y_history[0].pos = y;
146 smooth_y_history[0].dpos = smooth_y_history[0].pos - smooth_y_history[1].pos;
147
148 if (smooth_y_history[0].dpos >= 0)
149 smooth_y_history[0].vpos = (double)(smooth_y_history[0].dpos) / smooth_y_history[0].dt * FPS;
150 else
151 smooth_y_history[0].vpos = -((double)(smooth_y_history[0].dpos) / smooth_y_history[0].dt * FPS);
152 }
153
154 bx = x;
155 by = y;
156}
157#endif
158
159struct _Smart_Data
160{
161 Evas_Coord x, y, w, h;
162 Evas_Coord wx, wy, ww, wh; /* Last "wanted" geometry */
163
164 Evas_Object *smart_obj;
165 Evas_Object *child_obj;
166 Evas_Object *pan_obj;
167 Evas_Object *edje_obj;
168 Evas_Object *event_obj;
169
170 Evas_Object *widget;
171
172 Elm_Smart_Scroller_Policy hbar_flags, vbar_flags;
173
174 struct
175 {
176 Evas_Coord x, y;
177 Evas_Coord sx, sy;
178 Evas_Coord dx, dy;
179 Evas_Coord pdx, pdy;
180 Evas_Coord bx, by;
181 Evas_Coord ax, ay;
182 Evas_Coord bx0, by0;
183 Evas_Coord b0x, b0y;
184 Evas_Coord b2x, b2y;
185 struct
186 {
187 Evas_Coord x, y;
188 double timestamp, localtimestamp;
189 } history[60];
190 struct
191 {
192 double tadd, dxsum, dysum;
193 double est_timestamp_diff;
194 } hist;
195 double anim_start;
196 double anim_start2;
197 double anim_start3;
198 double onhold_vx, onhold_vy, onhold_tlast, onhold_vxe, onhold_vye;
199 double extra_time;
200 Evas_Coord hold_x, hold_y;
201 Ecore_Animator *hold_animator;
202 Ecore_Animator *onhold_animator;
203 Ecore_Animator *momentum_animator;
204 Ecore_Animator *bounce_x_animator;
205 Ecore_Animator *bounce_y_animator;
206 Evas_Coord locked_x, locked_y;
207 int hdir, vdir;
208 Eina_Bool now : 1;
209 Eina_Bool cancelled : 1;
210 Eina_Bool hold : 1;
211 Eina_Bool hold_parent : 1;
212 Eina_Bool want_dragged : 1;
213 Eina_Bool dragged : 1;
214 Eina_Bool dragged_began : 1;
215 Eina_Bool dir_x : 1;
216 Eina_Bool dir_y : 1;
217 Eina_Bool locked : 1;
218 Eina_Bool bounce_x_hold : 1;
219 Eina_Bool bounce_y_hold : 1;
220 Eina_Bool scroll : 1;
221 Eina_Bool want_reset : 1;
222 } down;
223
224 struct
225 {
226 Evas_Coord w, h;
227 Eina_Bool resized : 1;
228 } child;
229 struct
230 {
231 Evas_Coord x, y;
232 } step, page;
233
234 struct
235 {
236 void (*set) (Evas_Object *obj, Evas_Coord x, Evas_Coord y);
237 void (*get) (Evas_Object *obj, Evas_Coord *x, Evas_Coord *y);
238 void (*max_get) (Evas_Object *obj, Evas_Coord *x, Evas_Coord *y);
239 void (*min_get) (Evas_Object *obj, Evas_Coord *x, Evas_Coord *y);
240 void (*child_size_get) (Evas_Object *obj, Evas_Coord *x, Evas_Coord *y);
241 void (*gravity_set) (Evas_Object *obj, double x, double y);
242 void (*gravity_get) (Evas_Object *obj, double *x, double *y);
243 } pan_func;
244
245 struct
246 {
247 struct
248 {
249 Evas_Coord start, end;
250 double t_start, t_end;
251 Ecore_Animator *animator;
252 } x, y;
253 } scrollto;
254
255 double pagerel_h, pagerel_v;
256 Evas_Coord pagesize_h, pagesize_v;
257
258 Eina_Bool hbar_visible : 1;
259 Eina_Bool vbar_visible : 1;
260 Eina_Bool extern_pan : 1;
261 Eina_Bool one_dir_at_a_time : 1;
262 Eina_Bool hold : 1;
263 Eina_Bool freeze : 1;
264 Eina_Bool bouncemex : 1;
265 Eina_Bool bouncemey : 1;
266 Eina_Bool bounce_horiz : 1;
267 Eina_Bool bounce_vert : 1;
268 Eina_Bool momentum_animator_disabled :1;
269 Eina_Bool bounce_animator_disabled :1;
270 Eina_Bool is_mirrored : 1;
271 Eina_Bool wheel_disabled : 1;
272 Eina_Bool go_left : 1;
273 Eina_Bool go_right : 1;
274 Eina_Bool go_up : 1;
275 Eina_Bool go_down : 1;
276};
277
278/* local subsystem functions */
279static void _smart_child_del_hook(void *data, Evas *e, Evas_Object *obj, void *event_info);
280static void _smart_pan_changed_hook(void *data, Evas_Object *obj, void *event_info);
281static void _smart_event_wheel(void *data, Evas *e, Evas_Object *obj, void *event_info);
282static void _smart_event_mouse_down(void *data, Evas *e, Evas_Object *obj, void *event_info);
283static Eina_Bool _smart_hold_animator(void *data);
284static Eina_Bool _smart_momentum_animator(void *data);
285static void _smart_event_mouse_up(void *data, Evas *e, Evas_Object *obj, void *event_info);
286static Eina_Bool _smart_onhold_animator(void *data);
287static void _smart_event_mouse_move(void *data, Evas *e, Evas_Object *obj, void *event_info);
288static void _smart_edje_drag_v_start(void *data, Evas_Object *obj, const char *emission, const char *source);
289static void _smart_edje_drag_v_stop(void *data, Evas_Object *obj, const char *emission, const char *source);
290static void _smart_edje_drag_v(void *data, Evas_Object *obj, const char *emission, const char *source);
291static void _smart_edje_drag_h_start(void *data, Evas_Object *obj, const char *emission, const char *source);
292static void _smart_edje_drag_h_stop(void *data, Evas_Object *obj, const char *emission, const char *source);
293static void _smart_edje_drag_h(void *data, Evas_Object *obj, const char *emission, const char *source);
294static void _smart_scrollbar_read(Smart_Data *sd);
295static void _smart_scrollbar_reset(Smart_Data *sd);
296static int _smart_scrollbar_bar_h_visibility_adjust(Smart_Data *sd);
297static int _smart_scrollbar_bar_v_visibility_adjust(Smart_Data *sd);
298static void _smart_scrollbar_bar_visibility_adjust(Smart_Data *sd);
299static void _smart_scrollbar_size_adjust(Smart_Data *sd);
300static void _smart_reconfigure(Smart_Data *sd);
301static void _smart_add(Evas_Object *obj);
302static void _smart_del(Evas_Object *obj);
303static void _smart_move(Evas_Object *obj, Evas_Coord x, Evas_Coord y);
304static void _smart_resize(Evas_Object *obj, Evas_Coord w, Evas_Coord h);
305static void _smart_show(Evas_Object *obj);
306static void _smart_hide(Evas_Object *obj);
307static void _smart_color_set(Evas_Object *obj, int r, int g, int b, int a);
308static void _smart_clip_set(Evas_Object *obj, Evas_Object *clip);
309static void _smart_clip_unset(Evas_Object *obj);
310static void _smart_init(void);
311
312static void _elm_smart_scroller_wanted_region_set(Evas_Object *obj);
313
314/* local subsystem globals */
315static Evas_Smart *_smart = NULL;
316
317/* externally accessible functions */
318Evas_Object *
319elm_smart_scroller_add(Evas *evas)
320{
321 _smart_init();
322 return evas_object_smart_add(evas, _smart);
323}
324
325static void
326_elm_direction_arrows_eval(Smart_Data *sd)
327{
328 Eina_Bool go_left = EINA_TRUE, go_right = EINA_TRUE;
329 Eina_Bool go_up = EINA_TRUE, go_down = EINA_TRUE;
330 Evas_Coord x = 0, y = 0, mx = 0, my = 0, minx = 0, miny = 0;
331
332 if (!sd->edje_obj || !sd->pan_obj) return;
333
334 sd->pan_func.max_get(sd->pan_obj, &mx, &my);
335 sd->pan_func.min_get(sd->pan_obj, &minx, &miny);
336 sd->pan_func.get(sd->pan_obj, &x, &y);
337
338 if (x == minx) go_left = EINA_FALSE;
339 if (x == (mx + minx)) go_right = EINA_FALSE;
340 if (y == miny) go_up = EINA_FALSE;
341 if (y == (my + miny)) go_down = EINA_FALSE;
342 if (go_left != sd->go_left)
343 {
344 if (go_left)
345 edje_object_signal_emit(sd->edje_obj, "elm,action,show,left", "elm");
346 else
347 edje_object_signal_emit(sd->edje_obj, "elm,action,hide,left", "elm");
348 sd->go_left = go_left;
349 }
350 if (go_right != sd->go_right)
351 {
352 if (go_right)
353 edje_object_signal_emit(sd->edje_obj, "elm,action,show,right", "elm");
354 else
355 edje_object_signal_emit(sd->edje_obj, "elm,action,hide,right", "elm");
356 sd->go_right= go_right;
357 }
358 if (go_up != sd->go_up)
359 {
360 if (go_up)
361 edje_object_signal_emit(sd->edje_obj, "elm,action,show,up", "elm");
362 else
363 edje_object_signal_emit(sd->edje_obj, "elm,action,hide,up", "elm");
364 sd->go_up = go_up;
365 }
366 if (go_down != sd->go_down)
367 {
368 if (go_down)
369 edje_object_signal_emit(sd->edje_obj, "elm,action,show,down", "elm");
370 else
371 edje_object_signal_emit(sd->edje_obj, "elm,action,hide,down", "elm");
372 sd->go_down= go_down;
373 }
374}
375
376static Evas_Coord
377_elm_smart_scroller_x_mirrored_get(Evas_Object *obj, Evas_Coord x)
378{
379 API_ENTRY return x;
380
381 Evas_Coord cw, ch, w, ret;
382 elm_smart_scroller_child_viewport_size_get(obj, &w, NULL);
383 sd->pan_func.child_size_get(sd->pan_obj, &cw, &ch);
384 ret = (cw - (x + w));
385 return (ret >= 0) ? ret : 0;
386}
387
388void
389elm_smart_scroller_mirrored_set(Evas_Object *obj, Eina_Bool mirrored)
390{
391 API_ENTRY return;
392 Evas_Coord wx;
393 if (sd->is_mirrored == mirrored)
394 return;
395
396 sd->is_mirrored = mirrored;
397 edje_object_mirrored_set(sd->edje_obj, mirrored);
398
399 if (sd->is_mirrored)
400 wx = _elm_smart_scroller_x_mirrored_get(sd->smart_obj, sd->wx);
401 else
402 wx = sd->wx;
403
404 elm_smart_scroller_child_pos_set(sd->smart_obj, wx, sd->wy);
405}
406
407void
408elm_smart_scroller_child_set(Evas_Object *obj, Evas_Object *child)
409{
410 Evas_Coord w, h;
411 Evas_Object *o;
412
413 API_ENTRY return;
414 if (sd->child_obj)
415 {
416 _elm_smart_pan_child_set(sd->pan_obj, NULL);
417 evas_object_event_callback_del_full(sd->child_obj, EVAS_CALLBACK_DEL, _smart_child_del_hook, sd);
418 }
419
420 sd->child_obj = child;
421 sd->wx = sd->wy = 0;
422 /* (-1) means want viewports size */
423 sd->ww = sd->wh = -1;
424 if (!child) return;
425
426 if (!sd->pan_obj)
427 {
428 o = _elm_smart_pan_add(evas_object_evas_get(obj));
429 sd->pan_obj = o;
430 evas_object_smart_callback_add(o, "changed", _smart_pan_changed_hook, sd);
431 edje_object_part_swallow(sd->edje_obj, "elm.swallow.content", o);
432 }
433
434 sd->pan_func.set = _elm_smart_pan_set;
435 sd->pan_func.get = _elm_smart_pan_get;
436 sd->pan_func.max_get = _elm_smart_pan_max_get;
437 sd->pan_func.min_get = _elm_smart_pan_min_get;
438 sd->pan_func.child_size_get = _elm_smart_pan_child_size_get;
439 sd->pan_func.gravity_set = _elm_smart_pan_gravity_set;
440 sd->pan_func.gravity_get = _elm_smart_pan_gravity_get;
441
442 evas_object_event_callback_add(child, EVAS_CALLBACK_DEL, _smart_child_del_hook, sd);
443 _elm_smart_pan_child_set(sd->pan_obj, child);
444 sd->pan_func.child_size_get(sd->pan_obj, &w, &h);
445 sd->child.w = w;
446 sd->child.h = h;
447 _smart_scrollbar_size_adjust(sd);
448 _smart_scrollbar_reset(sd);
449}
450
451void
452elm_smart_scroller_extern_pan_set(Evas_Object *obj, Evas_Object *pan,
453 void (*pan_set) (Evas_Object *obj, Evas_Coord x, Evas_Coord y),
454 void (*pan_get) (Evas_Object *obj, Evas_Coord *x, Evas_Coord *y),
455 void (*pan_max_get) (Evas_Object *obj, Evas_Coord *x, Evas_Coord *y),
456 void (*pan_min_get) (Evas_Object *obj, Evas_Coord *x, Evas_Coord *y),
457 void (*pan_child_size_get) (Evas_Object *obj, Evas_Coord *x, Evas_Coord *y))
458{
459 API_ENTRY return;
460
461 elm_smart_scroller_child_set(obj, NULL);
462
463 if (sd->pan_obj)
464 {
465 evas_object_smart_callback_del(sd->pan_obj, "changed", _smart_pan_changed_hook);
466 }
467
468 if (sd->extern_pan)
469 {
470 if (sd->pan_obj)
471 {
472 edje_object_part_unswallow(sd->edje_obj, sd->pan_obj);
473 sd->pan_obj = NULL;
474 }
475 }
476 else
477 {
478 if (sd->pan_obj)
479 {
480 evas_object_del(sd->pan_obj);
481 sd->pan_obj = NULL;
482 }
483 }
484 if (!pan)
485 {
486 sd->extern_pan = EINA_FALSE;
487 return;
488 }
489
490 sd->pan_obj = pan;
491 sd->pan_func.set = pan_set;
492 sd->pan_func.get = pan_get;
493 sd->pan_func.max_get = pan_max_get;
494 sd->pan_func.min_get = pan_min_get;
495 sd->pan_func.child_size_get = pan_child_size_get;
496 sd->pan_func.gravity_set = _elm_smart_pan_gravity_set;
497 sd->pan_func.gravity_get = _elm_smart_pan_gravity_get;
498 sd->extern_pan = EINA_TRUE;
499 evas_object_smart_callback_add(sd->pan_obj, "changed", _smart_pan_changed_hook, sd);
500 edje_object_part_swallow(sd->edje_obj, "elm.swallow.content", sd->pan_obj);
501 evas_object_show(sd->pan_obj);
502}
503
504static void
505_elm_smart_scroller_custom_edje_file_reload(void *data,
506 Evas_Object *obj,
507 const char *emission __UNUSED__,
508 const char *source __UNUSED__)
509{
510 Evas_Object *scroller = data;
511 const char *file;
512 const char *group;
513
514 edje_object_file_get(obj, &file, &group);
515 elm_smart_scroller_custom_edje_file_set(scroller, (char*) file, (char*) group);
516}
517
518void
519elm_smart_scroller_custom_edje_file_set(Evas_Object *obj, char *file, char *group)
520{
521 API_ENTRY return;
522
523 edje_object_file_set(sd->edje_obj, file, group);
524 if (sd->pan_obj)
525 edje_object_part_swallow(sd->edje_obj, "elm.swallow.content", sd->pan_obj);
526 edje_object_signal_callback_del(sd->edje_obj,
527 "edje,change,file", "edje",
528 _elm_smart_scroller_custom_edje_file_reload);
529 edje_object_signal_callback_add(sd->edje_obj,
530 "edje,change,file", "edje",
531 _elm_smart_scroller_custom_edje_file_reload,
532 obj);
533 sd->vbar_visible = !sd->vbar_visible;
534 sd->hbar_visible = !sd->hbar_visible;
535 _smart_scrollbar_bar_visibility_adjust(sd);
536 if (sd->hbar_flags == ELM_SMART_SCROLLER_POLICY_ON)
537 edje_object_signal_emit(sd->edje_obj, "elm,action,show_always,hbar", "elm");
538 else if (sd->hbar_flags == ELM_SMART_SCROLLER_POLICY_OFF)
539 edje_object_signal_emit(sd->edje_obj, "elm,action,hide,hbar", "elm");
540 else
541 edje_object_signal_emit(sd->edje_obj, "elm,action,show_notalways,hbar", "elm");
542 if (sd->vbar_flags == ELM_SMART_SCROLLER_POLICY_ON)
543 edje_object_signal_emit(sd->edje_obj, "elm,action,show_always,vbar", "elm");
544 else if (sd->vbar_flags == ELM_SMART_SCROLLER_POLICY_OFF)
545 edje_object_signal_emit(sd->edje_obj, "elm,action,hide,vbar", "elm");
546 else
547 edje_object_signal_emit(sd->edje_obj, "elm,action,show_notalways,vbar", "elm");
548 _elm_direction_arrows_eval(sd);
549}
550
551Eina_Bool
552elm_smart_scroller_momentum_animator_disabled_get(Evas_Object *obj)
553{
554 API_ENTRY return EINA_FALSE;
555 return sd->momentum_animator_disabled;
556}
557
558void
559elm_smart_scroller_momentum_animator_disabled_set(Evas_Object *obj, Eina_Bool disabled)
560{
561 API_ENTRY return;
562 sd->momentum_animator_disabled = disabled;
563 if (sd->momentum_animator_disabled)
564 {
565 if (sd->down.momentum_animator)
566 {
567 ecore_animator_del(sd->down.momentum_animator);
568 sd->down.momentum_animator = NULL;
569 if (sd->child.resized)
570 _elm_smart_scroller_wanted_region_set(sd->smart_obj);
571 }
572 }
573}
574
575Eina_Bool
576elm_smart_scroller_bounce_animator_disabled_get(Evas_Object *obj)
577{
578 API_ENTRY return EINA_FALSE;
579 return sd->bounce_animator_disabled;
580}
581
582void
583elm_smart_scroller_bounce_animator_disabled_set(Evas_Object *obj, Eina_Bool disabled)
584{
585 API_ENTRY return;
586 sd->bounce_animator_disabled = disabled;
587 if (sd->bounce_animator_disabled)
588 {
589 if (sd->scrollto.x.animator)
590 {
591 ecore_animator_del(sd->scrollto.x.animator);
592 sd->scrollto.x.animator = NULL;
593 }
594
595 if (sd->scrollto.y.animator)
596 {
597 ecore_animator_del(sd->scrollto.y.animator);
598 sd->scrollto.y.animator = NULL;
599 }
600 }
601}
602
603Eina_Bool
604elm_smart_scroller_wheel_disabled_get(Evas_Object *obj)
605{
606 API_ENTRY return EINA_FALSE;
607 return sd->wheel_disabled;
608}
609
610void
611elm_smart_scroller_wheel_disabled_set(Evas_Object *obj, Eina_Bool disabled)
612{
613 API_ENTRY return;
614 if ((!sd->wheel_disabled) && (disabled))
615 evas_object_event_callback_del_full(sd->event_obj, EVAS_CALLBACK_MOUSE_WHEEL, _smart_event_wheel, sd);
616 else if ((sd->wheel_disabled) && (!disabled))
617 evas_object_event_callback_add(sd->event_obj, EVAS_CALLBACK_MOUSE_WHEEL, _smart_event_wheel, sd);
618 sd->wheel_disabled = disabled;
619}
620
621/* Update the wanted coordinates according to the x, y passed
622 * widget directionality, child size and etc. */
623static void
624_update_wanted_coordinates(Smart_Data *sd, Evas_Coord x, Evas_Coord y)
625{
626 Evas_Coord cw, ch;
627
628 sd->pan_func.child_size_get(sd->pan_obj, &cw, &ch);
629
630 /* Update wx/y/w/h - and if the requested positions aren't legal
631 * adjust a bit. */
632 elm_smart_scroller_child_viewport_size_get(sd->smart_obj, &sd->ww, &sd->wh);
633 if (x < 0)
634 sd->wx = 0;
635 else if ((x + sd->ww) > cw)
636 sd->wx = cw - sd->ww;
637 else if (sd->is_mirrored)
638 sd->wx = _elm_smart_scroller_x_mirrored_get(sd->smart_obj, x);
639 else
640 sd->wx = x;
641 if (y < 0) sd->wy = 0;
642 else if ((y + sd->wh) > ch) sd->wy = ch - sd->wh;
643 else sd->wy = y;
644}
645
646static void
647_smart_anim_start(Evas_Object *obj)
648{
649 evas_object_smart_callback_call(obj, "animate,start", NULL);
650}
651
652static void
653_smart_anim_stop(Evas_Object *obj)
654{
655 evas_object_smart_callback_call(obj, "animate,stop", NULL);
656}
657
658static void
659_smart_drag_start(Evas_Object *obj)
660{
661 evas_object_smart_callback_call(obj, "drag,start", NULL);
662}
663
664static void
665_smart_drag_stop(Evas_Object *obj)
666{
667 evas_object_smart_callback_call(obj, "drag,stop", NULL);
668}
669
670static Eina_Bool
671_smart_scrollto_x_animator(void *data)
672{
673 Smart_Data *sd = data;
674 Evas_Coord px, py;
675 double t, tt;
676
677 t = ecore_loop_time_get();
678 tt = (t - sd->scrollto.x.t_start) / (sd->scrollto.x.t_end - sd->scrollto.x.t_start);
679 tt = 1.0 - tt;
680 tt = 1.0 - (tt * tt);
681 sd->pan_func.get(sd->pan_obj, &px, &py);
682 px = (sd->scrollto.x.start * (1.0 - tt)) +
683 (sd->scrollto.x.end * tt);
684 if (t >= sd->scrollto.x.t_end)
685 {
686 px = sd->scrollto.x.end;
687 elm_smart_scroller_child_pos_set(sd->smart_obj, px, py);
688 sd->down.sx = px;
689 sd->down.x = sd->down.history[0].x;
690 _update_wanted_coordinates(sd, px, py);
691 sd->scrollto.x.animator = NULL;
692 if ((!sd->scrollto.y.animator) && (!sd->down.bounce_y_animator))
693 _smart_anim_stop(sd->smart_obj);
694 return ECORE_CALLBACK_CANCEL;
695 }
696 elm_smart_scroller_child_pos_set(sd->smart_obj, px, py);
697 _update_wanted_coordinates(sd, px, py);
698 return ECORE_CALLBACK_RENEW;
699}
700
701static void
702_smart_momentum_end(Smart_Data *sd)
703{
704 if ((sd->down.bounce_x_animator) || (sd->down.bounce_y_animator)) return;
705 if (sd->down.momentum_animator)
706 {
707 Evas_Coord px, py;
708 elm_smart_scroller_child_pos_get(sd->smart_obj, &px, &py);
709 _update_wanted_coordinates(sd, px, py);
710
711 ecore_animator_del(sd->down.momentum_animator);
712 sd->down.momentum_animator = NULL;
713 sd->down.bounce_x_hold = EINA_FALSE;
714 sd->down.bounce_y_hold = EINA_FALSE;
715 sd->down.ax = 0;
716 sd->down.ay = 0;
717 sd->down.dx = 0;
718 sd->down.dy = 0;
719 sd->down.pdx = 0;
720 sd->down.pdy = 0;
721 if (sd->child.resized)
722 _elm_smart_scroller_wanted_region_set(sd->smart_obj);
723 }
724}
725
726static void
727_smart_scrollto_x(Smart_Data *sd, double t_in, Evas_Coord pos_x)
728{
729 Evas_Coord px, py, x, y, w, h;
730 double t;
731
732 if (sd->freeze) return;
733 if (t_in <= 0.0)
734 {
735 elm_smart_scroller_child_pos_get(sd->smart_obj, &x, &y);
736 elm_smart_scroller_child_viewport_size_get(sd->smart_obj, &w, &h);
737 x = pos_x;
738 elm_smart_scroller_child_region_set(sd->smart_obj, x, y, w, h);
739 return;
740 }
741 t = ecore_loop_time_get();
742 sd->pan_func.get(sd->pan_obj, &px, &py);
743 sd->scrollto.x.start = px;
744 sd->scrollto.x.end = pos_x;
745 sd->scrollto.x.t_start = t;
746 sd->scrollto.x.t_end = t + t_in;
747 if (!sd->scrollto.x.animator)
748 {
749 sd->scrollto.x.animator = ecore_animator_add(_smart_scrollto_x_animator, sd);
750 if (!sd->scrollto.y.animator)
751 _smart_anim_start(sd->smart_obj);
752 }
753 if (sd->down.bounce_x_animator)
754 {
755 ecore_animator_del(sd->down.bounce_x_animator);
756 sd->down.bounce_x_animator = NULL;
757 _smart_momentum_end(sd);
758 if (sd->child.resized)
759 _elm_smart_scroller_wanted_region_set(sd->smart_obj);
760 }
761 sd->bouncemex = EINA_FALSE;
762}
763
764static Eina_Bool
765_smart_scrollto_y_animator(void *data)
766{
767 Smart_Data *sd = data;
768 Evas_Coord px, py;
769 double t, tt;
770
771 t = ecore_loop_time_get();
772 tt = (t - sd->scrollto.y.t_start) / (sd->scrollto.y.t_end - sd->scrollto.y.t_start);
773 tt = 1.0 - tt;
774 tt = 1.0 - (tt * tt);
775 sd->pan_func.get(sd->pan_obj, &px, &py);
776 py = (sd->scrollto.y.start * (1.0 - tt)) +
777 (sd->scrollto.y.end * tt);
778 if (t >= sd->scrollto.y.t_end)
779 {
780 py = sd->scrollto.y.end;
781 elm_smart_scroller_child_pos_set(sd->smart_obj, px, py);
782 sd->down.sy = py;
783 sd->down.y = sd->down.history[0].y;
784 _update_wanted_coordinates(sd, px, py);
785 sd->scrollto.y.animator = NULL;
786 if ((!sd->scrollto.x.animator) && (!sd->down.bounce_x_animator))
787 _smart_anim_stop(sd->smart_obj);
788 return ECORE_CALLBACK_CANCEL;
789 }
790 elm_smart_scroller_child_pos_set(sd->smart_obj, px, py);
791 _update_wanted_coordinates(sd, px, py);
792
793 return ECORE_CALLBACK_RENEW;
794}
795
796static void
797_smart_scrollto_y(Smart_Data *sd, double t_in, Evas_Coord pos_y)
798{
799 Evas_Coord px, py, x, y, w, h;
800 double t;
801
802 if (sd->freeze) return;
803 if (t_in <= 0.0)
804 {
805 elm_smart_scroller_child_pos_get(sd->smart_obj, &x, &y);
806 elm_smart_scroller_child_viewport_size_get(sd->smart_obj, &w, &h);
807 y = pos_y;
808 elm_smart_scroller_child_region_set(sd->smart_obj, x, y, w, h);
809 return;
810 }
811 t = ecore_loop_time_get();
812 sd->pan_func.get(sd->pan_obj, &px, &py);
813 sd->scrollto.y.start = py;
814 sd->scrollto.y.end = pos_y;
815 sd->scrollto.y.t_start = t;
816 sd->scrollto.y.t_end = t + t_in;
817 if (!sd->scrollto.y.animator)
818 {
819 sd->scrollto.y.animator = ecore_animator_add(_smart_scrollto_y_animator, sd);
820 if (!sd->scrollto.x.animator)
821 _smart_anim_start(sd->smart_obj);
822 }
823 if (sd->down.bounce_y_animator)
824 {
825 ecore_animator_del(sd->down.bounce_y_animator);
826 sd->down.bounce_y_animator = NULL;
827 _smart_momentum_end(sd);
828 if (sd->child.resized)
829 _elm_smart_scroller_wanted_region_set(sd->smart_obj);
830 }
831 sd->bouncemey = EINA_FALSE;
832}
833
834static Eina_Bool
835_smart_do_page(Smart_Data *sd)
836{
837 if ((sd->pagerel_h == 0.0) && (!sd->pagesize_h) &&
838 (sd->pagerel_v == 0.0) && (!sd->pagesize_v))
839 return EINA_FALSE;
840 return EINA_TRUE;
841}
842
843static Evas_Coord
844_smart_page_x_get(Smart_Data *sd, int offset)
845{
846 Evas_Coord x, y, w, h, cw, ch, minx = 0;
847
848 elm_smart_scroller_child_pos_get(sd->smart_obj, &x, &y);
849 elm_smart_scroller_child_viewport_size_get(sd->smart_obj, &w, &h);
850 sd->pan_func.child_size_get(sd->pan_obj, &cw, &ch);
851 sd->pan_func.min_get(sd->pan_obj, &minx, NULL);
852
853 x += offset;
854
855 if (sd->pagerel_h > 0.0)
856 sd->pagesize_h = w * sd->pagerel_h;
857 if (sd->pagesize_h > 0)
858 {
859 x = x + (sd->pagesize_h * 0.5);
860 x = x / (sd->pagesize_h);
861 x = x * (sd->pagesize_h);
862 }
863 if ((x + w) > cw) x = cw - w;
864 if (x < minx) x = minx;
865 return x;
866}
867
868static Evas_Coord
869_smart_page_y_get(Smart_Data *sd, int offset)
870{
871 Evas_Coord x, y, w, h, cw, ch, miny = 0;
872
873 elm_smart_scroller_child_pos_get(sd->smart_obj, &x, &y);
874 elm_smart_scroller_child_viewport_size_get(sd->smart_obj, &w, &h);
875 sd->pan_func.child_size_get(sd->pan_obj, &cw, &ch);
876 sd->pan_func.min_get(sd->pan_obj, NULL, &miny);
877
878 y += offset;
879
880 if (sd->pagerel_v > 0.0)
881 sd->pagesize_v = h * sd->pagerel_v;
882 if (sd->pagesize_v > 0)
883 {
884 y = y + (sd->pagesize_v * 0.5);
885 y = y / (sd->pagesize_v);
886 y = y * (sd->pagesize_v);
887 }
888 if ((y + h) > ch) y = ch - h;
889 if (y < miny) y = miny;
890 return y;
891}
892
893static void
894_smart_page_adjust(Smart_Data *sd)
895{
896 Evas_Coord x, y, w, h;
897
898 if (!_smart_do_page(sd)) return;
899
900 elm_smart_scroller_child_viewport_size_get(sd->smart_obj, &w, &h);
901
902 x = _smart_page_x_get(sd, 0);
903 y = _smart_page_y_get(sd, 0);
904
905 elm_smart_scroller_child_region_set(sd->smart_obj, x, y, w, h);
906}
907
908static Eina_Bool
909_smart_bounce_x_animator(void *data)
910{
911 Smart_Data *sd;
912 Evas_Coord x, y, dx, w, odx, ed, md;
913 double t, p, dt, pd, r;
914
915 sd = data;
916 t = ecore_loop_time_get();
917 dt = t - sd->down.anim_start2;
918 if (dt >= 0.0)
919 {
920 dt = dt / _elm_config->thumbscroll_bounce_friction;
921 odx = sd->down.b2x - sd->down.bx;
922 elm_smart_scroller_child_viewport_size_get(sd->smart_obj, &w, NULL);
923 if (!sd->down.momentum_animator && (w > abs(odx)))
924 {
925 pd = (double)odx / (double)w;
926 pd = (pd > 0) ? pd : -pd;
927 pd = 1.0 - ((1.0 - pd) * (1.0 - pd));
928 dt = dt / pd;
929 }
930 if (dt > 1.0) dt = 1.0;
931 p = 1.0 - ((1.0 - dt) * (1.0 - dt));
932 elm_smart_scroller_child_pos_get(sd->smart_obj, &x, &y);
933 dx = (odx * p);
934 r = 1.0;
935 if (sd->down.momentum_animator)
936 {
937 ed = abs(sd->down.dx * (_elm_config->thumbscroll_friction + sd->down.extra_time) - sd->down.b0x);
938 md = abs(_elm_config->thumbscroll_friction * 5 * w);
939 if (ed > md) r = (double)(md)/(double)ed;
940 }
941 x = sd->down.b2x + (int)((double)(dx - odx) * r);
942 if (!sd->down.cancelled)
943 elm_smart_scroller_child_pos_set(sd->smart_obj, x, y);
944 if (dt >= 1.0)
945 {
946 if (sd->down.momentum_animator)
947 sd->down.bounce_x_hold = EINA_TRUE;
948 if ((!sd->down.bounce_y_animator) &&
949 (!sd->scrollto.y.animator))
950 _smart_anim_stop(sd->smart_obj);
951 sd->down.bounce_x_animator = NULL;
952 sd->down.pdx = 0;
953 sd->bouncemex = EINA_FALSE;
954 _smart_momentum_end(sd);
955 if (sd->child.resized)
956 _elm_smart_scroller_wanted_region_set(sd->smart_obj);
957 return ECORE_CALLBACK_CANCEL;
958 }
959 }
960 return ECORE_CALLBACK_RENEW;
961}
962
963static Eina_Bool
964_smart_bounce_y_animator(void *data)
965{
966 Smart_Data *sd;
967 Evas_Coord x, y, dy, h, ody, ed, md;
968 double t, p, dt, pd, r;
969
970 sd = data;
971 t = ecore_loop_time_get();
972 dt = t - sd->down.anim_start3;
973 if (dt >= 0.0)
974 {
975 dt = dt / _elm_config->thumbscroll_bounce_friction;
976 ody = sd->down.b2y - sd->down.by;
977 elm_smart_scroller_child_viewport_size_get(sd->smart_obj, NULL, &h);
978 if (!sd->down.momentum_animator && (h > abs(ody)))
979 {
980 pd = (double)ody / (double)h;
981 pd = (pd > 0) ? pd : -pd;
982 pd = 1.0 - ((1.0 - pd) * (1.0 - pd));
983 dt = dt / pd;
984 }
985 if (dt > 1.0) dt = 1.0;
986 p = 1.0 - ((1.0 - dt) * (1.0 - dt));
987 elm_smart_scroller_child_pos_get(sd->smart_obj, &x, &y);
988 dy = (ody * p);
989 r = 1.0;
990 if (sd->down.momentum_animator)
991 {
992 ed = abs(sd->down.dy * (_elm_config->thumbscroll_friction + sd->down.extra_time) - sd->down.b0y);
993 md = abs(_elm_config->thumbscroll_friction * 5 * h);
994 if (ed > md) r = (double)(md)/(double)ed;
995 }
996 y = sd->down.b2y + (int)((double)(dy - ody) * r);
997 if (!sd->down.cancelled)
998 elm_smart_scroller_child_pos_set(sd->smart_obj, x, y);
999 if (dt >= 1.0)
1000 {
1001 if (sd->down.momentum_animator)
1002 sd->down.bounce_y_hold = EINA_TRUE;
1003 if ((!sd->down.bounce_x_animator) &&
1004 (!sd->scrollto.y.animator))
1005 _smart_anim_stop(sd->smart_obj);
1006 sd->down.bounce_y_animator = NULL;
1007 sd->down.pdy = 0;
1008 sd->bouncemey = EINA_FALSE;
1009 _smart_momentum_end(sd);
1010 if (sd->child.resized)
1011 _elm_smart_scroller_wanted_region_set(sd->smart_obj);
1012 return ECORE_CALLBACK_CANCEL;
1013 }
1014 }
1015 return ECORE_CALLBACK_RENEW;
1016}
1017
1018#define LEFT 0
1019#define RIGHT 1
1020#define UP 2
1021#define DOWN 3
1022static Eina_Bool
1023can_scroll(Smart_Data *sd, int dir)
1024{
1025 Evas_Coord mx = 0, my = 0, px = 0, py = 0, minx = 0, miny = 0;
1026
1027 sd->pan_func.max_get(sd->pan_obj, &mx, &my);
1028 sd->pan_func.min_get(sd->pan_obj, &minx, &miny);
1029 sd->pan_func.get(sd->pan_obj, &px, &py);
1030 switch (dir)
1031 {
1032 case LEFT:
1033 if (px > minx) return EINA_TRUE;
1034 break;
1035 case RIGHT:
1036 if ((px - minx) < mx) return EINA_TRUE;
1037 break;
1038 case UP:
1039 if (py > miny) return EINA_TRUE;
1040 break;
1041 case DOWN:
1042 if ((py - miny) < my) return EINA_TRUE;
1043 break;
1044 default:
1045 break;
1046 }
1047 return EINA_FALSE;
1048}
1049
1050static Eina_Bool
1051_smart_momentum_animator(void *data)
1052{
1053 Smart_Data *sd;
1054 double t, dt, p;
1055 Evas_Coord x, y, dx, dy, px, py, maxx, maxy, minx, miny;
1056 Eina_Bool no_bounce_x_end = EINA_FALSE, no_bounce_y_end = EINA_FALSE;
1057
1058 sd = data;
1059 t = ecore_loop_time_get();
1060 dt = t - sd->down.anim_start;
1061 if (dt >= 0.0)
1062 {
1063 /*
1064 if (sd->down.hold_parent)
1065 {
1066 if ((sd->down.dir_x) && !can_scroll(sd, sd->down.hdir))
1067 {
1068 sd->down.dir_x = 0;
1069 }
1070 if ((sd->down.dir_y) && !can_scroll(sd, sd->down.vdir))
1071 {
1072 sd->down.dir_y = 0;
1073 }
1074 }
1075 if ((!sd->down.dir_x) && (!sd->down.dir_y))
1076 {
1077 sd->down.cancelled = 1;
1078 }
1079 */
1080 dt = dt / (_elm_config->thumbscroll_friction + sd->down.extra_time);
1081 if (dt > 1.0) dt = 1.0;
1082 p = 1.0 - ((1.0 - dt) * (1.0 - dt));
1083 dx = (sd->down.dx * (_elm_config->thumbscroll_friction + sd->down.extra_time) * p);
1084 dy = (sd->down.dy * (_elm_config->thumbscroll_friction + sd->down.extra_time) * p);
1085 sd->down.ax = dx;
1086 sd->down.ay = dy;
1087 x = sd->down.sx - dx;
1088 y = sd->down.sy - dy;
1089 elm_smart_scroller_child_pos_get(sd->smart_obj, &px, &py);
1090 if ((sd->down.bounce_x_animator) ||
1091 (sd->down.bounce_x_hold))
1092 {
1093 sd->down.bx = sd->down.bx0 - dx + sd->down.b0x;
1094 x = px;
1095 }
1096 if ((sd->down.bounce_y_animator) ||
1097 (sd->down.bounce_y_hold))
1098 {
1099 sd->down.by = sd->down.by0 - dy + sd->down.b0y;
1100 y = py;
1101 }
1102 elm_smart_scroller_child_pos_set(sd->smart_obj, x, y);
1103 _update_wanted_coordinates(sd, x, y);
1104 sd->pan_func.max_get(sd->pan_obj, &maxx, &maxy);
1105 sd->pan_func.min_get(sd->pan_obj, &minx, &miny);
1106 if (!sd->bounce_horiz)
1107 {
1108 if (x <= minx) no_bounce_x_end = EINA_TRUE;
1109 if ((x - minx) >= maxx) no_bounce_x_end = EINA_TRUE;
1110 }
1111 if (!sd->bounce_vert)
1112 {
1113 if (y <= miny) no_bounce_y_end = EINA_TRUE;
1114 if ((y - miny) >= maxy) no_bounce_y_end = EINA_TRUE;
1115 }
1116 if ((dt >= 1.0) ||
1117 ((sd->down.bounce_x_hold) && (sd->down.bounce_y_hold)) ||
1118 (no_bounce_x_end && no_bounce_y_end))
1119 {
1120 _smart_anim_stop(sd->smart_obj);
1121
1122 sd->down.momentum_animator = NULL;
1123 sd->down.bounce_x_hold = EINA_FALSE;
1124 sd->down.bounce_y_hold = EINA_FALSE;
1125 sd->down.ax = 0;
1126 sd->down.ay = 0;
1127 sd->down.pdx = 0;
1128 sd->down.pdy = 0;
1129 if (sd->child.resized)
1130 _elm_smart_scroller_wanted_region_set(sd->smart_obj);
1131 return ECORE_CALLBACK_CANCEL;
1132 }
1133 }
1134 return ECORE_CALLBACK_RENEW;
1135}
1136
1137static void
1138bounce_eval(Smart_Data *sd)
1139{
1140 Evas_Coord mx, my, px, py, bx, by, b2x, b2y, minx = 0, miny = 0;
1141
1142 if (sd->freeze) return;
1143 if ((!sd->bouncemex) && (!sd->bouncemey)) return;
1144 if (sd->down.now) return; // down bounce while still held down
1145 if (sd->down.onhold_animator)
1146 {
1147 ecore_animator_del(sd->down.onhold_animator);
1148 sd->down.onhold_animator = NULL;
1149 if (sd->child.resized)
1150 _elm_smart_scroller_wanted_region_set(sd->smart_obj);
1151 }
1152 if (sd->down.hold_animator)
1153 {
1154 ecore_animator_del(sd->down.hold_animator);
1155 sd->down.hold_animator = NULL;
1156 if (sd->child.resized)
1157 _elm_smart_scroller_wanted_region_set(sd->smart_obj);
1158 }
1159 sd->pan_func.max_get(sd->pan_obj, &mx, &my);
1160 sd->pan_func.min_get(sd->pan_obj, &minx, &miny);
1161 sd->pan_func.get(sd->pan_obj, &px, &py);
1162 bx = px;
1163 by = py;
1164 if (px < minx) px = minx;
1165 if ((px - minx) > mx) px = mx + minx;
1166 if (py < miny) py = miny;
1167 if ((py - miny) > my) py = my + miny;
1168 b2x = px;
1169 b2y = py;
1170 if ((!sd->widget) ||
1171 (!elm_widget_drag_child_locked_x_get(sd->widget)))
1172 {
1173 if ((!sd->down.bounce_x_animator) && (!sd->bounce_animator_disabled))
1174 {
1175 if (sd->bouncemex)
1176 {
1177 if (sd->scrollto.x.animator)
1178 {
1179 ecore_animator_del(sd->scrollto.x.animator);
1180 sd->scrollto.x.animator = NULL;
1181 }
1182 sd->down.bounce_x_animator = ecore_animator_add(_smart_bounce_x_animator, sd);
1183 sd->down.anim_start2 = ecore_loop_time_get();
1184 sd->down.bx = bx;
1185 sd->down.bx0 = bx;
1186 sd->down.b2x = b2x;
1187 if (sd->down.momentum_animator) sd->down.b0x = sd->down.ax;
1188 else sd->down.b0x = 0;
1189 }
1190 }
1191 }
1192 if ((!sd->widget) ||
1193 (!elm_widget_drag_child_locked_y_get(sd->widget)))
1194 {
1195 if ((!sd->down.bounce_y_animator) && (!sd->bounce_animator_disabled))
1196 {
1197 if (sd->bouncemey)
1198 {
1199 if (sd->scrollto.y.animator)
1200 {
1201 ecore_animator_del(sd->scrollto.y.animator);
1202 sd->scrollto.y.animator = NULL;
1203 }
1204 sd->down.bounce_y_animator = ecore_animator_add(_smart_bounce_y_animator, sd);
1205 sd->down.anim_start3 = ecore_loop_time_get();
1206 sd->down.by = by;
1207 sd->down.by0 = by;
1208 sd->down.b2y = b2y;
1209 if (sd->down.momentum_animator) sd->down.b0y = sd->down.ay;
1210 else sd->down.b0y = 0;
1211 }
1212 }
1213 }
1214}
1215
1216void
1217elm_smart_scroller_child_pos_set(Evas_Object *obj, Evas_Coord x, Evas_Coord y)
1218{
1219 Evas_Coord mx = 0, my = 0, px = 0, py = 0, minx = 0, miny = 0;
1220 double vx, vy;
1221
1222 API_ENTRY return;
1223 // FIXME: allow for bounce outside of range
1224 sd->pan_func.max_get(sd->pan_obj, &mx, &my);
1225 sd->pan_func.min_get(sd->pan_obj, &minx, &miny);
1226 if (mx > 0) vx = (double)(x - minx) / (double)mx;
1227 else vx = 0.0;
1228 if (vx < 0.0) vx = 0.0;
1229 else if (vx > 1.0) vx = 1.0;
1230 if (my > 0) vy = (double)(y - miny) / (double)my;
1231 else vy = 0.0;
1232 if (vy < 0.0) vy = 0.0;
1233 else if (vy > 1.0) vy = 1.0;
1234 edje_object_part_drag_value_set(sd->edje_obj, "elm.dragable.vbar", 0.0, vy);
1235 edje_object_part_drag_value_set(sd->edje_obj, "elm.dragable.hbar", vx, 0.0);
1236 sd->pan_func.get(sd->pan_obj, &px, &py);
1237 if (!_elm_config->thumbscroll_bounce_enable)
1238 {
1239 if (x < minx) x = minx;
1240 if ((x - minx) > mx) x = mx + minx;
1241 if (y < miny) y = miny;
1242 if ((y - miny) > my) y = my + miny;
1243 }
1244
1245 if (!sd->bounce_horiz)
1246 {
1247 if (x < minx) x = minx;
1248 if ((x - minx) > mx) x = mx + minx;
1249 }
1250 if (!sd->bounce_vert)
1251 {
1252 if (y < miny) y = miny;
1253 if (y - miny > my) y = my + miny;
1254 }
1255
1256 sd->pan_func.set(sd->pan_obj, x, y);
1257 if ((px != x) || (py != y))
1258 edje_object_signal_emit(sd->edje_obj, "elm,action,scroll", "elm");
1259 if (!sd->down.bounce_x_animator)
1260 {
1261 if (((x < minx) && (0 <= sd->down.dx)) ||
1262 ((x > (mx + minx)) && (0 >= sd->down.dx)))
1263 {
1264 sd->bouncemex = EINA_TRUE;
1265 bounce_eval(sd);
1266 }
1267 else
1268 sd->bouncemex = EINA_FALSE;
1269 }
1270 if (!sd->down.bounce_y_animator)
1271 {
1272 if (((y < miny) && (0 <= sd->down.dy)) ||
1273 ((y > (my + miny)) && (0 >= sd->down.dy)))
1274 {
1275 sd->bouncemey = EINA_TRUE;
1276 bounce_eval(sd);
1277 }
1278 else
1279 sd->bouncemey = EINA_FALSE;
1280 }
1281 if ((x != px) || (y != py))
1282 {
1283 evas_object_smart_callback_call(obj, "scroll", NULL);
1284 }
1285 if ((x != px)/* && (!sd->bouncemex)*/)
1286 {
1287 if (x == minx)
1288 evas_object_smart_callback_call(obj, "edge,left", NULL);
1289 if (x == (mx + minx))
1290 evas_object_smart_callback_call(obj, "edge,right", NULL);
1291 }
1292 if ((y != py)/* && (!sd->bouncemey)*/)
1293 {
1294 if (y == miny)
1295 evas_object_smart_callback_call(obj, "edge,top", NULL);
1296 if (y == my + miny)
1297 evas_object_smart_callback_call(obj, "edge,bottom", NULL);
1298 }
1299 _elm_direction_arrows_eval(sd);
1300}
1301
1302void
1303elm_smart_scroller_child_pos_get(Evas_Object *obj, Evas_Coord *x, Evas_Coord *y)
1304{
1305 API_ENTRY return;
1306 sd->pan_func.get(sd->pan_obj, x, y);
1307}
1308
1309/* returns TRUE when we need to move the scroller, FALSE otherwise.
1310 * Updates w and h either way, so save them if you need them. */
1311static Eina_Bool
1312_elm_smart_scroller_child_region_show_internal(Evas_Object *obj, Evas_Coord *_x, Evas_Coord *_y, Evas_Coord w, Evas_Coord h)
1313{
1314 Evas_Coord mx = 0, my = 0, cw = 0, ch = 0, px = 0, py = 0, nx, ny, minx = 0, miny = 0, pw = 0, ph = 0, x = *_x, y = *_y;
1315
1316 API_ENTRY return EINA_FALSE;
1317 sd->pan_func.max_get(sd->pan_obj, &mx, &my);
1318 sd->pan_func.min_get(sd->pan_obj, &minx, &miny);
1319 sd->pan_func.child_size_get(sd->pan_obj, &cw, &ch);
1320 sd->pan_func.get(sd->pan_obj, &px, &py);
1321 evas_object_geometry_get(sd->pan_obj, NULL, NULL, &pw, &ph);
1322
1323 nx = px;
1324 if ((x < px) && ((x + w) < (px + (cw - mx)))) nx = x;
1325 else if ((x > px) && ((x + w) > (px + (cw - mx)))) nx = x + w - (cw - mx);
1326 ny = py;
1327 if ((y < py) && ((y + h) < (py + (ch - my)))) ny = y;
1328 else if ((y > py) && ((y + h) > (py + (ch - my)))) ny = y + h - (ch - my);
1329
1330 if ((sd->down.bounce_x_animator) || (sd->down.bounce_y_animator) ||
1331 (sd->scrollto.x.animator) || (sd->scrollto.y.animator))
1332 {
1333 _smart_anim_stop(sd->smart_obj);
1334 }
1335 if (sd->scrollto.x.animator)
1336 {
1337 ecore_animator_del(sd->scrollto.x.animator);
1338 sd->scrollto.x.animator = NULL;
1339 }
1340 if (sd->scrollto.y.animator)
1341 {
1342 ecore_animator_del(sd->scrollto.y.animator);
1343 sd->scrollto.y.animator = NULL;
1344 }
1345 if (sd->down.bounce_x_animator)
1346 {
1347 ecore_animator_del(sd->down.bounce_x_animator);
1348 sd->down.bounce_x_animator = NULL;
1349 sd->bouncemex = EINA_FALSE;
1350 if (sd->child.resized)
1351 _elm_smart_scroller_wanted_region_set(sd->smart_obj);
1352 }
1353 if (sd->down.bounce_y_animator)
1354 {
1355 ecore_animator_del(sd->down.bounce_y_animator);
1356 sd->down.bounce_y_animator = NULL;
1357 sd->bouncemey = EINA_FALSE;
1358 if (sd->child.resized)
1359 _elm_smart_scroller_wanted_region_set(sd->smart_obj);
1360 }
1361 if (sd->down.hold_animator)
1362 {
1363 ecore_animator_del(sd->down.hold_animator);
1364 sd->down.hold_animator = NULL;
1365 _smart_drag_stop(sd->smart_obj);
1366 if (sd->child.resized)
1367 _elm_smart_scroller_wanted_region_set(sd->smart_obj);
1368 }
1369 if (sd->down.momentum_animator)
1370 {
1371 ecore_animator_del(sd->down.momentum_animator);
1372 sd->down.momentum_animator = NULL;
1373 sd->down.bounce_x_hold = EINA_FALSE;
1374 sd->down.bounce_y_hold = EINA_FALSE;
1375 sd->down.ax = 0;
1376 sd->down.ay = 0;
1377 sd->down.pdx = 0;
1378 sd->down.pdy = 0;
1379 if (sd->child.resized)
1380 _elm_smart_scroller_wanted_region_set(sd->smart_obj);
1381 }
1382
1383 x = nx;
1384 if ((x + pw) > cw) x = cw - pw;
1385 if (x < minx) x = minx;
1386 y = ny;
1387 if ((y + ph) > ch) y = ch - ph;
1388 if (y < miny) y = miny;
1389
1390 if ((x == px) && (y == py)) return EINA_FALSE;
1391 *_x = x;
1392 *_y = y;
1393 return EINA_TRUE;
1394}
1395
1396/* Set should be used for calculated positions, for example, when we move
1397 * because of an animation or because this is the correct position after
1398 * constraints. */
1399void
1400elm_smart_scroller_child_region_set(Evas_Object *obj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h)
1401{
1402 API_ENTRY return;
1403 if (_elm_smart_scroller_child_region_show_internal(obj, &x, &y, w, h))
1404 {
1405 elm_smart_scroller_child_pos_set(obj, x, y);
1406 sd->down.sx = x;
1407 sd->down.sy = y;
1408 sd->down.x = sd->down.history[0].x;
1409 sd->down.y = sd->down.history[0].y;
1410 }
1411}
1412
1413/* Set should be used for setting the wanted position, for example a user scroll
1414 * or moving the cursor in an entry. */
1415void
1416elm_smart_scroller_child_region_show(Evas_Object *obj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h)
1417{
1418 API_ENTRY return;
1419 sd->wx = x;
1420 sd->wy = y;
1421 sd->ww = w;
1422 sd->wh = h;
1423 if (_elm_smart_scroller_child_region_show_internal(obj, &x, &y, w, h))
1424 {
1425 elm_smart_scroller_child_pos_set(obj, x, y);
1426 sd->down.sx = x;
1427 sd->down.sy = y;
1428 sd->down.x = sd->down.history[0].x;
1429 sd->down.y = sd->down.history[0].y;
1430 }
1431}
1432
1433void
1434elm_smart_scroller_child_viewport_size_get(Evas_Object *obj, Evas_Coord *w, Evas_Coord *h)
1435{
1436 API_ENTRY return;
1437 if (!sd->pan_obj) return;
1438 edje_object_calc_force(sd->edje_obj);
1439 evas_object_geometry_get(sd->pan_obj, NULL, NULL, w, h);
1440}
1441
1442void
1443elm_smart_scroller_step_size_set(Evas_Object *obj, Evas_Coord x, Evas_Coord y)
1444{
1445 API_ENTRY return;
1446 if (x < 1) x = 1;
1447 if (y < 1) y = 1;
1448 sd->step.x = x;
1449 sd->step.y = y;
1450 _smart_scrollbar_size_adjust(sd);
1451}
1452
1453void
1454elm_smart_scroller_step_size_get(Evas_Object *obj, Evas_Coord *x, Evas_Coord *y)
1455{
1456 API_ENTRY return;
1457 if (x) *x = sd->step.x;
1458 if (y) *y = sd->step.y;
1459}
1460
1461void
1462elm_smart_scroller_page_size_set(Evas_Object *obj, Evas_Coord x, Evas_Coord y)
1463{
1464 API_ENTRY return;
1465 sd->page.x = x;
1466 sd->page.y = y;
1467 _smart_scrollbar_size_adjust(sd);
1468}
1469
1470void
1471elm_smart_scroller_page_size_get(Evas_Object *obj, Evas_Coord *x, Evas_Coord *y)
1472{
1473 API_ENTRY return;
1474 if (x) *x = sd->page.x;
1475 if (y) *y = sd->page.y;
1476}
1477
1478void
1479elm_smart_scroller_policy_set(Evas_Object *obj, Elm_Smart_Scroller_Policy hbar, Elm_Smart_Scroller_Policy vbar)
1480{
1481 API_ENTRY return;
1482 if ((sd->hbar_flags == hbar) && (sd->vbar_flags == vbar)) return;
1483 sd->hbar_flags = hbar;
1484 sd->vbar_flags = vbar;
1485 if (sd->hbar_flags == ELM_SMART_SCROLLER_POLICY_ON)
1486 edje_object_signal_emit(sd->edje_obj, "elm,action,show_always,hbar", "elm");
1487 else if (sd->hbar_flags == ELM_SMART_SCROLLER_POLICY_OFF)
1488 edje_object_signal_emit(sd->edje_obj, "elm,action,hide,hbar", "elm");
1489 else
1490 edje_object_signal_emit(sd->edje_obj, "elm,action,show_notalways,hbar", "elm");
1491 if (sd->vbar_flags == ELM_SMART_SCROLLER_POLICY_ON)
1492 edje_object_signal_emit(sd->edje_obj, "elm,action,show_always,vbar", "elm");
1493 else if (sd->vbar_flags == ELM_SMART_SCROLLER_POLICY_OFF)
1494 edje_object_signal_emit(sd->edje_obj, "elm,action,hide,vbar", "elm");
1495 else
1496 edje_object_signal_emit(sd->edje_obj, "elm,action,show_notalways,vbar", "elm");
1497 _smart_scrollbar_size_adjust(sd);
1498 _elm_direction_arrows_eval(sd);
1499}
1500
1501void
1502elm_smart_scroller_policy_get(Evas_Object *obj, Elm_Smart_Scroller_Policy *hbar, Elm_Smart_Scroller_Policy *vbar)
1503{
1504 API_ENTRY return;
1505 if (hbar) *hbar = sd->hbar_flags;
1506 if (vbar) *vbar = sd->vbar_flags;
1507}
1508
1509Evas_Object *
1510elm_smart_scroller_edje_object_get(Evas_Object *obj)
1511{
1512 API_ENTRY return NULL;
1513 return sd->edje_obj;
1514}
1515
1516void
1517elm_smart_scroller_single_dir_set(Evas_Object *obj, Eina_Bool single_dir)
1518{
1519 API_ENTRY return;
1520 sd->one_dir_at_a_time = single_dir;
1521}
1522
1523Eina_Bool
1524elm_smart_scroller_single_dir_get(Evas_Object *obj)
1525{
1526 API_ENTRY return EINA_FALSE;
1527 return sd->one_dir_at_a_time;
1528}
1529
1530void
1531elm_smart_scroller_object_theme_set(Evas_Object *parent, Evas_Object *obj, const char *clas, const char *group, const char *style)
1532{
1533 API_ENTRY return;
1534 Evas_Coord mw, mh;
1535 //Does this API require parent object absolutely? if then remove this exception.
1536 double parent_scale = parent ? elm_widget_scale_get(parent) : 1;
1537 _elm_theme_object_set(parent, sd->edje_obj, clas, group, style);
1538 edje_object_scale_set(sd->edje_obj, parent_scale * _elm_config->scale);
1539 if (sd->pan_obj)
1540 edje_object_part_swallow(sd->edje_obj, "elm.swallow.content", sd->pan_obj);
1541 mw = mh = -1;
1542 elm_coords_finger_size_adjust(1, &mw, 1, &mh);
1543 if (edje_object_part_exists(sd->edje_obj, "elm.scrollbar.base"))
1544 {
1545 Evas_Object *base;
1546 base = edje_object_part_swallow_get(sd->edje_obj, "elm.scrollbar.base");
1547 if (!base)
1548 {
1549 base = evas_object_rectangle_add(evas_object_evas_get(sd->edje_obj));
1550 evas_object_color_set(base, 0, 0, 0, 0);
1551 edje_object_part_swallow(sd->edje_obj, "elm.scrollbar.base", base);
1552 }
1553 if (!_elm_config->thumbscroll_enable)
1554 evas_object_size_hint_min_set(base, mw, mh);
1555 }
1556 sd->vbar_visible = !sd->vbar_visible;
1557 sd->hbar_visible = !sd->hbar_visible;
1558 _smart_scrollbar_bar_visibility_adjust(sd);
1559}
1560
1561void
1562elm_smart_scroller_hold_set(Evas_Object *obj, Eina_Bool hold)
1563{
1564 API_ENTRY return;
1565 sd->hold = hold;
1566}
1567
1568void
1569elm_smart_scroller_freeze_set(Evas_Object *obj, Eina_Bool freeze)
1570{
1571 API_ENTRY return;
1572 sd->freeze = freeze;
1573 if (sd->freeze)
1574 {
1575 if (sd->down.onhold_animator)
1576 {
1577 ecore_animator_del(sd->down.onhold_animator);
1578 sd->down.onhold_animator = NULL;
1579 if (sd->child.resized)
1580 _elm_smart_scroller_wanted_region_set(sd->smart_obj);
1581 }
1582 }
1583 else
1584 bounce_eval(sd);
1585}
1586
1587void
1588elm_smart_scroller_bounce_allow_set(Evas_Object *obj, Eina_Bool horiz, Eina_Bool vert)
1589{
1590 API_ENTRY return;
1591 sd->bounce_horiz = !!horiz;
1592 sd->bounce_vert = !!vert;
1593}
1594
1595void
1596elm_smart_scroller_bounce_allow_get(const Evas_Object *obj, Eina_Bool *horiz, Eina_Bool *vert)
1597{
1598 API_ENTRY return;
1599 if (horiz) *horiz = sd->bounce_horiz;
1600 if (vert) *vert = sd->bounce_vert;
1601}
1602
1603void
1604elm_smart_scroller_paging_set(Evas_Object *obj, double pagerel_h, double pagerel_v, Evas_Coord pagesize_h, Evas_Coord pagesize_v)
1605{
1606 API_ENTRY return;
1607 sd->pagerel_h = pagerel_h;
1608 sd->pagerel_v = pagerel_v;
1609 sd->pagesize_h = pagesize_h;
1610 sd->pagesize_v = pagesize_v;
1611 _smart_page_adjust(sd);
1612}
1613
1614void
1615elm_smart_scroller_paging_get(Evas_Object *obj, double *pagerel_h, double *pagerel_v, Evas_Coord *pagesize_h, Evas_Coord *pagesize_v)
1616{
1617 API_ENTRY return;
1618 if (pagerel_h) *pagerel_h = sd->pagerel_h;
1619 if (pagerel_v) *pagerel_v = sd->pagerel_v;
1620 if (pagesize_h) *pagesize_h = sd->pagesize_h;
1621 if (pagesize_v) *pagesize_v = sd->pagesize_v;
1622}
1623
1624void
1625elm_smart_scroller_current_page_get(Evas_Object *obj, int *pagenumber_h, int *pagenumber_v)
1626{
1627 API_ENTRY return;
1628 Evas_Coord x, y;
1629 elm_smart_scroller_child_pos_get(sd->smart_obj, &x, &y);
1630 if (pagenumber_h)
1631 {
1632 if (sd->pagesize_h > 0)
1633 *pagenumber_h = (x + sd->pagesize_h - 1) / sd->pagesize_h;
1634 else
1635 *pagenumber_h = 0;
1636 }
1637 if (pagenumber_v)
1638 {
1639 if (sd->pagesize_v > 0)
1640 *pagenumber_v = (y + sd->pagesize_v - 1) / sd->pagesize_v;
1641 else
1642 *pagenumber_v = 0;
1643 }
1644}
1645
1646void
1647elm_smart_scroller_last_page_get(Evas_Object *obj, int *pagenumber_h, int *pagenumber_v)
1648{
1649 API_ENTRY return;
1650 Evas_Coord cw, ch;
1651 sd->pan_func.child_size_get(sd->pan_obj, &cw, &ch);
1652 if (pagenumber_h)
1653 {
1654 if (sd->pagesize_h > 0)
1655 *pagenumber_h = cw / sd->pagesize_h + 1;
1656 else
1657 *pagenumber_h = 0;
1658 }
1659 if (pagenumber_v)
1660 {
1661 if (sd->pagesize_v > 0)
1662 *pagenumber_v = ch / sd->pagesize_v + 1;
1663 else
1664 *pagenumber_v = 0;
1665 }
1666}
1667
1668void
1669elm_smart_scroller_page_show(Evas_Object *obj, int pagenumber_h, int pagenumber_v)
1670{
1671 API_ENTRY return;
1672 Evas_Coord x, y, w, h;
1673 elm_smart_scroller_child_viewport_size_get(sd->smart_obj, &w, &h);
1674 if (pagenumber_h >= 0) x = sd->pagesize_h * pagenumber_h;
1675 if (pagenumber_v >= 0) y = sd->pagesize_v * pagenumber_v;
1676 if (_elm_smart_scroller_child_region_show_internal(obj, &x, &y, w, h))
1677 elm_smart_scroller_child_pos_set(obj, x, y);
1678}
1679
1680void
1681elm_smart_scroller_page_bring_in(Evas_Object *obj, int pagenumber_h, int pagenumber_v)
1682{
1683 API_ENTRY return;
1684 Evas_Coord x, y, w, h;
1685 elm_smart_scroller_child_viewport_size_get(sd->smart_obj, &w, &h);
1686 if (pagenumber_h >= 0) x = sd->pagesize_h * pagenumber_h;
1687 if (pagenumber_v >= 0) y = sd->pagesize_v * pagenumber_v;
1688 if (_elm_smart_scroller_child_region_show_internal(obj, &x, &y, w, h))
1689 {
1690 _smart_scrollto_x(sd, _elm_config->bring_in_scroll_friction, x);
1691 _smart_scrollto_y(sd, _elm_config->bring_in_scroll_friction, y);
1692 }
1693}
1694
1695void
1696elm_smart_scroller_region_bring_in(Evas_Object *obj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h)
1697{
1698 API_ENTRY return;
1699 if (_elm_smart_scroller_child_region_show_internal(obj, &x, &y, w, h))
1700 {
1701 _smart_scrollto_x(sd, _elm_config->bring_in_scroll_friction, x);
1702 _smart_scrollto_y(sd, _elm_config->bring_in_scroll_friction, y);
1703 }
1704}
1705
1706void
1707elm_smart_scroller_widget_set(Evas_Object *obj, Evas_Object *wid)
1708{
1709 API_ENTRY return;
1710 sd->widget = wid;
1711}
1712
1713static void
1714_elm_smart_scroller_wanted_region_set(Evas_Object *obj)
1715{
1716 INTERNAL_ENTRY;
1717 Evas_Coord ww, wh, wx = sd->wx;
1718
1719 if (sd->down.now || sd->down.momentum_animator ||
1720 sd->down.bounce_x_animator || sd->down.bounce_y_animator ||
1721 sd->down.hold_animator || sd->down.onhold_animator ||
1722 sd->scrollto.x.animator || sd->scrollto.y.animator) return;
1723
1724 sd->child.resized = EINA_FALSE;
1725
1726 /* Flip to RTL cords only if init in RTL mode */
1727 if (sd->is_mirrored)
1728 wx = _elm_smart_scroller_x_mirrored_get(obj, sd->wx);
1729
1730 if (sd->ww == -1)
1731 {
1732 elm_smart_scroller_child_viewport_size_get(obj, &ww, &wh);
1733 }
1734 else
1735 {
1736 ww = sd->ww;
1737 wh = sd->wh;
1738 }
1739
1740 elm_smart_scroller_child_region_set(obj, wx, sd->wy, ww, wh);
1741}
1742
1743/* local subsystem functions */
1744static void
1745_smart_edje_drag_v_start(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
1746{
1747 Smart_Data *sd;
1748
1749 sd = data;
1750 _smart_scrollbar_read(sd);
1751 _smart_drag_start(sd->smart_obj);
1752 sd->freeze = EINA_TRUE;
1753}
1754
1755static void
1756_smart_edje_drag_v_stop(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
1757{
1758 Smart_Data *sd;
1759
1760 sd = data;
1761 _smart_scrollbar_read(sd);
1762 _smart_drag_stop(sd->smart_obj);
1763 sd->freeze = EINA_FALSE;
1764}
1765
1766static void
1767_smart_edje_drag_v(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
1768{
1769 Smart_Data *sd;
1770
1771 sd = data;
1772 _smart_scrollbar_read(sd);
1773}
1774
1775static void
1776_smart_edje_drag_h_start(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
1777{
1778 Smart_Data *sd;
1779
1780 sd = data;
1781 _smart_scrollbar_read(sd);
1782 _smart_drag_start(sd->smart_obj);
1783 sd->freeze = EINA_TRUE;
1784}
1785
1786static void
1787_smart_edje_drag_h_stop(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
1788{
1789 Smart_Data *sd;
1790
1791 sd = data;
1792 _smart_scrollbar_read(sd);
1793 _smart_drag_stop(sd->smart_obj);
1794 sd->freeze = EINA_FALSE;
1795}
1796
1797static void
1798_smart_edje_drag_h(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
1799{
1800 Smart_Data *sd;
1801
1802 sd = data;
1803 _smart_scrollbar_read(sd);
1804}
1805
1806static void
1807_smart_child_del_hook(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
1808{
1809 Smart_Data *sd;
1810
1811 sd = data;
1812 sd->child_obj = NULL;
1813 _smart_scrollbar_size_adjust(sd);
1814 _smart_scrollbar_reset(sd);
1815}
1816
1817static void
1818_smart_pan_changed_hook(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
1819{
1820 Evas_Coord w, h;
1821 Smart_Data *sd;
1822
1823 sd = data;
1824 sd->pan_func.child_size_get(sd->pan_obj, &w, &h);
1825 if ((w != sd->child.w) || (h != sd->child.h))
1826 {
1827 sd->child.w = w;
1828 sd->child.h = h;
1829 _smart_scrollbar_size_adjust(sd);
1830 evas_object_size_hint_min_set(sd->smart_obj, sd->child.w, sd->child.h);
1831 sd->child.resized = EINA_TRUE;
1832 _elm_smart_scroller_wanted_region_set(sd->smart_obj);
1833 }
1834}
1835
1836void
1837elm_smart_scroller_gravity_set(Evas_Object *obj, double x, double y)
1838{
1839 API_ENTRY return;
1840
1841 sd->pan_func.gravity_set(sd->pan_obj, x, y);
1842}
1843
1844void
1845elm_smart_scroller_gravity_get(Evas_Object *obj, double *x, double *y)
1846{
1847 API_ENTRY return;
1848
1849 sd->pan_func.gravity_get(sd->pan_obj, x, y);
1850}
1851
1852static void
1853_smart_event_wheel(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
1854{
1855 Evas_Event_Mouse_Wheel *ev;
1856 Smart_Data *sd;
1857 Evas_Coord x = 0, y = 0;
1858 int direction = 0;
1859
1860 sd = data;
1861 ev = event_info;
1862 direction = ev->direction;
1863 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return ;
1864 if ((evas_key_modifier_is_set(ev->modifiers, "Control")) ||
1865 (evas_key_modifier_is_set(ev->modifiers, "Alt")) ||
1866 (evas_key_modifier_is_set(ev->modifiers, "Meta")) ||
1867 (evas_key_modifier_is_set(ev->modifiers, "Hyper")) ||
1868 (evas_key_modifier_is_set(ev->modifiers, "Super")))
1869 return;
1870 else if (evas_key_modifier_is_set(ev->modifiers, "Shift"))
1871 direction = 1;
1872 elm_smart_scroller_child_pos_get(sd->smart_obj, &x, &y);
1873 if ((sd->down.bounce_x_animator) || (sd->down.bounce_y_animator) ||
1874 (sd->scrollto.x.animator) || (sd->scrollto.y.animator))
1875 {
1876 _smart_anim_stop(sd->smart_obj);
1877 }
1878 if (sd->scrollto.x.animator)
1879 {
1880 ecore_animator_del(sd->scrollto.x.animator);
1881 sd->scrollto.x.animator = NULL;
1882 }
1883 if (sd->scrollto.y.animator)
1884 {
1885 ecore_animator_del(sd->scrollto.y.animator);
1886 sd->scrollto.y.animator = NULL;
1887 }
1888 if (sd->down.bounce_x_animator)
1889 {
1890 ecore_animator_del(sd->down.bounce_x_animator);
1891 sd->down.bounce_x_animator = NULL;
1892 sd->bouncemex = EINA_FALSE;
1893 if (sd->child.resized)
1894 _elm_smart_scroller_wanted_region_set(sd->smart_obj);
1895 }
1896 if (sd->down.bounce_y_animator)
1897 {
1898 ecore_animator_del(sd->down.bounce_y_animator);
1899 sd->down.bounce_y_animator = NULL;
1900 sd->bouncemey = EINA_FALSE;
1901 if (sd->child.resized)
1902 _elm_smart_scroller_wanted_region_set(sd->smart_obj);
1903 }
1904 if (!direction)
1905 y += ev->z * sd->step.y;
1906 else if (direction == 1)
1907 x += ev->z * sd->step.x;
1908
1909 if ((!sd->hold) && (!sd->freeze))
1910 {
1911 _update_wanted_coordinates(sd, x, y);
1912 elm_smart_scroller_child_pos_set(sd->smart_obj, x, y);
1913 }
1914}
1915
1916static void
1917_smart_event_mouse_down(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
1918{
1919 Evas_Event_Mouse_Down *ev;
1920 Smart_Data *sd;
1921 Evas_Coord x = 0, y = 0;
1922
1923 sd = data;
1924 ev = event_info;
1925
1926#ifdef SMOOTHDBG
1927 if (getenv("ELS_SCROLLER_SMOOTH_DEBUG")) _els_scroller_smooth_debug = 1;
1928 if (_els_scroller_smooth_debug) _els_scroller_smooth_debug_init();
1929#endif
1930
1931 // if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return ;
1932 if (_elm_config->thumbscroll_enable)
1933 {
1934 sd->down.hold = EINA_FALSE;
1935 if ((sd->down.bounce_x_animator) || (sd->down.bounce_y_animator) ||
1936 (sd->down.momentum_animator) || (sd->scrollto.x.animator) ||
1937 (sd->scrollto.y.animator))
1938 {
1939 ev->event_flags |= EVAS_EVENT_FLAG_ON_SCROLL | EVAS_EVENT_FLAG_ON_HOLD;
1940 sd->down.scroll = EINA_TRUE;
1941 sd->down.hold = EINA_TRUE;
1942 _smart_anim_stop(sd->smart_obj);
1943 }
1944 if (sd->scrollto.x.animator)
1945 {
1946 ecore_animator_del(sd->scrollto.x.animator);
1947 sd->scrollto.x.animator = NULL;
1948 }
1949 if (sd->scrollto.y.animator)
1950 {
1951 ecore_animator_del(sd->scrollto.y.animator);
1952 sd->scrollto.y.animator = NULL;
1953 }
1954 if (sd->down.bounce_x_animator)
1955 {
1956 ecore_animator_del(sd->down.bounce_x_animator);
1957 sd->down.bounce_x_animator = NULL;
1958 sd->bouncemex = EINA_FALSE;
1959 if (sd->child.resized)
1960 _elm_smart_scroller_wanted_region_set(sd->smart_obj);
1961 }
1962 if (sd->down.bounce_y_animator)
1963 {
1964 ecore_animator_del(sd->down.bounce_y_animator);
1965 sd->down.bounce_y_animator = NULL;
1966 sd->bouncemey = EINA_FALSE;
1967 if (sd->child.resized)
1968 _elm_smart_scroller_wanted_region_set(sd->smart_obj);
1969 }
1970 if (sd->down.hold_animator)
1971 {
1972 ecore_animator_del(sd->down.hold_animator);
1973 sd->down.hold_animator = NULL;
1974 _smart_drag_stop(sd->smart_obj);
1975 if (sd->child.resized)
1976 _elm_smart_scroller_wanted_region_set(sd->smart_obj);
1977 }
1978 if (sd->down.momentum_animator)
1979 {
1980 ecore_animator_del(sd->down.momentum_animator);
1981 sd->down.momentum_animator = NULL;
1982 sd->down.bounce_x_hold = EINA_FALSE;
1983 sd->down.bounce_y_hold = EINA_FALSE;
1984 sd->down.ax = 0;
1985 sd->down.ay = 0;
1986 if (sd->child.resized)
1987 _elm_smart_scroller_wanted_region_set(sd->smart_obj);
1988 }
1989 if (ev->button == 1)
1990 {
1991 sd->down.hist.est_timestamp_diff =
1992 ecore_loop_time_get() - ((double)ev->timestamp / 1000.0);
1993 sd->down.hist.tadd = 0.0;
1994 sd->down.hist.dxsum = 0.0;
1995 sd->down.hist.dysum = 0.0;
1996 sd->down.now = EINA_TRUE;
1997 sd->down.dragged = EINA_FALSE;
1998 sd->down.dir_x = EINA_FALSE;
1999 sd->down.dir_y = EINA_FALSE;
2000 sd->down.x = ev->canvas.x;
2001 sd->down.y = ev->canvas.y;
2002 elm_smart_scroller_child_pos_get(sd->smart_obj, &x, &y);
2003 sd->down.sx = x;
2004 sd->down.sy = y;
2005 sd->down.locked = EINA_FALSE;
2006 memset(&(sd->down.history[0]), 0, sizeof(sd->down.history[0]) * 60);
2007#ifdef EVTIME
2008 sd->down.history[0].timestamp = ev->timestamp / 1000.0;
2009 sd->down.history[0].localtimestamp = ecore_loop_time_get();
2010#else
2011 sd->down.history[0].timestamp = ecore_loop_time_get();
2012#endif
2013 sd->down.history[0].x = ev->canvas.x;
2014 sd->down.history[0].y = ev->canvas.y;
2015 }
2016 sd->down.dragged_began = EINA_FALSE;
2017 sd->down.hold_parent = EINA_FALSE;
2018 sd->down.cancelled = EINA_FALSE;
2019 if (sd->hold || sd->freeze)
2020 sd->down.want_reset = EINA_TRUE;
2021 else
2022 sd->down.want_reset = EINA_FALSE;
2023 }
2024}
2025
2026static void
2027_down_coord_eval(Smart_Data *sd, Evas_Coord *x, Evas_Coord *y)
2028{
2029 Evas_Coord minx, miny;
2030
2031 if (sd->down.dir_x) *x = sd->down.sx - (*x - sd->down.x);
2032 else *x = sd->down.sx;
2033 if (sd->down.dir_y) *y = sd->down.sy - (*y - sd->down.y);
2034 else *y = sd->down.sy;
2035
2036 if ((sd->down.dir_x) || (sd->down.dir_y))
2037 {
2038 if (!((sd->down.dir_x) && (sd->down.dir_y)))
2039 {
2040 if (sd->down.dir_x) *y = sd->down.locked_y;
2041 else *x = sd->down.locked_x;
2042 }
2043 }
2044
2045 sd->pan_func.min_get(sd->pan_obj, &minx, &miny);
2046
2047 if (*x < minx)
2048 *x += (minx - *x) * _elm_config->thumbscroll_border_friction;
2049 else if (sd->child.w <= sd->w)
2050 *x += (sd->down.sx - *x) * _elm_config->thumbscroll_border_friction;
2051 else if ((sd->child.w - sd->w + minx) < *x)
2052 *x += (sd->child.w - sd->w + minx - *x) *
2053 _elm_config->thumbscroll_border_friction;
2054
2055 if (*y < miny)
2056 *y += (miny - *y) * _elm_config->thumbscroll_border_friction;
2057 else if (sd->child.h <= sd->h)
2058 *y += (sd->down.sy - *y) * _elm_config->thumbscroll_border_friction;
2059 else if ((sd->child.h - sd->h + miny) < *y)
2060 *y += (sd->child.h - sd->h + miny - *y) *
2061 _elm_config->thumbscroll_border_friction;
2062}
2063
2064static Eina_Bool
2065_smart_hold_animator(void *data)
2066{
2067 Smart_Data *sd = data;
2068 Evas_Coord ox = 0, oy = 0, fx = 0, fy= 0;
2069
2070 fx = sd->down.hold_x;
2071 fy = sd->down.hold_y;
2072
2073 if ((!sd->hold) && (!sd->freeze) && (_elm_config->scroll_smooth_time_interval > 0.0))
2074 {
2075 int i, count = 0; //count for the real event number we have to deal with
2076 int queue_size = 10; //for event queue size
2077 int src_index = 0, dst_index = 0;
2078 int xsum = 0, ysum = 0;
2079 Evas_Coord x = 0, y = 0;
2080
2081 struct {
2082 Evas_Coord x, y;
2083 double t;
2084 } pos[queue_size];
2085
2086 double tdiff, tnow;
2087 double time_interval = _elm_config->scroll_smooth_time_interval;
2088 // FIXME: assume server and client have the same "timezone"
2089 // (0 timepoint) for now. this needs to be figured out in advance
2090 // though.
2091 tdiff = sd->down.hist.est_timestamp_diff;
2092 tnow = ecore_time_get() - tdiff;
2093
2094 memset(pos, 0, sizeof (pos));
2095
2096 for(i = 0; i < queue_size; i++)
2097 {
2098 x = sd->down.history[i].x;
2099 y = sd->down.history[i].y;
2100
2101 //if there is no history value , we don't deal with it
2102 //if there is better wat to know existance of history value , I will modify this code to it
2103 if ( (x == 0) && (y == 0) )
2104 {
2105 break;
2106 }
2107 _down_coord_eval(sd, &x, &y);
2108
2109 pos[i].x = x;
2110 pos[i].y = y;
2111 pos[i].t = tnow - sd->down.history[i].timestamp;
2112 }
2113 count = --i;
2114
2115 // we only deal with smooth scroll there is enough history
2116 for(i = 0; i < queue_size; i++)
2117 {
2118 if (src_index > count) break;
2119 if (i == 0)
2120 {
2121 xsum = pos[i].x;
2122 ysum = pos[i].y;
2123 dst_index++;
2124 continue;
2125 }
2126 while ((pos[src_index].t < time_interval * i) && (src_index <= count))
2127 {
2128 src_index++;
2129 }
2130 if (src_index <= count)
2131 {
2132 xsum += pos[src_index].x;
2133 ysum += pos[src_index].y;
2134 dst_index++;
2135 }
2136 }
2137 /* Note: difficult to trigger, but may be possible to get src_index == 0 and count < 0 and so trigger a divide by zero. */
2138 if (!dst_index) dst_index = 1;
2139 fx = xsum / dst_index;
2140 fy = ysum / dst_index;
2141 }
2142
2143 elm_smart_scroller_child_pos_get(sd->smart_obj, &ox, &oy);
2144 if (sd->down.dir_x)
2145 {
2146 if ((!sd->widget) ||
2147 (!elm_widget_drag_child_locked_x_get(sd->widget)))
2148 ox = fx;
2149 }
2150 if (sd->down.dir_y)
2151 {
2152 if ((!sd->widget) ||
2153 (!elm_widget_drag_child_locked_y_get(sd->widget)))
2154 oy = fy;
2155 }
2156
2157#ifdef SMOOTHDBG
2158 if (_els_scroller_smooth_debug)
2159 _els_scroller_smooth_debug_movetime_add(ox, oy);
2160#endif
2161
2162 elm_smart_scroller_child_pos_set(sd->smart_obj, ox, oy);
2163 return ECORE_CALLBACK_RENEW;
2164}
2165
2166static Eina_Bool
2167_smart_event_post_up(void *data, Evas *e __UNUSED__)
2168{
2169 Smart_Data *sd = data;
2170 if (sd->widget)
2171 {
2172 if (sd->down.dragged)
2173 {
2174 elm_widget_drag_lock_x_set(sd->widget, 0);
2175 elm_widget_drag_lock_y_set(sd->widget, 0);
2176 }
2177 }
2178 return EINA_TRUE;
2179}
2180
2181static void
2182_smart_event_mouse_up(void *data, Evas *e, Evas_Object *obj __UNUSED__, void *event_info)
2183{
2184 Evas_Event_Mouse_Down *ev;
2185 Smart_Data *sd;
2186 Evas_Coord x = 0, y = 0, ox = 0, oy = 0;
2187
2188#ifdef SMOOTHDBG
2189 if (_els_scroller_smooth_debug) _els_scroller_smooth_debug_shutdown();
2190#endif
2191
2192 sd = data;
2193 ev = event_info;
2194 sd->down.hold_parent = EINA_FALSE;
2195 sd->down.dx = 0;
2196 sd->down.dy = 0;
2197 // if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return ;
2198 evas_post_event_callback_push(e, _smart_event_post_up, sd);
2199 // FIXME: respect elm_widget_scroll_hold_get of parent container
2200 if (_elm_config->thumbscroll_enable)
2201 {
2202 if (ev->button == 1)
2203 {
2204 if (sd->down.onhold_animator)
2205 {
2206 ecore_animator_del(sd->down.onhold_animator);
2207 sd->down.onhold_animator = NULL;
2208 if (sd->child.resized)
2209 _elm_smart_scroller_wanted_region_set(sd->smart_obj);
2210 }
2211 x = ev->canvas.x - sd->down.x;
2212 y = ev->canvas.y - sd->down.y;
2213 if (sd->down.dragged)
2214 {
2215 _smart_drag_stop(sd->smart_obj);
2216 if ((!sd->hold) && (!sd->freeze))
2217 {
2218 double t, at, dt;
2219 int i;
2220 Evas_Coord ax, ay, dx, dy, vel;
2221
2222#ifdef EVTIME
2223 t = ev->timestamp / 1000.0;
2224#else
2225 t = ecore_loop_time_get();
2226#endif
2227 ax = ev->canvas.x;
2228 ay = ev->canvas.y;
2229 at = 0.0;
2230#ifdef SCROLLDBG
2231 printf("------ %i %i\n", ev->canvas.x, ev->canvas.y);
2232#endif
2233 for (i = 0; i < 60; i++)
2234 {
2235 dt = t - sd->down.history[i].timestamp;
2236 if (dt > 0.2) break;
2237#ifdef SCROLLDBG
2238 printf("H: %i %i @ %1.3f\n",
2239 sd->down.history[i].x,
2240 sd->down.history[i].y, dt);
2241#endif
2242 at += dt;
2243 ax += sd->down.history[i].x;
2244 ay += sd->down.history[i].y;
2245 }
2246 ax /= (i + 1);
2247 ay /= (i + 1);
2248 at /= (i + 1);
2249 at /= _elm_config->thumbscroll_sensitivity_friction;
2250 dx = ev->canvas.x - ax;
2251 dy = ev->canvas.y - ay;
2252 if (at > 0)
2253 {
2254 vel = sqrt((dx * dx) + (dy * dy)) / at;
2255 if ((_elm_config->thumbscroll_friction > 0.0) &&
2256 (vel > _elm_config->thumbscroll_momentum_threshold))
2257 {
2258 int minx, miny, mx, my, px, py;
2259 sd->pan_func.min_get(sd->pan_obj, &minx, &miny);
2260 sd->pan_func.max_get(sd->pan_obj, &mx, &my);
2261 sd->pan_func.get(sd->pan_obj, &px, &py);
2262 sd->down.dx = ((double)dx / at);
2263 sd->down.dy = ((double)dy / at);
2264 if (((sd->down.dx > 0) && (sd->down.pdx > 0)) ||
2265 ((sd->down.dx < 0) && (sd->down.pdx < 0)))
2266 if (px > minx && px < mx)
2267 sd->down.dx += (double)sd->down.pdx * 1.5; // FIXME: * 1.5 - probably should be config
2268 if (((sd->down.dy > 0) && (sd->down.pdy > 0)) ||
2269 ((sd->down.dy < 0) && (sd->down.pdy < 0)))
2270 if (py > miny && py < my)
2271 sd->down.dy += (double)sd->down.pdy * 1.5; // FIXME: * 1.5 - probably should be config
2272 if (((sd->down.dx > 0) && (sd->down.pdx > 0)) ||
2273 ((sd->down.dx < 0) && (sd->down.pdx < 0)) ||
2274 ((sd->down.dy > 0) && (sd->down.pdy > 0)) ||
2275 ((sd->down.dy < 0) && (sd->down.pdy < 0)))
2276 {
2277 double tt = ecore_loop_time_get();
2278 double dtt = tt - sd->down.anim_start;
2279
2280 if (dtt < 0.0) dtt = 0.0;
2281 else if (dtt > _elm_config->thumbscroll_friction)
2282 dtt = _elm_config->thumbscroll_friction;
2283 sd->down.extra_time = _elm_config->thumbscroll_friction - dtt;
2284 }
2285 else
2286 sd->down.extra_time = 0.0;
2287 sd->down.pdx = sd->down.dx;
2288 sd->down.pdy = sd->down.dy;
2289 ox = -sd->down.dx;
2290 oy = -sd->down.dy;
2291 if (!_smart_do_page(sd))
2292 {
2293 if ((!sd->down.momentum_animator) && (!sd->momentum_animator_disabled) &&
2294 (sd->widget) && (!elm_widget_drag_child_locked_y_get(sd->widget)))
2295 {
2296 sd->down.momentum_animator = ecore_animator_add(_smart_momentum_animator, sd);
2297 ev->event_flags |= EVAS_EVENT_FLAG_ON_SCROLL;
2298 _smart_anim_start(sd->smart_obj);
2299 }
2300 sd->down.anim_start = ecore_loop_time_get();
2301 elm_smart_scroller_child_pos_get(sd->smart_obj, &x, &y);
2302 sd->down.sx = x;
2303 sd->down.sy = y;
2304 sd->down.b0x = 0;
2305 sd->down.b0y = 0;
2306 }
2307 }
2308 }
2309 }
2310 else
2311 {
2312 sd->down.pdx = 0;
2313 sd->down.pdy = 0;
2314 }
2315 evas_event_feed_hold(e, 0, ev->timestamp, ev->data);
2316 if (_smart_do_page(sd))
2317 {
2318 Evas_Coord pgx, pgy;
2319
2320 elm_smart_scroller_child_pos_get(sd->smart_obj, &x, &y);
2321 if ((!sd->widget) ||
2322 (!elm_widget_drag_child_locked_x_get(sd->widget)))
2323 {
2324 pgx = _smart_page_x_get(sd, ox);
2325 if (pgx != x)
2326 {
2327 ev->event_flags |= EVAS_EVENT_FLAG_ON_SCROLL;
2328 _smart_scrollto_x(sd, _elm_config->page_scroll_friction, pgx);
2329 }
2330 }
2331 if ((!sd->widget) ||
2332 (!elm_widget_drag_child_locked_y_get(sd->widget)))
2333 {
2334 pgy = _smart_page_y_get(sd, oy);
2335 if (pgy != y)
2336 {
2337 ev->event_flags |= EVAS_EVENT_FLAG_ON_SCROLL;
2338 _smart_scrollto_y(sd, _elm_config->page_scroll_friction, pgy);
2339 }
2340 }
2341 }
2342 }
2343 else
2344 {
2345 sd->down.pdx = 0;
2346 sd->down.pdy = 0;
2347 if (_smart_do_page(sd))
2348 {
2349 Evas_Coord pgx, pgy;
2350
2351 elm_smart_scroller_child_pos_get(sd->smart_obj, &x, &y);
2352 if ((!sd->widget) ||
2353 (!elm_widget_drag_child_locked_x_get(sd->widget)))
2354 {
2355 pgx = _smart_page_x_get(sd, ox);
2356 if (pgx != x) _smart_scrollto_x(sd, _elm_config->page_scroll_friction, pgx);
2357 }
2358 if ((!sd->widget) ||
2359 (!elm_widget_drag_child_locked_y_get(sd->widget)))
2360 {
2361 pgy = _smart_page_y_get(sd, oy);
2362 if (pgy != y) _smart_scrollto_y(sd, _elm_config->page_scroll_friction, pgy);
2363 }
2364 }
2365 }
2366 if (sd->down.hold_animator)
2367 {
2368 ecore_animator_del(sd->down.hold_animator);
2369 sd->down.hold_animator = NULL;
2370 if (sd->child.resized)
2371 _elm_smart_scroller_wanted_region_set(sd->smart_obj);
2372 }
2373 if (sd->down.scroll)
2374 {
2375 ev->event_flags |= EVAS_EVENT_FLAG_ON_SCROLL;
2376 sd->down.scroll = EINA_FALSE;
2377 }
2378 if (sd->down.hold)
2379 sd->down.hold = EINA_FALSE;
2380 sd->down.dragged_began = EINA_FALSE;
2381 sd->down.dir_x = EINA_FALSE;
2382 sd->down.dir_y = EINA_FALSE;
2383 sd->down.want_dragged = EINA_FALSE;
2384 sd->down.dragged = EINA_FALSE;
2385 sd->down.now = EINA_FALSE;
2386 elm_smart_scroller_child_pos_get(sd->smart_obj, &x, &y);
2387 elm_smart_scroller_child_pos_set(sd->smart_obj, x, y);
2388 _update_wanted_coordinates(sd, x, y);
2389
2390 if (sd->child.resized)
2391 _elm_smart_scroller_wanted_region_set(sd->smart_obj);
2392
2393 if (!_smart_do_page(sd))
2394 bounce_eval(sd);
2395 }
2396 }
2397}
2398
2399static Eina_Bool
2400_smart_onhold_animator(void *data)
2401{
2402 Smart_Data *sd;
2403 double t, td;
2404 double vx, vy;
2405 Evas_Coord x, y, ox, oy;
2406
2407 sd = data;
2408 t = ecore_loop_time_get();
2409 if (sd->down.onhold_tlast > 0.0)
2410 {
2411 td = t - sd->down.onhold_tlast;
2412 vx = sd->down.onhold_vx * td * (double)_elm_config->thumbscroll_threshold * 2.0;
2413 vy = sd->down.onhold_vy * td * (double)_elm_config->thumbscroll_threshold * 2.0;
2414 elm_smart_scroller_child_pos_get(sd->smart_obj, &ox, &oy);
2415 x = ox;
2416 y = oy;
2417
2418 if (sd->down.dir_x)
2419 {
2420 if ((!sd->widget) ||
2421 (!elm_widget_drag_child_locked_x_get(sd->widget)))
2422 {
2423 sd->down.onhold_vxe += vx;
2424 x = ox + (int)sd->down.onhold_vxe;
2425 sd->down.onhold_vxe -= (int)sd->down.onhold_vxe;
2426 }
2427 }
2428
2429 if (sd->down.dir_y)
2430 {
2431 if ((!sd->widget) ||
2432 (!elm_widget_drag_child_locked_y_get(sd->widget)))
2433 {
2434 sd->down.onhold_vye += vy;
2435 y = oy + (int)sd->down.onhold_vye;
2436 sd->down.onhold_vye -= (int)sd->down.onhold_vye;
2437 }
2438 }
2439
2440 elm_smart_scroller_child_pos_set(sd->smart_obj, x, y);
2441 }
2442 sd->down.onhold_tlast = t;
2443 return ECORE_CALLBACK_RENEW;
2444}
2445
2446static Eina_Bool
2447_smart_event_post_move(void *data, Evas *e __UNUSED__)
2448{
2449 Smart_Data *sd = data;
2450
2451 if (sd->down.want_dragged)
2452 {
2453 int start = 0;
2454
2455 if (sd->down.hold_parent)
2456 {
2457 if ((sd->down.dir_x) && !can_scroll(sd, sd->down.hdir))
2458 {
2459 sd->down.dir_x = EINA_FALSE;
2460 }
2461 if ((sd->down.dir_y) && !can_scroll(sd, sd->down.vdir))
2462 {
2463 sd->down.dir_y = EINA_FALSE;
2464 }
2465 }
2466 if (sd->down.dir_x)
2467 {
2468 if ((!sd->widget) ||
2469 (!elm_widget_drag_child_locked_x_get(sd->widget)))
2470 {
2471 sd->down.want_dragged = EINA_FALSE;
2472 sd->down.dragged = EINA_TRUE;
2473 if (sd->widget)
2474 {
2475 elm_widget_drag_lock_x_set(sd->widget, 1);
2476 }
2477 start = 1;
2478 }
2479 else
2480 sd->down.dir_x = EINA_FALSE;
2481 }
2482 if (sd->down.dir_y)
2483 {
2484 if ((!sd->widget) ||
2485 (!elm_widget_drag_child_locked_y_get(sd->widget)))
2486 {
2487 sd->down.want_dragged = EINA_FALSE;
2488 sd->down.dragged = EINA_TRUE;
2489 if (sd->widget)
2490 {
2491 elm_widget_drag_lock_y_set(sd->widget, 1);
2492 }
2493 start = 1;
2494 }
2495 else
2496 sd->down.dir_y = EINA_FALSE;
2497 }
2498 if ((!sd->down.dir_x) && (!sd->down.dir_y))
2499 {
2500 sd->down.cancelled = EINA_TRUE;
2501 }
2502 if (start) _smart_drag_start(sd->smart_obj);
2503 }
2504 return EINA_TRUE;
2505}
2506
2507static void
2508_smart_event_mouse_move(void *data, Evas *e, Evas_Object *obj __UNUSED__, void *event_info)
2509{
2510 Evas_Event_Mouse_Move *ev;
2511 Smart_Data *sd;
2512 Evas_Coord x = 0, y = 0;
2513
2514 sd = data;
2515 ev = event_info;
2516 // if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return ;
2517 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
2518 sd->down.hold_parent = EINA_TRUE;
2519 evas_post_event_callback_push(e, _smart_event_post_move, sd);
2520
2521 // FIXME: respect elm_widget_scroll_hold_get of parent container
2522 if (_elm_config->thumbscroll_enable)
2523 {
2524 if (sd->down.now)
2525 {
2526 int dodir = 0;
2527
2528 if ((sd->scrollto.x.animator) && (!sd->hold) && (!sd->freeze))
2529 {
2530 Evas_Coord px;
2531 ecore_animator_del(sd->scrollto.x.animator);
2532 sd->scrollto.x.animator = NULL;
2533 sd->pan_func.get(sd->pan_obj, &px, NULL);
2534 sd->down.sx = px;
2535 sd->down.x = sd->down.history[0].x;
2536 }
2537
2538 if ((sd->scrollto.y.animator) && (!sd->hold) && (!sd->freeze))
2539 {
2540 Evas_Coord py;
2541 ecore_animator_del(sd->scrollto.y.animator);
2542 sd->scrollto.y.animator = NULL;
2543 sd->pan_func.get(sd->pan_obj, NULL, &py);
2544 sd->down.sy = py;
2545 sd->down.y = sd->down.history[0].y;
2546 }
2547
2548#ifdef SCROLLDBG
2549 printf("::: %i %i\n", ev->cur.canvas.x, ev->cur.canvas.y);
2550#endif
2551 memmove(&(sd->down.history[1]), &(sd->down.history[0]),
2552 sizeof(sd->down.history[0]) * (60 - 1));
2553#ifdef EVTIME
2554 sd->down.history[0].timestamp = ev->timestamp / 1000.0;
2555 sd->down.history[0].localtimestamp = ecore_loop_time_get();
2556#else
2557 sd->down.history[0].timestamp = ecore_loop_time_get();
2558#endif
2559 sd->down.history[0].x = ev->cur.canvas.x;
2560 sd->down.history[0].y = ev->cur.canvas.y;
2561
2562 if (!sd->down.dragged_began)
2563 {
2564 x = ev->cur.canvas.x - sd->down.x;
2565 y = ev->cur.canvas.y - sd->down.y;
2566
2567 sd->down.hdir = -1;
2568 sd->down.vdir = -1;
2569
2570 if (x > 0) sd->down.hdir = LEFT;
2571 else if (x < 0) sd->down.hdir = RIGHT;
2572 if (y > 0) sd->down.vdir = UP;
2573 else if (y < 0) sd->down.vdir = DOWN;
2574
2575 if (x < 0) x = -x;
2576 if (y < 0) y = -y;
2577
2578 if ((sd->one_dir_at_a_time) &&
2579 (!((sd->down.dir_x) || (sd->down.dir_y))))
2580 {
2581 if (x > _elm_config->thumbscroll_threshold)
2582 {
2583 if (x > (y * 2))
2584 {
2585 sd->down.dir_x = EINA_TRUE;
2586 sd->down.dir_y = EINA_FALSE;
2587 dodir++;
2588 }
2589 }
2590 if (y > _elm_config->thumbscroll_threshold)
2591 {
2592 if (y > (x * 2))
2593 {
2594 sd->down.dir_x = EINA_FALSE;
2595 sd->down.dir_y = EINA_TRUE;
2596 dodir++;
2597 }
2598 }
2599 if (!dodir)
2600 {
2601 sd->down.dir_x = EINA_TRUE;
2602 sd->down.dir_y = EINA_TRUE;
2603 }
2604 }
2605 else
2606 {
2607 sd->down.dir_x = EINA_TRUE;
2608 sd->down.dir_y = EINA_TRUE;
2609 }
2610 }
2611 if ((!sd->hold) && (!sd->freeze))
2612 {
2613 if ((sd->down.dragged) ||
2614 (((x * x) + (y * y)) >
2615 (_elm_config->thumbscroll_threshold *
2616 _elm_config->thumbscroll_threshold)))
2617 {
2618 sd->down.dragged_began = EINA_TRUE;
2619 if (!sd->down.dragged)
2620 {
2621 sd->down.want_dragged = EINA_TRUE;
2622 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
2623 // evas_event_feed_hold(e, 1, ev->timestamp, ev->data);
2624 // _smart_drag_start(sd->smart_obj);
2625 }
2626 if (sd->down.dragged)
2627 {
2628 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
2629 }
2630 // ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
2631 // sd->down.dragged = 1;
2632 if (sd->down.dir_x)
2633 x = sd->down.sx - (ev->cur.canvas.x - sd->down.x);
2634 else
2635 x = sd->down.sx;
2636 if (sd->down.dir_y)
2637 y = sd->down.sy - (ev->cur.canvas.y - sd->down.y);
2638 else
2639 y = sd->down.sy;
2640 if (sd->down.want_reset)
2641 {
2642 sd->down.x = ev->cur.canvas.x;
2643 sd->down.y = ev->cur.canvas.y;
2644 sd->down.want_reset = EINA_FALSE;
2645 }
2646 if ((sd->down.dir_x) || (sd->down.dir_y))
2647 {
2648 if (!sd->down.locked)
2649 {
2650 sd->down.locked_x = x;
2651 sd->down.locked_y = y;
2652 sd->down.locked = EINA_TRUE;
2653 }
2654 if (!((sd->down.dir_x) && (sd->down.dir_y)))
2655 {
2656 if (sd->down.dir_x) y = sd->down.locked_y;
2657 else x = sd->down.locked_x;
2658 }
2659 }
2660 {
2661 Evas_Coord minx, miny;
2662 sd->pan_func.min_get(sd->pan_obj, &minx, &miny);
2663 if (y < miny)
2664 y += (miny - y) *
2665 _elm_config->thumbscroll_border_friction;
2666 else if (sd->child.h <= sd->h)
2667 y += (sd->down.sy - y) *
2668 _elm_config->thumbscroll_border_friction;
2669 else if ((sd->child.h - sd->h + miny) < y)
2670 y += (sd->child.h - sd->h + miny - y) *
2671 _elm_config->thumbscroll_border_friction;
2672 if (x < minx)
2673 x += (minx - x) *
2674 _elm_config->thumbscroll_border_friction;
2675 else if (sd->child.w <= sd->w)
2676 x += (sd->down.sx - x) *
2677 _elm_config->thumbscroll_border_friction;
2678 else if ((sd->child.w - sd->w + minx) < x)
2679 x += (sd->child.w - sd->w + minx - x) *
2680 _elm_config->thumbscroll_border_friction;
2681 }
2682
2683 sd->down.hold_x = x;
2684 sd->down.hold_y = y;
2685 if (!sd->down.hold_animator)
2686 sd->down.hold_animator =
2687 ecore_animator_add(_smart_hold_animator, sd);
2688 // printf("a %i %i\n", sd->down.hold_x, sd->down.hold_y);
2689 // _smart_onhold_animator(sd);
2690 // elm_smart_scroller_child_pos_set(sd->smart_obj, x, y);
2691 }
2692 else
2693 {
2694 if (sd->down.dragged_began)
2695 {
2696 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
2697 if (!sd->down.hold)
2698 {
2699 sd->down.hold = EINA_TRUE;
2700 evas_event_feed_hold(e, 1, ev->timestamp, ev->data);
2701 }
2702 }
2703 }
2704 }
2705 else if (!sd->freeze)
2706 {
2707 Evas_Coord ex, ey, ew, eh;
2708 double vx = 0.0, vy = 0.0;
2709
2710 evas_object_geometry_get(sd->event_obj, &ex, &ey, &ew, &eh);
2711 x = ev->cur.canvas.x - ex;
2712 y = ev->cur.canvas.y - ey;
2713 if (x < _elm_config->thumbscroll_threshold)
2714 {
2715 if (_elm_config->thumbscroll_threshold > 0.0)
2716 vx = -(double)(_elm_config->thumbscroll_threshold - x) /
2717 _elm_config->thumbscroll_threshold;
2718 else
2719 vx = -1.0;
2720 }
2721 else if (x > (ew - _elm_config->thumbscroll_threshold))
2722 {
2723 if (_elm_config->thumbscroll_threshold > 0.0)
2724 vx = (double)(_elm_config->thumbscroll_threshold - (ew - x)) /
2725 _elm_config->thumbscroll_threshold;
2726 else
2727 vx = 1.0;
2728 }
2729 if (y < _elm_config->thumbscroll_threshold)
2730 {
2731 if (_elm_config->thumbscroll_threshold > 0.0)
2732 vy = -(double)(_elm_config->thumbscroll_threshold - y) /
2733 _elm_config->thumbscroll_threshold;
2734 else
2735 vy = -1.0;
2736 }
2737 else if (y > (eh - _elm_config->thumbscroll_threshold))
2738 {
2739 if (_elm_config->thumbscroll_threshold > 0.0)
2740 vy = (double)(_elm_config->thumbscroll_threshold - (eh - y)) /
2741 _elm_config->thumbscroll_threshold;
2742 else
2743 vy = 1.0;
2744 }
2745 if ((vx != 0.0) || (vy != 0.0))
2746 {
2747 sd->down.onhold_vx = vx;
2748 sd->down.onhold_vy = vy;
2749 if (!sd->down.onhold_animator)
2750 {
2751 sd->down.onhold_vxe = 0.0;
2752 sd->down.onhold_vye = 0.0;
2753 sd->down.onhold_tlast = 0.0;
2754 sd->down.onhold_animator = ecore_animator_add(_smart_onhold_animator, sd);
2755 }
2756 // printf("b %i %i\n", sd->down.hold_x, sd->down.hold_y);
2757 }
2758 else
2759 {
2760 if (sd->down.onhold_animator)
2761 {
2762 ecore_animator_del(sd->down.onhold_animator);
2763 sd->down.onhold_animator = NULL;
2764 if (sd->child.resized)
2765 _elm_smart_scroller_wanted_region_set(sd->smart_obj);
2766 }
2767 }
2768 }
2769 }
2770 }
2771}
2772
2773static void
2774_smart_scrollbar_read(Smart_Data *sd)
2775{
2776 Evas_Coord x, y, mx = 0, my = 0, px, py, minx = 0, miny = 0;
2777 double vx, vy;
2778
2779 if ((sd->down.dragged) || (sd->down.bounce_x_animator)
2780 || (sd->down.bounce_y_animator) || (sd->down.momentum_animator)
2781 || (sd->scrollto.x.animator) || (sd->scrollto.y.animator))
2782 return;
2783 edje_object_part_drag_value_get(sd->edje_obj, "elm.dragable.vbar", NULL, &vy);
2784 edje_object_part_drag_value_get(sd->edje_obj, "elm.dragable.hbar", &vx, NULL);
2785 sd->pan_func.max_get(sd->pan_obj, &mx, &my);
2786 sd->pan_func.min_get(sd->pan_obj, &minx, &miny);
2787 x = vx * (double)mx + minx;
2788 y = vy * (double)my + miny;
2789 sd->pan_func.get(sd->pan_obj, &px, &py);
2790 sd->pan_func.set(sd->pan_obj, x, y);
2791 if ((px != x) || (py != y))
2792 edje_object_signal_emit(sd->edje_obj, "elm,action,scroll", "elm");
2793 _elm_direction_arrows_eval(sd);
2794}
2795
2796static void
2797_smart_scrollbar_reset(Smart_Data *sd)
2798{
2799 Evas_Coord px = 0, py = 0, minx = 0, miny = 0;
2800
2801 edje_object_part_drag_value_set(sd->edje_obj, "elm.dragable.vbar", 0.0, 0.0);
2802 edje_object_part_drag_value_set(sd->edje_obj, "elm.dragable.hbar", 0.0, 0.0);
2803 if ((!sd->child_obj) && (!sd->extern_pan))
2804 {
2805 edje_object_part_drag_size_set(sd->edje_obj, "elm.dragable.vbar", 1.0, 1.0);
2806 edje_object_part_drag_size_set(sd->edje_obj, "elm.dragable.hbar", 1.0, 1.0);
2807 }
2808 if (sd->pan_obj)
2809 {
2810 sd->pan_func.min_get(sd->pan_obj, &minx, &miny);
2811 sd->pan_func.get(sd->pan_obj, &px, &py);
2812 sd->pan_func.set(sd->pan_obj, minx, miny);
2813 }
2814 if ((px != minx) || (py != miny))
2815 edje_object_signal_emit(sd->edje_obj, "elm,action,scroll", "elm");
2816 _elm_direction_arrows_eval(sd);
2817}
2818
2819static int
2820_smart_scrollbar_bar_v_visibility_adjust(Smart_Data *sd)
2821{
2822 int scroll_v_vis_change = 0;
2823 Evas_Coord h, vw = 0, vh = 0;
2824
2825 h = sd->child.h;
2826 if (sd->pan_obj)
2827 evas_object_geometry_get(sd->pan_obj, NULL, NULL, &vw, &vh);
2828 if (sd->vbar_visible)
2829 {
2830 if (sd->vbar_flags == ELM_SMART_SCROLLER_POLICY_AUTO)
2831 {
2832 if ((sd->child_obj) || (sd->extern_pan))
2833 {
2834 if (h <= vh)
2835 {
2836 scroll_v_vis_change = 1;
2837 sd->vbar_visible = EINA_FALSE;
2838 }
2839 }
2840 else
2841 {
2842 scroll_v_vis_change = 1;
2843 sd->vbar_visible = EINA_FALSE;
2844 }
2845 }
2846 else if (sd->vbar_flags == ELM_SMART_SCROLLER_POLICY_OFF)
2847 {
2848 scroll_v_vis_change = 1;
2849 sd->vbar_visible = EINA_FALSE;
2850 }
2851 }
2852 else
2853 {
2854 if (sd->vbar_flags == ELM_SMART_SCROLLER_POLICY_AUTO)
2855 {
2856 if ((sd->child_obj) || (sd->extern_pan))
2857 {
2858 if (h > vh)
2859 {
2860 scroll_v_vis_change = 1;
2861 sd->vbar_visible = EINA_TRUE;
2862 }
2863 }
2864 }
2865 else if (sd->vbar_flags == ELM_SMART_SCROLLER_POLICY_ON)
2866 {
2867 scroll_v_vis_change = 1;
2868 sd->vbar_visible = EINA_TRUE;
2869 }
2870 }
2871 if (scroll_v_vis_change)
2872 {
2873 if (sd->vbar_flags != ELM_SMART_SCROLLER_POLICY_OFF)
2874 {
2875 if (sd->vbar_visible)
2876 edje_object_signal_emit(sd->edje_obj, "elm,action,show,vbar", "elm");
2877 else
2878 edje_object_signal_emit(sd->edje_obj, "elm,action,hide,vbar", "elm");
2879 edje_object_message_signal_process(sd->edje_obj);
2880 _smart_scrollbar_size_adjust(sd);
2881 }
2882 else
2883 edje_object_signal_emit(sd->edje_obj, "elm,action,hide,vbar", "elm");
2884 }
2885 _elm_direction_arrows_eval(sd);
2886 return scroll_v_vis_change;
2887}
2888
2889static int
2890_smart_scrollbar_bar_h_visibility_adjust(Smart_Data *sd)
2891{
2892 int scroll_h_vis_change = 0;
2893 Evas_Coord w, vw = 0, vh = 0;
2894
2895 w = sd->child.w;
2896 if (sd->pan_obj)
2897 evas_object_geometry_get(sd->pan_obj, NULL, NULL, &vw, &vh);
2898 if (sd->hbar_visible)
2899 {
2900 if (sd->hbar_flags == ELM_SMART_SCROLLER_POLICY_AUTO)
2901 {
2902 if ((sd->child_obj) || (sd->extern_pan))
2903 {
2904 if (w <= vw)
2905 {
2906 scroll_h_vis_change = 1;
2907 sd->hbar_visible = EINA_FALSE;
2908 }
2909 }
2910 else
2911 {
2912 scroll_h_vis_change = 1;
2913 sd->hbar_visible = EINA_FALSE;
2914 }
2915 }
2916 else if (sd->hbar_flags == ELM_SMART_SCROLLER_POLICY_OFF)
2917 {
2918 scroll_h_vis_change = 1;
2919 sd->hbar_visible = EINA_FALSE;
2920 }
2921 }
2922 else
2923 {
2924 if (sd->hbar_flags == ELM_SMART_SCROLLER_POLICY_AUTO)
2925 {
2926 if ((sd->child_obj) || (sd->extern_pan))
2927 {
2928 if (w > vw)
2929 {
2930 scroll_h_vis_change = 1;
2931 sd->hbar_visible = EINA_TRUE;
2932 }
2933 }
2934 }
2935 else if (sd->hbar_flags == ELM_SMART_SCROLLER_POLICY_ON)
2936 {
2937 scroll_h_vis_change = 1;
2938 sd->hbar_visible = EINA_TRUE;
2939 }
2940 }
2941 if (scroll_h_vis_change)
2942 {
2943 if (sd->hbar_flags != ELM_SMART_SCROLLER_POLICY_OFF)
2944 {
2945 if (sd->hbar_visible)
2946 edje_object_signal_emit(sd->edje_obj, "elm,action,show,hbar", "elm");
2947 else
2948 edje_object_signal_emit(sd->edje_obj, "elm,action,hide,hbar", "elm");
2949 edje_object_message_signal_process(sd->edje_obj);
2950 _smart_scrollbar_size_adjust(sd);
2951 }
2952 else
2953 edje_object_signal_emit(sd->edje_obj, "elm,action,hide,hbar", "elm");
2954 _smart_scrollbar_size_adjust(sd);
2955 }
2956 _elm_direction_arrows_eval(sd);
2957 return scroll_h_vis_change;
2958}
2959
2960static void
2961_smart_scrollbar_bar_visibility_adjust(Smart_Data *sd)
2962{
2963 int changed = 0;
2964
2965 changed |= _smart_scrollbar_bar_h_visibility_adjust(sd);
2966 changed |= _smart_scrollbar_bar_v_visibility_adjust(sd);
2967 if (changed)
2968 {
2969 _smart_scrollbar_bar_h_visibility_adjust(sd);
2970 _smart_scrollbar_bar_v_visibility_adjust(sd);
2971 }
2972}
2973
2974static void
2975_smart_scrollbar_size_adjust(Smart_Data *sd)
2976{
2977 if (!sd->pan_obj) return;
2978 if ((sd->child_obj) || (sd->extern_pan))
2979 {
2980 Evas_Coord x, y, w, h, mx = 0, my = 0, vw = 0, vh = 0, px, py, minx = 0, miny = 0;
2981 double vx, vy, size;
2982
2983 edje_object_part_geometry_get(sd->edje_obj, "elm.swallow.content",
2984 NULL, NULL, &vw, &vh);
2985 w = sd->child.w;
2986 if (w < 1) w = 1;
2987 size = (double)vw / (double)w;
2988 if (size > 1.0)
2989 {
2990 size = 1.0;
2991 edje_object_part_drag_value_set(sd->edje_obj, "elm.dragable.hbar", 0.0, 0.0);
2992 }
2993 edje_object_part_drag_size_set(sd->edje_obj, "elm.dragable.hbar", size, 1.0);
2994
2995 h = sd->child.h;
2996 if (h < 1) h = 1;
2997 size = (double)vh / (double)h;
2998 if (size > 1.0)
2999 {
3000 size = 1.0;
3001 edje_object_part_drag_value_set(sd->edje_obj, "elm.dragable.vbar", 0.0, 0.0);
3002 }
3003 edje_object_part_drag_size_set(sd->edje_obj, "elm.dragable.vbar", 1.0, size);
3004
3005 edje_object_part_drag_value_get(sd->edje_obj, "elm.dragable.hbar", &vx, NULL);
3006 edje_object_part_drag_value_get(sd->edje_obj, "elm.dragable.vbar", NULL, &vy);
3007 sd->pan_func.max_get(sd->pan_obj, &mx, &my);
3008 sd->pan_func.min_get(sd->pan_obj, &minx, &miny);
3009 x = vx * mx + minx;
3010 y = vy * my + miny;
3011
3012 edje_object_part_drag_step_set(sd->edje_obj, "elm.dragable.hbar", (double)sd->step.x / (double)w, 0.0);
3013 edje_object_part_drag_step_set(sd->edje_obj, "elm.dragable.vbar", 0.0, (double)sd->step.y / (double)h);
3014 if (sd->page.x > 0)
3015 edje_object_part_drag_page_set(sd->edje_obj, "elm.dragable.hbar", (double)sd->page.x / (double)w, 0.0);
3016 else
3017 edje_object_part_drag_page_set(sd->edje_obj, "elm.dragable.hbar", -((double)sd->page.x * ((double)vw / (double)w)) / 100.0, 0.0);
3018 if (sd->page.y > 0)
3019 edje_object_part_drag_page_set(sd->edje_obj, "elm.dragable.vbar", 0.0, (double)sd->page.y / (double)h);
3020 else
3021 edje_object_part_drag_page_set(sd->edje_obj, "elm.dragable.vbar", 0.0, -((double)sd->page.y * ((double)vh / (double)h)) / 100.0);
3022
3023 sd->pan_func.get(sd->pan_obj, &px, &py);
3024 if (vx != mx) x = px;
3025 if (vy != my) y = py;
3026 sd->pan_func.set(sd->pan_obj, x, y);
3027 // if ((px != 0) || (py != 0))
3028 // edje_object_signal_emit(sd->edje_obj, "elm,action,scroll", "elm");
3029 }
3030 else
3031 {
3032 Evas_Coord px = 0, py = 0, minx = 0, miny = 0;
3033
3034 edje_object_part_drag_size_set(sd->edje_obj, "elm.dragable.vbar", 1.0, 1.0);
3035 edje_object_part_drag_size_set(sd->edje_obj, "elm.dragable.hbar", 1.0, 1.0);
3036 sd->pan_func.min_get(sd->pan_obj, &minx, &miny);
3037 sd->pan_func.get(sd->pan_obj, &px, &py);
3038 sd->pan_func.set(sd->pan_obj, minx, miny);
3039 if ((px != minx) || (py != miny))
3040 edje_object_signal_emit(sd->edje_obj, "elm,action,scroll", "elm");
3041 }
3042 _smart_scrollbar_bar_visibility_adjust(sd);
3043}
3044
3045static void
3046_smart_reconfigure(Smart_Data *sd)
3047{
3048 evas_object_move(sd->edje_obj, sd->x, sd->y);
3049 evas_object_resize(sd->edje_obj, sd->w, sd->h);
3050 evas_object_move(sd->event_obj, sd->x, sd->y);
3051 evas_object_resize(sd->event_obj, sd->w, sd->h);
3052 _smart_scrollbar_size_adjust(sd);
3053 _smart_page_adjust(sd);
3054}
3055
3056static void
3057_smart_add(Evas_Object *obj)
3058{
3059 Smart_Data *sd;
3060 Evas_Object *o;
3061
3062 sd = calloc(1, sizeof(Smart_Data));
3063 if (!sd) return;
3064 evas_object_smart_data_set(obj, sd);
3065
3066 sd->smart_obj = obj;
3067 sd->x = 0;
3068 sd->y = 0;
3069 sd->w = 0;
3070 sd->h = 0;
3071 sd->step.x = 32;
3072 sd->step.y = 32;
3073 sd->page.x = -50;
3074 sd->page.y = -50;
3075 sd->hbar_flags = ELM_SMART_SCROLLER_POLICY_AUTO;
3076 sd->vbar_flags = ELM_SMART_SCROLLER_POLICY_AUTO;
3077 sd->hbar_visible = EINA_TRUE;
3078 sd->vbar_visible = EINA_TRUE;
3079
3080 sd->bounce_horiz = EINA_TRUE;
3081 sd->bounce_vert = EINA_TRUE;
3082
3083 sd->one_dir_at_a_time = EINA_TRUE;
3084 sd->momentum_animator_disabled = EINA_FALSE;
3085 sd->bounce_animator_disabled = EINA_FALSE;
3086
3087 o = edje_object_add(evas_object_evas_get(obj));
3088 evas_object_propagate_events_set(o, 0);
3089 sd->edje_obj = o;
3090 elm_smart_scroller_object_theme_set(NULL, obj, "scroller", "base", "default");
3091 edje_object_signal_callback_add(o, "drag", "elm.dragable.vbar", _smart_edje_drag_v, sd);
3092 edje_object_signal_callback_add(o, "drag,set", "elm.dragable.vbar", _smart_edje_drag_v, sd);
3093 edje_object_signal_callback_add(o, "drag,start", "elm.dragable.vbar", _smart_edje_drag_v_start, sd);
3094 edje_object_signal_callback_add(o, "drag,stop", "elm.dragable.vbar", _smart_edje_drag_v_stop, sd);
3095 edje_object_signal_callback_add(o, "drag,step", "elm.dragable.vbar", _smart_edje_drag_v, sd);
3096 edje_object_signal_callback_add(o, "drag,page", "elm.dragable.vbar", _smart_edje_drag_v, sd);
3097 edje_object_signal_callback_add(o, "drag", "elm.dragable.hbar", _smart_edje_drag_h, sd);
3098 edje_object_signal_callback_add(o, "drag,set", "elm.dragable.hbar", _smart_edje_drag_h, sd);
3099 edje_object_signal_callback_add(o, "drag,start", "elm.dragable.hbar", _smart_edje_drag_h_start, sd);
3100 edje_object_signal_callback_add(o, "drag,stop", "elm.dragable.hbar", _smart_edje_drag_h_stop, sd);
3101 edje_object_signal_callback_add(o, "drag,step", "elm.dragable.hbar", _smart_edje_drag_h, sd);
3102 edje_object_signal_callback_add(o, "drag,page", "elm.dragable.hbar", _smart_edje_drag_h, sd);
3103 evas_object_smart_member_add(o, obj);
3104
3105 o = evas_object_rectangle_add(evas_object_evas_get(obj));
3106 sd->event_obj = o;
3107 evas_object_color_set(o, 0, 0, 0, 0);
3108 evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_WHEEL, _smart_event_wheel, sd);
3109 evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_DOWN, _smart_event_mouse_down, sd);
3110 evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_UP, _smart_event_mouse_up, sd);
3111 evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_MOVE, _smart_event_mouse_move, sd);
3112 evas_object_smart_member_add(o, obj);
3113 evas_object_repeat_events_set(o, 1);
3114
3115 sd->pan_func.set = _elm_smart_pan_set;
3116 sd->pan_func.get = _elm_smart_pan_get;
3117 sd->pan_func.max_get = _elm_smart_pan_max_get;
3118 sd->pan_func.min_get = _elm_smart_pan_min_get;
3119 sd->pan_func.child_size_get = _elm_smart_pan_child_size_get;
3120 sd->pan_func.gravity_set = _elm_smart_pan_gravity_set;
3121 sd->pan_func.gravity_get = _elm_smart_pan_gravity_get;
3122
3123 _smart_scrollbar_reset(sd);
3124}
3125
3126static void
3127_smart_del(Evas_Object *obj)
3128{
3129 INTERNAL_ENTRY;
3130 elm_smart_scroller_child_set(obj, NULL);
3131 if (!sd->extern_pan) evas_object_del(sd->pan_obj);
3132 evas_object_del(sd->edje_obj);
3133 evas_object_del(sd->event_obj);
3134 if (sd->down.hold_animator) ecore_animator_del(sd->down.hold_animator);
3135 if (sd->down.onhold_animator) ecore_animator_del(sd->down.onhold_animator);
3136 if (sd->down.momentum_animator) ecore_animator_del(sd->down.momentum_animator);
3137 if (sd->down.bounce_x_animator) ecore_animator_del(sd->down.bounce_x_animator);
3138 if (sd->down.bounce_y_animator) ecore_animator_del(sd->down.bounce_y_animator);
3139 if (sd->scrollto.x.animator) ecore_animator_del(sd->scrollto.x.animator);
3140 if (sd->scrollto.y.animator) ecore_animator_del(sd->scrollto.y.animator);
3141 free(sd);
3142 evas_object_smart_data_set(obj, NULL);
3143}
3144
3145static void
3146_smart_move(Evas_Object *obj, Evas_Coord x, Evas_Coord y)
3147{
3148 INTERNAL_ENTRY;
3149 sd->x = x;
3150 sd->y = y;
3151 _smart_reconfigure(sd);
3152}
3153
3154static void
3155_smart_resize(Evas_Object *obj, Evas_Coord w, Evas_Coord h)
3156{
3157 INTERNAL_ENTRY;
3158 sd->w = w;
3159 sd->h = h;
3160 _smart_reconfigure(sd);
3161 _elm_smart_scroller_wanted_region_set(obj);
3162}
3163
3164static void
3165_smart_show(Evas_Object *obj)
3166{
3167 INTERNAL_ENTRY;
3168 evas_object_show(sd->edje_obj);
3169 evas_object_show(sd->event_obj);
3170}
3171
3172static void
3173_smart_hide(Evas_Object *obj)
3174{
3175 INTERNAL_ENTRY;
3176 evas_object_hide(sd->edje_obj);
3177 evas_object_hide(sd->event_obj);
3178}
3179
3180static void
3181_smart_color_set(Evas_Object *obj, int r, int g, int b, int a)
3182{
3183 INTERNAL_ENTRY;
3184 evas_object_color_set(sd->edje_obj, r, g, b, a);
3185}
3186
3187static void
3188_smart_clip_set(Evas_Object *obj, Evas_Object *clip)
3189{
3190 INTERNAL_ENTRY;
3191 evas_object_clip_set(sd->edje_obj, clip);
3192 evas_object_clip_set(sd->event_obj, clip);
3193}
3194
3195static void
3196_smart_clip_unset(Evas_Object *obj)
3197{
3198 INTERNAL_ENTRY;
3199 evas_object_clip_unset(sd->edje_obj);
3200 evas_object_clip_unset(sd->event_obj);
3201}
3202
3203/* never need to touch this */
3204
3205static void
3206_smart_init(void)
3207{
3208 if (_smart) return;
3209 {
3210 static const Evas_Smart_Class sc =
3211 {
3212 SMART_NAME,
3213 EVAS_SMART_CLASS_VERSION,
3214 _smart_add,
3215 _smart_del,
3216 _smart_move,
3217 _smart_resize,
3218 _smart_show,
3219 _smart_hide,
3220 _smart_color_set,
3221 _smart_clip_set,
3222 _smart_clip_unset,
3223 NULL,
3224 NULL,
3225 NULL,
3226 NULL,
3227 NULL,
3228 NULL,
3229 NULL
3230 };
3231 _smart = evas_smart_class_new(&sc);
3232 }
3233}
diff --git a/src/lib/els_scroller.h b/src/lib/els_scroller.h
deleted file mode 100644
index 5566f4e5a..000000000
--- a/src/lib/els_scroller.h
+++ /dev/null
@@ -1,48 +0,0 @@
1typedef enum
2{
3 ELM_SMART_SCROLLER_POLICY_AUTO,
4 ELM_SMART_SCROLLER_POLICY_ON,
5 ELM_SMART_SCROLLER_POLICY_OFF
6}
7Elm_Smart_Scroller_Policy;
8
9Evas_Object *elm_smart_scroller_add(Evas *evas);
10void elm_smart_scroller_child_set(Evas_Object *obj, Evas_Object *child);
11void elm_smart_scroller_extern_pan_set(Evas_Object *obj, Evas_Object *pan, void (*pan_set)(Evas_Object *obj, Evas_Coord x, Evas_Coord y), void (*pan_get)(Evas_Object *obj, Evas_Coord *x, Evas_Coord *y), void (*pan_max_get)(Evas_Object *obj, Evas_Coord *x, Evas_Coord *y), void (*pan_min_get)(Evas_Object *obj, Evas_Coord *x, Evas_Coord *y), void (*pan_child_size_get)(Evas_Object *obj, Evas_Coord *x, Evas_Coord *y));
12void elm_smart_scroller_custom_edje_file_set(Evas_Object *obj, char *file, char *group);
13void elm_smart_scroller_child_pos_set(Evas_Object *obj, Evas_Coord x, Evas_Coord y);
14void elm_smart_scroller_child_pos_get(Evas_Object *obj, Evas_Coord *x, Evas_Coord *y);
15void elm_smart_scroller_child_region_show(Evas_Object *obj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h);
16void elm_smart_scroller_child_region_set(Evas_Object *obj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h);
17void elm_smart_scroller_child_viewport_size_get(Evas_Object *obj, Evas_Coord *w, Evas_Coord *h);
18void elm_smart_scroller_step_size_set(Evas_Object *obj, Evas_Coord x, Evas_Coord y);
19void elm_smart_scroller_step_size_get(Evas_Object *obj, Evas_Coord *x, Evas_Coord *y);
20void elm_smart_scroller_page_size_set(Evas_Object *obj, Evas_Coord x, Evas_Coord y);
21void elm_smart_scroller_page_size_get(Evas_Object *obj, Evas_Coord *x, Evas_Coord *y);
22void elm_smart_scroller_policy_set(Evas_Object *obj, Elm_Smart_Scroller_Policy hbar, Elm_Smart_Scroller_Policy vbar);
23void elm_smart_scroller_policy_get(Evas_Object *obj, Elm_Smart_Scroller_Policy *hbar, Elm_Smart_Scroller_Policy *vbar);
24Evas_Object *elm_smart_scroller_edje_object_get(Evas_Object *obj);
25void elm_smart_scroller_single_dir_set(Evas_Object *obj, Eina_Bool single_dir);
26Eina_Bool elm_smart_scroller_single_dir_get(Evas_Object *obj);
27void elm_smart_scroller_object_theme_set(Evas_Object *parent, Evas_Object *obj, const char *clas, const char *group, const char *style);
28void elm_smart_scroller_mirrored_set(Evas_Object *obj, Eina_Bool mirrored);
29void elm_smart_scroller_hold_set(Evas_Object *obj, Eina_Bool hold);
30void elm_smart_scroller_freeze_set(Evas_Object *obj, Eina_Bool freeze);
31void elm_smart_scroller_bounce_allow_set(Evas_Object *obj, Eina_Bool horiz, Eina_Bool vert);
32void elm_smart_scroller_bounce_allow_get(const Evas_Object *obj, Eina_Bool *horiz, Eina_Bool *vert);
33void elm_smart_scroller_paging_set(Evas_Object *obj, double pagerel_h, double pagerel_v, Evas_Coord pagesize_h, Evas_Coord pagesize_v);
34void elm_smart_scroller_paging_get(Evas_Object *obj, double *pagerel_h, double *pagerel_v, Evas_Coord *pagesize_h, Evas_Coord *pagesize_v);
35void elm_smart_scroller_current_page_get(Evas_Object *obj, int *pagenumber_h, int *pagenumber_v);
36void elm_smart_scroller_last_page_get(Evas_Object *obj, int *pagenumber_h, int *pagenumber_v);
37void elm_smart_scroller_page_show(Evas_Object *obj, int pagenumber_h, int pagenumber_v);
38void elm_smart_scroller_page_bring_in(Evas_Object *obj, int pagenumber_h, int pagenumber_v);
39void elm_smart_scroller_region_bring_in(Evas_Object *obj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h);
40void elm_smart_scroller_widget_set(Evas_Object *obj, Evas_Object *wid);
41void elm_smart_scroller_gravity_set(Evas_Object *obj, double x, double y);
42void elm_smart_scroller_gravity_get(Evas_Object *obj, double *x, double *y);
43Eina_Bool elm_smart_scroller_momentum_animator_disabled_get(Evas_Object *obj);
44void elm_smart_scroller_momentum_animator_disabled_set(Evas_Object *obj, Eina_Bool disabled);
45void elm_smart_scroller_bounce_animator_disabled_set(Evas_Object *obj, Eina_Bool disabled);
46Eina_Bool elm_smart_scroller_bounce_animator_disabled_get(Evas_Object *obj);
47Eina_Bool elm_smart_scroller_wheel_disabled_get(Evas_Object *obj);
48void elm_smart_scroller_wheel_disabled_set(Evas_Object *obj, Eina_Bool disabled);