[NUI] Improve Theme load
[platform/core/csapi/tizenfx.git] / src / Tizen.NUI.Components / Controls / Scrollbar.cs
index e8b6fae..be66340 100755 (executable)
@@ -1,5 +1,5 @@
-/*
- * Copyright(c) 2019 Samsung Electronics Co., Ltd.
+/*
+ * Copyright(c) 2020 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  *
  */
 using System;
-using Tizen.NUI.BaseComponents;
 using System.ComponentModel;
+using Tizen.NUI.BaseComponents;
 using Tizen.NUI.Binding;
 
 namespace Tizen.NUI.Components
 {
     /// <summary>
-    /// The ScrollBar class of nui component. It allows users to recognize the direction and the range of lists/content. .
+    /// The Scrollbar is a component that contains track and thumb to indicate the current scrolled position of a scrollable object.
     /// </summary>
-    /// <since_tizen> 6 </since_tizen>
-    public class ScrollBar : Control
+    [EditorBrowsable(EditorBrowsableState.Never)]
+    public class Scrollbar : ScrollbarBase
     {
-        /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
+        #region Fields
+
+        /// <summary>Bindable property of TrackThickness</summary>
         [EditorBrowsable(EditorBrowsableState.Never)]
-        public static readonly BindableProperty DirectionProperty = BindableProperty.Create("Direction", typeof(DirectionType), typeof(ScrollBar), DirectionType.Horizontal, propertyChanged: (bindable, oldValue, newValue) =>
+        public static readonly BindableProperty TrackThicknessProperty = BindableProperty.Create(nameof(TrackThickness), typeof(float), typeof(Scrollbar), default(float), propertyChanged: (bindable, oldValue, newValue) =>
         {
-            var instance = (ScrollBar)bindable;
-            if (newValue != null)
-            {
-                instance.Style.Direction = (DirectionType?)newValue;
-                instance.UpdateValue();
-            }
+            var instance = ((Scrollbar)bindable);
+            var thickness = (float?)newValue;
+
+            instance.scrollbarStyle.TrackThickness = thickness;
+            instance.UpdateTrackThickness(thickness ?? 0);
         },
         defaultValueCreator: (bindable) =>
         {
-            var instance = (ScrollBar)bindable;
-            return instance.Style.Direction;
+            return ((Scrollbar)bindable).scrollbarStyle.TrackThickness ?? 0;
         });
-        /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
+
+        /// <summary>Bindable property of ThumbThickness</summary>
         [EditorBrowsable(EditorBrowsableState.Never)]
-        public static readonly BindableProperty MaxValueProperty = BindableProperty.Create("MaxValue", typeof(int), typeof(ScrollBar), default(int), propertyChanged: (bindable, oldValue, newValue) =>
+        public static readonly BindableProperty ThumbThicknessProperty = BindableProperty.Create(nameof(ThumbThickness), typeof(float), typeof(Scrollbar), default(float), propertyChanged: (bindable, oldValue, newValue) =>
         {
-            var instance = (ScrollBar)bindable;
-            if (newValue != null)
-            {
-                if ((int)newValue >= 0)
-                {
-                    instance.maxValue = (int)newValue;
-                    instance.UpdateValue();
-                }
-            }
+            var instance = ((Scrollbar)bindable);
+            var thickness = (float?)newValue;
+
+            instance.scrollbarStyle.ThumbThickness = thickness;
+            instance.UpdateThumbThickness(thickness ?? 0);
         },
         defaultValueCreator: (bindable) =>
         {
-            var instance = (ScrollBar)bindable;
-            return instance.maxValue;
+            return ((Scrollbar)bindable).scrollbarStyle.ThumbThickness ?? 0;
         });
-        /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
+
+        /// <summary>Bindable property of TrackColor</summary>
         [EditorBrowsable(EditorBrowsableState.Never)]
-        public static readonly BindableProperty MinValueProperty = BindableProperty.Create("MinValue", typeof(int), typeof(ScrollBar), default(int), propertyChanged: (bindable, oldValue, newValue) =>
+        public static readonly BindableProperty TrackColorProperty = BindableProperty.Create(nameof(TrackColor), typeof(Color), typeof(Scrollbar), null, propertyChanged: (bindable, oldValue, newValue) =>
         {
-            var instance = (ScrollBar)bindable;
-            if (newValue != null)
-            {
-                if ((int)newValue >= 0)
-                {
-                    instance.minValue = (int)newValue;
-                    instance.UpdateValue();
-                }
-            }
+            var instance = ((Scrollbar)bindable);
+            var color = (Color)newValue;
+
+            instance.scrollbarStyle.TrackColor = color;
+            instance.UpdateTrackColor(color);
         },
         defaultValueCreator: (bindable) =>
         {
-            var instance = (ScrollBar)bindable;
-            return instance.minValue;
+            return ((Scrollbar)bindable).scrollbarStyle.TrackColor;
         });
-        /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
+
+        /// <summary>Bindable property of ThumbColor</summary>
         [EditorBrowsable(EditorBrowsableState.Never)]
-        public static readonly BindableProperty CurrentValueProperty = BindableProperty.Create("CurrentValue", typeof(int), typeof(ScrollBar), default(int), propertyChanged: (bindable, oldValue, newValue) =>
+        public static readonly BindableProperty ThumbColorProperty = BindableProperty.Create(nameof(ThumbColor), typeof(Color), typeof(Scrollbar), null, propertyChanged: (bindable, oldValue, newValue) =>
         {
-            var instance = (ScrollBar)bindable;
-            if (newValue != null)
-            {
-                if ((int)newValue >= 0)
-                {
-                    instance.curValue = (int)newValue;
-                    instance.UpdateValue();
-                }
-            }
+            var instance = ((Scrollbar)bindable);
+            var color = (Color)newValue;
+
+            instance.scrollbarStyle.ThumbColor = color;
+            instance.UpdateThumbColor(color);
         },
         defaultValueCreator: (bindable) =>
         {
-            var instance = (ScrollBar)bindable;
-            return instance.curValue;
+            return ((Scrollbar)bindable).scrollbarStyle.ThumbColor;
         });
-        /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
+
+        /// <summary>Bindable property of TrackPadding</summary>
         [EditorBrowsable(EditorBrowsableState.Never)]
-        public static readonly BindableProperty DurationProperty = BindableProperty.Create("Duration", typeof(uint), typeof(ScrollBar), default(uint), propertyChanged: (bindable, oldValue, newValue) =>
+        public static readonly BindableProperty TrackPaddingProperty = BindableProperty.Create(nameof(TrackPadding), typeof(Extents), typeof(Scrollbar), null, propertyChanged: (bindable, oldValue, newValue) =>
         {
-            var instance = (ScrollBar)bindable;
-            if (newValue != null)
-            {
-                instance.Style.Duration = (uint)newValue;
-                if (instance.scrollAniPlayer != null)
-                {
-                    instance.scrollAniPlayer.Duration = (int)newValue;
-                }
-            }
+            var instance = ((Scrollbar)bindable);
+            var trackPadding = (Extents)newValue;
+
+            instance.scrollbarStyle.TrackPadding = trackPadding;
+            instance.UpdateTrackPadding(trackPadding);
         },
         defaultValueCreator: (bindable) =>
         {
-            var instance = (ScrollBar)bindable;
-            return instance.Style.Duration;
+            return ((Scrollbar)bindable).scrollbarStyle.TrackPadding;
         });
 
-        private ImageView trackImage;
-        private ImageView thumbImage;
-        private Animation scrollAniPlayer = null;
-        private float thumbImagePosX;
-        private float thumbImagePosY;
-        private bool enableAni = false;
-        private int minValue;
-        private int maxValue;
-        private int curValue;
+        private ColorVisual trackVisual;
+        private ColorVisual thumbVisual;
+        private Animation thumbPositionAnimation;
+        private Animation thumbSizeAnimation;
+        private Calculator calculator;
+        private Size containerSize = new Size(0, 0);
+        private ScrollbarStyle scrollbarStyle => ViewStyle as ScrollbarStyle;
+        private bool mScrollEnabled = true;
+        private float previousPosition;
+
+        #endregion Fields
+
+
+        #region Constructors
 
         /// <summary>
-        /// The constructor of ScrollBar.
+        /// Create an empty Scrollbar.
         /// </summary>
-        /// <since_tizen> 6 </since_tizen>
-        public ScrollBar() : base()
+        public Scrollbar()
         {
-            Initialize();
         }
 
         /// <summary>
-        /// The constructor of ScrollBar with specific style.
+        /// Create a Scrollbar and initialize with properties.
         /// </summary>
-        /// <param name="style">style name</param>
-        /// <since_tizen> 6 </since_tizen>
-        /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
+        /// <param name="contentLength">The length of the scrollable content area.</param>
+        /// <param name="viewportLength">The length of the viewport representing the amount of visible content.</param>
+        /// <param name="currentPosition">The current position of the viewport in scrollable content area. This is the viewport's top position if the scroller is vertical, otherwise, left.</param>
+        /// <param name="isHorizontal">Whether the direction of scrolling is horizontal or not. It is vertical by default.</param>
         [EditorBrowsable(EditorBrowsableState.Never)]
-        public ScrollBar(string style) : base(style)
+        public Scrollbar(float contentLength, float viewportLength, float currentPosition, bool isHorizontal = false) : this()
         {
-            Initialize();
+            Initialize(contentLength, viewportLength, currentPosition, isHorizontal);
         }
 
         /// <summary>
-        /// The constructor of ScrollBar with specific style.
+        /// Create an empty Scrollbar with a ScrollbarStyle instance to set style properties.
         /// </summary>
-        /// <param name="style">The style object to initialize the ScrollBar.</param>
-        /// <since_tizen> 6 </since_tizen>
-        /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
         [EditorBrowsable(EditorBrowsableState.Never)]
-        public ScrollBar(ScrollBarStyle style) : base(style)
+        public Scrollbar(ScrollbarStyle style) : base(style)
         {
-            Initialize();
         }
 
         /// <summary>
-        /// The direction type of the Scroll.
+        /// Static constructor to initialize bindable properties when loading.
         /// </summary>
-        /// <since_tizen> 6 </since_tizen>
-        public enum DirectionType
-        {
-            /// <summary>
-            /// The Horizontal type.
-            /// </summary>
-            /// <since_tizen> 6 </since_tizen>
-            Horizontal,
-
-            /// <summary>
-            /// The Vertical type.
-            /// </summary>
-            /// <since_tizen> 6 </since_tizen>
-            Vertical
+        static Scrollbar()
+        {
         }
 
-        #region public property 
-        /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
-        [EditorBrowsable(EditorBrowsableState.Never)]
-        public new ScrollBarStyle Style => ViewStyle as ScrollBarStyle;
+        #endregion Constructors
+
+
+        #region Properties
 
         /// <summary>
-        /// The property to get/set the direction of the ScrollBar.
+        /// The thickness of the track.
         /// </summary>
-        /// <since_tizen> 6 </since_tizen>
-        public DirectionType Direction
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public float TrackThickness
         {
-            get
-            {
-                return (DirectionType)GetValue(DirectionProperty);
-            }
-            set
-            {
-                SetValue(DirectionProperty, value);
-            }
+            get => (float)GetValue(TrackThicknessProperty);
+            set => SetValue(TrackThicknessProperty, value);
         }
 
         /// <summary>
-        /// The property to get/set the size of the thumb object.
+        /// The thickness of the thumb.
         /// </summary>
-        /// <exception cref="InvalidOperationException">Throw when ThumbSize is null.</exception>
-        /// <example>
-        /// <code>
-        /// ScrollBar scroll;
-        /// try
-        /// {
-        ///     scroll.ThumbSize = new Size(500, 10, 0);
-        /// }
-        /// catch(InvalidOperationException e)
-        /// {
-        ///     Tizen.Log.Error(LogTag, "Failed to set ThumbSize value : " + e.Message);
-        /// }
-        /// </code>
-        /// </example>
-        /// <since_tizen> 6 </since_tizen>
-        public Size ThumbSize
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public float ThumbThickness
         {
-            get
-            {
-                if (Style.Thumb.Size == null)
-                {
-                    Style.Thumb.Size = new Size();
-                }
-                return Style.Thumb.Size;
-            }
-            set
-            {
-                if (Style.Thumb.Size == null)
-                {
-                    Style.Thumb.Size = new Size();
-                }
-                if (thumbImage != null)
-                {
-                    Style.Thumb.Size.Width = value.Width;
-                    Style.Thumb.Size.Height = value.Height;
-                    RelayoutRequest();
-                }
-            }
+            get => (float)GetValue(ThumbThicknessProperty);
+            set => SetValue(ThumbThicknessProperty, value);
         }
 
         /// <summary>
-        /// The property to get/set the image URL of the track object.
+        /// The color of the track part.
         /// </summary>
-        /// <since_tizen> 6 </since_tizen>
-        public string TrackImageURL
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public Color TrackColor
         {
-            get
-            {
-                return Style.Track.ResourceUrl.All;
-            }
-            set
-            {
-                if (trackImage != null)
-                {
-                    if (Style.Track.ResourceUrl == null)
-                    {
-                        Style.Track.ResourceUrl = new StringSelector();
-                    }
-                    Style.Track.ResourceUrl.All = value;
-                }
-                RelayoutRequest();
-            }
+            get => (Color)GetValue(TrackColorProperty);
+            set => SetValue(TrackColorProperty, value);
         }
 
         /// <summary>
-        /// The property to get/set the color of the track object.
+        /// The color of the thumb part.
         /// </summary>
-        /// <since_tizen> 6 </since_tizen>
-        public Color TrackColor
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public Color ThumbColor
         {
-            get
-            {
-                return Style.Track.BackgroundColor?.All;
-            }
-            set
-            {
-                if (Style.Track.BackgroundColor == null)
-                {
-                    Style.Track.BackgroundColor = new ColorSelector { All = value };
-                }
-                else
-                {
-                    Style.Track.BackgroundColor.All = value;
-                }
-                RelayoutRequest();
-            }
+            get => (Color)GetValue(ThumbColorProperty);
+            set => SetValue(ThumbColorProperty, value);
         }
 
         /// <summary>
-        /// The property to get/set the color of the thumb object.
+        /// The padding value of the track.
         /// </summary>
-        /// <since_tizen> 6 </since_tizen>
-        public Color ThumbColor
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public Extents TrackPadding
         {
-            get
+            get => (Extents)GetValue(TrackPaddingProperty);
+            set => SetValue(TrackPaddingProperty, value);
+        }
+
+        #endregion Properties
+
+
+        #region Methods
+
+        /// <inheritdoc/>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public override void Initialize(float contentLength, float viewportLength, float currentPosition, bool isHorizontal = false)
+        {
+            if (isHorizontal)
             {
-                return Style.Thumb.BackgroundColor?.All;
+                calculator = new HorizontalCalculator(contentLength > 0.0f ? contentLength : 0.0f, viewportLength, currentPosition);
             }
-            set
+            else
             {
-                if(Style.Thumb.BackgroundColor == null)
+                calculator = new VerticalCalculator(contentLength > 0.0f ? contentLength : 0.0f, viewportLength, currentPosition);
+            }
+
+            thumbPositionAnimation?.Stop();
+            thumbPositionAnimation = null;
+
+            thumbSizeAnimation?.Stop();
+            thumbSizeAnimation = null;
+
+            Size trackSize = calculator.CalculateTrackSize(TrackThickness, containerSize, TrackPadding);
+            Vector2 trackPosition = calculator.CalculateTrackPosition(TrackPadding);
+            Size thumbSize = calculator.CalculateThumbSize(ThumbThickness, trackSize);
+            Vector2 thumbPosition = calculator.CalculateThumbPosition(trackSize, thumbSize, TrackPadding);
+
+            if (trackVisual == null)
+            {
+                trackVisual = new ColorVisual
                 {
-                    Style.Thumb.BackgroundColor = new ColorSelector { All = value };
-                }
-                else
+                    SuppressUpdateVisual = true,
+                    Color = TrackColor,
+                    SizePolicy = VisualTransformPolicyType.Absolute,
+                    Origin = calculator.CalculatorTrackAlign(),
+                    AnchorPoint = calculator.CalculatorTrackAlign(),
+                    Size = trackSize,
+                    Position = trackPosition,
+                };
+
+                AddVisual("Track", trackVisual);
+            }
+            else
+            {
+                trackVisual.Size = trackSize;
+                trackVisual.Position = trackPosition;
+                trackVisual.UpdateVisual(true);
+            }
+
+            if (thumbVisual == null)
+            {
+                thumbVisual = new ColorVisual
                 {
-                    Style.Thumb.BackgroundColor.All = value;
-                }
-                RelayoutRequest();
+                    SuppressUpdateVisual = true,
+                    MixColor = ThumbColor,
+                    SizePolicy = VisualTransformPolicyType.Absolute,
+                    Origin = calculator.CalculatorThumbAlign(),
+                    AnchorPoint = calculator.CalculatorThumbAlign(),
+                    Opacity = calculator.CalculateThumbVisibility() ? 1.0f : 0.0f,
+                    Size = thumbSize,
+                    Position = thumbPosition,
+                };
+
+                AddVisual("Thumb", thumbVisual);
+            }
+            else
+            {
+                thumbVisual.Size = thumbSize;
+                thumbVisual.Position = thumbPosition;
+                thumbVisual.UpdateVisual(true);
             }
         }
 
-        /// <summary>
-        /// The property to get/set the max value of the ScrollBar.
-        /// </summary>
-        /// <since_tizen> 6 </since_tizen>
-        public int MaxValue
+        /// <inheritdoc/>
+        /// <remarks>Please note that, for now, only alpha functions created with BuiltinFunctions are valid when animating. Otherwise, it will be treated as a linear alpha function. </remarks>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public override void Update(float contentLength, float position, uint durationMs = 0, AlphaFunction alphaFunction = null)
         {
-            get
+            if (calculator == null)
             {
-                return (int)GetValue(MaxValueProperty);
+                return;
             }
-            set
+
+            calculator.contentLength = contentLength > 0.0f ? contentLength : 0.0f;
+            previousPosition = calculator.currentPosition;
+            calculator.currentPosition = position;
+
+            thumbVisual.Size = calculator.CalculateThumbSize(ThumbThickness, trackVisual.Size);
+            thumbVisual.Position = calculator.CalculateThumbScrollPosition(trackVisual.Size, thumbVisual.Position, TrackPadding);
+            thumbVisual.Opacity = calculator.CalculateThumbVisibility() ? 1.0f : 0.0f;
+
+            if (durationMs == 0)
             {
-                SetValue(MaxValueProperty, value);
+                thumbVisual.UpdateVisual(true);
+
+                return;
             }
+
+            // TODO Support non built-in alpha function for visual trainsition in DALi.
+            AlphaFunction.BuiltinFunctions builtinAlphaFunction = alphaFunction?.GetBuiltinFunction() ?? AlphaFunction.BuiltinFunctions.Default;
+
+            thumbPositionAnimation?.Stop();
+            thumbPositionAnimation = AnimateVisual(thumbVisual, "position", thumbVisual.Position, 0, (int)durationMs, builtinAlphaFunction);
+            thumbPositionAnimation.Play();
+
+            thumbSizeAnimation?.Stop();
+            thumbSizeAnimation = AnimateVisual(thumbVisual, "size", thumbVisual.Size, 0, (int)durationMs, builtinAlphaFunction);
+            thumbSizeAnimation.Play();
         }
 
-        /// <summary>
-        /// The property to get/set the min value of the ScrollBar.
-        /// </summary>
-        /// <since_tizen> 6 </since_tizen>
-        public int MinValue
+        /// <inheritdoc/>
+        /// <remarks>Please note that, for now, only alpha functions created with BuiltinFunctions are valid when animating. Otherwise, it will be treated as a linear alpha function. </remarks>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public override void ScrollTo(float position, uint durationMs = 0, AlphaFunction alphaFunction = null)
         {
-            get
+            if (mScrollEnabled == false)
             {
-                return (int)GetValue(MinValueProperty);
+                return;
             }
-            set
+
+            if (calculator == null)
+            {
+                return;
+            }
+
+            previousPosition = calculator.currentPosition;
+            calculator.currentPosition = position;
+            thumbVisual.Position = calculator.CalculateThumbScrollPosition(trackVisual.Size, thumbVisual.Position, TrackPadding);
+
+            if (durationMs == 0)
             {
-                SetValue(MinValueProperty, value);
+                thumbVisual.UpdateVisual(true);
+
+                return;
             }
+
+            // TODO Support non built-in alpha function for visual trainsition in DALi.
+            AlphaFunction.BuiltinFunctions builtinAlphaFunction = alphaFunction?.GetBuiltinFunction() ?? AlphaFunction.BuiltinFunctions.Default;
+
+            thumbPositionAnimation?.Stop();
+            thumbPositionAnimation = AnimateVisual(thumbVisual, "position", thumbVisual.Position, 0, (int)durationMs, builtinAlphaFunction);
+            thumbPositionAnimation.Play();
         }
 
-        /// <summary>
-        /// The property to get/set the current value of the ScrollBar.
-        /// </summary>
-        /// <exception cref="ArgumentOutOfRangeException">Throw when Current value is less than Min value, or greater than Max value.</exception>
-        /// <example>
-        /// <code>
-        /// ScrollBar scroll;
-        /// scroll.MaxValue = 100;
-        /// scroll.MinValue = 0;
-        /// try
-        /// {
-        ///     scroll.CurrentValue = 50;
-        /// }
-        /// catch(ArgumentOutOfRangeException e)
-        /// {
-        ///     Tizen.Log.Error(LogTag, "Failed to set Current value : " + e.Message);
-        /// }
-        /// </code>
-        /// </example>
-        /// <since_tizen> 6 </since_tizen>
-        public int CurrentValue
+        /// <inheritdoc/>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public override void OnRelayout(Vector2 size, RelayoutContainer container)
         {
-            get
+            base.OnRelayout(size, container);
+
+            if (size.Width == containerSize.Width && size.Height == containerSize.Height)
             {
-                return (int)GetValue(CurrentValueProperty);
+                return;
             }
-            set
+
+            containerSize = new Size(size.Width, size.Height);
+
+            if (calculator == null)
             {
-                SetValue(CurrentValueProperty, value);
+                return;
             }
+
+            trackVisual.Size = calculator.CalculateTrackSize(TrackThickness, containerSize, TrackPadding);
+            trackVisual.Position = calculator.CalculateTrackPosition(TrackPadding);
+            thumbVisual.Size = calculator.CalculateThumbSize(ThumbThickness, trackVisual.Size);
+            thumbVisual.Position = calculator.CalculateThumbPosition(trackVisual.Size, thumbVisual.Size, TrackPadding);
+
+            trackVisual.UpdateVisual(true);
+            thumbVisual.UpdateVisual(true);
         }
 
-        /// <summary>
-        /// Property to set/get animation duration.
-        /// </summary>
-        /// <since_tizen> 6 </since_tizen>
-        public uint Duration
+        /// <inheritdoc/>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public override void ApplyStyle(ViewStyle viewStyle)
         {
-            get
-            {
-                return (uint)GetValue(DurationProperty);
-            }
-            set
+            base.ApplyStyle(viewStyle);
+
+            if (viewStyle is ScrollbarStyle scrollbarStyle)
             {
-                SetValue(DurationProperty, value);
+                // Apply essential look.
+                if (scrollbarStyle.TrackThickness == null) scrollbarStyle.TrackThickness = 6.0f;
+                if (scrollbarStyle.ThumbThickness == null) scrollbarStyle.ThumbThickness = 6.0f;
+                if (scrollbarStyle.TrackColor == null) scrollbarStyle.TrackColor = new Color(1.0f, 1.0f, 1.0f, 0.15f);
+                if (scrollbarStyle.ThumbColor == null) scrollbarStyle.ThumbColor = new Color(0.6f, 0.6f, 0.6f, 1.0f);
+                if (scrollbarStyle.TrackPadding == null) scrollbarStyle.TrackPadding = 4;
+                if (scrollbarStyle.WidthResizePolicy == null) scrollbarStyle.WidthResizePolicy = ResizePolicyType.FillToParent;
+                if (scrollbarStyle.HeightResizePolicy == null) scrollbarStyle.HeightResizePolicy = ResizePolicyType.FillToParent;
             }
         }
-        #endregion
 
-        /// <summary>
-        /// Method to set current value. The thumb object would move to the corresponding position with animation or not.
-        /// </summary>
-        /// <param name="currentValue">The special current value.</param>
-        /// <param name="EnableAnimation">Enable move with animation or not, the default value is true.</param>
-        /// <exception cref="ArgumentOutOfRangeException">Throw when current size is less than the min value, or greater than the max value.</exception>
-        /// <example>
-        /// <code>
-        /// ScrollBar scroll;
-        /// scroll.MinValue = 0;
-        /// scroll.MaxValue = 100;
-        /// try
-        /// {
-        ///     scroll.SetCurrentValue(50);
-        /// }
-        /// catch(ArgumentOutOfRangeException e)
-        /// {
-        ///     Tizen.Log.Error(LogTag, "Failed to set current value : " + e.Message);
-        /// }
-        /// </code>
-        /// </example>
-        /// <since_tizen> 6 </since_tizen>
-        public void SetCurrentValue(int currentValue, bool enableAnimation = true)
-        {
-            if (currentValue < minValue || currentValue > maxValue)
-            {
-                //TNLog.E("Current value is less than the Min value, or greater than the Max value. currentValue = " + currentValue + ";");
-                throw new ArgumentOutOfRangeException("Wrong Current value. It shoud be greater than the Min value, and less than the Max value!");
-            }
-
-            enableAni = enableAnimation;
-            CurrentValue = currentValue;
+        /// <inheritdoc/>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        protected override ViewStyle CreateViewStyle()
+        {
+            return new ScrollbarStyle();
         }
 
         /// <summary>
-        /// Dispose ScrollBar.
+        /// Update TrackThickness property of the scrollbar.
         /// </summary>
-        /// <param name="type">The DisposeTypes value.</param>
-        /// <since_tizen> 6 </since_tizen>
-        protected override void Dispose(DisposeTypes type)
+        /// <param name="thickness">The width of the track.</param>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        protected virtual void UpdateTrackThickness(float thickness)
         {
-            if (disposed)
+            if (trackVisual == null)
             {
                 return;
             }
 
-            if (type == DisposeTypes.Explicit)
-            {
-                //Called by User
-                //Release your own managed resources here.
-                //You should release all of your own disposable objects here.
-
-                Utility.Dispose(trackImage);
-                Utility.Dispose(thumbImage);
+            trackVisual.Size = calculator.CalculateTrackSize(thickness, containerSize, TrackPadding);
+            trackVisual.UpdateVisual(true);
+        }
 
-                if (scrollAniPlayer != null)
-                {
-                    scrollAniPlayer.Stop();
-                    scrollAniPlayer.Clear();
-                    scrollAniPlayer.Dispose();
-                    scrollAniPlayer = null;
-                }
+        /// <summary>
+        /// Update ThumbThickness property of the scrollbar.
+        /// </summary>
+        /// <param name="thickness">The width of the track.</param>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        protected virtual void UpdateThumbThickness(float thickness)
+        {
+            if (thumbVisual == null)
+            {
+                return;
             }
 
-            //Release your own unmanaged resources here.
-            //You should not access any managed member here except static instance.
-            //because the execution order of Finalizes is non-deterministic.
-            //Unreference this from if a static instance refer to this. 
-
-            //You must call base.Dispose(type) just before exit.
-            base.Dispose(type);
+            thumbVisual.Size = calculator.CalculateThumbSize(thickness, trackVisual.Size);
+            thumbVisual.UpdateVisual(true);
         }
 
         /// <summary>
-        /// Get Scrollbar style.
+        /// Update TrackColor property of the scrollbar.
         /// </summary>
-        /// <since_tizen> 6 </since_tizen>
-        /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
+        /// <param name="color">The color of the track.</param>
         [EditorBrowsable(EditorBrowsableState.Never)]
-        protected override ViewStyle GetViewStyle()
+        protected virtual void UpdateTrackColor(Color color)
         {
-            return new ScrollBarStyle();
+            if (trackVisual == null)
+            {
+                return;
+            }
+
+            trackVisual.MixColor = color;
+            trackVisual.UpdateVisual(true);
         }
 
         /// <summary>
-        /// Theme change callback when theme is changed, this callback will be trigger.
+        /// Update ThumbColor property of the scrollbar.
         /// </summary>
-        /// <since_tizen> 6 </since_tizen>
-        /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
+        /// <param name="color">The color of the thumb.</param>
         [EditorBrowsable(EditorBrowsableState.Never)]
-        protected override void OnThemeChangedEvent(object sender, StyleManager.ThemeChangeEventArgs e)
+        protected virtual void UpdateThumbColor(Color color)
         {
-            ScrollBarStyle tempStyle = StyleManager.Instance.GetAttributes(style) as ScrollBarStyle;
-            if (tempStyle != null)
+            if (thumbVisual == null)
             {
-                Style.CopyFrom(tempStyle);
-                UpdateValue();
+                return;
             }
+
+            thumbVisual.MixColor = color;
+            thumbVisual.UpdateVisual(true);
         }
 
-        private void Initialize()
+        /// <summary>
+        /// Update TrackPadding property of the scrollbar.
+        /// </summary>
+        /// <param name="trackPadding">The padding of the track.</param>
+        protected virtual void UpdateTrackPadding(Extents trackPadding)
         {
-            this.Focusable = false;
-
-            trackImage = new ImageView
+            if (calculator == null)
             {
-                Focusable = false,
-                WidthResizePolicy = ResizePolicyType.FillToParent,
-                HeightResizePolicy = ResizePolicyType.FillToParent,
-                PositionUsesPivotPoint = true,
-                ParentOrigin = Tizen.NUI.ParentOrigin.CenterLeft,
-                PivotPoint = Tizen.NUI.PivotPoint.CenterLeft
-            };
-            this.Add(trackImage);
-            trackImage.ApplyStyle(Style.Track);
-
-            thumbImage = new ImageView
-            {
-                Focusable = false,
-                WidthResizePolicy = ResizePolicyType.Fixed,
-                HeightResizePolicy = ResizePolicyType.Fixed,
-                PositionUsesPivotPoint = true,
-                ParentOrigin = Tizen.NUI.ParentOrigin.CenterLeft,
-                PivotPoint = Tizen.NUI.PivotPoint.CenterLeft
-            };
-            this.Add(thumbImage);
-            thumbImage.ApplyStyle(Style.Thumb);
-
-            scrollAniPlayer = new Animation(334);
-            scrollAniPlayer.DefaultAlphaFunction = new AlphaFunction(AlphaFunction.BuiltinFunctions.Linear);
+                return;
+            }
 
-            thumbImagePosX = 0;
-            thumbImagePosY = 0;
-            LayoutDirectionChanged += OnLayoutDirectionChanged;
-        }
+            trackVisual.Size = calculator.CalculateTrackSize(TrackThickness, containerSize, trackPadding);
+            trackVisual.Position = calculator.CalculateTrackPosition(trackPadding);
+            thumbVisual.Size = calculator.CalculateThumbSize(ThumbThickness, trackVisual.Size);
+            thumbVisual.Position = calculator.CalculateThumbPaddingPosition(trackVisual.Size, thumbVisual.Size, thumbVisual.Position, trackPadding);
 
-        private void OnLayoutDirectionChanged(object sender, LayoutDirectionChangedEventArgs e)
-        {
-            RelayoutRequest();
+            trackVisual.UpdateVisual(true);
+            thumbVisual.UpdateVisual(true);
         }
 
-        private void UpdateValue()
+        /// <inheritdoc/>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public override bool ScrollEnabled
         {
-            if (minValue >= maxValue || curValue < minValue || curValue > maxValue) return;
-
-            float width = (float)Size2D.Width;
-            float height = (float)Size2D.Height;
-            float thumbW = 0.0f;
-            float thumbH = 0.0f;
-            if (Style.Thumb.Size == null)
+            get
             {
-                return;
+                return mScrollEnabled;
             }
-            else
+            set
             {
-                thumbW = Style.Thumb.Size.Width;
-                thumbH = Style.Thumb.Size.Height;
+                if (value != mScrollEnabled)
+                {
+                    mScrollEnabled = value;
+                }
             }
-            float ratio = (float)(curValue - minValue) / (float)(maxValue - minValue);
+        }
 
-            if (Style.Direction == DirectionType.Horizontal)
+        /// <inheritdoc/>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public override Position ScrollPosition
+        {
+            get
             {
-                if (LayoutDirection == ViewLayoutDirectionType.RTL)
+                if (calculator == null)
                 {
-                    ratio = 1.0f - ratio;
+                    return new Position(0.0f, 0.0f);
                 }
 
-                float posX = ratio * (width - thumbW);
-                float posY = (height - thumbH) / 2.0f;
+                float length = Math.Min(Math.Max(calculator.currentPosition, 0.0f), calculator.contentLength - calculator.visibleLength);
 
-                thumbImagePosX = posX;
-                if (null != scrollAniPlayer)
+                if (calculator is HorizontalCalculator)
                 {
-                    scrollAniPlayer.Stop();
-                }
-
-                if (!enableAni)
-                {
-                    thumbImage.Position = new Position(posX, posY, 0);
+                    return new Position(length, 0.0f);
                 }
                 else
                 {
-                    if (null != scrollAniPlayer)
-                    {
-                        scrollAniPlayer.Clear();
-                        scrollAniPlayer.AnimateTo(thumbImage, "PositionX", posX);
-                        scrollAniPlayer.Play();
-                    }
+                    return new Position(0.0f, length);
                 }
             }
-            else
+        }
+
+        /// <inheritdoc/>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public override Position ScrollCurrentPosition
+        {
+            get
             {
-                float posX = (width - thumbW) / 2.0f;
-                float posY = ratio * (height - thumbH);
+                if (calculator == null)
+                {
+                    return new Position(0.0f, 0.0f);
+                }
 
-                thumbImagePosY = posY;
-                if (null != scrollAniPlayer)
+                float length = Math.Min(Math.Max(calculator.currentPosition, 0.0f), calculator.contentLength - calculator.visibleLength);
+
+                if (thumbPositionAnimation != null)
                 {
-                    scrollAniPlayer.Stop();
+                    float progress = thumbPositionAnimation.CurrentProgress;
+                    float previousLength = Math.Min(Math.Max(previousPosition, 0.0f), calculator.contentLength - calculator.visibleLength);
+
+                    length = ((1.0f - progress) * previousLength) + (progress * length);
                 }
 
-                if (!enableAni)
+                if (calculator is HorizontalCalculator)
                 {
-                    thumbImage.Position = new Position(posX, posY, 0);
+                    return new Position(length, 0.0f);
                 }
                 else
                 {
-                    if (null != scrollAniPlayer)
-                    {
-                        scrollAniPlayer.Clear();
-                        scrollAniPlayer.AnimateTo(thumbImage, "PositionY", posY);
-                        scrollAniPlayer.Play();
-                    }
+                    return new Position(0.0f, length);
                 }
             }
+        }
+
+        #endregion Methods
+
+
+        #region Classes
+
+        private abstract class Calculator
+        {
+            public float contentLength;
+            public float visibleLength;
+            public float currentPosition;
 
-            if (enableAni) enableAni = false;
+            public Calculator(float contentLength, float visibleLength, float currentPosition)
+            {
+                this.contentLength = contentLength;
+                this.visibleLength = visibleLength;
+                this.currentPosition = currentPosition;
+            }
+
+            public bool CalculateThumbVisibility()
+            {
+                return contentLength > visibleLength;
+            }
+
+            public abstract Visual.AlignType CalculatorTrackAlign();
+            public abstract Visual.AlignType CalculatorThumbAlign();
+            public abstract Size CalculateTrackSize(float thickness, Size containerSize, Extents trackPadding);
+            public abstract Vector2 CalculateTrackPosition(Extents trackPadding);
+            public abstract Size CalculateThumbSize(float thickness, Size trackSize);
+            public abstract Vector2 CalculateThumbPosition(Size trackSize, Size thumbSize, Extents trackPadding);
+            public abstract Vector2 CalculateThumbPaddingPosition(Size trackSize, Size thumbSize, Vector2 thumbCurrentPosition, Extents trackPadding);
+            public abstract Vector2 CalculateThumbScrollPosition(Size trackSize, Vector2 thumbCurrentPosition, Extents trackPadding);
         }
 
-        private DirectionType CurrentDirection()
+        private class HorizontalCalculator : Calculator
         {
-            DirectionType dir = DirectionType.Horizontal;
-            if (null != Style.Direction)
+            public HorizontalCalculator(float contentLength, float visibleLength, float currentPosition) : base(contentLength, visibleLength, currentPosition)
+            {
+            }
+
+            public override Visual.AlignType CalculatorTrackAlign()
             {
-                dir = Style.Direction.Value;
+                return Visual.AlignType.BottomCenter;
+            }
+
+            public override Visual.AlignType CalculatorThumbAlign()
+            {
+                return Visual.AlignType.BottomBegin;
+            }
+
+            public override Size CalculateTrackSize(float thickness, Size containerSize, Extents trackPadding)
+            {
+                return new Size(containerSize.Width - trackPadding?.Start ?? 0 - trackPadding?.End ?? 0, thickness);
+            }
+
+            public override Vector2 CalculateTrackPosition(Extents trackPadding)
+            {
+                return new Vector2(0, -trackPadding?.Bottom ?? 0);
+            }
+
+            public override Size CalculateThumbSize(float thickness, Size trackSize)
+            {
+                return new Size(trackSize.Width * visibleLength / contentLength, thickness);
+            }
+
+            public override Vector2 CalculateThumbPosition(Size trackSize, Size thumbSize, Extents trackPadding)
+            {
+                float padding = ((trackSize.Height - thumbSize.Height) / 2.0f) + trackPadding?.Bottom ?? 0;
+                float pos = Math.Min(Math.Max(currentPosition, 0.0f), contentLength - visibleLength);
+                return new Vector2(trackPadding?.Start ?? 0 + trackSize.Width * pos / contentLength, -padding);
+            }
+
+            public override Vector2 CalculateThumbPaddingPosition(Size trackSize, Size thumbSize, Vector2 thumbCurrentPosition, Extents trackPadding)
+            {
+                float padding = ((trackSize.Height - thumbSize.Height) / 2.0f) + trackPadding?.Bottom ?? 0;
+                return new Vector2(thumbCurrentPosition.X, -padding);
+            }
+
+            public override Vector2 CalculateThumbScrollPosition(Size trackSize, Vector2 thumbCurrentPosition, Extents trackPadding)
+            {
+                float pos = Math.Min(Math.Max(currentPosition, 0.0f), contentLength - visibleLength);
+                return new Vector2(trackPadding?.Start ?? 0 + trackSize.Width * pos / contentLength, thumbCurrentPosition.Y);
             }
-            return dir;
         }
 
-        private int CalculateCurrentValue(float offset, DirectionType dir)
+        private class VerticalCalculator : Calculator
         {
-            if (dir == DirectionType.Horizontal)
+            public VerticalCalculator(float contentLength, float visibleLength, float currentPosition) : base(contentLength, visibleLength, currentPosition)
             {
-                thumbImagePosX += offset;
-                if (thumbImagePosX < 0)
-                {
-                    thumbImage.PositionX = 0;
-                    curValue = minValue;
-                }
-                else if (thumbImagePosX > Size2D.Width - thumbImage.Size2D.Width)
-                {
-                    thumbImage.PositionX = Size2D.Width - thumbImage.Size2D.Width;
-                    curValue = maxValue;
-                }
-                else
-                {
-                    thumbImage.PositionX = thumbImagePosX;
-                    curValue = (int)((thumbImagePosX / (float)(Size2D.Width - thumbImage.Size2D.Width)) * (float)(maxValue - minValue) + 0.5f);
-                }
             }
-            else
+
+            public override Visual.AlignType CalculatorTrackAlign()
             {
-                thumbImagePosY += offset;
-                if (thumbImagePosY < 0)
-                {
-                    thumbImage.PositionY = 0;
-                    curValue = minValue;
-                }
-                else if (thumbImagePosY > Size2D.Height - thumbImage.Size2D.Height)
-                {
-                    thumbImage.PositionY = Size2D.Height - thumbImage.Size2D.Height;
-                    curValue = maxValue;
-                }
-                else
-                {
-                    thumbImage.PositionY = thumbImagePosY;
-                    curValue = (int)((thumbImagePosY / (float)(Size2D.Height - thumbImage.Size2D.Height)) * (float)(maxValue - minValue) + 0.5f);
-                }
+                return Visual.AlignType.CenterEnd;
+            }
+
+            public override Visual.AlignType CalculatorThumbAlign()
+            {
+                return Visual.AlignType.TopEnd;
             }
 
-            return curValue;
+            public override Size CalculateTrackSize(float thickness, Size containerSize, Extents trackPadding)
+            {
+                return new Size(thickness, containerSize.Height - trackPadding?.Top ?? 0 - trackPadding?.Bottom ?? 0);
+            }
+
+            public override Vector2 CalculateTrackPosition(Extents trackPadding)
+            {
+                return new Vector2(-trackPadding?.End ?? 0, 0);
+            }
+
+            public override Size CalculateThumbSize(float thickness, Size trackSize)
+            {
+                return new Size(thickness, trackSize.Height * visibleLength / contentLength);
+            }
+
+            public override Vector2 CalculateThumbPosition(Size trackSize, Size thumbSize, Extents trackPadding)
+            {
+                float padding = ((trackSize.Width - thumbSize.Width) / 2.0f) + trackPadding?.End ?? 0;
+                float pos = Math.Min(Math.Max(currentPosition, 0.0f), contentLength - visibleLength);
+                return new Vector2(-padding, trackPadding?.Top ?? 0 + trackSize.Height * pos / contentLength);
+            }
+
+            public override Vector2 CalculateThumbPaddingPosition(Size trackSize, Size thumbSize, Vector2 thumbCurrentPosition, Extents trackPadding)
+            {
+                float padding = ((trackSize.Width - thumbSize.Width) / 2.0f) + trackPadding?.End ?? 0;
+                return new Vector2(-padding, thumbCurrentPosition.Y);
+            }
+
+            public override Vector2 CalculateThumbScrollPosition(Size trackSize, Vector2 thumbPosition, Extents trackPadding)
+            {
+                float pos = Math.Min(Math.Max(currentPosition, 0.0f), contentLength - visibleLength);
+                return new Vector2(thumbPosition.X, trackPadding?.Top ?? 0 + trackSize.Height * pos / contentLength);
+            }
         }
+
+        #endregion Classes
     }
 }