[NUI] Scrollbar uses View instead Visual since blinking issue (#2735)
[platform/core/csapi/tizenfx.git] / src / Tizen.NUI.Components / Controls / Scrollbar.cs
1 /*
2  * Copyright(c) 2020 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17 using System;
18 using System.ComponentModel;
19 using System.Diagnostics;
20 using Tizen.NUI.BaseComponents;
21 using Tizen.NUI.Binding;
22
23 namespace Tizen.NUI.Components
24 {
25     // Represents padding data : Start, End, Top, Bottom
26     using PaddingType = ValueTuple<ushort, ushort, ushort, ushort>;
27
28     /// <summary>
29     /// The Scrollbar is a component that contains track and thumb to indicate the current scrolled position of a scrollable object.
30     /// </summary>
31     [EditorBrowsable(EditorBrowsableState.Never)]
32     public class Scrollbar : ScrollbarBase
33     {
34         #region Fields
35
36         /// <summary>Bindable property of TrackThickness</summary>
37         [EditorBrowsable(EditorBrowsableState.Never)]
38         public static readonly BindableProperty TrackThicknessProperty = BindableProperty.Create(nameof(TrackThickness), typeof(float), typeof(Scrollbar), default(float), propertyChanged: (bindable, oldValue, newValue) =>
39         {
40             var instance = ((Scrollbar)bindable);
41             var thickness = (float?)newValue;
42
43             instance.scrollbarStyle.TrackThickness = thickness;
44             instance.UpdateTrackThickness(thickness ?? 0);
45         },
46         defaultValueCreator: (bindable) =>
47         {
48             return ((Scrollbar)bindable).scrollbarStyle.TrackThickness ?? 0;
49         });
50
51         /// <summary>Bindable property of ThumbThickness</summary>
52         [EditorBrowsable(EditorBrowsableState.Never)]
53         public static readonly BindableProperty ThumbThicknessProperty = BindableProperty.Create(nameof(ThumbThickness), typeof(float), typeof(Scrollbar), default(float), propertyChanged: (bindable, oldValue, newValue) =>
54         {
55             var instance = ((Scrollbar)bindable);
56             var thickness = (float?)newValue;
57
58             instance.scrollbarStyle.ThumbThickness = thickness;
59             instance.UpdateThumbThickness(thickness ?? 0);
60         },
61         defaultValueCreator: (bindable) =>
62         {
63             return ((Scrollbar)bindable).scrollbarStyle.ThumbThickness ?? 0;
64         });
65
66         /// <summary>Bindable property of TrackColor</summary>
67         [EditorBrowsable(EditorBrowsableState.Never)]
68         public static readonly BindableProperty TrackColorProperty = BindableProperty.Create(nameof(TrackColor), typeof(Color), typeof(Scrollbar), null, propertyChanged: (bindable, oldValue, newValue) =>
69         {
70             var instance = ((Scrollbar)bindable);
71             var color = (Color)newValue;
72
73             instance.scrollbarStyle.TrackColor = color;
74             instance.UpdateTrackColor(color);
75         },
76         defaultValueCreator: (bindable) =>
77         {
78             return ((Scrollbar)bindable).scrollbarStyle.TrackColor;
79         });
80
81         /// <summary>Bindable property of ThumbColor</summary>
82         [EditorBrowsable(EditorBrowsableState.Never)]
83         public static readonly BindableProperty ThumbColorProperty = BindableProperty.Create(nameof(ThumbColor), typeof(Color), typeof(Scrollbar), null, propertyChanged: (bindable, oldValue, newValue) =>
84         {
85             var instance = ((Scrollbar)bindable);
86             var color = (Color)newValue;
87
88             instance.scrollbarStyle.ThumbColor = color;
89             instance.UpdateThumbColor(color);
90         },
91         defaultValueCreator: (bindable) =>
92         {
93             return ((Scrollbar)bindable).scrollbarStyle.ThumbColor;
94         });
95
96         /// <summary>Bindable property of TrackPadding</summary>
97         [EditorBrowsable(EditorBrowsableState.Never)]
98         public static readonly BindableProperty TrackPaddingProperty = BindableProperty.Create(nameof(TrackPadding), typeof(Extents), typeof(Scrollbar), null, propertyChanged: (bindable, oldValue, newValue) =>
99         {
100             var instance = ((Scrollbar)bindable);
101             var trackPadding = (Extents)newValue;
102
103             instance.scrollbarStyle.TrackPadding = trackPadding;
104             instance.UpdateTrackPadding(trackPadding);
105         },
106         defaultValueCreator: (bindable) =>
107         {
108             return ((Scrollbar)bindable).scrollbarStyle.TrackPadding;
109         });
110
111         private View trackView;
112         private View thumbView;
113         private Animation thumbPositionAnimation;
114         private Animation thumbSizeAnimation;
115         private Animation opacityAnimation;
116         private Calculator calculator;
117         private Size containerSize = new Size(0, 0);
118         private ScrollbarStyle scrollbarStyle => ViewStyle as ScrollbarStyle;
119         private bool mScrollEnabled = true;
120         private float previousPosition;
121
122         #endregion Fields
123
124
125         #region Constructors
126
127         /// <summary>
128         /// Create an empty Scrollbar.
129         /// </summary>
130         public Scrollbar() : base()
131         {
132         }
133
134         /// <summary>
135         /// Create a Scrollbar and initialize with properties.
136         /// </summary>
137         /// <param name="contentLength">The length of the scrollable content area.</param>
138         /// <param name="viewportLength">The length of the viewport representing the amount of visible content.</param>
139         /// <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>
140         /// <param name="isHorizontal">Whether the direction of scrolling is horizontal or not. It is vertical by default.</param>
141         [EditorBrowsable(EditorBrowsableState.Never)]
142         public Scrollbar(float contentLength, float viewportLength, float currentPosition, bool isHorizontal = false) : this()
143         {
144             Initialize(contentLength, viewportLength, currentPosition, isHorizontal);
145         }
146
147         /// <summary>
148         /// Create an empty Scrollbar with a ScrollbarStyle instance to set style properties.
149         /// </summary>
150         [EditorBrowsable(EditorBrowsableState.Never)]
151         public Scrollbar(ScrollbarStyle style) : base(style)
152         {
153         }
154
155         /// <summary>
156         /// Static constructor to initialize bindable properties when loading.
157         /// </summary>
158         static Scrollbar()
159         {
160         }
161
162         #endregion Constructors
163
164
165         #region Properties
166
167         /// <summary>
168         /// Return a copied Style instance of Scrollbar
169         /// </summary>
170         /// <remarks>
171         /// It returns copied Style instance and changing it does not effect to the Scrollbar.
172         /// Style setting is possible by using constructor or the function of ApplyStyle(ViewStyle viewStyle)
173         /// </remarks>
174         [EditorBrowsable(EditorBrowsableState.Never)]
175         public new ScrollbarStyle Style
176         {
177             get
178             {
179                 var result = new ScrollbarStyle(scrollbarStyle);
180                 result.CopyPropertiesFromView(this);
181                 return result;
182             }
183         }
184
185         /// <summary>
186         /// The thickness of the track.
187         /// </summary>
188         [EditorBrowsable(EditorBrowsableState.Never)]
189         public float TrackThickness
190         {
191             get => (float)GetValue(TrackThicknessProperty);
192             set => SetValue(TrackThicknessProperty, value);
193         }
194
195         /// <summary>
196         /// The thickness of the thumb.
197         /// </summary>
198         [EditorBrowsable(EditorBrowsableState.Never)]
199         public float ThumbThickness
200         {
201             get => (float)GetValue(ThumbThicknessProperty);
202             set => SetValue(ThumbThicknessProperty, value);
203         }
204
205         /// <summary>
206         /// The color of the track part.
207         /// </summary>
208         [EditorBrowsable(EditorBrowsableState.Never)]
209         public Color TrackColor
210         {
211             get => (Color)GetValue(TrackColorProperty);
212             set => SetValue(TrackColorProperty, value);
213         }
214
215         /// <summary>
216         /// The color of the thumb part.
217         /// </summary>
218         [EditorBrowsable(EditorBrowsableState.Never)]
219         public Color ThumbColor
220         {
221             get => (Color)GetValue(ThumbColorProperty);
222             set => SetValue(ThumbColorProperty, value);
223         }
224
225         /// <summary>
226         /// The padding value of the track.
227         /// Note that when the scrollbar is for vertical direction, Start value is ignored.
228         /// In case of horizontal direction, Top value is ignored.
229         /// </summary>
230         [EditorBrowsable(EditorBrowsableState.Never)]
231         public Extents TrackPadding
232         {
233             get => (Extents)GetValue(TrackPaddingProperty);
234             set => SetValue(TrackPaddingProperty, value);
235         }
236
237         #endregion Properties
238
239
240         #region Methods
241
242         /// <inheritdoc/>
243         [EditorBrowsable(EditorBrowsableState.Never)]
244         public override void Initialize(float contentLength, float viewportLength, float currentPosition, bool isHorizontal = false)
245         {
246             if (isHorizontal)
247             {
248                 calculator = new HorizontalCalculator(contentLength > 0.0f ? contentLength : 0.0f, viewportLength, currentPosition);
249             }
250             else
251             {
252                 calculator = new VerticalCalculator(contentLength > 0.0f ? contentLength : 0.0f, viewportLength, currentPosition);
253             }
254
255             thumbPositionAnimation?.Stop();
256             thumbPositionAnimation = null;
257
258             thumbSizeAnimation?.Stop();
259             thumbSizeAnimation = null;
260
261             opacityAnimation?.Stop();
262             opacityAnimation = null;
263
264             PaddingType ensuredPadding = EnsurePadding(TrackPadding);
265             var trackSize = calculator.CalculateTrackSize(TrackThickness, containerSize, ensuredPadding);
266             var trackPosition = calculator.CalculateTrackPosition(ensuredPadding);
267             var thumbSize = calculator.CalculateThumbSize(ThumbThickness, trackSize);
268             var thumbPosition = calculator.CalculateThumbPosition(trackSize, thumbSize, ensuredPadding);
269
270             trackView?.Unparent();
271             trackView = new View()
272             {
273                 BackgroundColor = TrackColor,
274                 ParentOrigin = calculator.CalculatorTrackAlign(),
275                 PivotPoint = calculator.CalculatorTrackAlign(),
276                 Size = trackSize,
277                 Position = trackPosition,
278                 PositionUsesPivotPoint = true,
279             };
280             Add(trackView);
281
282             thumbView?.Unparent();
283             thumbView = new View()
284             {
285                 BackgroundColor = ThumbColor,
286                 ParentOrigin = calculator.CalculatorThumbAlign(),
287                 PivotPoint = calculator.CalculatorThumbAlign(),
288                 Size = thumbSize,
289                 Position = thumbPosition,
290                 PositionUsesPivotPoint = true,
291             };
292             Add(thumbView);
293
294             Opacity = calculator.IsScrollable() ? 1.0f : 0.0f;
295         }
296
297         /// <inheritdoc/>
298         /// <exception cref="InvalidOperationException">Thrown when the scrollabr not yet initialized.</exception>
299         [EditorBrowsable(EditorBrowsableState.Never)]
300         public override void Update(float contentLength, float viewportLength, float position, uint durationMs = 0, AlphaFunction alphaFunction = null)
301         {
302             if (calculator == null)
303             {
304                 throw new InvalidOperationException("Scrollbar is not initialized. Please call Initialize() first.");
305             }
306
307             calculator.visibleLength = viewportLength;
308             Update(contentLength, position, durationMs, alphaFunction);
309         }
310
311         /// <inheritdoc/>
312         /// <exception cref="InvalidOperationException">Thrown when the scrollabr not yet initialized.</exception>
313         [EditorBrowsable(EditorBrowsableState.Never)]
314         public override void Update(float contentLength, float position, uint durationMs = 0, AlphaFunction alphaFunction = null)
315         {
316             if (calculator == null)
317             {
318                 throw new InvalidOperationException("Scrollbar is not initialized. Please call Initialize() first.");
319             }
320
321             calculator.contentLength = contentLength > 0.0f ? contentLength : 0.0f;
322             calculator.currentPosition = position;
323
324             float newOpacity = calculator.IsScrollable() ? 1.0f : 0.0f;
325             bool opacityChanged = (int)Opacity != (int)newOpacity;
326
327             var thumbSize = calculator.CalculateThumbSize(ThumbThickness, trackView.Size);
328             var thumbPosition = calculator.CalculateThumbScrollPosition(trackView.Size, thumbView.Position, EnsurePadding(TrackPadding));
329
330             if (durationMs == 0)
331             {
332                 thumbView.Position = thumbPosition;
333                 thumbView.Size = thumbSize;
334
335                 if (opacityChanged)
336                 {
337                     Opacity = newOpacity;
338                 }
339                 return;
340             }
341
342             EnsureThumbPositionAnimation().AnimateTo(thumbView, "Position", thumbPosition, 0, (int)durationMs, alphaFunction);
343             thumbPositionAnimation.Play();
344
345             EnsureThumbSizeAnimation().AnimateTo(thumbView, "Size", thumbSize, 0, (int)durationMs, alphaFunction);
346             thumbSizeAnimation.Play();
347
348             if (opacityChanged)
349             {
350                 EnsureOpacityAnimation().AnimateTo(this, "Opacity", newOpacity, 0, (int)durationMs, alphaFunction);
351                 opacityAnimation.Play();
352             }
353         }
354
355         /// <inheritdoc/>
356         /// <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>
357         [EditorBrowsable(EditorBrowsableState.Never)]
358         public override void ScrollTo(float position, uint durationMs = 0, AlphaFunction alphaFunction = null)
359         {
360             if (mScrollEnabled == false)
361             {
362                 return;
363             }
364
365             if (calculator == null)
366             {
367                 return;
368             }
369
370             previousPosition = calculator.currentPosition;
371             calculator.currentPosition = position;
372             var thumbPosition = calculator.CalculateThumbScrollPosition(trackView.Size, thumbView.Position, EnsurePadding(TrackPadding));
373
374             if (durationMs == 0)
375             {
376                 thumbView.Position = thumbPosition;
377                 return;
378             }
379
380             EnsureThumbPositionAnimation().AnimateTo(thumbView, "position", thumbPosition, 0, (int)durationMs, alphaFunction);
381             thumbPositionAnimation.Play();
382         }
383
384         /// <inheritdoc/>
385         [EditorBrowsable(EditorBrowsableState.Never)]
386         public override void OnRelayout(Vector2 size, RelayoutContainer container)
387         {
388             base.OnRelayout(size, container);
389
390             if (size.Width == containerSize.Width && size.Height == containerSize.Height)
391             {
392                 return;
393             }
394
395             containerSize = new Size(size.Width, size.Height);
396
397             if (calculator == null)
398             {
399                 return;
400             }
401
402             PaddingType ensuredPadding = EnsurePadding(TrackPadding);
403             trackView.Size = calculator.CalculateTrackSize(TrackThickness, containerSize, ensuredPadding);
404             trackView.Position = calculator.CalculateTrackPosition(ensuredPadding);
405             thumbView.Size = calculator.CalculateThumbSize(ThumbThickness, trackView.Size);
406             thumbView.Position = calculator.CalculateThumbPosition(trackView.Size, thumbView.Size, ensuredPadding);
407         }
408
409         /// <inheritdoc/>
410         [EditorBrowsable(EditorBrowsableState.Never)]
411         public override void ApplyStyle(ViewStyle viewStyle)
412         {
413             if (viewStyle is ScrollbarStyle scrollbarStyle)
414             {
415                 // Apply essential look.
416                 if (scrollbarStyle.TrackThickness == null) scrollbarStyle.TrackThickness = 6.0f;
417                 if (scrollbarStyle.ThumbThickness == null) scrollbarStyle.ThumbThickness = 6.0f;
418                 if (scrollbarStyle.TrackColor == null) scrollbarStyle.TrackColor = new Color(1.0f, 1.0f, 1.0f, 0.15f);
419                 if (scrollbarStyle.ThumbColor == null) scrollbarStyle.ThumbColor = new Color(0.6f, 0.6f, 0.6f, 1.0f);
420                 if (scrollbarStyle.TrackPadding == null) scrollbarStyle.TrackPadding = 4;
421                 if (scrollbarStyle.WidthResizePolicy == null) scrollbarStyle.WidthResizePolicy = ResizePolicyType.FillToParent;
422                 if (scrollbarStyle.HeightResizePolicy == null) scrollbarStyle.HeightResizePolicy = ResizePolicyType.FillToParent;
423             }
424
425             base.ApplyStyle(viewStyle);
426         }
427
428         /// <inheritdoc/>
429         [EditorBrowsable(EditorBrowsableState.Never)]
430         protected override ViewStyle CreateViewStyle()
431         {
432             return new ScrollbarStyle();
433         }
434
435         /// <summary>
436         /// Update TrackThickness property of the scrollbar.
437         /// </summary>
438         /// <param name="thickness">The width of the track.</param>
439         [EditorBrowsable(EditorBrowsableState.Never)]
440         protected virtual void UpdateTrackThickness(float thickness)
441         {
442             if (trackView == null)
443             {
444                 return;
445             }
446
447             trackView.Size = calculator.CalculateTrackSize(thickness, containerSize, EnsurePadding(TrackPadding));
448         }
449
450         /// <summary>
451         /// Update ThumbThickness property of the scrollbar.
452         /// </summary>
453         /// <param name="thickness">The width of the track.</param>
454         [EditorBrowsable(EditorBrowsableState.Never)]
455         protected virtual void UpdateThumbThickness(float thickness)
456         {
457             if (thumbView == null)
458             {
459                 return;
460             }
461
462             thumbView.Size = calculator.CalculateThumbSize(thickness, trackView.Size);
463         }
464
465         /// <summary>
466         /// Update TrackColor property of the scrollbar.
467         /// </summary>
468         /// <param name="color">The color of the track.</param>
469         [EditorBrowsable(EditorBrowsableState.Never)]
470         protected virtual void UpdateTrackColor(Color color)
471         {
472             if (trackView == null)
473             {
474                 return;
475             }
476
477             trackView.BackgroundColor = color;
478         }
479
480         /// <summary>
481         /// Update ThumbColor property of the scrollbar.
482         /// </summary>
483         /// <param name="color">The color of the thumb.</param>
484         [EditorBrowsable(EditorBrowsableState.Never)]
485         protected virtual void UpdateThumbColor(Color color)
486         {
487             if (thumbView == null)
488             {
489                 return;
490             }
491
492             thumbView.BackgroundColor = color;
493         }
494
495         /// <summary>
496         /// Update TrackPadding property of the scrollbar.
497         /// </summary>
498         /// <param name="trackPadding">The padding of the track.</param>
499         protected virtual void UpdateTrackPadding(Extents trackPadding)
500         {
501             if (calculator == null || trackView == null || thumbView == null)
502             {
503                 return;
504             }
505
506             PaddingType ensuredPadding = EnsurePadding(trackPadding);
507             trackView.Size = calculator.CalculateTrackSize(TrackThickness, containerSize, ensuredPadding);
508             trackView.Position = calculator.CalculateTrackPosition(ensuredPadding);
509             thumbView.Size = calculator.CalculateThumbSize(ThumbThickness, trackView.Size);
510             thumbView.Position = calculator.CalculateThumbPaddingPosition(trackView.Size, thumbView.Size, thumbView.Position, ensuredPadding);
511         }
512
513         /// <inheritdoc/>
514         [EditorBrowsable(EditorBrowsableState.Never)]
515         public override bool ScrollEnabled
516         {
517             get
518             {
519                 return mScrollEnabled;
520             }
521             set
522             {
523                 if (value != mScrollEnabled)
524                 {
525                     mScrollEnabled = value;
526                 }
527             }
528         }
529
530         /// <inheritdoc/>
531         [EditorBrowsable(EditorBrowsableState.Never)]
532         public override Position ScrollPosition
533         {
534             get
535             {
536                 if (calculator == null)
537                 {
538                     return new Position(0.0f, 0.0f);
539                 }
540
541                 float length = Math.Min(Math.Max(calculator.currentPosition, 0.0f), calculator.contentLength - calculator.visibleLength);
542
543                 if (calculator is HorizontalCalculator)
544                 {
545                     return new Position(length, 0.0f);
546                 }
547                 else
548                 {
549                     return new Position(0.0f, length);
550                 }
551             }
552         }
553
554         /// <inheritdoc/>
555         [EditorBrowsable(EditorBrowsableState.Never)]
556         public override Position ScrollCurrentPosition
557         {
558             get
559             {
560                 if (calculator == null)
561                 {
562                     return new Position(0.0f, 0.0f);
563                 }
564
565                 float length = Math.Min(Math.Max(calculator.currentPosition, 0.0f), calculator.contentLength - calculator.visibleLength);
566
567                 if (thumbPositionAnimation != null)
568                 {
569                     float progress = thumbPositionAnimation.CurrentProgress;
570                     float previousLength = Math.Min(Math.Max(previousPosition, 0.0f), calculator.contentLength - calculator.visibleLength);
571
572                     length = ((1.0f - progress) * previousLength) + (progress * length);
573                 }
574
575                 if (calculator is HorizontalCalculator)
576                 {
577                     return new Position(length, 0.0f);
578                 }
579                 else
580                 {
581                     return new Position(0.0f, length);
582                 }
583             }
584         }
585
586         private PaddingType EnsurePadding(Extents padding) => padding == null ? new PaddingType(0, 0, 0 ,0) : new PaddingType(padding.Start, padding.End, padding.Top, padding.Bottom);
587
588         private Animation EnsureThumbPositionAnimation()
589         {
590             if (thumbPositionAnimation == null)
591             {
592                 thumbPositionAnimation = new Animation();
593             }
594             else
595             {
596                 thumbPositionAnimation.Stop();
597                 thumbPositionAnimation.Clear();
598             }
599             return thumbPositionAnimation;
600         }
601
602         private Animation EnsureThumbSizeAnimation()
603         {
604             if (thumbSizeAnimation == null)
605             {
606                 thumbSizeAnimation = new Animation();
607             }
608             else
609             {
610                 thumbSizeAnimation.Stop();
611                 thumbSizeAnimation.Clear();
612             }
613             return thumbSizeAnimation;
614         }
615
616         private Animation EnsureOpacityAnimation()
617         {
618             if (opacityAnimation == null)
619             {
620                 opacityAnimation = new Animation();
621             }
622             else
623             {
624                 opacityAnimation.Stop();
625                 opacityAnimation.Clear();
626             }
627             return opacityAnimation;
628         }
629
630         #endregion Methods
631
632
633         #region Classes
634
635         private abstract class Calculator
636         {
637             public float contentLength;
638             public float visibleLength;
639             public float currentPosition;
640
641             public Calculator(float contentLength, float visibleLength, float currentPosition)
642             {
643                 this.contentLength = contentLength;
644                 this.visibleLength = visibleLength;
645                 this.currentPosition = currentPosition;
646             }
647
648             public bool IsScrollable()
649             {
650                 return contentLength > visibleLength;
651             }
652
653             public abstract Position CalculatorTrackAlign();
654             public abstract Position CalculatorThumbAlign();
655             public abstract Size CalculateTrackSize(float thickness, Size containerSize, PaddingType trackPadding);
656             public abstract Position CalculateTrackPosition(PaddingType trackPadding);
657             public abstract Size CalculateThumbSize(float thickness, Size trackSize);
658             public abstract Position CalculateThumbPosition(Size trackSize, Size thumbSize, PaddingType trackPadding);
659             public abstract Position CalculateThumbPaddingPosition(Size trackSize, Size thumbSize, Position thumbCurrentPosition, PaddingType trackPadding);
660             public abstract Position CalculateThumbScrollPosition(Size trackSize, Position thumbCurrentPosition, PaddingType trackPadding);
661         }
662
663         private class HorizontalCalculator : Calculator
664         {
665             public HorizontalCalculator(float contentLength, float visibleLength, float currentPosition) : base(contentLength, visibleLength, currentPosition)
666             {
667             }
668
669             public override Position CalculatorTrackAlign()
670             {
671                 return Tizen.NUI.ParentOrigin.BottomLeft;
672             }
673
674             public override Position CalculatorThumbAlign()
675             {
676                 return Tizen.NUI.ParentOrigin.BottomLeft;
677             }
678
679             public override Size CalculateTrackSize(float thickness, Size containerSize, PaddingType trackPadding)
680             {
681                 return new Size(containerSize.Width - trackPadding.Item1 - trackPadding.Item2, thickness);
682             }
683
684             public override Position CalculateTrackPosition(PaddingType trackPadding)
685             {
686                 return new Position(trackPadding.Item1, -trackPadding.Item4);
687             }
688
689             public override Size CalculateThumbSize(float thickness, Size trackSize)
690             {
691                 return new Size(trackSize.Width * (IsScrollable() ? (visibleLength / contentLength) : 0.0f), thickness);
692             }
693
694             public override Position CalculateThumbPosition(Size trackSize, Size thumbSize, PaddingType trackPadding)
695             {
696                 float padding = ((trackSize.Height - thumbSize.Height) / 2.0f) + trackPadding.Item4;
697                 return new Position(trackPadding.Item1 + (IsScrollable() ? (trackSize.Width * (Math.Min(Math.Max(currentPosition, 0.0f), contentLength - visibleLength)) / contentLength) : 0.0f), -padding);
698             }
699
700             public override Position CalculateThumbPaddingPosition(Size trackSize, Size thumbSize, Position thumbCurrentPosition, PaddingType trackPadding)
701             {
702                 float padding = ((trackSize.Height - thumbSize.Height) / 2.0f) + trackPadding.Item4;
703                 return new Position(thumbCurrentPosition.X, -padding);
704             }
705
706             public override Position CalculateThumbScrollPosition(Size trackSize, Position thumbCurrentPosition, PaddingType trackPadding)
707             { 
708                 return new Position(trackPadding.Item1 + (IsScrollable() ? (trackSize.Width * (Math.Min(Math.Max(currentPosition, 0.0f), contentLength - visibleLength)) / contentLength) : 0.0f), thumbCurrentPosition.Y);
709             }
710         }
711
712         private class VerticalCalculator : Calculator
713         {
714             public VerticalCalculator(float contentLength, float visibleLength, float currentPosition) : base(contentLength, visibleLength, currentPosition)
715             {
716             }
717
718             public override Position CalculatorTrackAlign()
719             {
720                 return Tizen.NUI.ParentOrigin.TopRight;
721             }
722
723             public override Position CalculatorThumbAlign()
724             {
725                 return Tizen.NUI.ParentOrigin.TopRight;
726             }
727
728             public override Size CalculateTrackSize(float thickness, Size containerSize, PaddingType trackPadding)
729             {
730                 return new Size(thickness, containerSize.Height - trackPadding.Item3 - trackPadding.Item4);
731             }
732
733             public override Position CalculateTrackPosition(PaddingType trackPadding)
734             {
735                 return new Position(-trackPadding.Item2, trackPadding.Item3);
736             }
737
738             public override Size CalculateThumbSize(float thickness, Size trackSize)
739             {
740                 return new Size(thickness, trackSize.Height * (IsScrollable() ? (visibleLength / contentLength) : 0.0f));
741             }
742
743             public override Position CalculateThumbPosition(Size trackSize, Size thumbSize, PaddingType trackPadding)
744             {
745                 float padding = ((trackSize.Width - thumbSize.Width) / 2.0f) + trackPadding.Item2;
746                 return new Position(-padding, trackPadding.Item3 + (IsScrollable() ? (trackSize.Height * Math.Min(Math.Max(currentPosition, 0.0f), contentLength - visibleLength) / contentLength) : 0.0f));
747             }
748
749             public override Position CalculateThumbPaddingPosition(Size trackSize, Size thumbSize, Position thumbCurrentPosition, PaddingType trackPadding)
750             {
751                 float padding = ((trackSize.Width - thumbSize.Width) / 2.0f) + trackPadding.Item2;
752                 return new Position(-padding, thumbCurrentPosition.Y);
753             }
754
755             public override Position CalculateThumbScrollPosition(Size trackSize, Position thumbPosition, PaddingType trackPadding)
756             {
757                 return new Position(thumbPosition.X, trackPadding.Item3 + (IsScrollable() ? (trackSize.Height * Math.Min(Math.Max(currentPosition, 0.0f), contentLength - visibleLength) / contentLength) : 0.0f));
758             }
759         }
760
761         #endregion Classes
762     }
763 }