[NUI] Add ScrollEnabled to ScrollbarBase (#1838)
[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 Tizen.NUI.BaseComponents;
20 using Tizen.NUI.Binding;
21
22 namespace Tizen.NUI.Components
23 {
24     /// <summary>
25     /// The Scrollbar is a component that contains track and thumb to indicate the current scrolled position of a scrollable object.
26     /// </summary>
27     [EditorBrowsable(EditorBrowsableState.Never)]
28     public class Scrollbar : ScrollbarBase
29     {
30         #region Fields
31
32         /// <summary>Bindable property of TrackThickness</summary>
33         [EditorBrowsable(EditorBrowsableState.Never)]
34         public static readonly BindableProperty TrackThicknessProperty = BindableProperty.Create(nameof(TrackThickness), typeof(float), typeof(Scrollbar), default(float), propertyChanged: (bindable, oldValue, newValue) =>
35         {
36             var instance = ((Scrollbar)bindable);
37             var thickness = (float?)newValue;
38
39             instance.scrollbarStyle.TrackThickness = thickness;
40             instance.UpdateTrackThickness(thickness ?? 0);
41         },
42         defaultValueCreator: (bindable) =>
43         {
44             return ((Scrollbar)bindable).scrollbarStyle.TrackThickness ?? 0;
45         });
46
47         /// <summary>Bindable property of ThumbThickness</summary>
48         [EditorBrowsable(EditorBrowsableState.Never)]
49         public static readonly BindableProperty ThumbThicknessProperty = BindableProperty.Create(nameof(ThumbThickness), typeof(float), typeof(Scrollbar), default(float), propertyChanged: (bindable, oldValue, newValue) =>
50         {
51             var instance = ((Scrollbar)bindable);
52             var thickness = (float?)newValue;
53
54             instance.scrollbarStyle.ThumbThickness = thickness;
55             instance.UpdateThumbThickness(thickness ?? 0);
56         },
57         defaultValueCreator: (bindable) =>
58         {
59             return ((Scrollbar)bindable).scrollbarStyle.ThumbThickness ?? 0;
60         });
61
62         /// <summary>Bindable property of TrackColor</summary>
63         [EditorBrowsable(EditorBrowsableState.Never)]
64         public static readonly BindableProperty TrackColorProperty = BindableProperty.Create(nameof(TrackColor), typeof(Color), typeof(Scrollbar), null, propertyChanged: (bindable, oldValue, newValue) =>
65         {
66             var instance = ((Scrollbar)bindable);
67             var color = (Color)newValue;
68
69             instance.scrollbarStyle.TrackColor = color;
70             instance.UpdateTrackColor(color);
71         },
72         defaultValueCreator: (bindable) =>
73         {
74             return ((Scrollbar)bindable).scrollbarStyle.TrackColor;
75         });
76
77         /// <summary>Bindable property of ThumbColor</summary>
78         [EditorBrowsable(EditorBrowsableState.Never)]
79         public static readonly BindableProperty ThumbColorProperty = BindableProperty.Create(nameof(ThumbColor), typeof(Color), typeof(Scrollbar), null, propertyChanged: (bindable, oldValue, newValue) =>
80         {
81             var instance = ((Scrollbar)bindable);
82             var color = (Color)newValue;
83
84             instance.scrollbarStyle.ThumbColor = color;
85             instance.UpdateThumbColor(color);
86         },
87         defaultValueCreator: (bindable) =>
88         {
89             return ((Scrollbar)bindable).scrollbarStyle.ThumbColor;
90         });
91
92         /// <summary>Bindable property of TrackPadding</summary>
93         [EditorBrowsable(EditorBrowsableState.Never)]
94         public static readonly BindableProperty TrackPaddingProperty = BindableProperty.Create(nameof(TrackPadding), typeof(Extents), typeof(Scrollbar), null, propertyChanged: (bindable, oldValue, newValue) =>
95         {
96             var instance = ((Scrollbar)bindable);
97             var trackPadding = (Extents)newValue;
98
99             instance.scrollbarStyle.TrackPadding = trackPadding;
100             instance.UpdateTrackPadding(trackPadding);
101         },
102         defaultValueCreator: (bindable) =>
103         {
104             return ((Scrollbar)bindable).scrollbarStyle.TrackPadding;
105         });
106
107         private ColorVisual trackVisual;
108         private ColorVisual thumbVisual;
109         private Animation thumbPositionAnimation;
110         private Animation thumbSizeAnimation;
111         private Calculator calculator;
112         private Size containerSize = new Size(0, 0);
113         private ScrollbarStyle scrollbarStyle => ViewStyle as ScrollbarStyle;
114         private bool mScrollEnabled = true;
115
116         #endregion Fields
117
118
119         #region Constructors
120
121         /// <summary>
122         /// Create an empty Scrollbar.
123         /// </summary>
124         public Scrollbar() : base(new ScrollbarStyle())
125         {
126         }
127
128         /// <summary>
129         /// Create a Scrollbar and initialize with properties.
130         /// </summary>
131         /// <param name="contentLength">The length of the scrollable content area.</param>
132         /// <param name="viewportLength">The length of the viewport representing the amount of visible content.</param>
133         /// <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>
134         /// <param name="isHorizontal">Whether the direction of scrolling is horizontal or not. It is vertical by default.</param>
135         [EditorBrowsable(EditorBrowsableState.Never)]
136         public Scrollbar(float contentLength, float viewportLength, float currentPosition, bool isHorizontal = false) : base(new ScrollbarStyle())
137         {
138             Initialize(contentLength, viewportLength, currentPosition, isHorizontal);
139         }
140
141         /// <summary>
142         /// Create an empty Scrollbar with a ScrollbarStyle instance to set style properties.
143         /// </summary>
144         [EditorBrowsable(EditorBrowsableState.Never)]
145         public Scrollbar(ScrollbarStyle style) : base(style)
146         {
147         }
148
149         /// <summary>
150         /// Static constructor to initialize bindable properties when loading.
151         /// </summary>
152         static Scrollbar()
153         {
154         }
155
156         #endregion Constructors
157
158
159         #region Properties
160
161         /// <summary>
162         /// Return a copied Style instance of Scrollbar
163         /// </summary>
164         /// <remarks>
165         /// It returns copied Style instance and changing it does not effect to the Scrollbar.
166         /// Style setting is possible by using constructor or the function of ApplyStyle(ViewStyle viewStyle)
167         /// </remarks>
168         [EditorBrowsable(EditorBrowsableState.Never)]
169         public new ScrollbarStyle Style
170         {
171             get
172             {
173                 var result = new ScrollbarStyle(scrollbarStyle);
174                 result.CopyPropertiesFromView(this);
175                 return result;
176             }
177         }
178
179         /// <summary>
180         /// The thickness of the track.
181         /// </summary>
182         [EditorBrowsable(EditorBrowsableState.Never)]
183         public float TrackThickness
184         {
185             get => (float)GetValue(TrackThicknessProperty);
186             set => SetValue(TrackThicknessProperty, value);
187         }
188
189         /// <summary>
190         /// The thickness of the thumb.
191         /// </summary>
192         [EditorBrowsable(EditorBrowsableState.Never)]
193         public float ThumbThickness
194         {
195             get => (float)GetValue(ThumbThicknessProperty);
196             set => SetValue(ThumbThicknessProperty, value);
197         }
198
199         /// <summary>
200         /// The color of the track part.
201         /// </summary>
202         [EditorBrowsable(EditorBrowsableState.Never)]
203         public Color TrackColor
204         {
205             get => (Color)GetValue(TrackColorProperty);
206             set => SetValue(TrackColorProperty, value);
207         }
208
209         /// <summary>
210         /// The color of the thumb part.
211         /// </summary>
212         [EditorBrowsable(EditorBrowsableState.Never)]
213         public Color ThumbColor
214         {
215             get => (Color)GetValue(ThumbColorProperty);
216             set => SetValue(ThumbColorProperty, value);
217         }
218
219         /// <summary>
220         /// The padding value of the track.
221         /// </summary>
222         [EditorBrowsable(EditorBrowsableState.Never)]
223         public Extents TrackPadding
224         {
225             get => (Extents)GetValue(TrackPaddingProperty);
226             set => SetValue(TrackPaddingProperty, value);
227         }
228
229         #endregion Properties
230
231
232         #region Methods
233
234         /// <inheritdoc/>
235         [EditorBrowsable(EditorBrowsableState.Never)]
236         public override void Initialize(float contentLength, float viewportLength, float currentPosition, bool isHorizontal = false)
237         {
238             if (isHorizontal)
239             {
240                 calculator = new HorizontalCalculator(contentLength > 0.0f ? contentLength : 0.0f, viewportLength, currentPosition);
241             }
242             else
243             {
244                 calculator = new VerticalCalculator(contentLength > 0.0f ? contentLength : 0.0f, viewportLength, currentPosition);
245             }
246
247             thumbPositionAnimation?.Stop();
248             thumbPositionAnimation = null;
249
250             thumbSizeAnimation?.Stop();
251             thumbSizeAnimation = null;
252
253             Size trackSize = calculator.CalculateTrackSize(TrackThickness, containerSize, TrackPadding);
254             Vector2 trackPosition = calculator.CalculateTrackPosition(TrackPadding);
255             Size thumbSize = calculator.CalculateThumbSize(ThumbThickness, trackSize);
256             Vector2 thumbPosition = calculator.CalculateThumbPosition(trackSize, thumbSize, TrackPadding);
257
258             if (trackVisual == null)
259             {
260                 trackVisual = new ColorVisual
261                 {
262                     SuppressUpdateVisual = true,
263                     Color = TrackColor,
264                     SizePolicy = VisualTransformPolicyType.Absolute,
265                     Origin = calculator.CalculatorTrackAlign(),
266                     AnchorPoint = calculator.CalculatorTrackAlign(),
267                     Size = trackSize,
268                     Position = trackPosition,
269                 };
270
271                 AddVisual("Track", trackVisual);
272             }
273             else
274             {
275                 trackVisual.Size = trackSize;
276                 trackVisual.Position = trackPosition;
277                 trackVisual.UpdateVisual(true);
278             }
279
280             if (thumbVisual == null)
281             {
282                 thumbVisual = new ColorVisual
283                 {
284                     SuppressUpdateVisual = true,
285                     MixColor = ThumbColor,
286                     SizePolicy = VisualTransformPolicyType.Absolute,
287                     Origin = calculator.CalculatorThumbAlign(),
288                     AnchorPoint = calculator.CalculatorThumbAlign(),
289                     Opacity = calculator.CalculateThumbVisibility() ? 1.0f : 0.0f,
290                     Size = thumbSize,
291                     Position = thumbPosition,
292                 };
293
294                 AddVisual("Thumb", thumbVisual);
295             }
296             else
297             {
298                 thumbVisual.Size = thumbSize;
299                 thumbVisual.Position = thumbPosition;
300                 thumbVisual.UpdateVisual(true);
301             }
302         }
303
304         /// <inheritdoc/>
305         /// <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>
306         [EditorBrowsable(EditorBrowsableState.Never)]
307         public override void Update(float contentLength, float position, uint durationMs = 0, AlphaFunction alphaFunction = null)
308         {
309             if (calculator == null)
310             {
311                 return;
312             }
313
314             calculator.contentLength = contentLength > 0.0f ? contentLength : 0.0f;
315             calculator.currentPosition = position;
316
317             thumbVisual.Size = calculator.CalculateThumbSize(ThumbThickness, trackVisual.Size);
318             thumbVisual.Position = calculator.CalculateThumbScrollPosition(trackVisual.Size, thumbVisual.Position, TrackPadding);
319             thumbVisual.Opacity = calculator.CalculateThumbVisibility() ? 1.0f : 0.0f;
320
321             if (durationMs == 0)
322             {
323                 thumbVisual.UpdateVisual(true);
324
325                 return;
326             }
327
328             // TODO Support non built-in alpha function for visual trainsition in DALi.
329             AlphaFunction.BuiltinFunctions builtinAlphaFunction = alphaFunction?.GetBuiltinFunction() ?? AlphaFunction.BuiltinFunctions.Default;
330
331             thumbPositionAnimation?.Stop();
332             thumbPositionAnimation = AnimateVisual(thumbVisual, "position", thumbVisual.Position, 0, (int)durationMs, builtinAlphaFunction);
333             thumbPositionAnimation.Play();
334
335             thumbSizeAnimation?.Stop();
336             thumbSizeAnimation = AnimateVisual(thumbVisual, "size", thumbVisual.Size, 0, (int)durationMs, builtinAlphaFunction);
337             thumbSizeAnimation.Play();
338         }
339
340         /// <inheritdoc/>
341         /// <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>
342         [EditorBrowsable(EditorBrowsableState.Never)]
343         public override void ScrollTo(float position, uint durationMs = 0, AlphaFunction alphaFunction = null)
344         {
345             if (mScrollEnabled == false)
346             {
347                 return;
348             }
349
350             if (calculator == null)
351             {
352                 return;
353             }
354
355             calculator.currentPosition = position;
356             thumbVisual.Position = calculator.CalculateThumbScrollPosition(trackVisual.Size, thumbVisual.Position, TrackPadding);
357
358             if (durationMs == 0)
359             {
360                 thumbVisual.UpdateVisual(true);
361
362                 return;
363             }
364
365             // TODO Support non built-in alpha function for visual trainsition in DALi.
366             AlphaFunction.BuiltinFunctions builtinAlphaFunction = alphaFunction?.GetBuiltinFunction() ?? AlphaFunction.BuiltinFunctions.Default;
367
368             thumbPositionAnimation?.Stop();
369             thumbPositionAnimation = AnimateVisual(thumbVisual, "position", thumbVisual.Position, 0, (int)durationMs, builtinAlphaFunction);
370             thumbPositionAnimation.Play();
371         }
372
373         /// <inheritdoc/>
374         [EditorBrowsable(EditorBrowsableState.Never)]
375         public override void OnRelayout(Vector2 size, RelayoutContainer container)
376         {
377             base.OnRelayout(size, container);
378
379             if (size.Width == containerSize.Width && size.Height == containerSize.Height)
380             {
381                 return;
382             }
383
384             containerSize = new Size(size.Width, size.Height);
385
386             if (calculator == null)
387             {
388                 return;
389             }
390
391             trackVisual.Size = calculator.CalculateTrackSize(TrackThickness, containerSize, TrackPadding);
392             trackVisual.Position = calculator.CalculateTrackPosition(TrackPadding);
393             thumbVisual.Size = calculator.CalculateThumbSize(ThumbThickness, trackVisual.Size);
394             thumbVisual.Position = calculator.CalculateThumbPosition(trackVisual.Size, thumbVisual.Size, TrackPadding);
395
396             trackVisual.UpdateVisual(true);
397             thumbVisual.UpdateVisual(true);
398         }
399
400         /// <inheritdoc/>
401         [EditorBrowsable(EditorBrowsableState.Never)]
402         protected override ViewStyle CreateViewStyle()
403         {
404             return new ScrollbarStyle();
405         }
406
407         /// <summary>
408         /// Update TrackThickness property of the scrollbar.
409         /// </summary>
410         /// <param name="thickness">The width of the track.</param>
411         [EditorBrowsable(EditorBrowsableState.Never)]
412         protected virtual void UpdateTrackThickness(float thickness)
413         {
414             if (trackVisual == null)
415             {
416                 return;
417             }
418
419             trackVisual.Size = calculator.CalculateTrackSize(thickness, containerSize, TrackPadding);
420             trackVisual.UpdateVisual(true);
421         }
422
423         /// <summary>
424         /// Update ThumbThickness property of the scrollbar.
425         /// </summary>
426         /// <param name="thickness">The width of the track.</param>
427         [EditorBrowsable(EditorBrowsableState.Never)]
428         protected virtual void UpdateThumbThickness(float thickness)
429         {
430             if (thumbVisual == null)
431             {
432                 return;
433             }
434
435             thumbVisual.Size = calculator.CalculateThumbSize(thickness, trackVisual.Size);
436             thumbVisual.UpdateVisual(true);
437         }
438
439         /// <summary>
440         /// Update TrackColor property of the scrollbar.
441         /// </summary>
442         /// <param name="color">The color of the track.</param>
443         [EditorBrowsable(EditorBrowsableState.Never)]
444         protected virtual void UpdateTrackColor(Color color)
445         {
446             if (trackVisual == null)
447             {
448                 return;
449             }
450
451             trackVisual.MixColor = color;
452             trackVisual.UpdateVisual(true);
453         }
454
455         /// <summary>
456         /// Update ThumbColor property of the scrollbar.
457         /// </summary>
458         /// <param name="color">The color of the thumb.</param>
459         [EditorBrowsable(EditorBrowsableState.Never)]
460         protected virtual void UpdateThumbColor(Color color)
461         {
462             if (thumbVisual == null)
463             {
464                 return;
465             }
466
467             thumbVisual.MixColor = color;
468             thumbVisual.UpdateVisual(true);
469         }
470
471         /// <summary>
472         /// Update TrackPadding property of the scrollbar.
473         /// </summary>
474         /// <param name="trackPadding">The padding of the track.</param>
475         protected virtual void UpdateTrackPadding(Extents trackPadding)
476         {
477             if (calculator == null)
478             {
479                 return;
480             }
481
482             trackVisual.Size = calculator.CalculateTrackSize(TrackThickness, containerSize, trackPadding); 
483             trackVisual.Position = calculator.CalculateTrackPosition(trackPadding);
484             thumbVisual.Size = calculator.CalculateThumbSize(ThumbThickness, trackVisual.Size);
485             thumbVisual.Position = calculator.CalculateThumbPaddingPosition(trackVisual.Size, thumbVisual.Size, thumbVisual.Position, trackPadding);
486
487             trackVisual.UpdateVisual(true);
488             thumbVisual.UpdateVisual(true);
489         }
490
491         /// <inheritdoc/>
492         [EditorBrowsable(EditorBrowsableState.Never)]
493         public override bool ScrollEnabled
494         {
495             get
496             {
497                 return mScrollEnabled;
498             }
499             set
500             {
501                 if (value != mScrollEnabled)
502                 {
503                     mScrollEnabled = value;
504                 }
505             }
506         }
507
508         #endregion Methods
509
510
511         #region Classes
512
513         private abstract class Calculator
514         {
515             public float contentLength;
516             public float visibleLength;
517             public float currentPosition;
518
519             public Calculator(float contentLength, float visibleLength, float currentPosition)
520             {
521                 this.contentLength = contentLength;
522                 this.visibleLength = visibleLength;
523                 this.currentPosition = currentPosition;
524             }
525
526             public bool CalculateThumbVisibility()
527             {
528                 return contentLength > visibleLength;
529             }
530
531             public abstract Visual.AlignType CalculatorTrackAlign();
532             public abstract Visual.AlignType CalculatorThumbAlign();
533             public abstract Size CalculateTrackSize(float thickness, Size containerSize, Extents trackPadding);
534             public abstract Vector2 CalculateTrackPosition(Extents trackPadding);
535             public abstract Size CalculateThumbSize(float thickness, Size trackSize);
536             public abstract Vector2 CalculateThumbPosition(Size trackSize, Size thumbSize, Extents trackPadding);
537             public abstract Vector2 CalculateThumbPaddingPosition(Size trackSize, Size thumbSize, Vector2 thumbCurrentPosition, Extents trackPadding);
538             public abstract Vector2 CalculateThumbScrollPosition(Size trackSize, Vector2 thumbCurrentPosition, Extents trackPadding);
539         }
540
541         private class HorizontalCalculator : Calculator
542         {
543             public HorizontalCalculator(float contentLength, float visibleLength, float currentPosition) : base(contentLength, visibleLength, currentPosition)
544             {
545             }
546
547             public override Visual.AlignType CalculatorTrackAlign()
548             {
549                 return Visual.AlignType.BottomCenter;
550             }
551
552             public override Visual.AlignType CalculatorThumbAlign()
553             {
554                 return Visual.AlignType.BottomBegin;
555             }
556
557             public override Size CalculateTrackSize(float thickness, Size containerSize, Extents trackPadding)
558             {
559                 return new Size(containerSize.Width - trackPadding.Start - trackPadding.End, thickness);
560             }
561
562             public override Vector2 CalculateTrackPosition(Extents trackPadding)
563             {
564                 return new Vector2(0, -trackPadding.Bottom);
565             }
566
567             public override Size CalculateThumbSize(float thickness, Size trackSize)
568             {
569                 return new Size(trackSize.Width * visibleLength / contentLength, thickness);
570             }
571
572             public override Vector2 CalculateThumbPosition(Size trackSize, Size thumbSize, Extents trackPadding)
573             {
574                 float padding = ((trackSize.Height - thumbSize.Height) / 2.0f) + trackPadding.Bottom;
575                 float pos = Math.Min(Math.Max(currentPosition, 0.0f), contentLength - visibleLength);
576                 return new Vector2(trackPadding.Start + trackSize.Width * pos / contentLength, -padding);
577             }
578
579             public override Vector2 CalculateThumbPaddingPosition(Size trackSize, Size thumbSize, Vector2 thumbCurrentPosition, Extents trackPadding)
580             {
581                 float padding = ((trackSize.Height - thumbSize.Height) / 2.0f) + trackPadding.Bottom;
582                 return new Vector2(thumbCurrentPosition.X, -padding);
583             }
584
585             public override Vector2 CalculateThumbScrollPosition(Size trackSize, Vector2 thumbCurrentPosition, Extents trackPadding)
586             {
587                 float pos = Math.Min(Math.Max(currentPosition, 0.0f), contentLength - visibleLength);
588                 return new Vector2(trackPadding.Start + trackSize.Width * pos / contentLength, thumbCurrentPosition.Y);
589             }
590         }
591
592         private class VerticalCalculator : Calculator
593         {
594             public VerticalCalculator(float contentLength, float visibleLength, float currentPosition) : base(contentLength, visibleLength, currentPosition)
595             {
596             }
597
598             public override Visual.AlignType CalculatorTrackAlign()
599             {
600                 return Visual.AlignType.CenterEnd;
601             }
602
603             public override Visual.AlignType CalculatorThumbAlign()
604             {
605                 return Visual.AlignType.TopEnd;
606             }
607
608             public override Size CalculateTrackSize(float thickness, Size containerSize, Extents trackPadding)
609             {
610                 return new Size(thickness, containerSize.Height - trackPadding.Top - trackPadding.Bottom);
611             }
612
613             public override Vector2 CalculateTrackPosition(Extents trackPadding)
614             {
615                 return new Vector2(-trackPadding.End, 0);
616             }
617
618             public override Size CalculateThumbSize(float thickness, Size trackSize)
619             {
620                 return new Size(thickness, trackSize.Height * visibleLength / contentLength);
621             }
622
623             public override Vector2 CalculateThumbPosition(Size trackSize, Size thumbSize, Extents trackPadding)
624             {
625                 float padding = ((trackSize.Width - thumbSize.Width) / 2.0f) + trackPadding.End;
626                 float pos = Math.Min(Math.Max(currentPosition, 0.0f), contentLength - visibleLength);
627                 return new Vector2(-padding, trackPadding.Top + trackSize.Height * pos / contentLength);
628             }
629
630             public override Vector2 CalculateThumbPaddingPosition(Size trackSize, Size thumbSize, Vector2 thumbCurrentPosition, Extents trackPadding)
631             {
632                 float padding = ((trackSize.Width - thumbSize.Width) / 2.0f) + trackPadding.End;
633                 return new Vector2(-padding, thumbCurrentPosition.Y);
634             }
635
636             public override Vector2 CalculateThumbScrollPosition(Size trackSize, Vector2 thumbPosition, Extents trackPadding)
637             {
638                 float pos = Math.Min(Math.Max(currentPosition, 0.0f), contentLength - visibleLength);
639                 return new Vector2(thumbPosition.X, trackPadding.Top + trackSize.Height * pos / contentLength);
640             }
641         }
642
643         #endregion Classes
644     }
645 }