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