51120fa8a71bc1fa73015fc68f8642fd98789387
[framework/uifw/elementary.git] / src / lib / elm_scroller.c
1 #include <Elementary.h>
2 #include "elm_priv.h"
3
4 /**
5  * @defgroup Scroller Scroller
6  * @ingroup Elementary
7  *
8  * A scroller holds a single object and "scrolls it around". This means that
9  * it allows the user to use a scrollbar (or a finger) to drag the viewable
10  * region around, allowing to move through a much larger object that is
11  * contained in the scroller. The scroiller will always have a small minimum
12  * size by default as it won't be limited by the contents of the scroller.
13  *
14  * Signals that you can add callbacks for are:
15  *
16  * edge,left - the left edge of the content has been reached
17  *
18  * edge,right - the right edge of the content has been reached
19  *
20  * edge,top - the top edge of the content has been reached
21  *
22  * edge,bottom - the bottom edge of the content has been reached
23  *
24  * scroll - the content has been scrolled (moved)
25  *
26  * scroll,anim,start - scrolling animation has started
27  *
28  * scroll,anim,stop - scrolling animation has stopped
29  *
30  * scroll,drag,start - dragging the contents around has started
31  *
32  * scroll,drag,stop - dragging the contents around has stopped
33  */
34 typedef struct _Widget_Data Widget_Data;
35
36 struct _Widget_Data
37 {
38    Evas_Object *scr;
39    Evas_Object *content;
40    const char *widget_name, *widget_base;
41    Eina_Bool min_w : 1;
42    Eina_Bool min_h : 1;
43    double pagerel_h, pagerel_v;
44    Evas_Coord pagesize_h, pagesize_v;
45 };
46
47 static const char *widtype = NULL;
48 static void _del_hook(Evas_Object *obj);
49 static void _theme_hook(Evas_Object *obj);
50 static void _show_region_hook(void *data, Evas_Object *obj);
51 static void _sizing_eval(Evas_Object *obj);
52 static void _sub_del(void *data, Evas_Object *obj, void *event_info);
53
54 static const char SIG_SCROLL[] = "scroll";
55 static const char SIG_SCROLL_ANIM_START[] = "scroll,anim,start";
56 static const char SIG_SCROLL_ANIM_STOP[] = "scroll,anim,stop";
57 static const char SIG_SCROLL_DRAG_START[] = "scroll,drag,start";
58 static const char SIG_SCROLL_DRAG_STOP[] = "scroll,drag,stop";
59 static const char SIG_EDGE_LEFT[] = "edge,left";
60 static const char SIG_EDGE_RIGHT[] = "edge,right";
61 static const char SIG_EDGE_TOP[] = "edge,top";
62 static const char SIG_EDGE_BOTTOM[] = "edge,bottom";
63 static const Evas_Smart_Cb_Description _signals[] = {
64   {SIG_SCROLL, ""},
65   {SIG_SCROLL_ANIM_START, ""},
66   {SIG_SCROLL_ANIM_STOP, ""},
67   {SIG_SCROLL_DRAG_START, ""},
68   {SIG_SCROLL_DRAG_STOP, ""},
69   {SIG_EDGE_LEFT, ""},
70   {SIG_EDGE_RIGHT, ""},
71   {SIG_EDGE_TOP, ""},
72   {SIG_EDGE_BOTTOM, ""},
73   {NULL, NULL}
74 };
75
76 static void
77 _del_hook(Evas_Object *obj)
78 {
79    Widget_Data *wd = elm_widget_data_get(obj);
80    if (!wd) return;
81    free(wd);
82 }
83
84 static void
85 _theme_hook(Evas_Object *obj)
86 {
87    Widget_Data *wd = elm_widget_data_get(obj);
88    if (!wd) return;
89    if (wd->scr)
90      {
91         elm_smart_scroller_object_theme_set(obj, wd->scr,
92                                             wd->widget_name, wd->widget_base,
93                                             elm_widget_style_get(obj));
94 //        edje_object_scale_set(wd->scr, elm_widget_scale_get(obj) * _elm_config->scale);
95      }
96    _sizing_eval(obj);
97 }
98
99 static void
100 _signal_emit_hook(Evas_Object *obj, const char *emission, const char *source)
101 {
102    Widget_Data *wd = elm_widget_data_get(obj);
103    if (!wd) return;
104    edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr),
105          emission, source);
106 }
107
108 static void
109 _show_region_hook(void *data, Evas_Object *obj)
110 {
111
112    Widget_Data *wd = elm_widget_data_get(data);
113    Evas_Coord x, y, w, h;
114    if (!wd) return;
115    elm_widget_show_region_get(obj, &x, &y, &w, &h);
116    if (wd->scr)
117      elm_smart_scroller_child_region_show(wd->scr, x, y, w, h);
118 }
119
120 static void
121 _sizing_eval(Evas_Object *obj)
122 {
123
124    Widget_Data *wd = elm_widget_data_get(obj);
125    Evas_Coord  vw, vh, minw, minh, maxw, maxh, w, h, vmw, vmh;
126    double xw, yw;
127
128    if (!wd) return;
129    evas_object_size_hint_min_get(wd->content, &minw, &minh);
130    evas_object_size_hint_max_get(wd->content, &maxw, &maxh);
131    evas_object_size_hint_weight_get(wd->content, &xw, &yw);
132    //evas_object_geometry_get(wd->content, NULL, NULL, &w, &h);
133
134    if (wd->scr)
135      {
136         elm_smart_scroller_child_viewport_size_get(wd->scr, &vw, &vh);
137         if (xw > 0.0)
138           {
139 //               if(w > vw) vw = w;
140              if ((minw > 0) && (vw < minw))  vw = minw;
141              else if ((maxw > 0) && (vw > maxw)) vw = maxw;
142           }
143         else if (minw > 0) vw = minw;
144
145         if (yw > 0.0)
146           {
147   //             if(h > vh) vh = h;
148              if ((minh > 0) && (vh < minh))  vh = minh;
149              else if ((maxh > 0) && (vh > maxh)) vh = maxh;
150           }
151         else if (minh > 0) vh = minh;
152
153         evas_object_resize(wd->content, vw, vh);
154         w = -1;
155         h = -1;
156         edje_object_size_min_calc(elm_smart_scroller_edje_object_get(wd->scr), &vmw, &vmh);
157         if (wd->min_w) w = vmw + minw;
158         if (wd->min_h) h = vmh + minh;
159                 
160         evas_object_size_hint_max_get(obj, &maxw, &maxh);
161         if ((maxw > 0) && (w > maxw)) w = maxw;
162         if ((maxh > 0) && (h > maxh)) h = maxh;
163
164         evas_object_size_hint_min_set(obj, w, h);
165      }
166 }
167
168 static void
169 _changed_size_hints(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
170 {
171    _sizing_eval(data);
172 }
173
174 static void
175 _sub_del(void *data __UNUSED__, Evas_Object *obj, void *event_info)
176 {
177
178    Widget_Data *wd = elm_widget_data_get(obj);
179    Evas_Object *sub = event_info;
180
181    if (!wd) return;
182    if (sub == wd->content)
183      {
184         elm_widget_on_show_region_hook_set(wd->content, NULL, NULL);
185         evas_object_event_callback_del_full (sub, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
186            _changed_size_hints, obj);
187         wd->content = NULL;
188         _sizing_eval(obj);
189      }
190    else if (sub == wd->scr)
191      wd->scr = NULL;
192 }
193
194 static void
195 _hold_on(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
196 {
197
198    Widget_Data *wd = elm_widget_data_get(obj);
199
200    if (!wd) return;
201    if (wd->scr)
202      elm_smart_scroller_hold_set(wd->scr, 1);
203 }
204
205 static void
206 _hold_off(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
207 {
208
209    Widget_Data *wd = elm_widget_data_get(obj);
210
211    if (!wd) return;
212    if (wd->scr)
213      elm_smart_scroller_hold_set(wd->scr, 0);
214 }
215
216 static void
217 _freeze_on(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
218 {
219
220    Widget_Data *wd = elm_widget_data_get(obj);
221
222    if (!wd) return;
223    if (wd->scr)
224      elm_smart_scroller_freeze_set(wd->scr, 1);
225 }
226
227 static void
228 _freeze_off(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
229 {
230
231    Widget_Data *wd = elm_widget_data_get(obj);
232
233    if (!wd) return;
234    if (wd->scr)
235      elm_smart_scroller_freeze_set(wd->scr, 0);
236 }
237
238 static void
239 _resize(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
240 {
241    _sizing_eval(data);
242 }
243
244 static void
245 _edge_left(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
246 {
247    evas_object_smart_callback_call(data, SIG_EDGE_LEFT, NULL);
248 }
249
250 static void
251 _edge_right(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
252 {
253    evas_object_smart_callback_call(data, SIG_EDGE_RIGHT, NULL);
254 }
255
256 static void
257 _edge_top(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
258 {
259    evas_object_smart_callback_call(data, SIG_EDGE_TOP, NULL);
260 }
261
262 static void
263 _edge_bottom(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
264 {
265    evas_object_smart_callback_call(data, SIG_EDGE_BOTTOM, NULL);
266 }
267
268 static void
269 _scroll(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
270 {
271    evas_object_smart_callback_call(data, SIG_SCROLL, NULL);
272 }
273
274 static void
275 _scroll_anim_start(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
276 {
277    evas_object_smart_callback_call(data, SIG_SCROLL_ANIM_START, NULL);
278 }
279
280 static void
281 _scroll_anim_stop(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
282 {
283    evas_object_smart_callback_call(data, SIG_SCROLL_ANIM_STOP, NULL);
284 }
285
286 static void
287 _scroll_drag_start(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
288 {
289    evas_object_smart_callback_call(data, SIG_SCROLL_DRAG_START, NULL);
290 }
291
292 static void
293 _scroll_drag_stop(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
294 {
295    evas_object_smart_callback_call(data, SIG_SCROLL_DRAG_STOP, NULL);
296 }
297
298 /**
299  * Add a new scroller to the parent
300  *
301  * @param parent The parent object
302  * @return The new object or NULL if it cannot be created
303  *
304  * @ingroup Scroller
305  */
306 EAPI Evas_Object *
307 elm_scroller_add(Evas_Object *parent)
308 {
309    Evas_Object *obj;
310    Evas *e;
311    Widget_Data *wd;
312    Evas_Coord minw, minh;
313
314    wd = ELM_NEW(Widget_Data);
315    e = evas_object_evas_get(parent);
316    obj = elm_widget_add(e);
317    ELM_SET_WIDTYPE(widtype, "scroller");
318    elm_widget_type_set(obj, "scroller");
319    elm_widget_sub_object_add(parent, obj);
320    elm_widget_data_set(obj, wd);
321    elm_widget_del_hook_set(obj, _del_hook);
322    elm_widget_theme_hook_set(obj, _theme_hook);
323    elm_widget_signal_emit_hook_set(obj, _signal_emit_hook);
324
325    wd->widget_name = eina_stringshare_add("scroller");
326    wd->widget_base = eina_stringshare_add("base");
327
328    wd->scr = elm_smart_scroller_add(e);
329    elm_smart_scroller_widget_set(wd->scr, obj);
330    elm_smart_scroller_object_theme_set(obj, wd->scr,
331                                        wd->widget_name, wd->widget_base,
332                                        elm_widget_style_get(obj));
333    elm_widget_resize_object_set(obj, wd->scr);
334    evas_object_event_callback_add(wd->scr, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
335                                   _changed_size_hints, obj);
336
337    edje_object_size_min_calc(elm_smart_scroller_edje_object_get(wd->scr), &minw, &minh);
338    evas_object_size_hint_min_set(obj, minw, minh);
339    evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE, _resize, obj);
340
341    evas_object_smart_callback_add(obj, "sub-object-del", _sub_del, obj);
342    evas_object_smart_callback_add(obj, "scroll-hold-on", _hold_on, obj);
343    evas_object_smart_callback_add(obj, "scroll-hold-off", _hold_off, obj);
344    evas_object_smart_callback_add(obj, "scroll-freeze-on", _freeze_on, obj);
345    evas_object_smart_callback_add(obj, "scroll-freeze-off", _freeze_off, obj);
346
347    evas_object_smart_callback_add(wd->scr, "edge,left", _edge_left, obj);
348    evas_object_smart_callback_add(wd->scr, "edge,right", _edge_right, obj);
349    evas_object_smart_callback_add(wd->scr, "edge,top", _edge_top, obj);
350    evas_object_smart_callback_add(wd->scr, "edge,bottom", _edge_bottom, obj);
351    evas_object_smart_callback_add(wd->scr, "scroll", _scroll, obj);
352    evas_object_smart_callback_add(wd->scr, "animate,start", _scroll_anim_start, obj);
353    evas_object_smart_callback_add(wd->scr, "animate,stop", _scroll_anim_stop, obj);
354    evas_object_smart_callback_add(wd->scr, "drag,start", _scroll_drag_start, obj);
355    evas_object_smart_callback_add(wd->scr, "drag,stop", _scroll_drag_stop, obj);
356
357    _sizing_eval(obj);
358
359    // TODO: convert Elementary to subclassing of Evas_Smart_Class
360    // TODO: and save some bytes, making descriptions per-class and not instance!
361    evas_object_smart_callbacks_descriptions_set(obj, _signals);
362    return obj;
363 }
364
365
366 /**
367  * Set the content of the scroller widget (the object to be scrolled around).
368  *
369  * Once the content object is set, a previously set one will be deleted.
370  * If you want to keep that old content object, use the
371  * elm_scroller_content_unset() function.
372  *
373  * @param obj The scroller object
374  * @param content The new content object
375  *
376  * @ingroup Scroller
377  */
378 EAPI void
379 elm_scroller_content_set(Evas_Object *obj, Evas_Object *content)
380 {
381    ELM_CHECK_WIDTYPE(obj, widtype);
382    Widget_Data *wd = elm_widget_data_get(obj);
383    if (!wd) return;
384    if (wd->content == content) return;
385    if (wd->content) evas_object_del(wd->content);
386    wd->content = content;
387    if (content)
388      {
389         elm_widget_on_show_region_hook_set(content, _show_region_hook, obj);
390         elm_widget_sub_object_add(obj, content);
391     if (wd->scr)
392         elm_smart_scroller_child_set(wd->scr, content);
393         evas_object_event_callback_add(content, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
394                                        _changed_size_hints, obj);
395      }
396    _sizing_eval(obj);
397 }
398
399 /**
400  * Get the content of the scroller widget
401  *
402  * Return the content object which is set for this widget
403  *
404  * @param obj The slider object
405  * @return The content that is being used
406  *
407  * @ingroup Scroller
408  */
409 EAPI Evas_Object *
410 elm_scroller_content_get(const Evas_Object *obj)
411 {
412    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
413    Widget_Data *wd = elm_widget_data_get(obj);
414    if (!wd) return NULL;
415    return wd->content;
416 }
417
418 /**
419  * Unset the content of the scroller widget
420  *
421  * Unparent and return the content object which was set for this widget
422  *
423  * @param obj The slider objecet
424  * @return The content that was being used
425  *
426  * @ingroup Scroller
427  */
428 EAPI Evas_Object *
429 elm_scroller_content_unset(Evas_Object *obj)
430 {
431    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
432    Widget_Data *wd = elm_widget_data_get(obj);
433    Evas_Object *content;
434    if (!wd) return NULL;
435    if (!wd->content) return NULL;
436    content = wd->content;
437    elm_widget_sub_object_del(obj, wd->content);
438    edje_object_part_unswallow(wd->scr, wd->content);
439    wd->content = NULL;
440    return content;
441 }
442
443 /**
444  * Set custom theme elements for the scroller
445  *
446  * @param obj The scroller object
447  * @param widget The widget name to use (default is "scroller")
448  * @param base The base name to use (default is "base")
449  *
450  * @ingroup Scroller
451  */
452 EAPI void
453 elm_scroller_custom_widget_base_theme_set(Evas_Object *obj, const char *widget, const char *base)
454 {
455    ELM_CHECK_WIDTYPE(obj, widtype);
456    Widget_Data *wd = elm_widget_data_get(obj);
457    if (!wd) return;
458    if ((!widget) || (!base)) return;
459    if (eina_stringshare_replace(&wd->widget_name, widget) |
460        eina_stringshare_replace(&wd->widget_base, base))
461      _theme_hook(obj);
462 }
463
464 /**
465  * Make the scroller minimum size limited to the minimum size of the content
466  *
467  * By default the scroller will be as small as its design allows, irrespective
468  * of its content. This will make the scroller minimum size the right size
469  * horizontally and/or vertically to perfectly fit its content.
470  *
471  * @param obj The scroller object
472  * @param w Enable limiting minimum size horizontally
473  * @param h Enable limiting minimum size vertically
474  *
475  * @ingroup Scroller
476  */
477 EAPI void
478 elm_scroller_content_min_limit(Evas_Object *obj, Eina_Bool w, Eina_Bool h)
479 {
480    ELM_CHECK_WIDTYPE(obj, widtype);
481    Widget_Data *wd = elm_widget_data_get(obj);
482    if (!wd) return;
483    wd->min_w = w;
484    wd->min_h = h;
485    _sizing_eval(obj);
486 }
487
488 /**
489  * Show a specific virtual region within the scroller content object
490  *
491  * This will ensure all (or part if it does not fit) of the designated
492  * region in the virtual content object (0, 0 starting at the top-left of the
493  * virtual content object) is shown within the scroller.
494  *
495  * @param obj The scroller object
496  * @param x X coordinate of the region
497  * @param y Y coordinate of the region
498  * @param w Width of the region
499  * @param h Height of the region
500  *
501  * @ingroup Scroller
502  */
503 EAPI void
504 elm_scroller_region_show(Evas_Object *obj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h)
505 {
506    ELM_CHECK_WIDTYPE(obj, widtype);
507    Widget_Data *wd = elm_widget_data_get(obj);
508    if (!wd) return;
509    if (wd->scr)
510      elm_smart_scroller_child_region_show(wd->scr, x, y, w, h);
511 }
512
513 /**
514  * Set the scroller scrollbar policy
515  *
516  * This sets the scrollbar visibility policy for the given scroller.
517  * ELM_SMART_SCROLLER_POLICY_AUTO means the scrollber is made visible if it
518  * is needed, and otherwise kept hidden. ELM_SMART_SCROLLER_POLICY_ON turns
519  * it on all the time, and ELM_SMART_SCROLLER_POLICY_OFF always keeps it off.
520  * This applies respectively for the horizontal and vertical scrollbars.
521  *
522  * @param obj The scroller object
523  * @param policy_h Horizontal scrollbar policy
524  * @param policy_v Vertical scrollbar policy
525  *
526  * @ingroup Scroller
527  */
528 EAPI void
529 elm_scroller_policy_set(Evas_Object *obj, Elm_Scroller_Policy policy_h, Elm_Scroller_Policy policy_v)
530 {
531    ELM_CHECK_WIDTYPE(obj, widtype);
532    Widget_Data *wd = elm_widget_data_get(obj);
533    const Elm_Scroller_Policy map[3] =
534      {
535         ELM_SMART_SCROLLER_POLICY_AUTO,
536           ELM_SMART_SCROLLER_POLICY_ON,
537           ELM_SMART_SCROLLER_POLICY_OFF
538      };
539    if (!wd) return;
540    if ((policy_h >= 3) || (policy_v >= 3)) return;
541    if (wd->scr)
542      elm_smart_scroller_policy_set(wd->scr, map[policy_h], map[policy_v]);
543 }
544
545 EAPI void
546 elm_scroller_policy_get(const Evas_Object *obj, Elm_Scroller_Policy *policy_h, Elm_Scroller_Policy *policy_v)
547 {
548    ELM_CHECK_WIDTYPE(obj, widtype);
549    Widget_Data *wd = elm_widget_data_get(obj);
550    Elm_Smart_Scroller_Policy s_policy_h, s_policy_v;
551    if (!wd) return;
552    if (wd->scr)
553      elm_smart_scroller_policy_get(wd->scr, &s_policy_h, &s_policy_v);
554    *policy_h = (Elm_Scroller_Policy) s_policy_h;
555    *policy_v = (Elm_Scroller_Policy) s_policy_v;
556 }
557
558 /**
559  * Get the currently visible content region
560  *
561  * This gets the current region in the content object that is visible through
562  * the scroller. Also see elm_scroller_region_show(). The region co-ordinates
563  * are returned in the @p x, @p y, @p w, @p h values pointed to.
564  *
565  * @param obj The scroller object
566  * @param x X coordinate of the region
567  * @param y Y coordinate of the region
568  * @param w Width of the region
569  * @param h Height of the region
570  *
571  * @ingroup Scroller
572  */
573 EAPI void
574 elm_scroller_region_get(const Evas_Object *obj, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h)
575 {
576    ELM_CHECK_WIDTYPE(obj, widtype);
577    Widget_Data *wd = elm_widget_data_get(obj);
578    if (!wd) return;
579    if (wd->scr)
580      {
581         if ((x) && (y)) elm_smart_scroller_child_pos_get(wd->scr, x, y);
582         if ((w) && (h)) elm_smart_scroller_child_viewport_size_get(wd->scr, w, h);
583      }
584 }
585
586 /**
587  * Get the size of the content child object
588  *
589  * This gets the size of the child object of the scroller. Actually the
590  * content of a scroller doesn't specifically need to be an actual object
591  * as it can be virtual and defined purely by callbacks.
592  *
593  * @param obj The scroller object
594  * @param w Width return
595  * @param h Height return
596  *
597  * @ingroup Scroller
598  */
599 EAPI void
600 elm_scroller_child_size_get(const Evas_Object *obj, Evas_Coord *w, Evas_Coord *h)
601 {
602    ELM_CHECK_WIDTYPE(obj, widtype);
603    Widget_Data *wd = elm_widget_data_get(obj);
604    if (!wd) return;
605    evas_object_geometry_get(wd->content, NULL, NULL, w, h);
606 }
607
608 /**
609  * Set bouncing behavior
610  *
611  * When scrolling, the scroller may "bounce" when reaching an edge of the child
612  * object. This is a visual way to indicate the end has been reached. This is
613  * enabled by default for both axes. This will set if it is enabled for that
614  * axis with the boolean parameers for each axis.
615  *
616  * @param obj The scroller object
617  * @param h_bounce Will the scroller bounce horizontally or not
618  * @param v_bounce Will the scroller bounce vertically or not
619  *
620  * @ingroup Scroller
621  */
622 EAPI void
623 elm_scroller_bounce_set(Evas_Object *obj, Eina_Bool h_bounce, Eina_Bool v_bounce)
624 {
625    ELM_CHECK_WIDTYPE(obj, widtype);
626    Widget_Data *wd = elm_widget_data_get(obj);
627    if (!wd) return;
628    if (wd->scr)
629      elm_smart_scroller_bounce_allow_set(wd->scr, h_bounce, v_bounce);
630 }
631
632 /**
633  * Get the bounce mode
634  *
635  * @param obj The Scroller object
636  * @param h_bounce Allow bounce horizontally
637  * @param v_bounce Allow bounce vertically
638  *
639  * @ingroup Scroller
640  */
641 EAPI void
642 elm_scroller_bounce_get(const Evas_Object *obj, Eina_Bool *h_bounce, Eina_Bool *v_bounce)
643 {
644    ELM_CHECK_WIDTYPE(obj, widtype);
645    Widget_Data *wd = elm_widget_data_get(obj);
646    if (!wd) return;
647    elm_smart_scroller_bounce_allow_get(wd->scr, h_bounce, v_bounce);
648 }
649
650 /**
651  * Set scroll page size relative to viewport size
652  *
653  * The scroller is sapale of limiting scrolling by the user to "pages". That
654  * is to jump by and only show a "whole page" at a time as if the continuous
655  * area of the scroller conent is split into page sized pieces. This sets
656  * the size of a page relative to the viewport of the scroller. 1.0 is "1
657  * viewport" is size (horizontally or vertically). 0.0 turns it off in that
658  * axis. This is mutually exclusive with page size
659  * (see elm_scroller_page_size_set()  for more information). likewise 0.5
660  * is "half a viewport". Sane usable valus are normally between 0.0 and 1.0
661  * including 1.0. If you only want 1 axis to be page "limited", use 0.0 for
662  * the other axis.
663  *
664  * @param obj The scroller object
665  * @param h_pagerel The horizontal page relative size
666  * @param v_pagerel The vertical page relative size
667  *
668  * @ingroup Scroller
669  */
670 EAPI void
671 elm_scroller_page_relative_set(Evas_Object *obj, double h_pagerel, double v_pagerel)
672 {
673    ELM_CHECK_WIDTYPE(obj, widtype);
674    Widget_Data *wd = elm_widget_data_get(obj);
675    if (!wd) return;
676    wd->pagerel_h = h_pagerel;
677    wd->pagerel_v = v_pagerel;
678    if (wd->scr)
679      elm_smart_scroller_paging_set(wd->scr, wd->pagerel_h, wd->pagerel_v,
680                                    wd->pagesize_h, wd->pagesize_v);
681 }
682
683 /**
684  * Set scroll page size
685  *
686  * See also elm_scroller_page_relative_set(). This, instead of a page size
687  * being relaive to the viewport, sets it to an absolute fixed value, with
688  * 0 turning it off for that axis.
689  *
690  * @param obj The scroller object
691  * @param h_pagesize The horizontal page size
692  * @param v_pagesize The vertical page size
693  *
694  * @ingroup Scroller
695  */
696 EAPI void
697 elm_scroller_page_size_set(Evas_Object *obj, Evas_Coord h_pagesize, Evas_Coord v_pagesize)
698 {
699    ELM_CHECK_WIDTYPE(obj, widtype);
700    Widget_Data *wd = elm_widget_data_get(obj);
701    if (!wd) return;
702    wd->pagesize_h = h_pagesize;
703    wd->pagesize_v = v_pagesize;
704    if (wd->scr)
705      elm_smart_scroller_paging_set(wd->scr, wd->pagerel_h, wd->pagerel_v,
706                                    wd->pagesize_h, wd->pagesize_v);
707 }
708
709 /**
710  * Show a specific virtual region within the scroller content object
711  *
712  * This will ensure all (or part if it does not fit) of the designated
713  * region in the virtual content object (0, 0 starting at the top-left of the
714  * virtual content object) is shown within the scroller. Unlike
715  * elm_scroller_region_show(), this allow the scroller to "smoothly slide"
716  * to this location (if configuration in general calls for transitions). It
717  * may not jump immediately to the new location and make take a while and
718  * show other content along the way.
719  *
720  * @param obj The scroller object
721  * @param x X coordinate of the region
722  * @param y Y coordinate of the region
723  * @param w Width of the region
724  * @param h Height of the region
725  *
726  * @ingroup Scroller
727  */
728 EAPI void
729 elm_scroller_region_bring_in(Evas_Object *obj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h)
730 {
731    ELM_CHECK_WIDTYPE(obj, widtype);
732    Widget_Data *wd = elm_widget_data_get(obj);
733    if (!wd) return;
734    if (wd->scr)
735      elm_smart_scroller_region_bring_in(wd->scr, x, y, w, h);
736 }
737
738 /**
739  * Set scroll only one page
740  *
741  * @param obj The scroller object
742  * @param set Flag
743  *
744  * @ingroup Scroller
745  */
746 EAPI void
747 elm_scroller_page_move_set(Evas_Object *obj, Eina_Bool set)
748 {
749    Widget_Data *wd = elm_widget_data_get(obj);
750    if (!wd) return;
751
752    elm_smart_scroller_page_move_set(wd->scr, set);
753 }
754
755 /**
756  * Set events propagation
757  *
758  * @param obj The scroller object
759  * @param set Flag
760  *
761  * @ingroup Scroller
762  */
763 EAPI void
764 elm_scroller_propagate_events_set(Evas_Object *obj, Eina_Bool set)
765 {
766    Widget_Data *wd = elm_widget_data_get(obj);
767    if (!wd) return;
768
769    evas_object_propagate_events_set(wd->scr, set);
770 }