[ElmSharp*] Add Scrollable interface 73/157473/8
authorpius.lee <pius.lee@samsung.com>
Tue, 24 Oct 2017 14:22:19 +0000 (23:22 +0900)
committerpius.lee <pius.lee@samsung.com>
Wed, 25 Oct 2017 05:51:02 +0000 (14:51 +0900)
Implement Scroll to Entry, GenGrid, GenList, List, Panel, Toolbar.

Fix NaviItem Style to override.

Change-Id: I2349a272359eba6f00c23cbf470786876e3500f8

src/ElmSharp.Wearable/ElmSharp.Wearable/CircleGenList.cs
src/ElmSharp/ElmSharp/Entry.cs
src/ElmSharp/ElmSharp/GenGrid.cs
src/ElmSharp/ElmSharp/GenList.cs
src/ElmSharp/ElmSharp/IScrollable.cs [new file with mode: 0644]
src/ElmSharp/ElmSharp/List.cs
src/ElmSharp/ElmSharp/Panel.cs
src/ElmSharp/ElmSharp/ScrollableAdapter.cs [new file with mode: 0644]
src/ElmSharp/ElmSharp/Scroller.cs
src/ElmSharp/ElmSharp/Toolbar.cs

index 7dc18e1..f465547 100644 (file)
@@ -189,7 +189,7 @@ namespace ElmSharp.Wearable
         /// ScrollBarVisiblePolicy.Auto means the vertical scrollbar is made visible if it is needed, and otherwise kept hidden.
         /// ScrollBarVisiblePolicy.Visible turns it on all the time, and ScrollBarVisiblePolicy.Invisible always keeps it off.
         /// </remarks>
-        public ScrollBarVisiblePolicy VerticalScrollBarVisiblePolicy
+        public override ScrollBarVisiblePolicy VerticalScrollBarVisiblePolicy
         {
             get
             {
@@ -199,6 +199,7 @@ namespace ElmSharp.Wearable
             }
             set
             {
+                base.VerticalScrollBarVisiblePolicy = value;
                 int h;
                 Interop.Eext.eext_circle_object_genlist_scroller_policy_get(CircleHandle, out h, IntPtr.Zero);
                 Interop.Eext.eext_circle_object_genlist_scroller_policy_set(CircleHandle, (int)h, (int)value);
index 92f57b5..3929a9a 100755 (executable)
@@ -250,8 +250,9 @@ namespace ElmSharp
     /// <summary>
     /// The entry is a convenience widget that shows a box in which the user can enter text.
     /// </summary>
-    public class Entry : Layout
+    public class Entry : Layout, IScrollable
     {
+        ScrollableAdapter _scroller;
         SmartEvent _clicked;
         SmartEvent _changedByUser;
         SmartEvent _cursorChanged;
@@ -277,6 +278,8 @@ namespace ElmSharp
 
             _activated = new SmartEvent(this, this.RealHandle, "activated");
             _activated.On += (s, e) => Activated?.Invoke(this, EventArgs.Empty);
+
+            _scroller = new ScrollableAdapter(this);
         }
 
         /// <summary>
@@ -788,94 +791,6 @@ namespace ElmSharp
         }
 
         /// <summary>
-        /// Sets or gets the value of HorizontalScrollBarVisiblePolicy
-        /// </summary>
-        /// <remarks>
-        /// ScrollBarVisiblePolicy.Auto means the horizontal scrollbar is made visible if it is needed, and otherwise kept hidden.
-        /// ScrollBarVisiblePolicy.Visible turns it on all the time, and ScrollBarVisiblePolicy.Invisible always keeps it off.
-        /// </remarks>
-        public virtual ScrollBarVisiblePolicy HorizontalScrollBarVisiblePolicy
-        {
-            get
-            {
-                int policy;
-                Interop.Elementary.elm_scroller_policy_get(RealHandle, out policy, IntPtr.Zero);
-                return (ScrollBarVisiblePolicy)policy;
-            }
-            set
-            {
-                ScrollBarVisiblePolicy v = VerticalScrollBarVisiblePolicy;
-                Interop.Elementary.elm_scroller_policy_set(RealHandle, (int)value, (int)v);
-            }
-        }
-
-        /// <summary>
-        /// Sets or gets the value of VerticalScrollBarVisiblePolicy
-        /// </summary>
-        /// <remarks>
-        /// ScrollBarVisiblePolicy.Auto means the vertical scrollbar is made visible if it is needed, and otherwise kept hidden.
-        /// ScrollBarVisiblePolicy.Visible turns it on all the time, and ScrollBarVisiblePolicy.Invisible always keeps it off.
-        /// </remarks>
-        public virtual ScrollBarVisiblePolicy VerticalScrollBarVisiblePolicy
-        {
-            get
-            {
-                int policy;
-                Interop.Elementary.elm_scroller_policy_get(RealHandle, IntPtr.Zero, out policy);
-                return (ScrollBarVisiblePolicy)policy;
-            }
-            set
-            {
-                ScrollBarVisiblePolicy h = HorizontalScrollBarVisiblePolicy;
-                Interop.Elementary.elm_scroller_policy_set(RealHandle, (int)h, (int)value);
-            }
-        }
-
-        /// <summary>
-        /// Sets or gets the vertical bounce behaviour.
-        /// When scrolling, the scroller may "bounce" when reaching an edge of the content object.
-        /// This is a visual way to indicate the end has been reached.
-        /// This is enabled by default for both axis.
-        /// This API will set if it is enabled for the given axis with the boolean parameters for each axis.
-        /// </summary>
-        public bool VerticalBounce
-        {
-            get
-            {
-                bool v, h;
-                Interop.Elementary.elm_scroller_bounce_get(RealHandle, out h, out v);
-                return v;
-            }
-            set
-            {
-                bool h = HorizontalBounce;
-                Interop.Elementary.elm_scroller_bounce_set(RealHandle, h, value);
-            }
-        }
-
-        /// <summary>
-        /// Sets or gets the horizontal bounce behaviour.
-        /// When scrolling, the scroller may "bounce" when reaching an edge of the content object.
-        /// This is a visual way to indicate the end has been reached.
-        /// This is enabled by default for both axis.
-        /// This API will set if it is enabled for the given axis with the boolean parameters for each axis.
-        /// </summary>
-        public bool HorizontalBounce
-        {
-            get
-            {
-                bool v, h;
-                Interop.Elementary.elm_scroller_bounce_get(RealHandle, out h, out v);
-                return h;
-            }
-            set
-            {
-                bool v = VerticalBounce;
-                Interop.Elementary.elm_scroller_bounce_set(RealHandle, value, v);
-            }
-        }
-
-        /// <summary>
         /// Inserts the given text into the entry at the current cursor position.
         /// </summary>
         /// <param name="text"></param>
@@ -1114,5 +1029,390 @@ namespace ElmSharp
         {
             return Interop.Elementary.elm_entry_add(parent.Handle);
         }
+
+        #region IScroller Implementation
+
+        /// <summary>
+        /// Scrolled will be triggered when the content has been scrolled.
+        /// </summary>
+        public event EventHandler Scrolled
+        {
+            add => _scroller.Scrolled += value;
+            remove => _scroller.Scrolled -= value;
+        }
+
+        /// <summary>
+        /// DragStart will be triggered when dragging the contents around has started.
+        /// </summary>
+        public event EventHandler DragStart
+        {
+            add => _scroller.DragStart += value;
+            remove => _scroller.DragStart -= value;
+        }
+
+        /// <summary>
+        /// DragStop will be triggered when dragging the contents around has stopped.
+        /// </summary>
+        public event EventHandler DragStop
+        {
+            add => _scroller.DragStop += value;
+            remove => _scroller.DragStop -= value;
+        }
+
+        /// <summary>
+        /// PageScrolled will be triggered when the visible page has changed.
+        /// </summary>
+        public event EventHandler PageScrolled
+        {
+            add => _scroller.PageScrolled += value;
+            remove => _scroller.PageScrolled -= value;
+        }
+
+        /// <summary>
+        /// Gets the current region in the content object that is visible through the Scroller.
+        /// </summary>
+        public Rect CurrentRegion => _scroller.CurrentRegion;
+
+        /// <summary>
+        /// Sets or gets the value of HorizontalScrollBarVisiblePolicy
+        /// </summary>
+        /// <remarks>
+        /// ScrollBarVisiblePolicy.Auto means the horizontal scrollbar is made visible if it is needed, and otherwise kept hidden.
+        /// ScrollBarVisiblePolicy.Visible turns it on all the time, and ScrollBarVisiblePolicy.Invisible always keeps it off.
+        /// </remarks>
+        public virtual ScrollBarVisiblePolicy HorizontalScrollBarVisiblePolicy
+        {
+            get => _scroller.HorizontalScrollBarVisiblePolicy;
+            set => _scroller.HorizontalScrollBarVisiblePolicy = value;
+        }
+
+        /// <summary>
+        /// Sets or gets the value of VerticalScrollBarVisiblePolicy
+        /// </summary>
+        /// <remarks>
+        /// ScrollBarVisiblePolicy.Auto means the vertical scrollbar is made visible if it is needed, and otherwise kept hidden.
+        /// ScrollBarVisiblePolicy.Visible turns it on all the time, and ScrollBarVisiblePolicy.Invisible always keeps it off.
+        /// </remarks>
+        public virtual ScrollBarVisiblePolicy VerticalScrollBarVisiblePolicy
+        {
+            get => _scroller.VerticalScrollBarVisiblePolicy;
+            set => _scroller.VerticalScrollBarVisiblePolicy = value;
+        }
+
+        /// <summary>
+        /// Sets or gets the value of ScrollBlock.
+        /// </summary>
+        /// <remarks>
+        /// This function will block scrolling movement  in a given direction.One can disable movements in the X axis, the Y axis or both.
+        /// The default value is ScrollBlock.None, where movements are allowed in both directions.
+        /// </remarks>
+        public ScrollBlock ScrollBlock
+        {
+            get => _scroller.ScrollBlock;
+            set => _scroller.ScrollBlock = value;
+        }
+
+        /// <summary>
+        /// Sets or gets scroll current page number.
+        /// </summary>
+        /// <remarks>
+        /// Current page means the page which meets the top of the viewport.
+        /// If there are two or more pages in the viewport, it returns the number of the page which meets the top of the viewport.
+        /// The page number starts from 0. 0 is the first page.
+        /// </remarks>
+        public int VerticalPageIndex => _scroller.VerticalPageIndex;
+
+        /// <summary>
+        /// Sets or gets scroll current page number.
+        /// </summary>
+        /// <remarks>
+        /// Current page means the page which meets the left of the viewport.
+        /// If there are two or more pages in the viewport, it returns the number of the page which meets the left of the viewport.
+        /// The page number starts from 0. 0 is the first page.
+        /// </remarks>
+        public int HorizontalPageIndex => _scroller.HorizontalPageIndex;
+
+        /// <summary>
+        /// Sets or gets the maximum limit of the movable page at vertical direction.
+        /// </summary>
+        public int VerticalPageScrollLimit
+        {
+            get => _scroller.VerticalPageScrollLimit;
+            set => _scroller.VerticalPageScrollLimit = value;
+        }
+
+        /// <summary>
+        /// Sets or gets the maximum limit of the movable page at horizontal direction.
+        /// </summary>
+        public int HorizontalPageScrollLimit
+        {
+            get => _scroller.HorizontalPageScrollLimit;
+            set => _scroller.HorizontalPageScrollLimit = value;
+        }
+
+        /// <summary>
+        /// Sets or gets the vertical bounce behaviour.
+        /// When scrolling, the scroller may "bounce" when reaching an edge of the content object.
+        /// This is a visual way to indicate the end has been reached.
+        /// This is enabled by default for both axis.
+        /// This API will set if it is enabled for the given axis with the boolean parameters for each axis.
+        /// </summary>
+        public bool VerticalBounce
+        {
+            get => _scroller.VerticalBounce;
+            set => _scroller.VerticalBounce = value;
+        }
+
+        /// <summary>
+        /// Sets or gets the horizontal bounce behaviour.
+        /// When scrolling, the scroller may "bounce" when reaching an edge of the content object.
+        /// This is a visual way to indicate the end has been reached.
+        /// This is enabled by default for both axis.
+        /// This API will set if it is enabled for the given axis with the boolean parameters for each axis.
+        /// </summary>
+        public bool HorizontalBounce
+        {
+            get => _scroller.HorizontalBounce;
+            set => _scroller.HorizontalBounce = value;
+        }
+
+        /// <summary>
+        /// Gets the width of the content object of the scroller.
+        /// </summary>
+        public int ChildWidth
+        {
+            get => _scroller.ChildWidth;
+        }
+
+        /// <summary>
+        /// Gets the height of the content object of the scroller.
+        /// </summary>
+        public int ChildHeight
+        {
+            get => _scroller.ChildHeight;
+        }
+
+        /// <summary>
+        /// Set scrolling gravity values for a scroller.
+        /// The gravity, defines how the scroller will adjust its view when the size of the scroller contents increase.
+        /// The scroller will adjust the view to glue itself as follows.
+        /// x=0.0, for staying where it is relative to the left edge of the content x=1.0, for staying where it is relative to the rigth edge of the content y=0.0, for staying where it is relative to the top edge of the content y=1.0, for staying where it is relative to the bottom edge of the content
+        /// Default values for x and y are 0.0
+        /// </summary>
+        public double HorizontalGravity
+        {
+            get => _scroller.HorizontalGravity;
+            set => _scroller.HorizontalGravity = value;
+        }
+
+        /// <summary>
+        /// Set scrolling gravity values for a scroller.
+        /// The gravity, defines how the scroller will adjust its view when the size of the scroller contents increase.
+        /// The scroller will adjust the view to glue itself as follows.
+        /// x=0.0, for staying where it is relative to the left edge of the content x=1.0, for staying where it is relative to the rigth edge of the content y=0.0, for staying where it is relative to the top edge of the content y=1.0, for staying where it is relative to the bottom edge of the content
+        /// Default values for x and y are 0.0
+        /// </summary>
+        public double VerticalGravity
+        {
+            get => _scroller.VerticalGravity;
+            set => _scroller.VerticalGravity = value;
+        }
+
+        /// <summary>
+        /// Get scroll last page number.
+        /// The page number starts from 0. 0 is the first page. This returns the last page number among the pages.
+        /// </summary>
+        public int LastVerticalPageNumber => _scroller.LastVerticalPageNumber;
+
+        /// <summary>
+        /// Get scroll last page number.
+        /// The page number starts from 0. 0 is the first page. This returns the last page number among the pages.
+        /// </summary>
+        public int LastHorizontalPageNumber => _scroller.LastHorizontalPageNumber;
+
+        /// <summary>
+        /// Set an infinite loop_ for a scroller.
+        /// This function sets the infinite loop vertically.
+        /// If the content is set, it will be shown repeatedly.
+        /// </summary>
+        public bool VerticalLoop
+        {
+            get => _scroller.VerticalLoop;
+            set => _scroller.VerticalLoop = value;
+        }
+
+        /// <summary>
+        /// Set an infinite loop_ for a scroller.
+        /// This function sets the infinite loop horizontally.
+        /// If the content is set, it will be shown repeatedly.
+        /// </summary>
+        public bool HorizontalLoop
+        {
+            get => _scroller.HorizontalLoop;
+            set => _scroller.HorizontalLoop = value;
+        }
+
+        /// <summary>
+        /// Gets or sets the page size to an absolute fixed value, with 0 turning it off for that axis.
+        /// </summary>
+        public int HorizontalPageSize
+        {
+            get => _scroller.HorizontalPageSize;
+            set => _scroller.HorizontalPageSize = value;
+        }
+
+        /// <summary>
+        /// Gets or sets the page size to an absolute fixed value, with 0 turning it off for that axis.
+        /// </summary>
+        public int VerticalPageSize
+        {
+            get => _scroller.VerticalPageSize;
+            set => _scroller.VerticalPageSize = value;
+        }
+
+        /// <summary>
+        /// Gets or sets a given scroller widget's scrolling page size, relative to its viewport size.
+        /// </summary>
+        public double VerticalRelativePageSize
+        {
+            get => _scroller.VerticalRelativePageSize;
+            set => _scroller.VerticalRelativePageSize = value;
+        }
+
+        /// <summary>
+        /// Gets or sets a given scroller widget's scrolling page size, relative to its viewport size.
+        /// </summary>
+        public double HorizontalRelativePageSize
+        {
+            get => _scroller.HorizontalRelativePageSize;
+            set => _scroller.HorizontalRelativePageSize = value;
+        }
+
+        /// <summary>
+        /// Gets or Sets the page snapping behavior of a scroller.
+        /// </summary>
+        /// <remarks>
+        /// When scrolling, if a scroller is paged (see VerticalRelativePageSize),
+        /// the scroller may snap to pages when being scrolled, i.e., even if it had momentum to scroll further,
+        /// it will stop at the next page boundaries. This is disabled, by default, for both axis.
+        /// This function will set if it that is enabled or not, for each axis.
+        /// </remarks>
+        public bool VerticalSnap
+        {
+            get => _scroller.VerticalSnap;
+            set => _scroller.VerticalSnap = value;
+        }
+
+        /// <summary>
+        /// Gets or Sets the page snapping behavior of a scroller.
+        /// </summary>
+        /// <remarks>
+        /// When scrolling, if a scroller is paged (see HorizontalRelativePageSize),
+        /// the scroller may snap to pages when being scrolled, i.e., even if it had momentum to scroll further,
+        /// it will stop at the next page boundaries. This is disabled, by default, for both axis.
+        /// This function will set if it that is enabled or not, for each axis.
+        /// </remarks>
+        public bool HorizontalSnap
+        {
+            get => _scroller.HorizontalSnap;
+            set => _scroller.HorizontalSnap = value;
+        }
+
+        /// <summary>
+        /// Gets or sets the page size to an absolute fixed value, with 0 turning it off for that axis.
+        /// </summary>
+        public int PageHeight
+        {
+            get => _scroller.PageHeight;
+            set => _scroller.PageHeight = value;
+        }
+
+        /// <summary>
+        /// Gets or sets the page size to an absolute fixed value, with 0 turning it off for that axis.
+        /// </summary>
+        public int PageWidth
+        {
+            get => _scroller.PageWidth;
+            set => _scroller.PageWidth = value;
+        }
+
+        /// <summary>
+        /// Gets or sets the step size to move scroller by key event.
+        /// </summary>
+        public int HorizontalStepSize
+        {
+            get => _scroller.HorizontalStepSize;
+            set => _scroller.HorizontalStepSize = value;
+        }
+
+        /// <summary>
+        /// Gets or sets the step size to move scroller by key event.
+        /// </summary>
+        public int VerticalStepSize
+        {
+            get => _scroller.VerticalStepSize;
+            set => _scroller.VerticalStepSize = value;
+        }
+
+        /// <summary>
+        /// Gets or sets a value whether mouse wheel is enabled or not over the scroller.
+        /// </summary>
+        public bool WheelDisabled
+        {
+            get => _scroller.WheelDisabled;
+            set => _scroller.WheelDisabled = value;
+        }
+
+        /// <summary>
+        /// Gets or sets the type of single direction scroll.
+        /// </summary>
+        public ScrollSingleDirection SingleDirection
+        {
+            get => _scroller.SingleDirection;
+            set => _scroller.SingleDirection = value;
+        }
+
+        /// <summary>
+        /// Sets the scroller minimum size limited to the minimum size of the content.
+        /// By default the scroller will be as small as its design allows, irrespective of its content.
+        /// This will make the scroller minimum size the right size horizontally and/or vertically to perfectly fit its content in that direction.
+        /// </summary>
+        /// <param name="horizontal">Enable limiting minimum size horizontally</param>
+        /// <param name="vertical">Enable limiting minimum size vertically</param>
+        public void MinimumLimit(bool horizontal, bool vertical)
+        {
+            _scroller.MinimumLimit(horizontal, vertical);
+        }
+
+        /// <summary>
+        /// Shows a specific virtual region within the scroller content object by the page number.
+        /// (0, 0) of the indicated page is located at the top-left corner of the viewport.
+        /// </summary>
+        /// <param name="horizontalPageIndex">The horizontal page number.</param>
+        /// <param name="verticalPageIndex">The vertical page number.</param>
+        /// <param name="animated">True means slider with animation.</param>
+        public void ScrollTo(int horizontalPageIndex, int verticalPageIndex, bool animated)
+        {
+            _scroller.ScrollTo(horizontalPageIndex, verticalPageIndex, animated);
+        }
+
+        /// <summary>
+        /// Shows a specific virtual region within the scroller content object.
+        /// </summary>
+        /// <remarks>
+        /// This ensures that all (or part, if it does not fit) of the designated region in the virtual content object ((0, 0)
+        /// starting at the top-left of the virtual content object) is shown within the scroller.
+        /// If set "animated" to true, it will allows the scroller to "smoothly slide" to this location
+        /// (if configuration in general calls for transitions).
+        /// It may not jump immediately to the new location and may take a while and show other content along the way.
+        /// </remarks>
+        /// <param name="region">Rect struct of region.</param>
+        /// <param name="animated">True means allows the scroller to "smoothly slide" to this location.</param>
+        public void ScrollTo(Rect region, bool animated)
+        {
+            _scroller.ScrollTo(region, animated);
+        }
+
+        #endregion
     }
 }
\ No newline at end of file
index 146112b..c27ef52 100755 (executable)
@@ -44,8 +44,9 @@ namespace ElmSharp
     /// It has two direction in which a given GenGrid widget expands while placing its items, horizontal and vertical.
     /// The GenGrid items are represented through <see cref="GenItemClass"/> definition field details.
     /// </summary>
-    public class GenGrid : Layout
+    public class GenGrid : Layout, IScrollable
     {
+        ScrollableAdapter _scroller;
         HashSet<GenGridItem> _children = new HashSet<GenGridItem>();
 
         SmartEvent<GenGridItemEventArgs> _selected;
@@ -66,6 +67,7 @@ namespace ElmSharp
         public GenGrid(EvasObject parent) : base(parent)
         {
             InitializeSmartEvent();
+            _scroller = new ScrollableAdapter(this);
         }
 
         /// <summary>
@@ -291,50 +293,6 @@ namespace ElmSharp
         }
 
         /// <summary>
-        /// Sets or gets the value of HorizontalScrollBarVisiblePolicy
-        /// </summary>
-        /// <remarks>
-        /// ScrollBarVisiblePolicy.Auto means the horizontal scrollbar is made visible if it is needed, and otherwise kept hidden.
-        /// ScrollBarVisiblePolicy.Visible turns it on all the time, and ScrollBarVisiblePolicy.Invisible always keeps it off.
-        /// </remarks>
-        public ScrollBarVisiblePolicy HorizontalScrollBarVisiblePolicy
-        {
-            get
-            {
-                int policy;
-                Interop.Elementary.elm_scroller_policy_get(RealHandle, out policy, IntPtr.Zero);
-                return (ScrollBarVisiblePolicy)policy;
-            }
-            set
-            {
-                ScrollBarVisiblePolicy v = VerticalScrollBarVisiblePolicy;
-                Interop.Elementary.elm_scroller_policy_set(RealHandle, (int)value, (int)v);
-            }
-        }
-
-        /// <summary>
-        /// Sets or gets the value of VerticalScrollBarVisiblePolicy
-        /// </summary>
-        /// <remarks>
-        /// ScrollBarVisiblePolicy.Auto means the vertical scrollbar is made visible if it is needed, and otherwise kept hidden.
-        /// ScrollBarVisiblePolicy.Visible turns it on all the time, and ScrollBarVisiblePolicy.Invisible always keeps it off.
-        /// </remarks>
-        public ScrollBarVisiblePolicy VerticalScrollBarVisiblePolicy
-        {
-            get
-            {
-                int policy;
-                Interop.Elementary.elm_scroller_policy_get(RealHandle, IntPtr.Zero, out policy);
-                return (ScrollBarVisiblePolicy)policy;
-            }
-            set
-            {
-                ScrollBarVisiblePolicy h = HorizontalScrollBarVisiblePolicy;
-                Interop.Elementary.elm_scroller_policy_set(RealHandle, (int)h, (int)value);
-            }
-        }
-
-        /// <summary>
         /// Gets the first item in a given gengrid widget.
         /// </summary>
         public GenGridItem FirstItem
@@ -572,6 +530,391 @@ namespace ElmSharp
             return handle;
         }
 
+        #region IScroller Implementation
+
+        /// <summary>
+        /// Scrolled will be triggered when the content has been scrolled.
+        /// </summary>
+        public event EventHandler Scrolled
+        {
+            add => _scroller.Scrolled += value;
+            remove => _scroller.Scrolled -= value;
+        }
+
+        /// <summary>
+        /// DragStart will be triggered when dragging the contents around has started.
+        /// </summary>
+        public event EventHandler DragStart
+        {
+            add => _scroller.DragStart += value;
+            remove => _scroller.DragStart -= value;
+        }
+
+        /// <summary>
+        /// DragStop will be triggered when dragging the contents around has stopped.
+        /// </summary>
+        public event EventHandler DragStop
+        {
+            add => _scroller.DragStop += value;
+            remove => _scroller.DragStop -= value;
+        }
+
+        /// <summary>
+        /// PageScrolled will be triggered when the visible page has changed.
+        /// </summary>
+        public event EventHandler PageScrolled
+        {
+            add => _scroller.PageScrolled += value;
+            remove => _scroller.PageScrolled -= value;
+        }
+
+        /// <summary>
+        /// Gets the current region in the content object that is visible through the Scroller.
+        /// </summary>
+        public Rect CurrentRegion => _scroller.CurrentRegion;
+
+        /// <summary>
+        /// Sets or gets the value of HorizontalScrollBarVisiblePolicy
+        /// </summary>
+        /// <remarks>
+        /// ScrollBarVisiblePolicy.Auto means the horizontal scrollbar is made visible if it is needed, and otherwise kept hidden.
+        /// ScrollBarVisiblePolicy.Visible turns it on all the time, and ScrollBarVisiblePolicy.Invisible always keeps it off.
+        /// </remarks>
+        public virtual ScrollBarVisiblePolicy HorizontalScrollBarVisiblePolicy
+        {
+            get => _scroller.HorizontalScrollBarVisiblePolicy;
+            set => _scroller.HorizontalScrollBarVisiblePolicy = value;
+        }
+
+        /// <summary>
+        /// Sets or gets the value of VerticalScrollBarVisiblePolicy
+        /// </summary>
+        /// <remarks>
+        /// ScrollBarVisiblePolicy.Auto means the vertical scrollbar is made visible if it is needed, and otherwise kept hidden.
+        /// ScrollBarVisiblePolicy.Visible turns it on all the time, and ScrollBarVisiblePolicy.Invisible always keeps it off.
+        /// </remarks>
+        public virtual ScrollBarVisiblePolicy VerticalScrollBarVisiblePolicy
+        {
+            get => _scroller.VerticalScrollBarVisiblePolicy;
+            set => _scroller.VerticalScrollBarVisiblePolicy = value;
+        }
+
+        /// <summary>
+        /// Sets or gets the value of ScrollBlock.
+        /// </summary>
+        /// <remarks>
+        /// This function will block scrolling movement  in a given direction.One can disable movements in the X axis, the Y axis or both.
+        /// The default value is ScrollBlock.None, where movements are allowed in both directions.
+        /// </remarks>
+        public ScrollBlock ScrollBlock
+        {
+            get => _scroller.ScrollBlock;
+            set => _scroller.ScrollBlock = value;
+        }
+
+        /// <summary>
+        /// Sets or gets scroll current page number.
+        /// </summary>
+        /// <remarks>
+        /// Current page means the page which meets the top of the viewport.
+        /// If there are two or more pages in the viewport, it returns the number of the page which meets the top of the viewport.
+        /// The page number starts from 0. 0 is the first page.
+        /// </remarks>
+        public int VerticalPageIndex => _scroller.VerticalPageIndex;
+
+        /// <summary>
+        /// Sets or gets scroll current page number.
+        /// </summary>
+        /// <remarks>
+        /// Current page means the page which meets the left of the viewport.
+        /// If there are two or more pages in the viewport, it returns the number of the page which meets the left of the viewport.
+        /// The page number starts from 0. 0 is the first page.
+        /// </remarks>
+        public int HorizontalPageIndex => _scroller.HorizontalPageIndex;
+
+        /// <summary>
+        /// Sets or gets the maximum limit of the movable page at vertical direction.
+        /// </summary>
+        public int VerticalPageScrollLimit
+        {
+            get => _scroller.VerticalPageScrollLimit;
+            set => _scroller.VerticalPageScrollLimit = value;
+        }
+
+        /// <summary>
+        /// Sets or gets the maximum limit of the movable page at horizontal direction.
+        /// </summary>
+        public int HorizontalPageScrollLimit
+        {
+            get => _scroller.HorizontalPageScrollLimit;
+            set => _scroller.HorizontalPageScrollLimit = value;
+        }
+
+        /// <summary>
+        /// Sets or gets the vertical bounce behaviour.
+        /// When scrolling, the scroller may "bounce" when reaching an edge of the content object.
+        /// This is a visual way to indicate the end has been reached.
+        /// This is enabled by default for both axis.
+        /// This API will set if it is enabled for the given axis with the boolean parameters for each axis.
+        /// </summary>
+        public bool VerticalBounce
+        {
+            get => _scroller.VerticalBounce;
+            set => _scroller.VerticalBounce = value;
+        }
+
+        /// <summary>
+        /// Sets or gets the horizontal bounce behaviour.
+        /// When scrolling, the scroller may "bounce" when reaching an edge of the content object.
+        /// This is a visual way to indicate the end has been reached.
+        /// This is enabled by default for both axis.
+        /// This API will set if it is enabled for the given axis with the boolean parameters for each axis.
+        /// </summary>
+        public bool HorizontalBounce
+        {
+            get => _scroller.HorizontalBounce;
+            set => _scroller.HorizontalBounce = value;
+        }
+
+        /// <summary>
+        /// Gets the width of the content object of the scroller.
+        /// </summary>
+        public int ChildWidth
+        {
+            get => _scroller.ChildWidth;
+        }
+
+        /// <summary>
+        /// Gets the height of the content object of the scroller.
+        /// </summary>
+        public int ChildHeight
+        {
+            get => _scroller.ChildHeight;
+        }
+
+        /// <summary>
+        /// Set scrolling gravity values for a scroller.
+        /// The gravity, defines how the scroller will adjust its view when the size of the scroller contents increase.
+        /// The scroller will adjust the view to glue itself as follows.
+        /// x=0.0, for staying where it is relative to the left edge of the content x=1.0, for staying where it is relative to the rigth edge of the content y=0.0, for staying where it is relative to the top edge of the content y=1.0, for staying where it is relative to the bottom edge of the content
+        /// Default values for x and y are 0.0
+        /// </summary>
+        public double HorizontalGravity
+        {
+            get => _scroller.HorizontalGravity;
+            set => _scroller.HorizontalGravity = value;
+        }
+
+        /// <summary>
+        /// Set scrolling gravity values for a scroller.
+        /// The gravity, defines how the scroller will adjust its view when the size of the scroller contents increase.
+        /// The scroller will adjust the view to glue itself as follows.
+        /// x=0.0, for staying where it is relative to the left edge of the content x=1.0, for staying where it is relative to the rigth edge of the content y=0.0, for staying where it is relative to the top edge of the content y=1.0, for staying where it is relative to the bottom edge of the content
+        /// Default values for x and y are 0.0
+        /// </summary>
+        public double VerticalGravity
+        {
+            get => _scroller.VerticalGravity;
+            set => _scroller.VerticalGravity = value;
+        }
+
+        /// <summary>
+        /// Get scroll last page number.
+        /// The page number starts from 0. 0 is the first page. This returns the last page number among the pages.
+        /// </summary>
+        public int LastVerticalPageNumber => _scroller.LastVerticalPageNumber;
+
+        /// <summary>
+        /// Get scroll last page number.
+        /// The page number starts from 0. 0 is the first page. This returns the last page number among the pages.
+        /// </summary>
+        public int LastHorizontalPageNumber => _scroller.LastHorizontalPageNumber;
+
+        /// <summary>
+        /// Set an infinite loop_ for a scroller.
+        /// This function sets the infinite loop vertically.
+        /// If the content is set, it will be shown repeatedly.
+        /// </summary>
+        public bool VerticalLoop
+        {
+            get => _scroller.VerticalLoop;
+            set => _scroller.VerticalLoop = value;
+        }
+
+        /// <summary>
+        /// Set an infinite loop_ for a scroller.
+        /// This function sets the infinite loop horizontally.
+        /// If the content is set, it will be shown repeatedly.
+        /// </summary>
+        public bool HorizontalLoop
+        {
+            get => _scroller.HorizontalLoop;
+            set => _scroller.HorizontalLoop = value;
+        }
+
+        /// <summary>
+        /// Gets or sets the page size to an absolute fixed value, with 0 turning it off for that axis.
+        /// </summary>
+        public int HorizontalPageSize
+        {
+            get => _scroller.HorizontalPageSize;
+            set => _scroller.HorizontalPageSize = value;
+        }
+
+        /// <summary>
+        /// Gets or sets the page size to an absolute fixed value, with 0 turning it off for that axis.
+        /// </summary>
+        public int VerticalPageSize
+        {
+            get => _scroller.VerticalPageSize;
+            set => _scroller.VerticalPageSize = value;
+        }
+
+        /// <summary>
+        /// Gets or sets a given scroller widget's scrolling page size, relative to its viewport size.
+        /// </summary>
+        public double VerticalRelativePageSize
+        {
+            get => _scroller.VerticalRelativePageSize;
+            set => _scroller.VerticalRelativePageSize = value;
+        }
+
+        /// <summary>
+        /// Gets or sets a given scroller widget's scrolling page size, relative to its viewport size.
+        /// </summary>
+        public double HorizontalRelativePageSize
+        {
+            get => _scroller.HorizontalRelativePageSize;
+            set => _scroller.HorizontalRelativePageSize = value;
+        }
+
+        /// <summary>
+        /// Gets or Sets the page snapping behavior of a scroller.
+        /// </summary>
+        /// <remarks>
+        /// When scrolling, if a scroller is paged (see VerticalRelativePageSize),
+        /// the scroller may snap to pages when being scrolled, i.e., even if it had momentum to scroll further,
+        /// it will stop at the next page boundaries. This is disabled, by default, for both axis.
+        /// This function will set if it that is enabled or not, for each axis.
+        /// </remarks>
+        public bool VerticalSnap
+        {
+            get => _scroller.VerticalSnap;
+            set => _scroller.VerticalSnap = value;
+        }
+
+        /// <summary>
+        /// Gets or Sets the page snapping behavior of a scroller.
+        /// </summary>
+        /// <remarks>
+        /// When scrolling, if a scroller is paged (see HorizontalRelativePageSize),
+        /// the scroller may snap to pages when being scrolled, i.e., even if it had momentum to scroll further,
+        /// it will stop at the next page boundaries. This is disabled, by default, for both axis.
+        /// This function will set if it that is enabled or not, for each axis.
+        /// </remarks>
+        public bool HorizontalSnap
+        {
+            get => _scroller.HorizontalSnap;
+            set => _scroller.HorizontalSnap = value;
+        }
+
+        /// <summary>
+        /// Gets or sets the page size to an absolute fixed value, with 0 turning it off for that axis.
+        /// </summary>
+        public int PageHeight
+        {
+            get => _scroller.PageHeight;
+            set => _scroller.PageHeight = value;
+        }
+
+        /// <summary>
+        /// Gets or sets the page size to an absolute fixed value, with 0 turning it off for that axis.
+        /// </summary>
+        public int PageWidth
+        {
+            get => _scroller.PageWidth;
+            set => _scroller.PageWidth = value;
+        }
+
+        /// <summary>
+        /// Gets or sets the step size to move scroller by key event.
+        /// </summary>
+        public int HorizontalStepSize
+        {
+            get => _scroller.HorizontalStepSize;
+            set => _scroller.HorizontalStepSize = value;
+        }
+
+        /// <summary>
+        /// Gets or sets the step size to move scroller by key event.
+        /// </summary>
+        public int VerticalStepSize
+        {
+            get => _scroller.VerticalStepSize;
+            set => _scroller.VerticalStepSize = value;
+        }
+
+        /// <summary>
+        /// Gets or sets a value whether mouse wheel is enabled or not over the scroller.
+        /// </summary>
+        public bool WheelDisabled
+        {
+            get => _scroller.WheelDisabled;
+            set => _scroller.WheelDisabled = value;
+        }
+
+        /// <summary>
+        /// Gets or sets the type of single direction scroll.
+        /// </summary>
+        public ScrollSingleDirection SingleDirection
+        {
+            get => _scroller.SingleDirection;
+            set => _scroller.SingleDirection = value;
+        }
+
+        /// <summary>
+        /// Sets the scroller minimum size limited to the minimum size of the content.
+        /// By default the scroller will be as small as its design allows, irrespective of its content.
+        /// This will make the scroller minimum size the right size horizontally and/or vertically to perfectly fit its content in that direction.
+        /// </summary>
+        /// <param name="horizontal">Enable limiting minimum size horizontally</param>
+        /// <param name="vertical">Enable limiting minimum size vertically</param>
+        public void MinimumLimit(bool horizontal, bool vertical)
+        {
+            _scroller.MinimumLimit(horizontal, vertical);
+        }
+
+        /// <summary>
+        /// Shows a specific virtual region within the scroller content object by the page number.
+        /// (0, 0) of the indicated page is located at the top-left corner of the viewport.
+        /// </summary>
+        /// <param name="horizontalPageIndex">The horizontal page number.</param>
+        /// <param name="verticalPageIndex">The vertical page number.</param>
+        /// <param name="animated">True means slider with animation.</param>
+        public void ScrollTo(int horizontalPageIndex, int verticalPageIndex, bool animated)
+        {
+            _scroller.ScrollTo(horizontalPageIndex, verticalPageIndex, animated);
+        }
+
+        /// <summary>
+        /// Shows a specific virtual region within the scroller content object.
+        /// </summary>
+        /// <remarks>
+        /// This ensures that all (or part, if it does not fit) of the designated region in the virtual content object ((0, 0)
+        /// starting at the top-left of the virtual content object) is shown within the scroller.
+        /// If set "animated" to true, it will allows the scroller to "smoothly slide" to this location
+        /// (if configuration in general calls for transitions).
+        /// It may not jump immediately to the new location and may take a while and show other content along the way.
+        /// </remarks>
+        /// <param name="region">Rect struct of region.</param>
+        /// <param name="animated">True means allows the scroller to "smoothly slide" to this location.</param>
+        public void ScrollTo(Rect region, bool animated)
+        {
+            _scroller.ScrollTo(region, animated);
+        }
+
+        #endregion
+
         void InitializeSmartEvent()
         {
             _selected = new SmartEvent<GenGridItemEventArgs>(this, this.RealHandle, "selected", GenGridItemEventArgs.CreateFromSmartEvent);
index 600c57b..c8c2c45 100755 (executable)
@@ -128,8 +128,9 @@ namespace ElmSharp
     /// But the price to pay is more complexity when it comes to usage.
     /// If all you want is a simple list with icons and a single text, use the <see cref="List"/> widget.
     /// </summary>
-    public class GenList : Layout
+    public class GenList : Layout, IScrollable
     {
+        ScrollableAdapter _scroller;
         HashSet<GenListItem> _children = new HashSet<GenListItem>();
 
         SmartEvent<GenListItemEventArgs> _selected;
@@ -750,9 +751,396 @@ namespace ElmSharp
             RealHandle = Interop.Elementary.elm_genlist_add(handle);
             Interop.Elementary.elm_object_part_content_set(handle, "elm.swallow.content", RealHandle);
 
+            _scroller = new ScrollableAdapter(this);
+
             return handle;
         }
 
+        #region IScroller Implementation
+
+        /// <summary>
+        /// Scrolled will be triggered when the content has been scrolled.
+        /// </summary>
+        public event EventHandler Scrolled
+        {
+            add => _scroller.Scrolled += value;
+            remove => _scroller.Scrolled -= value;
+        }
+
+        /// <summary>
+        /// DragStart will be triggered when dragging the contents around has started.
+        /// </summary>
+        public event EventHandler DragStart
+        {
+            add => _scroller.DragStart += value;
+            remove => _scroller.DragStart -= value;
+        }
+
+        /// <summary>
+        /// DragStop will be triggered when dragging the contents around has stopped.
+        /// </summary>
+        public event EventHandler DragStop
+        {
+            add => _scroller.DragStop += value;
+            remove => _scroller.DragStop -= value;
+        }
+
+        /// <summary>
+        /// PageScrolled will be triggered when the visible page has changed.
+        /// </summary>
+        public event EventHandler PageScrolled
+        {
+            add => _scroller.PageScrolled += value;
+            remove => _scroller.PageScrolled -= value;
+        }
+
+        /// <summary>
+        /// Gets the current region in the content object that is visible through the Scroller.
+        /// </summary>
+        public Rect CurrentRegion => _scroller.CurrentRegion;
+
+        /// <summary>
+        /// Sets or gets the value of HorizontalScrollBarVisiblePolicy
+        /// </summary>
+        /// <remarks>
+        /// ScrollBarVisiblePolicy.Auto means the horizontal scrollbar is made visible if it is needed, and otherwise kept hidden.
+        /// ScrollBarVisiblePolicy.Visible turns it on all the time, and ScrollBarVisiblePolicy.Invisible always keeps it off.
+        /// </remarks>
+        public virtual ScrollBarVisiblePolicy HorizontalScrollBarVisiblePolicy
+        {
+            get => _scroller.HorizontalScrollBarVisiblePolicy;
+            set => _scroller.HorizontalScrollBarVisiblePolicy = value;
+        }
+
+        /// <summary>
+        /// Sets or gets the value of VerticalScrollBarVisiblePolicy
+        /// </summary>
+        /// <remarks>
+        /// ScrollBarVisiblePolicy.Auto means the vertical scrollbar is made visible if it is needed, and otherwise kept hidden.
+        /// ScrollBarVisiblePolicy.Visible turns it on all the time, and ScrollBarVisiblePolicy.Invisible always keeps it off.
+        /// </remarks>
+        public virtual ScrollBarVisiblePolicy VerticalScrollBarVisiblePolicy
+        {
+            get => _scroller.VerticalScrollBarVisiblePolicy;
+            set => _scroller.VerticalScrollBarVisiblePolicy = value;
+        }
+
+        /// <summary>
+        /// Sets or gets the value of ScrollBlock.
+        /// </summary>
+        /// <remarks>
+        /// This function will block scrolling movement  in a given direction.One can disable movements in the X axis, the Y axis or both.
+        /// The default value is ScrollBlock.None, where movements are allowed in both directions.
+        /// </remarks>
+        public ScrollBlock ScrollBlock
+        {
+            get => _scroller.ScrollBlock;
+            set => _scroller.ScrollBlock = value;
+        }
+
+        /// <summary>
+        /// Sets or gets scroll current page number.
+        /// </summary>
+        /// <remarks>
+        /// Current page means the page which meets the top of the viewport.
+        /// If there are two or more pages in the viewport, it returns the number of the page which meets the top of the viewport.
+        /// The page number starts from 0. 0 is the first page.
+        /// </remarks>
+        public int VerticalPageIndex => _scroller.VerticalPageIndex;
+
+        /// <summary>
+        /// Sets or gets scroll current page number.
+        /// </summary>
+        /// <remarks>
+        /// Current page means the page which meets the left of the viewport.
+        /// If there are two or more pages in the viewport, it returns the number of the page which meets the left of the viewport.
+        /// The page number starts from 0. 0 is the first page.
+        /// </remarks>
+        public int HorizontalPageIndex => _scroller.HorizontalPageIndex;
+
+        /// <summary>
+        /// Sets or gets the maximum limit of the movable page at vertical direction.
+        /// </summary>
+        public int VerticalPageScrollLimit
+        {
+            get => _scroller.VerticalPageScrollLimit;
+            set => _scroller.VerticalPageScrollLimit = value;
+        }
+
+        /// <summary>
+        /// Sets or gets the maximum limit of the movable page at horizontal direction.
+        /// </summary>
+        public int HorizontalPageScrollLimit
+        {
+            get => _scroller.HorizontalPageScrollLimit;
+            set => _scroller.HorizontalPageScrollLimit = value;
+        }
+
+        /// <summary>
+        /// Sets or gets the vertical bounce behaviour.
+        /// When scrolling, the scroller may "bounce" when reaching an edge of the content object.
+        /// This is a visual way to indicate the end has been reached.
+        /// This is enabled by default for both axis.
+        /// This API will set if it is enabled for the given axis with the boolean parameters for each axis.
+        /// </summary>
+        public bool VerticalBounce
+        {
+            get => _scroller.VerticalBounce;
+            set => _scroller.VerticalBounce = value;
+        }
+
+        /// <summary>
+        /// Sets or gets the horizontal bounce behaviour.
+        /// When scrolling, the scroller may "bounce" when reaching an edge of the content object.
+        /// This is a visual way to indicate the end has been reached.
+        /// This is enabled by default for both axis.
+        /// This API will set if it is enabled for the given axis with the boolean parameters for each axis.
+        /// </summary>
+        public bool HorizontalBounce
+        {
+            get => _scroller.HorizontalBounce;
+            set => _scroller.HorizontalBounce = value;
+        }
+
+        /// <summary>
+        /// Gets the width of the content object of the scroller.
+        /// </summary>
+        public int ChildWidth
+        {
+            get => _scroller.ChildWidth;
+        }
+
+        /// <summary>
+        /// Gets the height of the content object of the scroller.
+        /// </summary>
+        public int ChildHeight
+        {
+            get => _scroller.ChildHeight;
+        }
+
+        /// <summary>
+        /// Set scrolling gravity values for a scroller.
+        /// The gravity, defines how the scroller will adjust its view when the size of the scroller contents increase.
+        /// The scroller will adjust the view to glue itself as follows.
+        /// x=0.0, for staying where it is relative to the left edge of the content x=1.0, for staying where it is relative to the rigth edge of the content y=0.0, for staying where it is relative to the top edge of the content y=1.0, for staying where it is relative to the bottom edge of the content
+        /// Default values for x and y are 0.0
+        /// </summary>
+        public double HorizontalGravity
+        {
+            get => _scroller.HorizontalGravity;
+            set => _scroller.HorizontalGravity = value;
+        }
+
+        /// <summary>
+        /// Set scrolling gravity values for a scroller.
+        /// The gravity, defines how the scroller will adjust its view when the size of the scroller contents increase.
+        /// The scroller will adjust the view to glue itself as follows.
+        /// x=0.0, for staying where it is relative to the left edge of the content x=1.0, for staying where it is relative to the rigth edge of the content y=0.0, for staying where it is relative to the top edge of the content y=1.0, for staying where it is relative to the bottom edge of the content
+        /// Default values for x and y are 0.0
+        /// </summary>
+        public double VerticalGravity
+        {
+            get => _scroller.VerticalGravity;
+            set => _scroller.VerticalGravity = value;
+        }
+
+        /// <summary>
+        /// Get scroll last page number.
+        /// The page number starts from 0. 0 is the first page. This returns the last page number among the pages.
+        /// </summary>
+        public int LastVerticalPageNumber => _scroller.LastVerticalPageNumber;
+
+        /// <summary>
+        /// Get scroll last page number.
+        /// The page number starts from 0. 0 is the first page. This returns the last page number among the pages.
+        /// </summary>
+        public int LastHorizontalPageNumber => _scroller.LastHorizontalPageNumber;
+
+        /// <summary>
+        /// Set an infinite loop_ for a scroller.
+        /// This function sets the infinite loop vertically.
+        /// If the content is set, it will be shown repeatedly.
+        /// </summary>
+        public bool VerticalLoop
+        {
+            get => _scroller.VerticalLoop;
+            set => _scroller.VerticalLoop = value;
+        }
+
+        /// <summary>
+        /// Set an infinite loop_ for a scroller.
+        /// This function sets the infinite loop horizontally.
+        /// If the content is set, it will be shown repeatedly.
+        /// </summary>
+        public bool HorizontalLoop
+        {
+            get => _scroller.HorizontalLoop;
+            set => _scroller.HorizontalLoop = value;
+        }
+
+        /// <summary>
+        /// Gets or sets the page size to an absolute fixed value, with 0 turning it off for that axis.
+        /// </summary>
+        public int HorizontalPageSize
+        {
+            get => _scroller.HorizontalPageSize;
+            set => _scroller.HorizontalPageSize = value;
+        }
+
+        /// <summary>
+        /// Gets or sets the page size to an absolute fixed value, with 0 turning it off for that axis.
+        /// </summary>
+        public int VerticalPageSize
+        {
+            get => _scroller.VerticalPageSize;
+            set => _scroller.VerticalPageSize = value;
+        }
+
+        /// <summary>
+        /// Gets or sets a given scroller widget's scrolling page size, relative to its viewport size.
+        /// </summary>
+        public double VerticalRelativePageSize
+        {
+            get => _scroller.VerticalRelativePageSize;
+            set => _scroller.VerticalRelativePageSize = value;
+        }
+
+        /// <summary>
+        /// Gets or sets a given scroller widget's scrolling page size, relative to its viewport size.
+        /// </summary>
+        public double HorizontalRelativePageSize
+        {
+            get => _scroller.HorizontalRelativePageSize;
+            set => _scroller.HorizontalRelativePageSize = value;
+        }
+
+        /// <summary>
+        /// Gets or Sets the page snapping behavior of a scroller.
+        /// </summary>
+        /// <remarks>
+        /// When scrolling, if a scroller is paged (see VerticalRelativePageSize),
+        /// the scroller may snap to pages when being scrolled, i.e., even if it had momentum to scroll further,
+        /// it will stop at the next page boundaries. This is disabled, by default, for both axis.
+        /// This function will set if it that is enabled or not, for each axis.
+        /// </remarks>
+        public bool VerticalSnap
+        {
+            get => _scroller.VerticalSnap;
+            set => _scroller.VerticalSnap = value;
+        }
+
+        /// <summary>
+        /// Gets or Sets the page snapping behavior of a scroller.
+        /// </summary>
+        /// <remarks>
+        /// When scrolling, if a scroller is paged (see HorizontalRelativePageSize),
+        /// the scroller may snap to pages when being scrolled, i.e., even if it had momentum to scroll further,
+        /// it will stop at the next page boundaries. This is disabled, by default, for both axis.
+        /// This function will set if it that is enabled or not, for each axis.
+        /// </remarks>
+        public bool HorizontalSnap
+        {
+            get => _scroller.HorizontalSnap;
+            set => _scroller.HorizontalSnap = value;
+        }
+
+        /// <summary>
+        /// Gets or sets the page size to an absolute fixed value, with 0 turning it off for that axis.
+        /// </summary>
+        public int PageHeight
+        {
+            get => _scroller.PageHeight;
+            set => _scroller.PageHeight = value;
+        }
+
+        /// <summary>
+        /// Gets or sets the page size to an absolute fixed value, with 0 turning it off for that axis.
+        /// </summary>
+        public int PageWidth
+        {
+            get => _scroller.PageWidth;
+            set => _scroller.PageWidth = value;
+        }
+
+        /// <summary>
+        /// Gets or sets the step size to move scroller by key event.
+        /// </summary>
+        public int HorizontalStepSize
+        {
+            get => _scroller.HorizontalStepSize;
+            set => _scroller.HorizontalStepSize = value;
+        }
+
+        /// <summary>
+        /// Gets or sets the step size to move scroller by key event.
+        /// </summary>
+        public int VerticalStepSize
+        {
+            get => _scroller.VerticalStepSize;
+            set => _scroller.VerticalStepSize = value;
+        }
+
+        /// <summary>
+        /// Gets or sets a value whether mouse wheel is enabled or not over the scroller.
+        /// </summary>
+        public bool WheelDisabled
+        {
+            get => _scroller.WheelDisabled;
+            set => _scroller.WheelDisabled = value;
+        }
+
+        /// <summary>
+        /// Gets or sets the type of single direction scroll.
+        /// </summary>
+        public ScrollSingleDirection SingleDirection
+        {
+            get => _scroller.SingleDirection;
+            set => _scroller.SingleDirection = value;
+        }
+
+        /// <summary>
+        /// Sets the scroller minimum size limited to the minimum size of the content.
+        /// By default the scroller will be as small as its design allows, irrespective of its content.
+        /// This will make the scroller minimum size the right size horizontally and/or vertically to perfectly fit its content in that direction.
+        /// </summary>
+        /// <param name="horizontal">Enable limiting minimum size horizontally</param>
+        /// <param name="vertical">Enable limiting minimum size vertically</param>
+        public void MinimumLimit(bool horizontal, bool vertical)
+        {
+            _scroller.MinimumLimit(horizontal, vertical);
+        }
+
+        /// <summary>
+        /// Shows a specific virtual region within the scroller content object by the page number.
+        /// (0, 0) of the indicated page is located at the top-left corner of the viewport.
+        /// </summary>
+        /// <param name="horizontalPageIndex">The horizontal page number.</param>
+        /// <param name="verticalPageIndex">The vertical page number.</param>
+        /// <param name="animated">True means slider with animation.</param>
+        public void ScrollTo(int horizontalPageIndex, int verticalPageIndex, bool animated)
+        {
+            _scroller.ScrollTo(horizontalPageIndex, verticalPageIndex, animated);
+        }
+
+        /// <summary>
+        /// Shows a specific virtual region within the scroller content object.
+        /// </summary>
+        /// <remarks>
+        /// This ensures that all (or part, if it does not fit) of the designated region in the virtual content object ((0, 0)
+        /// starting at the top-left of the virtual content object) is shown within the scroller.
+        /// If set "animated" to true, it will allows the scroller to "smoothly slide" to this location
+        /// (if configuration in general calls for transitions).
+        /// It may not jump immediately to the new location and may take a while and show other content along the way.
+        /// </remarks>
+        /// <param name="region">Rect struct of region.</param>
+        /// <param name="animated">True means allows the scroller to "smoothly slide" to this location.</param>
+        public void ScrollTo(Rect region, bool animated)
+        {
+            _scroller.ScrollTo(region, animated);
+        }
+
+        #endregion
+
         void InitializeSmartEvent()
         {
             _selected = new SmartEvent<GenListItemEventArgs>(this, this.RealHandle, "selected", GenListItemEventArgs.CreateFromSmartEvent);
diff --git a/src/ElmSharp/ElmSharp/IScrollable.cs b/src/ElmSharp/ElmSharp/IScrollable.cs
new file mode 100644 (file)
index 0000000..d4e9e9f
--- /dev/null
@@ -0,0 +1,334 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace ElmSharp
+{
+    /// <summary>
+    /// Interface for all other scrollable widgets
+    /// </summary>
+    public interface IScrollable
+    {
+
+        /// <summary>
+        /// Scrolled will be triggered when the content has been scrolled.
+        /// </summary>
+        event EventHandler Scrolled;
+
+        /// <summary>
+        /// DragStart will be triggered when dragging the contents around has started.
+        /// </summary>
+        event EventHandler DragStart;
+
+        /// <summary>
+        /// DragStop will be triggered when dragging the contents around has stopped.
+        /// </summary>
+        event EventHandler DragStop;
+
+        /// <summary>
+        /// PageScrolled will be triggered when the visible page has changed.
+        /// </summary>
+        event EventHandler PageScrolled;
+
+        /// <summary>
+        /// Set scrolling gravity values for a scroller.
+        /// The gravity, defines how the scroller will adjust its view when the size of the scroller contents increase.
+        /// The scroller will adjust the view to glue itself as follows.
+        /// x=0.0, for staying where it is relative to the left edge of the content x=1.0, for staying where it is relative to the rigth edge of the content y=0.0, for staying where it is relative to the top edge of the content y=1.0, for staying where it is relative to the bottom edge of the content
+        /// Default values for x and y are 0.0
+        /// </summary>
+        double VerticalGravity { get; set; }
+
+        /// <summary>
+        /// Set scrolling gravity values for a scroller.
+        /// The gravity, defines how the scroller will adjust its view when the size of the scroller contents increase.
+        /// The scroller will adjust the view to glue itself as follows.
+        /// x=0.0, for staying where it is relative to the left edge of the content x=1.0, for staying where it is relative to the rigth edge of the content y=0.0, for staying where it is relative to the top edge of the content y=1.0, for staying where it is relative to the bottom edge of the content
+        /// Default values for x and y are 0.0
+        /// </summary>
+        double HorizontalGravity { get; set; }
+
+        /// <summary>
+        /// Sets or gets the vertical bounce behaviour.
+        /// When scrolling, the scroller may "bounce" when reaching an edge of the content object.
+        /// This is a visual way to indicate the end has been reached.
+        /// This is enabled by default for both axis.
+        /// This API will set if it is enabled for the given axis with the boolean parameters for each axis.
+        /// </summary>
+        bool VerticalBounce { get; set; }
+
+        /// <summary>
+        /// Sets or gets the horizontal bounce behaviour.
+        /// When scrolling, the scroller may "bounce" when reaching an edge of the content object.
+        /// This is a visual way to indicate the end has been reached.
+        /// This is enabled by default for both axis.
+        /// This API will set if it is enabled for the given axis with the boolean parameters for each axis.
+        /// </summary>
+        bool HorizontalBounce { get; set; }
+
+        /// <summary>
+        /// Gets or sets a value whether mouse wheel is enabled or not over the scroller.
+        /// </summary>
+        bool WheelDisabled { get; set; }
+
+        /// <summary>
+        /// Sets or gets the value of ScrollBlock.
+        /// </summary>
+        /// <remarks>
+        /// This function will block scrolling movement  in a given direction.One can disable movements in the X axis, the Y axis or both.
+        /// The default value is ScrollBlock.None, where movements are allowed in both directions.
+        /// </remarks>
+        ScrollBlock ScrollBlock { get; set; }
+
+        /// <summary>
+        /// Sets or gets the value of VerticalScrollBarVisiblePolicy
+        /// </summary>
+        /// <remarks>
+        /// ScrollBarVisiblePolicy.Auto means the vertical scrollbar is made visible if it is needed, and otherwise kept hidden.
+        /// ScrollBarVisiblePolicy.Visible turns it on all the time, and ScrollBarVisiblePolicy.Invisible always keeps it off.
+        /// </remarks>
+        ScrollBarVisiblePolicy VerticalScrollBarVisiblePolicy { get; set; }
+
+        /// <summary>
+        /// Sets or gets the value of HorizontalScrollBarVisiblePolicy
+        /// </summary>
+        /// <remarks>
+        /// ScrollBarVisiblePolicy.Auto means the horizontal scrollbar is made visible if it is needed, and otherwise kept hidden.
+        /// ScrollBarVisiblePolicy.Visible turns it on all the time, and ScrollBarVisiblePolicy.Invisible always keeps it off.
+        /// </remarks>
+        ScrollBarVisiblePolicy HorizontalScrollBarVisiblePolicy { get; set; }
+
+        /// <summary>
+        /// Gets the current region in the content object that is visible through the Scroller.
+        /// </summary>
+        Rect CurrentRegion { get; }
+
+        /// <summary>
+        /// Sets or gets the maximum limit of the movable page at vertical direction.
+        /// </summary>
+        int VerticalPageScrollLimit { get; set; }
+
+        /// <summary>
+        /// Sets or gets the maximum limit of the movable page at horizontal direction.
+        /// </summary>
+        int HorizontalPageScrollLimit { get; set; }
+
+        /// <summary>
+        /// Gets or sets the page size to an absolute fixed value, with 0 turning it off for that axis.
+        /// </summary>
+        int HorizontalPageSize { get; set; }
+
+        /// <summary>
+        /// Gets or sets the page size to an absolute fixed value, with 0 turning it off for that axis.
+        /// </summary>
+        int VerticalPageSize { get; set; }
+
+        /// <summary>
+        /// Gets or Sets the page snapping behavior of a scroller.
+        /// </summary>
+        /// <remarks>
+        /// When scrolling, if a scroller is paged (see VerticalRelativePageSize),
+        /// the scroller may snap to pages when being scrolled, i.e., even if it had momentum to scroll further,
+        /// it will stop at the next page boundaries. This is disabled, by default, for both axis.
+        /// This function will set if it that is enabled or not, for each axis.
+        /// </remarks>
+        bool VerticalSnap { get; set; }
+
+        /// <summary>
+        /// Gets or Sets the page snapping behavior of a scroller.
+        /// </summary>
+        /// <remarks>
+        /// When scrolling, if a scroller is paged (see HorizontalRelativePageSize),
+        /// the scroller may snap to pages when being scrolled, i.e., even if it had momentum to scroll further,
+        /// it will stop at the next page boundaries. This is disabled, by default, for both axis.
+        /// This function will set if it that is enabled or not, for each axis.
+        /// </remarks>
+        bool HorizontalSnap { get; set; }
+
+        /// <summary>
+        /// Gets or sets the page size to an absolute fixed value, with 0 turning it off for that axis.
+        /// </summary>
+        int PageHeight { get; set; }
+
+        /// <summary>
+        /// Gets or sets the page size to an absolute fixed value, with 0 turning it off for that axis.
+        /// </summary>
+        int PageWidth { get; set; }
+
+        /// <summary>
+        /// Gets or sets the type of single direction scroll.
+        /// </summary>
+        ScrollSingleDirection SingleDirection { get; set; }
+
+        /// <summary>
+        /// Gets or sets the step size to move scroller by key event.
+        /// </summary>
+        int HorizontalStepSize { get; set; }
+
+        /// <summary>
+        /// Gets or sets the step size to move scroller by key event.
+        /// </summary>
+        int VerticalStepSize { get; set; }
+
+        /// <summary>
+        /// Set an infinite loop_ for a scroller.
+        /// This function sets the infinite loop vertically.
+        /// If the content is set, it will be shown repeatedly.
+        /// </summary>
+        bool VerticalLoop { get; set; }
+
+        /// <summary>
+        /// Set an infinite loop_ for a scroller.
+        /// This function sets the infinite loop horizontally.
+        /// If the content is set, it will be shown repeatedly.
+        /// </summary>
+        bool HorizontalLoop { get; set; }
+
+        /// <summary>
+        /// Gets or sets a given scroller widget's scrolling page size, relative to its viewport size.
+        /// </summary>
+        double VerticalRelativePageSize { get; set; }
+
+        /// <summary>
+        /// Gets or sets a given scroller widget's scrolling page size, relative to its viewport size.
+        /// </summary>
+        double HorizontalRelativePageSize { get; set; }
+
+        /// <summary>
+        /// Get scroll last page number.
+        /// The page number starts from 0. 0 is the first page. This returns the last page number among the pages.
+        /// </summary>
+        int LastVerticalPageNumber { get; }
+
+        /// <summary>
+        /// Get scroll last page number.
+        /// The page number starts from 0. 0 is the first page. This returns the last page number among the pages.
+        /// </summary>
+        int LastHorizontalPageNumber { get; }
+
+        /// <summary>
+        /// Sets or gets scroll current page number.
+        /// </summary>
+        /// <remarks>
+        /// Current page means the page which meets the top of the viewport.
+        /// If there are two or more pages in the viewport, it returns the number of the page which meets the top of the viewport.
+        /// The page number starts from 0. 0 is the first page.
+        /// </remarks>
+        int VerticalPageIndex { get; }
+
+        /// <summary>
+        /// Sets or gets scroll current page number.
+        /// </summary>
+        /// <remarks>
+        /// Current page means the page which meets the left of the viewport.
+        /// If there are two or more pages in the viewport, it returns the number of the page which meets the left of the viewport.
+        /// The page number starts from 0. 0 is the first page.
+        /// </remarks>
+        int HorizontalPageIndex { get; }
+
+        /// <summary>
+        /// Gets the width of the content object of the scroller.
+        /// </summary>
+        int ChildWidth { get; }
+
+        /// <summary>
+        /// Gets the height of the content object of the scroller.
+        /// </summary>
+        int ChildHeight { get; }
+
+        /// <summary>
+        /// Sets the scroller minimum size limited to the minimum size of the content.
+        /// By default the scroller will be as small as its design allows, irrespective of its content.
+        /// This will make the scroller minimum size the right size horizontally and/or vertically to perfectly fit its content in that direction.
+        /// </summary>
+        /// <param name="horizontal">Enable limiting minimum size horizontally</param>
+        /// <param name="vertical">Enable limiting minimum size vertically</param>
+        void MinimumLimit(bool horizontal, bool vertical);
+
+        /// <summary>
+        /// Shows a specific virtual region within the scroller content object by the page number.
+        /// (0, 0) of the indicated page is located at the top-left corner of the viewport.
+        /// </summary>
+        /// <param name="horizontalPageIndex">The horizontal page number.</param>
+        /// <param name="verticalPageIndex">The vertical page number.</param>
+        /// <param name="animated">True means slider with animation.</param>
+        void ScrollTo(int horizontalPageIndex, int verticalPageIndex, bool animated);
+
+        /// <summary>
+        /// Shows a specific virtual region within the scroller content object.
+        /// </summary>
+        /// <remarks>
+        /// This ensures that all (or part, if it does not fit) of the designated region in the virtual content object ((0, 0)
+        /// starting at the top-left of the virtual content object) is shown within the scroller.
+        /// If set "animated" to true, it will allows the scroller to "smoothly slide" to this location
+        /// (if configuration in general calls for transitions).
+        /// It may not jump immediately to the new location and may take a while and show other content along the way.
+        /// </remarks>
+        /// <param name="region">Rect struct of region.</param>
+        /// <param name="animated">True means allows the scroller to "smoothly slide" to this location.</param>
+        void ScrollTo(Rect region, bool animated);
+    }
+
+    /// <summary>
+    /// Enumeration for visible type of scrollbar.
+    /// </summary>
+    public enum ScrollBarVisiblePolicy
+    {
+        /// <summary>
+        /// Show scrollbars as needed
+        /// </summary>
+        Auto = 0,
+
+        /// <summary>
+        /// Always show scrollbars
+        /// </summary>
+        Visible,
+
+        /// <summary>
+        /// Never show scrollbars
+        /// </summary>
+        Invisible
+    }
+
+    /// <summary>
+    /// Enumeration for visible type of scrollbar.
+    /// </summary>
+    public enum ScrollBlock
+    {
+        /// <summary>
+        /// Scrolling movement is allowed in both direction.(X axis and Y axis)
+        /// </summary>
+        None = 1,
+
+        /// <summary>
+        /// Scrolling movement is not allowed in Y axis direction.
+        /// </summary>
+        Vertical = 2,
+
+        /// <summary>
+        /// Scrolling movement is not allowed in X axis direction.
+        /// </summary>
+        Horizontal = 4
+    }
+
+    /// <summary>
+    /// Type that controls how the content is scrolled.
+    /// </summary>
+    public enum ScrollSingleDirection
+    {
+        /// <summary>
+        /// Scroll every direction.
+        /// </summary>
+        None,
+
+        /// <summary>
+        /// Scroll single direction if the direction is certain.
+        /// </summary>
+        Soft,
+
+        /// <summary>
+        /// Scroll only single direction.
+        /// </summary>
+        Hard,
+    }
+}
index 59eec69..a8f2bc9 100755 (executable)
@@ -73,8 +73,9 @@ namespace ElmSharp
     /// </summary>
     /// <seealso cref="GenList"/>
     /// <seealso cref="GenGrid"/>
-    public class List : Layout
+    public class List : Layout, IScrollable
     {
+        ScrollableAdapter _scroller;
         HashSet<ListItem> _children = new HashSet<ListItem>();
         SmartEvent<ListItemEventArgs> _selected;
         SmartEvent<ListItemEventArgs> _unselected;
@@ -241,9 +242,396 @@ namespace ElmSharp
             RealHandle = Interop.Elementary.elm_list_add(handle);
             Interop.Elementary.elm_object_part_content_set(handle, "elm.swallow.content", RealHandle);
 
+            _scroller = new ScrollableAdapter(this);
+
             return handle;
         }
 
+        #region IScroller Implementation
+
+        /// <summary>
+        /// Scrolled will be triggered when the content has been scrolled.
+        /// </summary>
+        public event EventHandler Scrolled
+        {
+            add => _scroller.Scrolled += value;
+            remove => _scroller.Scrolled -= value;
+        }
+
+        /// <summary>
+        /// DragStart will be triggered when dragging the contents around has started.
+        /// </summary>
+        public event EventHandler DragStart
+        {
+            add => _scroller.DragStart += value;
+            remove => _scroller.DragStart -= value;
+        }
+
+        /// <summary>
+        /// DragStop will be triggered when dragging the contents around has stopped.
+        /// </summary>
+        public event EventHandler DragStop
+        {
+            add => _scroller.DragStop += value;
+            remove => _scroller.DragStop -= value;
+        }
+
+        /// <summary>
+        /// PageScrolled will be triggered when the visible page has changed.
+        /// </summary>
+        public event EventHandler PageScrolled
+        {
+            add => _scroller.PageScrolled += value;
+            remove => _scroller.PageScrolled -= value;
+        }
+
+        /// <summary>
+        /// Gets the current region in the content object that is visible through the Scroller.
+        /// </summary>
+        public Rect CurrentRegion => _scroller.CurrentRegion;
+
+        /// <summary>
+        /// Sets or gets the value of HorizontalScrollBarVisiblePolicy
+        /// </summary>
+        /// <remarks>
+        /// ScrollBarVisiblePolicy.Auto means the horizontal scrollbar is made visible if it is needed, and otherwise kept hidden.
+        /// ScrollBarVisiblePolicy.Visible turns it on all the time, and ScrollBarVisiblePolicy.Invisible always keeps it off.
+        /// </remarks>
+        public virtual ScrollBarVisiblePolicy HorizontalScrollBarVisiblePolicy
+        {
+            get => _scroller.HorizontalScrollBarVisiblePolicy;
+            set => _scroller.HorizontalScrollBarVisiblePolicy = value;
+        }
+
+        /// <summary>
+        /// Sets or gets the value of VerticalScrollBarVisiblePolicy
+        /// </summary>
+        /// <remarks>
+        /// ScrollBarVisiblePolicy.Auto means the vertical scrollbar is made visible if it is needed, and otherwise kept hidden.
+        /// ScrollBarVisiblePolicy.Visible turns it on all the time, and ScrollBarVisiblePolicy.Invisible always keeps it off.
+        /// </remarks>
+        public virtual ScrollBarVisiblePolicy VerticalScrollBarVisiblePolicy
+        {
+            get => _scroller.VerticalScrollBarVisiblePolicy;
+            set => _scroller.VerticalScrollBarVisiblePolicy = value;
+        }
+
+        /// <summary>
+        /// Sets or gets the value of ScrollBlock.
+        /// </summary>
+        /// <remarks>
+        /// This function will block scrolling movement  in a given direction.One can disable movements in the X axis, the Y axis or both.
+        /// The default value is ScrollBlock.None, where movements are allowed in both directions.
+        /// </remarks>
+        public ScrollBlock ScrollBlock
+        {
+            get => _scroller.ScrollBlock;
+            set => _scroller.ScrollBlock = value;
+        }
+
+        /// <summary>
+        /// Sets or gets scroll current page number.
+        /// </summary>
+        /// <remarks>
+        /// Current page means the page which meets the top of the viewport.
+        /// If there are two or more pages in the viewport, it returns the number of the page which meets the top of the viewport.
+        /// The page number starts from 0. 0 is the first page.
+        /// </remarks>
+        public int VerticalPageIndex => _scroller.VerticalPageIndex;
+
+        /// <summary>
+        /// Sets or gets scroll current page number.
+        /// </summary>
+        /// <remarks>
+        /// Current page means the page which meets the left of the viewport.
+        /// If there are two or more pages in the viewport, it returns the number of the page which meets the left of the viewport.
+        /// The page number starts from 0. 0 is the first page.
+        /// </remarks>
+        public int HorizontalPageIndex => _scroller.HorizontalPageIndex;
+
+        /// <summary>
+        /// Sets or gets the maximum limit of the movable page at vertical direction.
+        /// </summary>
+        public int VerticalPageScrollLimit
+        {
+            get => _scroller.VerticalPageScrollLimit;
+            set => _scroller.VerticalPageScrollLimit = value;
+        }
+
+        /// <summary>
+        /// Sets or gets the maximum limit of the movable page at horizontal direction.
+        /// </summary>
+        public int HorizontalPageScrollLimit
+        {
+            get => _scroller.HorizontalPageScrollLimit;
+            set => _scroller.HorizontalPageScrollLimit = value;
+        }
+
+        /// <summary>
+        /// Sets or gets the vertical bounce behaviour.
+        /// When scrolling, the scroller may "bounce" when reaching an edge of the content object.
+        /// This is a visual way to indicate the end has been reached.
+        /// This is enabled by default for both axis.
+        /// This API will set if it is enabled for the given axis with the boolean parameters for each axis.
+        /// </summary>
+        public bool VerticalBounce
+        {
+            get => _scroller.VerticalBounce;
+            set => _scroller.VerticalBounce = value;
+        }
+
+        /// <summary>
+        /// Sets or gets the horizontal bounce behaviour.
+        /// When scrolling, the scroller may "bounce" when reaching an edge of the content object.
+        /// This is a visual way to indicate the end has been reached.
+        /// This is enabled by default for both axis.
+        /// This API will set if it is enabled for the given axis with the boolean parameters for each axis.
+        /// </summary>
+        public bool HorizontalBounce
+        {
+            get => _scroller.HorizontalBounce;
+            set => _scroller.HorizontalBounce = value;
+        }
+
+        /// <summary>
+        /// Gets the width of the content object of the scroller.
+        /// </summary>
+        public int ChildWidth
+        {
+            get => _scroller.ChildWidth;
+        }
+
+        /// <summary>
+        /// Gets the height of the content object of the scroller.
+        /// </summary>
+        public int ChildHeight
+        {
+            get => _scroller.ChildHeight;
+        }
+
+        /// <summary>
+        /// Set scrolling gravity values for a scroller.
+        /// The gravity, defines how the scroller will adjust its view when the size of the scroller contents increase.
+        /// The scroller will adjust the view to glue itself as follows.
+        /// x=0.0, for staying where it is relative to the left edge of the content x=1.0, for staying where it is relative to the rigth edge of the content y=0.0, for staying where it is relative to the top edge of the content y=1.0, for staying where it is relative to the bottom edge of the content
+        /// Default values for x and y are 0.0
+        /// </summary>
+        public double HorizontalGravity
+        {
+            get => _scroller.HorizontalGravity;
+            set => _scroller.HorizontalGravity = value;
+        }
+
+        /// <summary>
+        /// Set scrolling gravity values for a scroller.
+        /// The gravity, defines how the scroller will adjust its view when the size of the scroller contents increase.
+        /// The scroller will adjust the view to glue itself as follows.
+        /// x=0.0, for staying where it is relative to the left edge of the content x=1.0, for staying where it is relative to the rigth edge of the content y=0.0, for staying where it is relative to the top edge of the content y=1.0, for staying where it is relative to the bottom edge of the content
+        /// Default values for x and y are 0.0
+        /// </summary>
+        public double VerticalGravity
+        {
+            get => _scroller.VerticalGravity;
+            set => _scroller.VerticalGravity = value;
+        }
+
+        /// <summary>
+        /// Get scroll last page number.
+        /// The page number starts from 0. 0 is the first page. This returns the last page number among the pages.
+        /// </summary>
+        public int LastVerticalPageNumber => _scroller.LastVerticalPageNumber;
+
+        /// <summary>
+        /// Get scroll last page number.
+        /// The page number starts from 0. 0 is the first page. This returns the last page number among the pages.
+        /// </summary>
+        public int LastHorizontalPageNumber => _scroller.LastHorizontalPageNumber;
+
+        /// <summary>
+        /// Set an infinite loop_ for a scroller.
+        /// This function sets the infinite loop vertically.
+        /// If the content is set, it will be shown repeatedly.
+        /// </summary>
+        public bool VerticalLoop
+        {
+            get => _scroller.VerticalLoop;
+            set => _scroller.VerticalLoop = value;
+        }
+
+        /// <summary>
+        /// Set an infinite loop_ for a scroller.
+        /// This function sets the infinite loop horizontally.
+        /// If the content is set, it will be shown repeatedly.
+        /// </summary>
+        public bool HorizontalLoop
+        {
+            get => _scroller.HorizontalLoop;
+            set => _scroller.HorizontalLoop = value;
+        }
+
+        /// <summary>
+        /// Gets or sets the page size to an absolute fixed value, with 0 turning it off for that axis.
+        /// </summary>
+        public int HorizontalPageSize
+        {
+            get => _scroller.HorizontalPageSize;
+            set => _scroller.HorizontalPageSize = value;
+        }
+
+        /// <summary>
+        /// Gets or sets the page size to an absolute fixed value, with 0 turning it off for that axis.
+        /// </summary>
+        public int VerticalPageSize
+        {
+            get => _scroller.VerticalPageSize;
+            set => _scroller.VerticalPageSize = value;
+        }
+
+        /// <summary>
+        /// Gets or sets a given scroller widget's scrolling page size, relative to its viewport size.
+        /// </summary>
+        public double VerticalRelativePageSize
+        {
+            get => _scroller.VerticalRelativePageSize;
+            set => _scroller.VerticalRelativePageSize = value;
+        }
+
+        /// <summary>
+        /// Gets or sets a given scroller widget's scrolling page size, relative to its viewport size.
+        /// </summary>
+        public double HorizontalRelativePageSize
+        {
+            get => _scroller.HorizontalRelativePageSize;
+            set => _scroller.HorizontalRelativePageSize = value;
+        }
+
+        /// <summary>
+        /// Gets or Sets the page snapping behavior of a scroller.
+        /// </summary>
+        /// <remarks>
+        /// When scrolling, if a scroller is paged (see VerticalRelativePageSize),
+        /// the scroller may snap to pages when being scrolled, i.e., even if it had momentum to scroll further,
+        /// it will stop at the next page boundaries. This is disabled, by default, for both axis.
+        /// This function will set if it that is enabled or not, for each axis.
+        /// </remarks>
+        public bool VerticalSnap
+        {
+            get => _scroller.VerticalSnap;
+            set => _scroller.VerticalSnap = value;
+        }
+
+        /// <summary>
+        /// Gets or Sets the page snapping behavior of a scroller.
+        /// </summary>
+        /// <remarks>
+        /// When scrolling, if a scroller is paged (see HorizontalRelativePageSize),
+        /// the scroller may snap to pages when being scrolled, i.e., even if it had momentum to scroll further,
+        /// it will stop at the next page boundaries. This is disabled, by default, for both axis.
+        /// This function will set if it that is enabled or not, for each axis.
+        /// </remarks>
+        public bool HorizontalSnap
+        {
+            get => _scroller.HorizontalSnap;
+            set => _scroller.HorizontalSnap = value;
+        }
+
+        /// <summary>
+        /// Gets or sets the page size to an absolute fixed value, with 0 turning it off for that axis.
+        /// </summary>
+        public int PageHeight
+        {
+            get => _scroller.PageHeight;
+            set => _scroller.PageHeight = value;
+        }
+
+        /// <summary>
+        /// Gets or sets the page size to an absolute fixed value, with 0 turning it off for that axis.
+        /// </summary>
+        public int PageWidth
+        {
+            get => _scroller.PageWidth;
+            set => _scroller.PageWidth = value;
+        }
+
+        /// <summary>
+        /// Gets or sets the step size to move scroller by key event.
+        /// </summary>
+        public int HorizontalStepSize
+        {
+            get => _scroller.HorizontalStepSize;
+            set => _scroller.HorizontalStepSize = value;
+        }
+
+        /// <summary>
+        /// Gets or sets the step size to move scroller by key event.
+        /// </summary>
+        public int VerticalStepSize
+        {
+            get => _scroller.VerticalStepSize;
+            set => _scroller.VerticalStepSize = value;
+        }
+
+        /// <summary>
+        /// Gets or sets a value whether mouse wheel is enabled or not over the scroller.
+        /// </summary>
+        public bool WheelDisabled
+        {
+            get => _scroller.WheelDisabled;
+            set => _scroller.WheelDisabled = value;
+        }
+
+        /// <summary>
+        /// Gets or sets the type of single direction scroll.
+        /// </summary>
+        public ScrollSingleDirection SingleDirection
+        {
+            get => _scroller.SingleDirection;
+            set => _scroller.SingleDirection = value;
+        }
+
+        /// <summary>
+        /// Sets the scroller minimum size limited to the minimum size of the content.
+        /// By default the scroller will be as small as its design allows, irrespective of its content.
+        /// This will make the scroller minimum size the right size horizontally and/or vertically to perfectly fit its content in that direction.
+        /// </summary>
+        /// <param name="horizontal">Enable limiting minimum size horizontally</param>
+        /// <param name="vertical">Enable limiting minimum size vertically</param>
+        public void MinimumLimit(bool horizontal, bool vertical)
+        {
+            _scroller.MinimumLimit(horizontal, vertical);
+        }
+
+        /// <summary>
+        /// Shows a specific virtual region within the scroller content object by the page number.
+        /// (0, 0) of the indicated page is located at the top-left corner of the viewport.
+        /// </summary>
+        /// <param name="horizontalPageIndex">The horizontal page number.</param>
+        /// <param name="verticalPageIndex">The vertical page number.</param>
+        /// <param name="animated">True means slider with animation.</param>
+        public void ScrollTo(int horizontalPageIndex, int verticalPageIndex, bool animated)
+        {
+            _scroller.ScrollTo(horizontalPageIndex, verticalPageIndex, animated);
+        }
+
+        /// <summary>
+        /// Shows a specific virtual region within the scroller content object.
+        /// </summary>
+        /// <remarks>
+        /// This ensures that all (or part, if it does not fit) of the designated region in the virtual content object ((0, 0)
+        /// starting at the top-left of the virtual content object) is shown within the scroller.
+        /// If set "animated" to true, it will allows the scroller to "smoothly slide" to this location
+        /// (if configuration in general calls for transitions).
+        /// It may not jump immediately to the new location and may take a while and show other content along the way.
+        /// </remarks>
+        /// <param name="region">Rect struct of region.</param>
+        /// <param name="animated">True means allows the scroller to "smoothly slide" to this location.</param>
+        public void ScrollTo(Rect region, bool animated)
+        {
+            _scroller.ScrollTo(region, animated);
+        }
+
+        #endregion
+
         void AddInternal(ListItem item)
         {
             _children.Add(item);
index f34cde3..b2270d8 100755 (executable)
@@ -44,8 +44,9 @@ namespace ElmSharp
     /// <summary>
     /// The Panel is a container that can contain subobjects.
     /// </summary>
-    public class Panel : Layout
+    public class Panel : Layout, IScrollable
     {
+        ScrollableAdapter _scroller;
         SmartEvent _toggled;
 
         /// <summary>
@@ -56,6 +57,7 @@ namespace ElmSharp
         {
             _toggled = new SmartEvent(this, this.RealHandle, "toggled");
             _toggled.On += (s, e) => Toggled?.Invoke(this, EventArgs.Empty);
+            _scroller = new ScrollableAdapter(this);
         }
 
         /// <summary>
@@ -138,5 +140,390 @@ namespace ElmSharp
 
             return handle;
         }
+
+        #region IScroller Implementation
+
+        /// <summary>
+        /// Scrolled will be triggered when the content has been scrolled.
+        /// </summary>
+        public event EventHandler Scrolled
+        {
+            add => _scroller.Scrolled += value;
+            remove => _scroller.Scrolled -= value;
+        }
+
+        /// <summary>
+        /// DragStart will be triggered when dragging the contents around has started.
+        /// </summary>
+        public event EventHandler DragStart
+        {
+            add => _scroller.DragStart += value;
+            remove => _scroller.DragStart -= value;
+        }
+
+        /// <summary>
+        /// DragStop will be triggered when dragging the contents around has stopped.
+        /// </summary>
+        public event EventHandler DragStop
+        {
+            add => _scroller.DragStop += value;
+            remove => _scroller.DragStop -= value;
+        }
+
+        /// <summary>
+        /// PageScrolled will be triggered when the visible page has changed.
+        /// </summary>
+        public event EventHandler PageScrolled
+        {
+            add => _scroller.PageScrolled += value;
+            remove => _scroller.PageScrolled -= value;
+        }
+
+        /// <summary>
+        /// Gets the current region in the content object that is visible through the Scroller.
+        /// </summary>
+        public Rect CurrentRegion => _scroller.CurrentRegion;
+
+        /// <summary>
+        /// Sets or gets the value of HorizontalScrollBarVisiblePolicy
+        /// </summary>
+        /// <remarks>
+        /// ScrollBarVisiblePolicy.Auto means the horizontal scrollbar is made visible if it is needed, and otherwise kept hidden.
+        /// ScrollBarVisiblePolicy.Visible turns it on all the time, and ScrollBarVisiblePolicy.Invisible always keeps it off.
+        /// </remarks>
+        public virtual ScrollBarVisiblePolicy HorizontalScrollBarVisiblePolicy
+        {
+            get => _scroller.HorizontalScrollBarVisiblePolicy;
+            set => _scroller.HorizontalScrollBarVisiblePolicy = value;
+        }
+
+        /// <summary>
+        /// Sets or gets the value of VerticalScrollBarVisiblePolicy
+        /// </summary>
+        /// <remarks>
+        /// ScrollBarVisiblePolicy.Auto means the vertical scrollbar is made visible if it is needed, and otherwise kept hidden.
+        /// ScrollBarVisiblePolicy.Visible turns it on all the time, and ScrollBarVisiblePolicy.Invisible always keeps it off.
+        /// </remarks>
+        public virtual ScrollBarVisiblePolicy VerticalScrollBarVisiblePolicy
+        {
+            get => _scroller.VerticalScrollBarVisiblePolicy;
+            set => _scroller.VerticalScrollBarVisiblePolicy = value;
+        }
+
+        /// <summary>
+        /// Sets or gets the value of ScrollBlock.
+        /// </summary>
+        /// <remarks>
+        /// This function will block scrolling movement  in a given direction.One can disable movements in the X axis, the Y axis or both.
+        /// The default value is ScrollBlock.None, where movements are allowed in both directions.
+        /// </remarks>
+        public ScrollBlock ScrollBlock
+        {
+            get => _scroller.ScrollBlock;
+            set => _scroller.ScrollBlock = value;
+        }
+
+        /// <summary>
+        /// Sets or gets scroll current page number.
+        /// </summary>
+        /// <remarks>
+        /// Current page means the page which meets the top of the viewport.
+        /// If there are two or more pages in the viewport, it returns the number of the page which meets the top of the viewport.
+        /// The page number starts from 0. 0 is the first page.
+        /// </remarks>
+        public int VerticalPageIndex => _scroller.VerticalPageIndex;
+
+        /// <summary>
+        /// Sets or gets scroll current page number.
+        /// </summary>
+        /// <remarks>
+        /// Current page means the page which meets the left of the viewport.
+        /// If there are two or more pages in the viewport, it returns the number of the page which meets the left of the viewport.
+        /// The page number starts from 0. 0 is the first page.
+        /// </remarks>
+        public int HorizontalPageIndex => _scroller.HorizontalPageIndex;
+
+        /// <summary>
+        /// Sets or gets the maximum limit of the movable page at vertical direction.
+        /// </summary>
+        public int VerticalPageScrollLimit
+        {
+            get => _scroller.VerticalPageScrollLimit;
+            set => _scroller.VerticalPageScrollLimit = value;
+        }
+
+        /// <summary>
+        /// Sets or gets the maximum limit of the movable page at horizontal direction.
+        /// </summary>
+        public int HorizontalPageScrollLimit
+        {
+            get => _scroller.HorizontalPageScrollLimit;
+            set => _scroller.HorizontalPageScrollLimit = value;
+        }
+
+        /// <summary>
+        /// Sets or gets the vertical bounce behaviour.
+        /// When scrolling, the scroller may "bounce" when reaching an edge of the content object.
+        /// This is a visual way to indicate the end has been reached.
+        /// This is enabled by default for both axis.
+        /// This API will set if it is enabled for the given axis with the boolean parameters for each axis.
+        /// </summary>
+        public bool VerticalBounce
+        {
+            get => _scroller.VerticalBounce;
+            set => _scroller.VerticalBounce = value;
+        }
+
+        /// <summary>
+        /// Sets or gets the horizontal bounce behaviour.
+        /// When scrolling, the scroller may "bounce" when reaching an edge of the content object.
+        /// This is a visual way to indicate the end has been reached.
+        /// This is enabled by default for both axis.
+        /// This API will set if it is enabled for the given axis with the boolean parameters for each axis.
+        /// </summary>
+        public bool HorizontalBounce
+        {
+            get => _scroller.HorizontalBounce;
+            set => _scroller.HorizontalBounce = value;
+        }
+
+        /// <summary>
+        /// Gets the width of the content object of the scroller.
+        /// </summary>
+        public int ChildWidth
+        {
+            get => _scroller.ChildWidth;
+        }
+
+        /// <summary>
+        /// Gets the height of the content object of the scroller.
+        /// </summary>
+        public int ChildHeight
+        {
+            get => _scroller.ChildHeight;
+        }
+
+        /// <summary>
+        /// Set scrolling gravity values for a scroller.
+        /// The gravity, defines how the scroller will adjust its view when the size of the scroller contents increase.
+        /// The scroller will adjust the view to glue itself as follows.
+        /// x=0.0, for staying where it is relative to the left edge of the content x=1.0, for staying where it is relative to the rigth edge of the content y=0.0, for staying where it is relative to the top edge of the content y=1.0, for staying where it is relative to the bottom edge of the content
+        /// Default values for x and y are 0.0
+        /// </summary>
+        public double HorizontalGravity
+        {
+            get => _scroller.HorizontalGravity;
+            set => _scroller.HorizontalGravity = value;
+        }
+
+        /// <summary>
+        /// Set scrolling gravity values for a scroller.
+        /// The gravity, defines how the scroller will adjust its view when the size of the scroller contents increase.
+        /// The scroller will adjust the view to glue itself as follows.
+        /// x=0.0, for staying where it is relative to the left edge of the content x=1.0, for staying where it is relative to the rigth edge of the content y=0.0, for staying where it is relative to the top edge of the content y=1.0, for staying where it is relative to the bottom edge of the content
+        /// Default values for x and y are 0.0
+        /// </summary>
+        public double VerticalGravity
+        {
+            get => _scroller.VerticalGravity;
+            set => _scroller.VerticalGravity = value;
+        }
+
+        /// <summary>
+        /// Get scroll last page number.
+        /// The page number starts from 0. 0 is the first page. This returns the last page number among the pages.
+        /// </summary>
+        public int LastVerticalPageNumber => _scroller.LastVerticalPageNumber;
+
+        /// <summary>
+        /// Get scroll last page number.
+        /// The page number starts from 0. 0 is the first page. This returns the last page number among the pages.
+        /// </summary>
+        public int LastHorizontalPageNumber => _scroller.LastHorizontalPageNumber;
+
+        /// <summary>
+        /// Set an infinite loop_ for a scroller.
+        /// This function sets the infinite loop vertically.
+        /// If the content is set, it will be shown repeatedly.
+        /// </summary>
+        public bool VerticalLoop
+        {
+            get => _scroller.VerticalLoop;
+            set => _scroller.VerticalLoop = value;
+        }
+
+        /// <summary>
+        /// Set an infinite loop_ for a scroller.
+        /// This function sets the infinite loop horizontally.
+        /// If the content is set, it will be shown repeatedly.
+        /// </summary>
+        public bool HorizontalLoop
+        {
+            get => _scroller.HorizontalLoop;
+            set => _scroller.HorizontalLoop = value;
+        }
+
+        /// <summary>
+        /// Gets or sets the page size to an absolute fixed value, with 0 turning it off for that axis.
+        /// </summary>
+        public int HorizontalPageSize
+        {
+            get => _scroller.HorizontalPageSize;
+            set => _scroller.HorizontalPageSize = value;
+        }
+
+        /// <summary>
+        /// Gets or sets the page size to an absolute fixed value, with 0 turning it off for that axis.
+        /// </summary>
+        public int VerticalPageSize
+        {
+            get => _scroller.VerticalPageSize;
+            set => _scroller.VerticalPageSize = value;
+        }
+
+        /// <summary>
+        /// Gets or sets a given scroller widget's scrolling page size, relative to its viewport size.
+        /// </summary>
+        public double VerticalRelativePageSize
+        {
+            get => _scroller.VerticalRelativePageSize;
+            set => _scroller.VerticalRelativePageSize = value;
+        }
+
+        /// <summary>
+        /// Gets or sets a given scroller widget's scrolling page size, relative to its viewport size.
+        /// </summary>
+        public double HorizontalRelativePageSize
+        {
+            get => _scroller.HorizontalRelativePageSize;
+            set => _scroller.HorizontalRelativePageSize = value;
+        }
+
+        /// <summary>
+        /// Gets or Sets the page snapping behavior of a scroller.
+        /// </summary>
+        /// <remarks>
+        /// When scrolling, if a scroller is paged (see VerticalRelativePageSize),
+        /// the scroller may snap to pages when being scrolled, i.e., even if it had momentum to scroll further,
+        /// it will stop at the next page boundaries. This is disabled, by default, for both axis.
+        /// This function will set if it that is enabled or not, for each axis.
+        /// </remarks>
+        public bool VerticalSnap
+        {
+            get => _scroller.VerticalSnap;
+            set => _scroller.VerticalSnap = value;
+        }
+
+        /// <summary>
+        /// Gets or Sets the page snapping behavior of a scroller.
+        /// </summary>
+        /// <remarks>
+        /// When scrolling, if a scroller is paged (see HorizontalRelativePageSize),
+        /// the scroller may snap to pages when being scrolled, i.e., even if it had momentum to scroll further,
+        /// it will stop at the next page boundaries. This is disabled, by default, for both axis.
+        /// This function will set if it that is enabled or not, for each axis.
+        /// </remarks>
+        public bool HorizontalSnap
+        {
+            get => _scroller.HorizontalSnap;
+            set => _scroller.HorizontalSnap = value;
+        }
+
+        /// <summary>
+        /// Gets or sets the page size to an absolute fixed value, with 0 turning it off for that axis.
+        /// </summary>
+        public int PageHeight
+        {
+            get => _scroller.PageHeight;
+            set => _scroller.PageHeight = value;
+        }
+
+        /// <summary>
+        /// Gets or sets the page size to an absolute fixed value, with 0 turning it off for that axis.
+        /// </summary>
+        public int PageWidth
+        {
+            get => _scroller.PageWidth;
+            set => _scroller.PageWidth = value;
+        }
+
+        /// <summary>
+        /// Gets or sets the step size to move scroller by key event.
+        /// </summary>
+        public int HorizontalStepSize
+        {
+            get => _scroller.HorizontalStepSize;
+            set => _scroller.HorizontalStepSize = value;
+        }
+
+        /// <summary>
+        /// Gets or sets the step size to move scroller by key event.
+        /// </summary>
+        public int VerticalStepSize
+        {
+            get => _scroller.VerticalStepSize;
+            set => _scroller.VerticalStepSize = value;
+        }
+
+        /// <summary>
+        /// Gets or sets a value whether mouse wheel is enabled or not over the scroller.
+        /// </summary>
+        public bool WheelDisabled
+        {
+            get => _scroller.WheelDisabled;
+            set => _scroller.WheelDisabled = value;
+        }
+
+        /// <summary>
+        /// Gets or sets the type of single direction scroll.
+        /// </summary>
+        public ScrollSingleDirection SingleDirection
+        {
+            get => _scroller.SingleDirection;
+            set => _scroller.SingleDirection = value;
+        }
+
+        /// <summary>
+        /// Sets the scroller minimum size limited to the minimum size of the content.
+        /// By default the scroller will be as small as its design allows, irrespective of its content.
+        /// This will make the scroller minimum size the right size horizontally and/or vertically to perfectly fit its content in that direction.
+        /// </summary>
+        /// <param name="horizontal">Enable limiting minimum size horizontally</param>
+        /// <param name="vertical">Enable limiting minimum size vertically</param>
+        public void MinimumLimit(bool horizontal, bool vertical)
+        {
+            _scroller.MinimumLimit(horizontal, vertical);
+        }
+
+        /// <summary>
+        /// Shows a specific virtual region within the scroller content object by the page number.
+        /// (0, 0) of the indicated page is located at the top-left corner of the viewport.
+        /// </summary>
+        /// <param name="horizontalPageIndex">The horizontal page number.</param>
+        /// <param name="verticalPageIndex">The vertical page number.</param>
+        /// <param name="animated">True means slider with animation.</param>
+        public void ScrollTo(int horizontalPageIndex, int verticalPageIndex, bool animated)
+        {
+            _scroller.ScrollTo(horizontalPageIndex, verticalPageIndex, animated);
+        }
+
+        /// <summary>
+        /// Shows a specific virtual region within the scroller content object.
+        /// </summary>
+        /// <remarks>
+        /// This ensures that all (or part, if it does not fit) of the designated region in the virtual content object ((0, 0)
+        /// starting at the top-left of the virtual content object) is shown within the scroller.
+        /// If set "animated" to true, it will allows the scroller to "smoothly slide" to this location
+        /// (if configuration in general calls for transitions).
+        /// It may not jump immediately to the new location and may take a while and show other content along the way.
+        /// </remarks>
+        /// <param name="region">Rect struct of region.</param>
+        /// <param name="animated">True means allows the scroller to "smoothly slide" to this location.</param>
+        public void ScrollTo(Rect region, bool animated)
+        {
+            _scroller.ScrollTo(region, animated);
+        }
+
+        #endregion
     }
 }
diff --git a/src/ElmSharp/ElmSharp/ScrollableAdapter.cs b/src/ElmSharp/ElmSharp/ScrollableAdapter.cs
new file mode 100644 (file)
index 0000000..4f85d2a
--- /dev/null
@@ -0,0 +1,270 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+using static Interop.Elementary;
+
+namespace ElmSharp
+{
+    class ScrollableAdapter : IScrollable
+    {
+        EvasObject obj;
+        SmartEvent _scroll;
+        SmartEvent _dragStart;
+        SmartEvent _dragStop;
+        SmartEvent _scrollPage;
+
+        public ScrollableAdapter(List list) : this(list as EvasObject)
+        {
+        }
+
+        public ScrollableAdapter(Entry entry) : this(entry as EvasObject)
+        {
+        }
+
+        public ScrollableAdapter(Panel panel) : this(panel as EvasObject)
+        {
+        }
+
+        public ScrollableAdapter(GenGrid gengrid) : this(gengrid as EvasObject)
+        {
+        }
+
+        public ScrollableAdapter(Scroller scroller) : this(scroller as EvasObject)
+        {
+        }
+
+        public ScrollableAdapter(GenList genlist) : this(genlist as EvasObject)
+        {
+        }
+
+        public ScrollableAdapter(Toolbar toolbar) : this(toolbar as EvasObject)
+        {
+        }
+
+        ScrollableAdapter(EvasObject scrollable)
+        {
+            obj = scrollable;
+            _scroll = new SmartEvent(obj, obj.RealHandle, "scroll");
+            _dragStart = new SmartEvent(obj, obj.RealHandle, "scroll,drag,start");
+            _dragStop = new SmartEvent(obj, obj.RealHandle, "scroll,drag,stop");
+            _scrollPage = new SmartEvent(obj, obj.RealHandle, "scroll,page,changed");
+        }
+
+        public event EventHandler Scrolled
+        {
+            add => _scroll.On += value;
+            remove => _scroll.On -= value;
+        }
+        public event EventHandler DragStart
+        {
+            add => _dragStart.On += value;
+            remove => _dragStart.On -= value;
+        }
+        public event EventHandler DragStop
+        {
+            add => _dragStop.On += value;
+            remove => _dragStop.On -= value;
+        }
+        public event EventHandler PageScrolled
+        {
+            add => _scrollPage.On += value;
+            remove => _scrollPage.On -= value;
+        }
+
+        public double VerticalGravity
+        {
+            get => Get2<double>(elm_scroller_gravity_get);
+            set => Set(elm_scroller_gravity_set, HorizontalGravity, value);
+        }
+        public double HorizontalGravity
+        {
+            get => Get1<double>(elm_scroller_gravity_get);
+            set => Set(elm_scroller_gravity_set, value, VerticalGravity);
+        }
+        public bool VerticalBounce
+        {
+            get => Get2<bool>(elm_scroller_bounce_get);
+            set => Set(elm_scroller_bounce_set, HorizontalBounce, value);
+        }
+        public bool HorizontalBounce
+        {
+            get => Get1<bool>(elm_scroller_bounce_get);
+            set => Set(elm_scroller_bounce_set, value, VerticalBounce);
+        }
+        public bool WheelDisabled
+        {
+            get => Get(elm_scroller_wheel_disabled_get);
+            set => Set(elm_scroller_wheel_disabled_set, value);
+        }
+        public ScrollBlock ScrollBlock
+        {
+            get => (ScrollBlock)Get(elm_scroller_movement_block_get);
+            set => Set(elm_scroller_movement_block_set, (int)value);
+        }
+        public ScrollBarVisiblePolicy VerticalScrollBarVisiblePolicy
+        {
+            get => (ScrollBarVisiblePolicy)Get2<int>(elm_scroller_policy_get);
+            set => Set(elm_scroller_policy_set, (int)HorizontalScrollBarVisiblePolicy, (int)value);
+        }
+        public ScrollBarVisiblePolicy HorizontalScrollBarVisiblePolicy
+        {
+            get => (ScrollBarVisiblePolicy)Get1<int>(elm_scroller_policy_get);
+            set => Set(elm_scroller_policy_set, (int)value, (int)VerticalScrollBarVisiblePolicy);
+        }
+
+        public Rect CurrentRegion
+        {
+            get
+            {
+                int x, y, w, h;
+                elm_scroller_region_get(obj.RealHandle, out x, out y, out w, out h);
+                return new Rect(x, y, w, h);
+            }
+        }
+
+        public int VerticalPageScrollLimit
+        {
+            get => Get2<int>(elm_scroller_page_scroll_limit_get);
+            set => Set(elm_scroller_page_scroll_limit_set, HorizontalPageScrollLimit, value);
+        }
+        public int HorizontalPageScrollLimit
+        {
+            get => Get1<int>(elm_scroller_page_scroll_limit_get);
+            set => Set(elm_scroller_page_scroll_limit_set, value, VerticalPageScrollLimit);
+        }
+
+        public int HorizontalPageSize
+        {
+            get => Get1<int>(elm_scroller_page_size_get);
+            set => Set(elm_scroller_page_size_set, value, VerticalPageSize);
+        }
+
+        public int VerticalPageSize
+        {
+            get => Get2<int>(elm_scroller_page_size_get);
+            set => Set(elm_scroller_page_size_set, HorizontalPageSize, value);
+        }
+
+        public bool VerticalSnap
+        {
+            get => Get2<bool>(elm_scroller_page_snap_get);
+            set => Set(elm_scroller_page_snap_set, HorizontalSnap, value);
+        }
+        public bool HorizontalSnap
+        {
+            get => Get1<bool>(elm_scroller_page_snap_get);
+            set => Set(elm_scroller_page_snap_set, value, VerticalSnap);
+        }
+        public int PageHeight
+        {
+            get => Get2<int>(elm_scroller_page_size_get);
+            set => Set(elm_scroller_page_size_set, PageWidth, value);
+        }
+        public int PageWidth
+        {
+            get => Get1<int>(elm_scroller_page_size_get);
+            set => Set(elm_scroller_page_size_set, value, PageHeight);
+        }
+        public ScrollSingleDirection SingleDirection
+        {
+            get => (ScrollSingleDirection)elm_scroller_single_direction_get(obj.RealHandle);
+            set => Set(elm_scroller_single_direction_set, (int)value);
+        }
+        public int HorizontalStepSize
+        {
+            get => Get1<int>(elm_scroller_step_size_get);
+            set => Set(elm_scroller_step_size_set, value, VerticalStepSize);
+        }
+        public int VerticalStepSize
+        {
+            get => Get2<int>(elm_scroller_step_size_get);
+            set => Set(elm_scroller_step_size_set, HorizontalStepSize, value);
+        }
+        public bool VerticalLoop
+        {
+            get => Get2<bool>(elm_scroller_loop_get);
+            set => Set(elm_scroller_loop_set, HorizontalLoop, value);
+        }
+        public bool HorizontalLoop
+        {
+            get => Get1<bool>(elm_scroller_loop_get);
+            set => Set(elm_scroller_loop_set, value, VerticalLoop);
+        }
+        public double VerticalRelativePageSize
+        {
+            get => Get2<double>(elm_scroller_page_relative_get);
+            set => Set(elm_scroller_page_relative_set, HorizontalRelativePageSize, value);
+        }
+        public double HorizontalRelativePageSize
+        {
+            get => Get1<double>(elm_scroller_page_relative_get);
+            set => Set(elm_scroller_page_relative_set, value, VerticalRelativePageSize);
+        }
+
+        public int LastVerticalPageNumber => Get2<int>(elm_scroller_last_page_get);
+
+        public int LastHorizontalPageNumber => Get1<int>(elm_scroller_last_page_get);
+
+        public int VerticalPageIndex => Get2<int>(elm_scroller_current_page_get);
+
+        public int HorizontalPageIndex => Get1<int>(elm_scroller_current_page_get);
+
+        public int ChildWidth => Get1<int>(elm_scroller_child_size_get);
+
+        public int ChildHeight => Get2<int>(elm_scroller_child_size_get);
+
+        public void MinimumLimit(bool horizontal, bool vertical)
+        {
+            Set(elm_scroller_content_min_limit, horizontal, vertical);
+        }
+
+        public void ScrollTo(int horizontalPageIndex, int verticalPageIndex, bool animated)
+        {
+            if (animated)
+            {
+                Set(elm_scroller_page_bring_in, horizontalPageIndex, verticalPageIndex);
+            }
+            else
+            {
+                Set(elm_scroller_page_show, horizontalPageIndex, verticalPageIndex);
+            }
+        }
+
+        public void ScrollTo(Rect region, bool animated)
+        {
+            if (animated)
+            {
+                elm_scroller_region_bring_in(obj.RealHandle, region.X, region.Y, region.Width, region.Height);
+            }
+            else
+            {
+                elm_scroller_region_show(obj.RealHandle, region.X, region.Y, region.Width, region.Height);
+            }
+        }
+
+        delegate T Getter<T>(IntPtr handle);
+        delegate void Setter<T>(IntPtr handle, T v);
+        delegate void DoubleGetter<T>(IntPtr handle, out T v1, out T v2);
+        delegate void DoubleSetter<T>(IntPtr handle, T v1, T v2);
+
+        T Get<T>(Getter<T> func) => func(obj.RealHandle);
+        void Set<T>(Setter<T> func,  T value) => func(obj.RealHandle, value);
+
+        T Get1<T>(DoubleGetter<T> func)
+        {
+            T v1, v2;
+            func(obj.RealHandle, out v1, out v2);
+            return v1;
+        }
+
+        T Get2<T>(DoubleGetter<T> func)
+        {
+            T v1, v2;
+            func(obj.RealHandle, out v1, out v2);
+            return v2;
+        }
+
+        void Set<T>(DoubleSetter<T> func, T v1, T v2) => func(obj.RealHandle, v1, v2);
+    }
+}
index a6063a7..926b68f 100755 (executable)
@@ -19,77 +19,11 @@ using System;
 namespace ElmSharp
 {
     /// <summary>
-    /// Enumeration for visible type of scrollbar.
-    /// </summary>
-    public enum ScrollBarVisiblePolicy
-    {
-        /// <summary>
-        /// Show scrollbars as needed
-        /// </summary>
-        Auto = 0,
-
-        /// <summary>
-        /// Always show scrollbars
-        /// </summary>
-        Visible,
-
-        /// <summary>
-        /// Never show scrollbars
-        /// </summary>
-        Invisible
-    }
-
-    /// <summary>
-    /// Enumeration for visible type of scrollbar.
-    /// </summary>
-    public enum ScrollBlock
-    {
-        /// <summary>
-        /// Scrolling movement is allowed in both direction.(X axis and Y axis)
-        /// </summary>
-        None = 1,
-
-        /// <summary>
-        /// Scrolling movement is not allowed in Y axis direction.
-        /// </summary>
-        Vertical = 2,
-
-        /// <summary>
-        /// Scrolling movement is not allowed in X axis direction.
-        /// </summary>
-        Horizontal = 4
-    }
-
-    /// <summary>
-    /// Type that controls how the content is scrolled.
-    /// </summary>
-    public enum ScrollSingleDirection
-    {
-        /// <summary>
-        /// Scroll every direction.
-        /// </summary>
-        None,
-
-        /// <summary>
-        /// Scroll single direction if the direction is certain.
-        /// </summary>
-        Soft,
-
-        /// <summary>
-        /// Scroll only single direction.
-        /// </summary>
-        Hard,
-    }
-
-    /// <summary>
     /// The Scroller is a container that holds and clips a single object and allows you to scroll across it.
     /// </summary>
-    public class Scroller : Layout
+    public class Scroller : Layout, IScrollable
     {
-        SmartEvent _scroll;
-        SmartEvent _dragStart;
-        SmartEvent _dragStop;
-        SmartEvent _scrollpage;
+        ScrollableAdapter _adapter;
 
         /// <summary>
         /// Creates and initializes a new instance of the Scroller class.
@@ -111,14 +45,8 @@ namespace ElmSharp
         /// </summary>
         public event EventHandler Scrolled
         {
-            add
-            {
-                _scroll.On += value;
-            }
-            remove
-            {
-                _scroll.On -= value;
-            }
+            add => _adapter.Scrolled += value;
+            remove => _adapter.Scrolled -= value;
         }
 
         /// <summary>
@@ -126,14 +54,8 @@ namespace ElmSharp
         /// </summary>
         public event EventHandler DragStart
         {
-            add
-            {
-                _dragStart.On += value;
-            }
-            remove
-            {
-                _dragStart.On -= value;
-            }
+            add => _adapter.DragStart += value;
+            remove => _adapter.DragStart -= value;
         }
 
         /// <summary>
@@ -141,14 +63,8 @@ namespace ElmSharp
         /// </summary>
         public event EventHandler DragStop
         {
-            add
-            {
-                _dragStop.On += value;
-            }
-            remove
-            {
-                _dragStop.On -= value;
-            }
+            add => _adapter.DragStop += value;
+            remove => _adapter.DragStop -= value;
         }
 
         /// <summary>
@@ -156,28 +72,14 @@ namespace ElmSharp
         /// </summary>
         public event EventHandler PageScrolled
         {
-            add
-            {
-                _scrollpage.On += value;
-            }
-            remove
-            {
-                _scrollpage.On -= value;
-            }
+            add => _adapter.PageScrolled += value;
+            remove => _adapter.PageScrolled -= value;
         }
 
         /// <summary>
         /// Gets the current region in the content object that is visible through the Scroller.
         /// </summary>
-        public Rect CurrentRegion
-        {
-            get
-            {
-                int x, y, w, h;
-                Interop.Elementary.elm_scroller_region_get(RealHandle, out x, out y, out w, out h);
-                return new Rect(x, y, w, h);
-            }
-        }
+        public Rect CurrentRegion => _adapter.CurrentRegion;
 
         /// <summary>
         /// Sets or gets the value of HorizontalScrollBarVisiblePolicy
@@ -188,17 +90,8 @@ namespace ElmSharp
         /// </remarks>
         public virtual ScrollBarVisiblePolicy HorizontalScrollBarVisiblePolicy
         {
-            get
-            {
-                int policy;
-                Interop.Elementary.elm_scroller_policy_get(RealHandle, out policy, IntPtr.Zero);
-                return (ScrollBarVisiblePolicy)policy;
-            }
-            set
-            {
-                ScrollBarVisiblePolicy v = VerticalScrollBarVisiblePolicy;
-                Interop.Elementary.elm_scroller_policy_set(RealHandle, (int)value, (int)v);
-            }
+            get => _adapter.HorizontalScrollBarVisiblePolicy;
+            set => _adapter.HorizontalScrollBarVisiblePolicy = value;
         }
 
         /// <summary>
@@ -210,17 +103,8 @@ namespace ElmSharp
         /// </remarks>
         public virtual ScrollBarVisiblePolicy VerticalScrollBarVisiblePolicy
         {
-            get
-            {
-                int policy;
-                Interop.Elementary.elm_scroller_policy_get(RealHandle, IntPtr.Zero, out policy);
-                return (ScrollBarVisiblePolicy)policy;
-            }
-            set
-            {
-                ScrollBarVisiblePolicy h = HorizontalScrollBarVisiblePolicy;
-                Interop.Elementary.elm_scroller_policy_set(RealHandle, (int)h, (int)value);
-            }
+            get => _adapter.VerticalScrollBarVisiblePolicy;
+            set => _adapter.VerticalScrollBarVisiblePolicy = value;
         }
 
         /// <summary>
@@ -232,14 +116,8 @@ namespace ElmSharp
         /// </remarks>
         public ScrollBlock ScrollBlock
         {
-            get
-            {
-                return (ScrollBlock)Interop.Elementary.elm_scroller_movement_block_get(RealHandle);
-            }
-            set
-            {
-                Interop.Elementary.elm_scroller_movement_block_set(RealHandle, (int)value);
-            }
+            get => _adapter.ScrollBlock;
+            set => _adapter.ScrollBlock = value;
         }
 
         /// <summary>
@@ -250,15 +128,7 @@ namespace ElmSharp
         /// If there are two or more pages in the viewport, it returns the number of the page which meets the top of the viewport.
         /// The page number starts from 0. 0 is the first page.
         /// </remarks>
-        public int VerticalPageIndex
-        {
-            get
-            {
-                int v, h;
-                Interop.Elementary.elm_scroller_current_page_get(RealHandle, out h, out v);
-                return v;
-            }
-        }
+        public int VerticalPageIndex => _adapter.VerticalPageIndex;
 
         /// <summary>
         /// Sets or gets scroll current page number.
@@ -268,32 +138,15 @@ namespace ElmSharp
         /// If there are two or more pages in the viewport, it returns the number of the page which meets the left of the viewport.
         /// The page number starts from 0. 0 is the first page.
         /// </remarks>
-        public int HorizontalPageIndex
-        {
-            get
-            {
-                int v, h;
-                Interop.Elementary.elm_scroller_current_page_get(RealHandle, out h, out v);
-                return h;
-            }
-        }
+        public int HorizontalPageIndex => _adapter.HorizontalPageIndex;
 
         /// <summary>
         /// Sets or gets the maximum limit of the movable page at vertical direction.
         /// </summary>
         public int VerticalPageScrollLimit
         {
-            get
-            {
-                int v, h;
-                Interop.Elementary.elm_scroller_page_scroll_limit_get(RealHandle, out h, out v);
-                return v;
-            }
-            set
-            {
-                int h = HorizontalPageScrollLimit;
-                Interop.Elementary.elm_scroller_page_scroll_limit_set(RealHandle, h, value);
-            }
+            get => _adapter.VerticalPageScrollLimit;
+            set => _adapter.VerticalPageScrollLimit = value;
         }
 
         /// <summary>
@@ -301,17 +154,8 @@ namespace ElmSharp
         /// </summary>
         public int HorizontalPageScrollLimit
         {
-            get
-            {
-                int v, h;
-                Interop.Elementary.elm_scroller_page_scroll_limit_get(RealHandle, out h, out v);
-                return h;
-            }
-            set
-            {
-                int v = VerticalPageScrollLimit;
-                Interop.Elementary.elm_scroller_page_scroll_limit_set(RealHandle, value, v);
-            }
+            get => _adapter.HorizontalPageScrollLimit;
+            set => _adapter.HorizontalPageScrollLimit = value;
         }
 
         /// <summary>
@@ -323,17 +167,8 @@ namespace ElmSharp
         /// </summary>
         public bool VerticalBounce
         {
-            get
-            {
-                bool v, h;
-                Interop.Elementary.elm_scroller_bounce_get(RealHandle, out h, out v);
-                return v;
-            }
-            set
-            {
-                bool h = HorizontalBounce;
-                Interop.Elementary.elm_scroller_bounce_set(RealHandle, h, value);
-            }
+            get => _adapter.VerticalBounce;
+            set => _adapter.VerticalBounce = value;
         }
 
         /// <summary>
@@ -345,17 +180,8 @@ namespace ElmSharp
         /// </summary>
         public bool HorizontalBounce
         {
-            get
-            {
-                bool v, h;
-                Interop.Elementary.elm_scroller_bounce_get(RealHandle, out h, out v);
-                return h;
-            }
-            set
-            {
-                bool v = VerticalBounce;
-                Interop.Elementary.elm_scroller_bounce_set(RealHandle, value, v);
-            }
+            get => _adapter.HorizontalBounce;
+            set => _adapter.HorizontalBounce = value;
         }
 
         /// <summary>
@@ -363,12 +189,7 @@ namespace ElmSharp
         /// </summary>
         public int ChildWidth
         {
-            get
-            {
-                int w, h;
-                Interop.Elementary.elm_scroller_child_size_get(RealHandle, out w, out h);
-                return w;
-            }
+            get => _adapter.ChildWidth;
         }
 
         /// <summary>
@@ -376,12 +197,7 @@ namespace ElmSharp
         /// </summary>
         public int ChildHeight
         {
-            get
-            {
-                int w, h;
-                Interop.Elementary.elm_scroller_child_size_get(RealHandle, out w, out h);
-                return h;
-            }
+            get => _adapter.ChildHeight;
         }
 
         /// <summary>
@@ -393,17 +209,8 @@ namespace ElmSharp
         /// </summary>
         public double HorizontalGravity
         {
-            get
-            {
-                double v, h;
-                Interop.Elementary.elm_scroller_gravity_get(RealHandle, out h, out v);
-                return h;
-            }
-            set
-            {
-                double v = VerticalGravity;
-                Interop.Elementary.elm_scroller_gravity_set(RealHandle, value, v);
-            }
+            get => _adapter.HorizontalGravity;
+            set => _adapter.HorizontalGravity = value;
         }
 
         /// <summary>
@@ -415,46 +222,21 @@ namespace ElmSharp
         /// </summary>
         public double VerticalGravity
         {
-            get
-            {
-                double v, h;
-                Interop.Elementary.elm_scroller_gravity_get(RealHandle, out h, out v);
-                return v;
-            }
-            set
-            {
-                double h = HorizontalGravity;
-                Interop.Elementary.elm_scroller_gravity_set(RealHandle, h, value);
-            }
+            get => _adapter.VerticalGravity;
+            set => _adapter.VerticalGravity = value;
         }
 
         /// <summary>
         /// Get scroll last page number.
         /// The page number starts from 0. 0 is the first page. This returns the last page number among the pages.
         /// </summary>
-        public int LastVerticalPageNumber
-        {
-            get
-            {
-                int v, h;
-                Interop.Elementary.elm_scroller_last_page_get(RealHandle, out h, out v);
-                return v;
-            }
-        }
+        public int LastVerticalPageNumber => _adapter.LastVerticalPageNumber;
 
         /// <summary>
         /// Get scroll last page number.
         /// The page number starts from 0. 0 is the first page. This returns the last page number among the pages.
         /// </summary>
-        public int LastHorizontalPageNumber
-        {
-            get
-            {
-                int v, h;
-                Interop.Elementary.elm_scroller_last_page_get(RealHandle, out h, out v);
-                return h;
-            }
-        }
+        public int LastHorizontalPageNumber => _adapter.LastHorizontalPageNumber;
 
         /// <summary>
         /// Set an infinite loop_ for a scroller.
@@ -463,17 +245,8 @@ namespace ElmSharp
         /// </summary>
         public bool VerticalLoop
         {
-            get
-            {
-                bool v, h;
-                Interop.Elementary.elm_scroller_loop_get(RealHandle, out h, out v);
-                return v;
-            }
-            set
-            {
-                bool h = HorizontalLoop;
-                Interop.Elementary.elm_scroller_loop_set(RealHandle, h, value);
-            }
+            get => _adapter.VerticalLoop;
+            set => _adapter.VerticalLoop = value;
         }
 
         /// <summary>
@@ -483,17 +256,26 @@ namespace ElmSharp
         /// </summary>
         public bool HorizontalLoop
         {
-            get
-            {
-                bool v, h;
-                Interop.Elementary.elm_scroller_loop_get(RealHandle, out h, out v);
-                return h;
-            }
-            set
-            {
-                bool v = VerticalLoop;
-                Interop.Elementary.elm_scroller_loop_set(RealHandle, value, v);
-            }
+            get => _adapter.HorizontalLoop;
+            set => _adapter.HorizontalLoop = value;
+        }
+
+        /// <summary>
+        /// Gets or sets the page size to an absolute fixed value, with 0 turning it off for that axis.
+        /// </summary>
+        public int HorizontalPageSize
+        {
+            get => _adapter.HorizontalPageSize;
+            set => _adapter.HorizontalPageSize = value;
+        }
+
+        /// <summary>
+        /// Gets or sets the page size to an absolute fixed value, with 0 turning it off for that axis.
+        /// </summary>
+        public int VerticalPageSize
+        {
+            get => _adapter.VerticalPageSize;
+            set => _adapter.VerticalPageSize = value;
         }
 
         /// <summary>
@@ -501,17 +283,8 @@ namespace ElmSharp
         /// </summary>
         public double VerticalRelativePageSize
         {
-            get
-            {
-                double v, h;
-                Interop.Elementary.elm_scroller_page_relative_get(RealHandle, out h, out v);
-                return v;
-            }
-            set
-            {
-                double h = HorizontalRelativePageSize;
-                Interop.Elementary.elm_scroller_page_relative_set(RealHandle, h, value);
-            }
+            get => _adapter.VerticalRelativePageSize;
+            set => _adapter.VerticalRelativePageSize = value;
         }
 
         /// <summary>
@@ -519,17 +292,8 @@ namespace ElmSharp
         /// </summary>
         public double HorizontalRelativePageSize
         {
-            get
-            {
-                double v, h;
-                Interop.Elementary.elm_scroller_page_relative_get(RealHandle, out h, out v);
-                return h;
-            }
-            set
-            {
-                double v = VerticalRelativePageSize;
-                Interop.Elementary.elm_scroller_page_relative_set(RealHandle, value, v);
-            }
+            get => _adapter.HorizontalRelativePageSize;
+            set => _adapter.HorizontalRelativePageSize = value;
         }
 
         /// <summary>
@@ -543,17 +307,8 @@ namespace ElmSharp
         /// </remarks>
         public bool VerticalSnap
         {
-            get
-            {
-                bool v, h;
-                Interop.Elementary.elm_scroller_page_snap_get(RealHandle, out h, out v);
-                return v;
-            }
-            set
-            {
-                bool h = HorizontalSnap;
-                Interop.Elementary.elm_scroller_page_snap_set(RealHandle, h, value);
-            }
+            get => _adapter.VerticalSnap;
+            set => _adapter.VerticalSnap = value;
         }
 
         /// <summary>
@@ -567,17 +322,8 @@ namespace ElmSharp
         /// </remarks>
         public bool HorizontalSnap
         {
-            get
-            {
-                bool v, h;
-                Interop.Elementary.elm_scroller_page_snap_get(RealHandle, out h, out v);
-                return h;
-            }
-            set
-            {
-                bool v = VerticalSnap;
-                Interop.Elementary.elm_scroller_page_snap_set(RealHandle, value, v);
-            }
+            get => _adapter.HorizontalSnap;
+            set => _adapter.HorizontalSnap = value;
         }
 
         /// <summary>
@@ -585,17 +331,8 @@ namespace ElmSharp
         /// </summary>
         public int PageHeight
         {
-            get
-            {
-                int w, h;
-                Interop.Elementary.elm_scroller_page_size_get(RealHandle, out w, out h);
-                return h;
-            }
-            set
-            {
-                int w = PageWidth;
-                Interop.Elementary.elm_scroller_page_size_set(RealHandle, w, value);
-            }
+            get => _adapter.PageHeight;
+            set => _adapter.PageHeight = value;
         }
 
         /// <summary>
@@ -603,17 +340,8 @@ namespace ElmSharp
         /// </summary>
         public int PageWidth
         {
-            get
-            {
-                int w, h;
-                Interop.Elementary.elm_scroller_page_size_get(RealHandle, out w, out h);
-                return w;
-            }
-            set
-            {
-                int h = PageHeight;
-                Interop.Elementary.elm_scroller_page_size_set(RealHandle, value, h);
-            }
+            get => _adapter.PageWidth;
+            set => _adapter.PageWidth = value;
         }
 
         /// <summary>
@@ -638,17 +366,8 @@ namespace ElmSharp
         /// </summary>
         public int HorizontalStepSize
         {
-            get
-            {
-                int h, v;
-                Interop.Elementary.elm_scroller_step_size_get(RealHandle, out h, out v);
-                return h;
-            }
-            set
-            {
-                int v = VerticalStepSize;
-                Interop.Elementary.elm_scroller_step_size_set(RealHandle, value, v);
-            }
+            get => _adapter.HorizontalStepSize;
+            set => _adapter.HorizontalStepSize = value;
         }
 
         /// <summary>
@@ -656,17 +375,8 @@ namespace ElmSharp
         /// </summary>
         public int VerticalStepSize
         {
-            get
-            {
-                int h, v;
-                Interop.Elementary.elm_scroller_step_size_get(RealHandle, out h, out v);
-                return v;
-            }
-            set
-            {
-                int h = HorizontalStepSize;
-                Interop.Elementary.elm_scroller_step_size_set(RealHandle, h, value);
-            }
+            get => _adapter.VerticalStepSize;
+            set => _adapter.VerticalStepSize = value;
         }
 
         /// <summary>
@@ -674,14 +384,8 @@ namespace ElmSharp
         /// </summary>
         public bool WheelDisabled
         {
-            get
-            {
-                return Interop.Elementary.elm_scroller_wheel_disabled_get(RealHandle);
-            }
-            set
-            {
-                Interop.Elementary.elm_scroller_wheel_disabled_set(RealHandle, value);
-            }
+            get => _adapter.WheelDisabled;
+            set => _adapter.WheelDisabled = value;
         }
 
         /// <summary>
@@ -689,14 +393,8 @@ namespace ElmSharp
         /// </summary>
         public ScrollSingleDirection SingleDirection
         {
-            get
-            {
-                return (ScrollSingleDirection)Interop.Elementary.elm_scroller_single_direction_get(RealHandle);
-            }
-            set
-            {
-                Interop.Elementary.elm_scroller_single_direction_set(RealHandle, (int)value);
-            }
+            get => _adapter.SingleDirection;
+            set => _adapter.SingleDirection = value;
         }
 
         /// <summary>
@@ -708,7 +406,7 @@ namespace ElmSharp
         /// <param name="vertical">Enable limiting minimum size vertically</param>
         public void MinimumLimit(bool horizontal, bool vertical)
         {
-            Interop.Elementary.elm_scroller_content_min_limit(RealHandle, horizontal, vertical);
+            _adapter.MinimumLimit(horizontal, vertical);
         }
 
         /// <summary>
@@ -749,14 +447,7 @@ namespace ElmSharp
         /// <param name="animated">True means slider with animation.</param>
         public void ScrollTo(int horizontalPageIndex, int verticalPageIndex, bool animated)
         {
-            if (animated)
-            {
-                Interop.Elementary.elm_scroller_page_bring_in(RealHandle, horizontalPageIndex, verticalPageIndex);
-            }
-            else
-            {
-                Interop.Elementary.elm_scroller_page_show(RealHandle, horizontalPageIndex, verticalPageIndex);
-            }
+            _adapter.ScrollTo(horizontalPageIndex, verticalPageIndex, animated);
         }
 
         /// <summary>
@@ -773,26 +464,7 @@ namespace ElmSharp
         /// <param name="animated">True means allows the scroller to "smoothly slide" to this location.</param>
         public void ScrollTo(Rect region, bool animated)
         {
-            if (animated)
-            {
-                Interop.Elementary.elm_scroller_region_bring_in(RealHandle, region.X, region.Y, region.Width, region.Height);
-            }
-            else
-            {
-                Interop.Elementary.elm_scroller_region_show(RealHandle, region.X, region.Y, region.Width, region.Height);
-            }
-        }
-
-        /// <summary>
-        /// The callback of Realized Event
-        /// </summary>
-        protected override void OnRealized()
-        {
-            base.OnRealized();
-            _scroll = new SmartEvent(this, this.RealHandle, "scroll");
-            _dragStart = new SmartEvent(this, this.RealHandle, "scroll,drag,start");
-            _dragStop = new SmartEvent(this, this.RealHandle, "scroll,drag,stop");
-            _scrollpage = new SmartEvent(this, this.RealHandle, "scroll,page,changed");
+            _adapter.ScrollTo(region, animated);
         }
 
         /// <summary>
@@ -808,6 +480,8 @@ namespace ElmSharp
             RealHandle = Interop.Elementary.elm_scroller_add(handle);
             Interop.Elementary.elm_object_part_content_set(handle, "elm.swallow.content", RealHandle);
 
+            _adapter = new ScrollableAdapter(this);
+
             return handle;
         }
     }
index 49d7178..5b92ca7 100755 (executable)
@@ -125,8 +125,9 @@ namespace ElmSharp
     /// <summary>
     /// The Toolbar is a widget that displays a list of items inside a box.
     /// </summary>
-    public class Toolbar : Widget
+    public class Toolbar : Widget, IScrollable
     {
+        ScrollableAdapter _scroller;
         SmartEvent<ToolbarItemEventArgs> _clicked;
         SmartEvent<ToolbarItemEventArgs> _selected;
         SmartEvent<ToolbarItemEventArgs> _longpressed;
@@ -158,6 +159,8 @@ namespace ElmSharp
             {
                 e.Item?.SendClicked();
             };
+
+            _scroller = new ScrollableAdapter(this);
         }
 
         /// <summary>
@@ -466,5 +469,390 @@ namespace ElmSharp
 
             return handle;
         }
+
+        #region IScroller Implementation
+
+        /// <summary>
+        /// Scrolled will be triggered when the content has been scrolled.
+        /// </summary>
+        public event EventHandler Scrolled
+        {
+            add => _scroller.Scrolled += value;
+            remove => _scroller.Scrolled -= value;
+        }
+
+        /// <summary>
+        /// DragStart will be triggered when dragging the contents around has started.
+        /// </summary>
+        public event EventHandler DragStart
+        {
+            add => _scroller.DragStart += value;
+            remove => _scroller.DragStart -= value;
+        }
+
+        /// <summary>
+        /// DragStop will be triggered when dragging the contents around has stopped.
+        /// </summary>
+        public event EventHandler DragStop
+        {
+            add => _scroller.DragStop += value;
+            remove => _scroller.DragStop -= value;
+        }
+
+        /// <summary>
+        /// PageScrolled will be triggered when the visible page has changed.
+        /// </summary>
+        public event EventHandler PageScrolled
+        {
+            add => _scroller.PageScrolled += value;
+            remove => _scroller.PageScrolled -= value;
+        }
+
+        /// <summary>
+        /// Gets the current region in the content object that is visible through the Scroller.
+        /// </summary>
+        public Rect CurrentRegion => _scroller.CurrentRegion;
+
+        /// <summary>
+        /// Sets or gets the value of HorizontalScrollBarVisiblePolicy
+        /// </summary>
+        /// <remarks>
+        /// ScrollBarVisiblePolicy.Auto means the horizontal scrollbar is made visible if it is needed, and otherwise kept hidden.
+        /// ScrollBarVisiblePolicy.Visible turns it on all the time, and ScrollBarVisiblePolicy.Invisible always keeps it off.
+        /// </remarks>
+        public virtual ScrollBarVisiblePolicy HorizontalScrollBarVisiblePolicy
+        {
+            get => _scroller.HorizontalScrollBarVisiblePolicy;
+            set => _scroller.HorizontalScrollBarVisiblePolicy = value;
+        }
+
+        /// <summary>
+        /// Sets or gets the value of VerticalScrollBarVisiblePolicy
+        /// </summary>
+        /// <remarks>
+        /// ScrollBarVisiblePolicy.Auto means the vertical scrollbar is made visible if it is needed, and otherwise kept hidden.
+        /// ScrollBarVisiblePolicy.Visible turns it on all the time, and ScrollBarVisiblePolicy.Invisible always keeps it off.
+        /// </remarks>
+        public virtual ScrollBarVisiblePolicy VerticalScrollBarVisiblePolicy
+        {
+            get => _scroller.VerticalScrollBarVisiblePolicy;
+            set => _scroller.VerticalScrollBarVisiblePolicy = value;
+        }
+
+        /// <summary>
+        /// Sets or gets the value of ScrollBlock.
+        /// </summary>
+        /// <remarks>
+        /// This function will block scrolling movement  in a given direction.One can disable movements in the X axis, the Y axis or both.
+        /// The default value is ScrollBlock.None, where movements are allowed in both directions.
+        /// </remarks>
+        public ScrollBlock ScrollBlock
+        {
+            get => _scroller.ScrollBlock;
+            set => _scroller.ScrollBlock = value;
+        }
+
+        /// <summary>
+        /// Sets or gets scroll current page number.
+        /// </summary>
+        /// <remarks>
+        /// Current page means the page which meets the top of the viewport.
+        /// If there are two or more pages in the viewport, it returns the number of the page which meets the top of the viewport.
+        /// The page number starts from 0. 0 is the first page.
+        /// </remarks>
+        public int VerticalPageIndex => _scroller.VerticalPageIndex;
+
+        /// <summary>
+        /// Sets or gets scroll current page number.
+        /// </summary>
+        /// <remarks>
+        /// Current page means the page which meets the left of the viewport.
+        /// If there are two or more pages in the viewport, it returns the number of the page which meets the left of the viewport.
+        /// The page number starts from 0. 0 is the first page.
+        /// </remarks>
+        public int HorizontalPageIndex => _scroller.HorizontalPageIndex;
+
+        /// <summary>
+        /// Sets or gets the maximum limit of the movable page at vertical direction.
+        /// </summary>
+        public int VerticalPageScrollLimit
+        {
+            get => _scroller.VerticalPageScrollLimit;
+            set => _scroller.VerticalPageScrollLimit = value;
+        }
+
+        /// <summary>
+        /// Sets or gets the maximum limit of the movable page at horizontal direction.
+        /// </summary>
+        public int HorizontalPageScrollLimit
+        {
+            get => _scroller.HorizontalPageScrollLimit;
+            set => _scroller.HorizontalPageScrollLimit = value;
+        }
+
+        /// <summary>
+        /// Sets or gets the vertical bounce behaviour.
+        /// When scrolling, the scroller may "bounce" when reaching an edge of the content object.
+        /// This is a visual way to indicate the end has been reached.
+        /// This is enabled by default for both axis.
+        /// This API will set if it is enabled for the given axis with the boolean parameters for each axis.
+        /// </summary>
+        public bool VerticalBounce
+        {
+            get => _scroller.VerticalBounce;
+            set => _scroller.VerticalBounce = value;
+        }
+
+        /// <summary>
+        /// Sets or gets the horizontal bounce behaviour.
+        /// When scrolling, the scroller may "bounce" when reaching an edge of the content object.
+        /// This is a visual way to indicate the end has been reached.
+        /// This is enabled by default for both axis.
+        /// This API will set if it is enabled for the given axis with the boolean parameters for each axis.
+        /// </summary>
+        public bool HorizontalBounce
+        {
+            get => _scroller.HorizontalBounce;
+            set => _scroller.HorizontalBounce = value;
+        }
+
+        /// <summary>
+        /// Gets the width of the content object of the scroller.
+        /// </summary>
+        public int ChildWidth
+        {
+            get => _scroller.ChildWidth;
+        }
+
+        /// <summary>
+        /// Gets the height of the content object of the scroller.
+        /// </summary>
+        public int ChildHeight
+        {
+            get => _scroller.ChildHeight;
+        }
+
+        /// <summary>
+        /// Set scrolling gravity values for a scroller.
+        /// The gravity, defines how the scroller will adjust its view when the size of the scroller contents increase.
+        /// The scroller will adjust the view to glue itself as follows.
+        /// x=0.0, for staying where it is relative to the left edge of the content x=1.0, for staying where it is relative to the rigth edge of the content y=0.0, for staying where it is relative to the top edge of the content y=1.0, for staying where it is relative to the bottom edge of the content
+        /// Default values for x and y are 0.0
+        /// </summary>
+        public double HorizontalGravity
+        {
+            get => _scroller.HorizontalGravity;
+            set => _scroller.HorizontalGravity = value;
+        }
+
+        /// <summary>
+        /// Set scrolling gravity values for a scroller.
+        /// The gravity, defines how the scroller will adjust its view when the size of the scroller contents increase.
+        /// The scroller will adjust the view to glue itself as follows.
+        /// x=0.0, for staying where it is relative to the left edge of the content x=1.0, for staying where it is relative to the rigth edge of the content y=0.0, for staying where it is relative to the top edge of the content y=1.0, for staying where it is relative to the bottom edge of the content
+        /// Default values for x and y are 0.0
+        /// </summary>
+        public double VerticalGravity
+        {
+            get => _scroller.VerticalGravity;
+            set => _scroller.VerticalGravity = value;
+        }
+
+        /// <summary>
+        /// Get scroll last page number.
+        /// The page number starts from 0. 0 is the first page. This returns the last page number among the pages.
+        /// </summary>
+        public int LastVerticalPageNumber => _scroller.LastVerticalPageNumber;
+
+        /// <summary>
+        /// Get scroll last page number.
+        /// The page number starts from 0. 0 is the first page. This returns the last page number among the pages.
+        /// </summary>
+        public int LastHorizontalPageNumber => _scroller.LastHorizontalPageNumber;
+
+        /// <summary>
+        /// Set an infinite loop_ for a scroller.
+        /// This function sets the infinite loop vertically.
+        /// If the content is set, it will be shown repeatedly.
+        /// </summary>
+        public bool VerticalLoop
+        {
+            get => _scroller.VerticalLoop;
+            set => _scroller.VerticalLoop = value;
+        }
+
+        /// <summary>
+        /// Set an infinite loop_ for a scroller.
+        /// This function sets the infinite loop horizontally.
+        /// If the content is set, it will be shown repeatedly.
+        /// </summary>
+        public bool HorizontalLoop
+        {
+            get => _scroller.HorizontalLoop;
+            set => _scroller.HorizontalLoop = value;
+        }
+
+        /// <summary>
+        /// Gets or sets the page size to an absolute fixed value, with 0 turning it off for that axis.
+        /// </summary>
+        public int HorizontalPageSize
+        {
+            get => _scroller.HorizontalPageSize;
+            set => _scroller.HorizontalPageSize = value;
+        }
+
+        /// <summary>
+        /// Gets or sets the page size to an absolute fixed value, with 0 turning it off for that axis.
+        /// </summary>
+        public int VerticalPageSize
+        {
+            get => _scroller.VerticalPageSize;
+            set => _scroller.VerticalPageSize = value;
+        }
+
+        /// <summary>
+        /// Gets or sets a given scroller widget's scrolling page size, relative to its viewport size.
+        /// </summary>
+        public double VerticalRelativePageSize
+        {
+            get => _scroller.VerticalRelativePageSize;
+            set => _scroller.VerticalRelativePageSize = value;
+        }
+
+        /// <summary>
+        /// Gets or sets a given scroller widget's scrolling page size, relative to its viewport size.
+        /// </summary>
+        public double HorizontalRelativePageSize
+        {
+            get => _scroller.HorizontalRelativePageSize;
+            set => _scroller.HorizontalRelativePageSize = value;
+        }
+
+        /// <summary>
+        /// Gets or Sets the page snapping behavior of a scroller.
+        /// </summary>
+        /// <remarks>
+        /// When scrolling, if a scroller is paged (see VerticalRelativePageSize),
+        /// the scroller may snap to pages when being scrolled, i.e., even if it had momentum to scroll further,
+        /// it will stop at the next page boundaries. This is disabled, by default, for both axis.
+        /// This function will set if it that is enabled or not, for each axis.
+        /// </remarks>
+        public bool VerticalSnap
+        {
+            get => _scroller.VerticalSnap;
+            set => _scroller.VerticalSnap = value;
+        }
+
+        /// <summary>
+        /// Gets or Sets the page snapping behavior of a scroller.
+        /// </summary>
+        /// <remarks>
+        /// When scrolling, if a scroller is paged (see HorizontalRelativePageSize),
+        /// the scroller may snap to pages when being scrolled, i.e., even if it had momentum to scroll further,
+        /// it will stop at the next page boundaries. This is disabled, by default, for both axis.
+        /// This function will set if it that is enabled or not, for each axis.
+        /// </remarks>
+        public bool HorizontalSnap
+        {
+            get => _scroller.HorizontalSnap;
+            set => _scroller.HorizontalSnap = value;
+        }
+
+        /// <summary>
+        /// Gets or sets the page size to an absolute fixed value, with 0 turning it off for that axis.
+        /// </summary>
+        public int PageHeight
+        {
+            get => _scroller.PageHeight;
+            set => _scroller.PageHeight = value;
+        }
+
+        /// <summary>
+        /// Gets or sets the page size to an absolute fixed value, with 0 turning it off for that axis.
+        /// </summary>
+        public int PageWidth
+        {
+            get => _scroller.PageWidth;
+            set => _scroller.PageWidth = value;
+        }
+
+        /// <summary>
+        /// Gets or sets the step size to move scroller by key event.
+        /// </summary>
+        public int HorizontalStepSize
+        {
+            get => _scroller.HorizontalStepSize;
+            set => _scroller.HorizontalStepSize = value;
+        }
+
+        /// <summary>
+        /// Gets or sets the step size to move scroller by key event.
+        /// </summary>
+        public int VerticalStepSize
+        {
+            get => _scroller.VerticalStepSize;
+            set => _scroller.VerticalStepSize = value;
+        }
+
+        /// <summary>
+        /// Gets or sets a value whether mouse wheel is enabled or not over the scroller.
+        /// </summary>
+        public bool WheelDisabled
+        {
+            get => _scroller.WheelDisabled;
+            set => _scroller.WheelDisabled = value;
+        }
+
+        /// <summary>
+        /// Gets or sets the type of single direction scroll.
+        /// </summary>
+        public ScrollSingleDirection SingleDirection
+        {
+            get => _scroller.SingleDirection;
+            set => _scroller.SingleDirection = value;
+        }
+
+        /// <summary>
+        /// Sets the scroller minimum size limited to the minimum size of the content.
+        /// By default the scroller will be as small as its design allows, irrespective of its content.
+        /// This will make the scroller minimum size the right size horizontally and/or vertically to perfectly fit its content in that direction.
+        /// </summary>
+        /// <param name="horizontal">Enable limiting minimum size horizontally</param>
+        /// <param name="vertical">Enable limiting minimum size vertically</param>
+        public void MinimumLimit(bool horizontal, bool vertical)
+        {
+            _scroller.MinimumLimit(horizontal, vertical);
+        }
+
+        /// <summary>
+        /// Shows a specific virtual region within the scroller content object by the page number.
+        /// (0, 0) of the indicated page is located at the top-left corner of the viewport.
+        /// </summary>
+        /// <param name="horizontalPageIndex">The horizontal page number.</param>
+        /// <param name="verticalPageIndex">The vertical page number.</param>
+        /// <param name="animated">True means slider with animation.</param>
+        public void ScrollTo(int horizontalPageIndex, int verticalPageIndex, bool animated)
+        {
+            _scroller.ScrollTo(horizontalPageIndex, verticalPageIndex, animated);
+        }
+
+        /// <summary>
+        /// Shows a specific virtual region within the scroller content object.
+        /// </summary>
+        /// <remarks>
+        /// This ensures that all (or part, if it does not fit) of the designated region in the virtual content object ((0, 0)
+        /// starting at the top-left of the virtual content object) is shown within the scroller.
+        /// If set "animated" to true, it will allows the scroller to "smoothly slide" to this location
+        /// (if configuration in general calls for transitions).
+        /// It may not jump immediately to the new location and may take a while and show other content along the way.
+        /// </remarks>
+        /// <param name="region">Rect struct of region.</param>
+        /// <param name="animated">True means allows the scroller to "smoothly slide" to this location.</param>
+        public void ScrollTo(Rect region, bool animated)
+        {
+            _scroller.ScrollTo(region, animated);
+        }
+
+        #endregion
     }
 }
\ No newline at end of file