2 * Copyright(c) 2020 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 using System.ComponentModel;
19 using Tizen.NUI.BaseComponents;
20 using Tizen.NUI.Binding;
22 namespace Tizen.NUI.Components
25 /// The Scrollbar is a component that contains track and thumb to indicate the current scrolled position of a scrollable object.
27 [EditorBrowsable(EditorBrowsableState.Never)]
28 public class Scrollbar : ScrollbarBase
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) =>
36 var instance = ((Scrollbar)bindable);
37 var thickness = (float?)newValue;
39 ((ScrollbarStyle)instance.viewStyle).TrackThickness = thickness;
40 instance.UpdateTrackThickness(thickness ?? 0);
42 defaultValueCreator: (bindable) =>
44 return ((ScrollbarStyle)((Scrollbar)bindable).viewStyle)?.TrackThickness ?? 0;
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) =>
51 var instance = ((Scrollbar)bindable);
52 var thickness = (float?)newValue;
54 ((ScrollbarStyle)instance.viewStyle).ThumbThickness = thickness;
55 instance.UpdateThumbThickness(thickness ?? 0);
57 defaultValueCreator: (bindable) =>
59 return ((ScrollbarStyle)((Scrollbar)bindable).viewStyle)?.ThumbThickness ?? 0;
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) =>
66 var instance = ((Scrollbar)bindable);
67 var color = (Color)newValue;
69 ((ScrollbarStyle)instance.viewStyle).TrackColor = color;
70 instance.UpdateTrackColor(color);
72 defaultValueCreator: (bindable) =>
74 return ((ScrollbarStyle)((Scrollbar)bindable).viewStyle)?.TrackColor;
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) =>
81 var instance = ((Scrollbar)bindable);
82 var color = (Color)newValue;
84 ((ScrollbarStyle)instance.viewStyle).ThumbColor = color;
85 instance.UpdateThumbColor(color);
87 defaultValueCreator: (bindable) =>
89 return ((ScrollbarStyle)((Scrollbar)bindable).viewStyle)?.ThumbColor;
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) =>
96 var instance = ((Scrollbar)bindable);
97 var trackPadding = (Extents)newValue;
99 ((ScrollbarStyle)instance.viewStyle).TrackPadding = trackPadding;
100 instance.UpdateTrackPadding(trackPadding);
102 defaultValueCreator: (bindable) =>
104 return ((ScrollbarStyle)((Scrollbar)bindable).viewStyle)?.TrackPadding;
107 private static readonly string TrackVisualName = "Track";
108 private static readonly string ThumbVisualName = "Thumb";
109 private ColorVisual trackVisual;
110 private ColorVisual thumbVisual;
111 private Animation thumbPositionAnimation;
112 private Animation thumbSizeAnimation;
113 private Calculator calculator;
121 /// Create an empty Scrollbar.
123 public Scrollbar() : base(new ScrollbarStyle())
128 /// Create a Scrollbar and initialize with properties.
130 /// <param name="contentLength">The total length of the content.</param>
131 /// <param name="viewSize">The size of View that contains the content to scroll.</param>
132 /// <param name="currentPosition">The start position of the View in content length. This is the View's top position if the scroller is vertical, otherwise, View's left position.</param>
133 /// <param name="isHorizontal">Whether the direction of scrolling is horizontal or not. It is vertical if the value is false.</param>
134 [EditorBrowsable(EditorBrowsableState.Never)]
135 public Scrollbar(float contentLength, Size viewSize, float currentPosition, bool isHorizontal = false) : base(new ScrollbarStyle())
137 Initialize(contentLength, viewSize, currentPosition, isHorizontal);
141 /// Create an empty Scrollbar with a ScrollbarStyle instance to set style properties.
143 [EditorBrowsable(EditorBrowsableState.Never)]
144 public Scrollbar(ScrollbarStyle style) : base(style)
149 /// Static constructor to initialize bindable properties when loading.
155 #endregion Constructors
161 /// The thickness of the track.
163 [EditorBrowsable(EditorBrowsableState.Never)]
164 public float TrackThickness
166 get => (float)GetValue(TrackThicknessProperty);
167 set => SetValue(TrackThicknessProperty, value);
171 /// The thickness of the thumb.
173 [EditorBrowsable(EditorBrowsableState.Never)]
174 public float ThumbThickness
176 get => (float)GetValue(ThumbThicknessProperty);
177 set => SetValue(ThumbThicknessProperty, value);
181 /// The color of the track part.
183 [EditorBrowsable(EditorBrowsableState.Never)]
184 public Color TrackColor
186 get => (Color)GetValue(TrackColorProperty);
187 set => SetValue(TrackColorProperty, value);
191 /// The color of the thumb part.
193 [EditorBrowsable(EditorBrowsableState.Never)]
194 public Color ThumbColor
196 get => (Color)GetValue(ThumbColorProperty);
197 set => SetValue(ThumbColorProperty, value);
201 /// The padding value of the track.
203 [EditorBrowsable(EditorBrowsableState.Never)]
204 public Extents TrackPadding
206 get => (Extents)GetValue(TrackPaddingProperty);
207 set => SetValue(TrackPaddingProperty, value);
210 #endregion Properties
216 [EditorBrowsable(EditorBrowsableState.Never)]
217 public override void Initialize(float contentLength, Size viewSize, float currentPosition, bool isHorizontal = false)
221 calculator = new HorizontalCalculator(contentLength > 0.0f ? contentLength : 0.0f, viewSize.Width);
225 calculator = new VerticalCalculator(contentLength > 0.0f ? contentLength : 0.0f, viewSize.Height);
230 thumbPositionAnimation?.Stop();
231 thumbPositionAnimation = null;
233 thumbSizeAnimation?.Stop();
234 thumbSizeAnimation = null;
237 CreateThumbVisual(currentPosition);
239 AddVisual(TrackVisualName, trackVisual);
240 AddVisual(ThumbVisualName, thumbVisual);
244 /// <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>
245 [EditorBrowsable(EditorBrowsableState.Never)]
246 public override void Update(float contentLength, float position, uint durationMs = 0, AlphaFunction alphaFunction = null)
248 if (calculator == null)
253 calculator.Update(contentLength > 0.0f ? contentLength : 0.0f);
255 thumbVisual.Size = calculator.CalculateThumbSize(ThumbThickness, trackVisual.Size);
256 thumbVisual.Position = calculator.CalculateThumbScrollPosition(position, trackVisual.Size, thumbVisual.Position, TrackPadding);
257 thumbVisual.Opacity = calculator.CalculateThumbVisibility() ? 1.0f : 0.0f;
261 thumbVisual.UpdateVisual(true);
266 // TODO Support non built-in alpha function for visual trainsition in DALi.
267 AlphaFunction.BuiltinFunctions builtinAlphaFunction = alphaFunction?.GetBuiltinFunction() ?? AlphaFunction.BuiltinFunctions.Default;
269 thumbPositionAnimation?.Stop();
270 thumbPositionAnimation = AnimateVisual(thumbVisual, "position", thumbVisual.Position, 0, (int)durationMs, builtinAlphaFunction);
271 thumbPositionAnimation.Play();
273 thumbSizeAnimation?.Stop();
274 thumbSizeAnimation = AnimateVisual(thumbVisual, "size", thumbVisual.Size, 0, (int)durationMs, builtinAlphaFunction);
275 thumbSizeAnimation.Play();
279 /// <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>
280 [EditorBrowsable(EditorBrowsableState.Never)]
281 public override void ScrollTo(float position, uint durationMs = 0, AlphaFunction alphaFunction = null)
283 if (thumbVisual == null)
288 thumbVisual.Position = calculator.CalculateThumbScrollPosition(position, trackVisual.Size, thumbVisual.Position, TrackPadding);
292 thumbVisual.UpdateVisual(true);
297 // TODO Support non built-in alpha function for visual trainsition in DALi.
298 AlphaFunction.BuiltinFunctions builtinAlphaFunction = alphaFunction?.GetBuiltinFunction() ?? AlphaFunction.BuiltinFunctions.Default;
300 thumbPositionAnimation?.Stop();
301 thumbPositionAnimation = AnimateVisual(thumbVisual, "position", thumbVisual.Position, 0, (int)durationMs, builtinAlphaFunction);
302 thumbPositionAnimation.Play();
306 [EditorBrowsable(EditorBrowsableState.Never)]
307 protected override ViewStyle GetViewStyle()
309 return new ScrollbarStyle();
313 /// Create a track visual.
315 [EditorBrowsable(EditorBrowsableState.Never)]
316 protected virtual void CreateTrackVisual()
318 trackVisual = new ColorVisual
320 SuppressUpdateVisual = true,
322 SizePolicy = VisualTransformPolicyType.Absolute,
323 Origin = calculator.CalculatorTrackAlign(),
324 AnchorPoint = calculator.CalculatorTrackAlign(),
325 Size = calculator.CalculateTrackSize(TrackThickness, TrackPadding),
326 Position = calculator.CalculateTrackPosition(TrackPadding),
331 /// Create a thumb visual.
333 [EditorBrowsable(EditorBrowsableState.Never)]
334 protected virtual void CreateThumbVisual(float currentPosition)
336 Size thumbSize = calculator.CalculateThumbSize(ThumbThickness, trackVisual.Size);
338 thumbVisual = new ColorVisual
340 SuppressUpdateVisual = true,
341 MixColor = ThumbColor,
342 SizePolicy = VisualTransformPolicyType.Absolute,
343 Origin = calculator.CalculatorThumbAlign(),
344 AnchorPoint = calculator.CalculatorThumbAlign(),
346 Position = calculator.CalculateThumbPosition(currentPosition, trackVisual.Size, thumbSize, TrackPadding),
347 Opacity = (calculator.CalculateThumbVisibility() ? 1.0f : 0.0f),
352 /// Update TrackThickness property of the scrollbar.
354 /// <param name="thickness">The width of the track.</param>
355 [EditorBrowsable(EditorBrowsableState.Never)]
356 protected virtual void UpdateTrackThickness(float thickness)
358 if (trackVisual == null)
363 trackVisual.Size = calculator.CalculateTrackSize(thickness, TrackPadding);
364 trackVisual.UpdateVisual(true);
368 /// Update ThumbThickness property of the scrollbar.
370 /// <param name="thickness">The width of the track.</param>
371 [EditorBrowsable(EditorBrowsableState.Never)]
372 protected virtual void UpdateThumbThickness(float thickness)
374 if (thumbVisual == null)
379 thumbVisual.Size = calculator.CalculateThumbSize(thickness, trackVisual.Size);
380 thumbVisual.UpdateVisual(true);
384 /// Update TrackColor property of the scrollbar.
386 /// <param name="color">The color of the track.</param>
387 [EditorBrowsable(EditorBrowsableState.Never)]
388 protected virtual void UpdateTrackColor(Color color)
390 if (trackVisual == null)
395 trackVisual.MixColor = color;
396 trackVisual.UpdateVisual(true);
400 /// Update ThumbColor property of the scrollbar.
402 /// <param name="color">The color of the thumb.</param>
403 [EditorBrowsable(EditorBrowsableState.Never)]
404 protected virtual void UpdateThumbColor(Color color)
406 if (thumbVisual == null)
411 thumbVisual.MixColor = color;
412 thumbVisual.UpdateVisual(true);
416 /// Update TrackPadding property of the scrollbar.
418 /// <param name="trackPadding">The padding of the track.</param>
419 protected virtual void UpdateTrackPadding(Extents trackPadding)
421 if (trackVisual == null || thumbVisual == null)
426 trackVisual.Size = calculator.CalculateTrackSize(TrackThickness, trackPadding);
427 trackVisual.Position = calculator.CalculateTrackPosition(trackPadding);
428 thumbVisual.Size = calculator.CalculateThumbSize(ThumbThickness, trackVisual.Size);
429 thumbVisual.Position = calculator.CalculateThumbPaddingPosition(trackVisual.Size, thumbVisual.Size, thumbVisual.Position, trackPadding);
431 trackVisual.UpdateVisual(true);
432 thumbVisual.UpdateVisual(true);
440 private abstract class Calculator
442 protected float contentLength;
443 protected float visibleLength;
445 public Calculator(float contentLength, float visibleLength)
447 this.contentLength = contentLength;
448 this.visibleLength = visibleLength;
451 public void Update(float contentLength)
453 this.contentLength = contentLength;
456 public bool CalculateThumbVisibility()
458 return contentLength > visibleLength;
461 public abstract Visual.AlignType CalculatorTrackAlign();
462 public abstract Visual.AlignType CalculatorThumbAlign();
463 public abstract Size CalculateTrackSize(float thickness, Extents trackPadding);
464 public abstract Vector2 CalculateTrackPosition(Extents trackPadding);
465 public abstract Size CalculateThumbSize(float thickness, Size trackSize);
466 public abstract Vector2 CalculateThumbPosition(float position, Size trackSize, Size thumbSize, Extents trackPadding);
467 public abstract Vector2 CalculateThumbPaddingPosition(Size trackSize, Size thumbSize, Vector2 thumbCurrentPosition, Extents trackPadding);
468 public abstract Vector2 CalculateThumbScrollPosition(float position, Size trackSize, Vector2 thumbCurrentPosition, Extents trackPadding);
471 private class HorizontalCalculator : Calculator
473 public HorizontalCalculator(float contentLength, float visibleLength) : base(contentLength, visibleLength)
477 public override Visual.AlignType CalculatorTrackAlign()
479 return Visual.AlignType.BottomCenter;
482 public override Visual.AlignType CalculatorThumbAlign()
484 return Visual.AlignType.BottomBegin;
487 public override Size CalculateTrackSize(float thickness, Extents trackPadding)
489 return new Size(visibleLength - trackPadding.Start - trackPadding.End, thickness);
492 public override Vector2 CalculateTrackPosition(Extents trackPadding)
494 return new Vector2(0, -trackPadding.Bottom);
497 public override Size CalculateThumbSize(float thickness, Size trackSize)
499 return new Size(trackSize.Width * visibleLength / contentLength, thickness);
502 public override Vector2 CalculateThumbPosition(float position, Size trackSize, Size thumbSize, Extents trackPadding)
504 float padding = ((trackSize.Height - thumbSize.Height) / 2.0f) + trackPadding.Bottom;
505 float pos = Math.Min(Math.Max(position, 0.0f), contentLength - visibleLength);
506 return new Vector2(trackPadding.Start + trackSize.Width * pos / contentLength, -padding);
509 public override Vector2 CalculateThumbPaddingPosition(Size trackSize, Size thumbSize, Vector2 thumbCurrentPosition, Extents trackPadding)
511 float padding = ((trackSize.Height - thumbSize.Height) / 2.0f) + trackPadding.Bottom;
512 return new Vector2(thumbCurrentPosition.X, -padding);
515 public override Vector2 CalculateThumbScrollPosition(float position, Size trackSize, Vector2 thumbCurrentPosition, Extents trackPadding)
517 float pos = Math.Min(Math.Max(position, 0.0f), contentLength - visibleLength);
518 return new Vector2(trackPadding.Start + trackSize.Width * pos / contentLength, thumbCurrentPosition.Y);
522 private class VerticalCalculator : Calculator
524 public VerticalCalculator(float contentLength, float visibleLength) : base(contentLength, visibleLength)
528 public override Visual.AlignType CalculatorTrackAlign()
530 return Visual.AlignType.CenterEnd;
533 public override Visual.AlignType CalculatorThumbAlign()
535 return Visual.AlignType.TopEnd;
538 public override Size CalculateTrackSize(float thickness, Extents trackPadding)
540 return new Size(thickness, visibleLength - trackPadding.Top - trackPadding.Bottom);
543 public override Vector2 CalculateTrackPosition(Extents trackPadding)
545 return new Vector2(-trackPadding.End, 0);
548 public override Size CalculateThumbSize(float thickness, Size trackSize)
550 return new Size(thickness, trackSize.Height * visibleLength / contentLength);
553 public override Vector2 CalculateThumbPosition(float position, Size trackSize, Size thumbSize, Extents trackPadding)
555 float padding = ((trackSize.Width - thumbSize.Width) / 2.0f) + trackPadding.End;
556 float pos = Math.Min(Math.Max(position, 0.0f), contentLength - visibleLength);
557 return new Vector2(-padding, trackPadding.Top + trackSize.Height * pos / contentLength);
560 public override Vector2 CalculateThumbPaddingPosition(Size trackSize, Size thumbSize, Vector2 thumbCurrentPosition, Extents trackPadding)
562 float padding = ((trackSize.Width - thumbSize.Width) / 2.0f) + trackPadding.End;
563 return new Vector2(-padding, thumbCurrentPosition.Y);
566 public override Vector2 CalculateThumbScrollPosition(float position, Size trackSize, Vector2 thumbPosition, Extents trackPadding)
568 float pos = Math.Min(Math.Max(position, 0.0f), contentLength - visibleLength);
569 return new Vector2(thumbPosition.X, trackPadding.Top + trackSize.Height * pos / contentLength);