diff --git a/src/Perspex.Controls/Perspex.Controls.csproj b/src/Perspex.Controls/Perspex.Controls.csproj index 58aee7f2a5..d0d54a0eb6 100644 --- a/src/Perspex.Controls/Perspex.Controls.csproj +++ b/src/Perspex.Controls/Perspex.Controls.csproj @@ -72,6 +72,7 @@ + diff --git a/src/Perspex.Controls/Slider.cs b/src/Perspex.Controls/Slider.cs new file mode 100644 index 0000000000..9faa2ccdf3 --- /dev/null +++ b/src/Perspex.Controls/Slider.cs @@ -0,0 +1,146 @@ +// Copyright (c) The Perspex Project. All rights reserved. +// Licensed under the MIT license. See licence.md file in the project root for full license information. + +using System; +using Perspex.Controls.Primitives; +using Perspex.Controls.Templates; +using Perspex.Input; +using Perspex.Interactivity; + +namespace Perspex.Controls +{ + /// + /// A control that lets the user select from a range of values by moving a Thumb control along a Track. + /// + public class Slider : RangeBase + { + /// + /// Defines the property. + /// + public static readonly StyledProperty OrientationProperty = + PerspexProperty.Register(nameof(Orientation), Orientation.Horizontal); + + /// + /// Defines the property. + /// + public static readonly StyledProperty IsSnapToTickEnabledProperty = + PerspexProperty.Register(nameof(IsSnapToTickEnabled), false); + + /// + /// Defines the property. + /// + public static readonly StyledProperty TickFrequencyProperty = + PerspexProperty.Register(nameof(TickFrequencyProperty), 0.0); + + // Slider required parts + private Track _track; + + /// + /// Initializes static members of the class. + /// + static Slider() + { + Thumb.DragStartedEvent.AddClassHandler(x => x.OnThumbDragStarted, RoutingStrategies.Bubble); + Thumb.DragDeltaEvent.AddClassHandler(x => x.OnThumbDragDelta, RoutingStrategies.Bubble); + Thumb.DragCompletedEvent.AddClassHandler(x => x.OnThumbDragCompleted, RoutingStrategies.Bubble); + } + + /// + /// Instantiates a new instance of the class. + /// + public Slider() + { + } + + /// + /// Gets or sets the orientation of a . + /// + public Orientation Orientation + { + get { return GetValue(OrientationProperty); } + set { SetValue(OrientationProperty, value); } + } + + /// + /// Gets or sets a value that indicates whether the automatically moves the to the closest tick mark. + /// + public bool IsSnapToTickEnabled + { + get { return GetValue(IsSnapToTickEnabledProperty); } + set { SetValue(IsSnapToTickEnabledProperty, value); } + } + + /// + /// Gets or sets the interval between tick marks. + /// + public double TickFrequency + { + get { return GetValue(TickFrequencyProperty); } + set { SetValue(TickFrequencyProperty, value); } + } + + /// + protected override void OnTemplateApplied(TemplateAppliedEventArgs e) + { + _track = e.NameScope.Get("PART_Track"); + } + + /// + /// Called when user start dragging the . + /// + /// + protected virtual void OnThumbDragStarted(VectorEventArgs e) + { + } + + /// + /// Called when user dragging the . + /// + /// + protected virtual void OnThumbDragDelta(VectorEventArgs e) + { + Thumb thumb = e.Source as Thumb; + if (thumb != null && _track.Thumb == thumb) + { + MoveToNextTick(_track.Value); + } + } + + /// + /// Called when user stop dragging the . + /// + /// + protected virtual void OnThumbDragCompleted(VectorEventArgs e) + { + } + + /// + /// Searches for the closest tick and sets Value to that tick. + /// + /// Value that want to snap to closest Tick. + private void MoveToNextTick(double value) + { + double next = SnapToTick(Math.Max(Minimum, Math.Min(Maximum, value))); + if (next != value) + { + Value = next; + } + } + + /// + /// Snap the input 'value' to the closest tick. + /// + /// Value that want to snap to closest Tick. + private double SnapToTick(double value) + { + if (IsSnapToTickEnabled && TickFrequency > 0.0) + { + double previous = Minimum + (Math.Round(((value - Minimum) / TickFrequency)) * TickFrequency); + double next = Math.Min(Maximum, previous + TickFrequency); + value = value > (previous + next) * 0.5 ? next : previous; + } + + return value; + } + } +} \ No newline at end of file diff --git a/src/Perspex.Themes.Default/DefaultTheme.paml b/src/Perspex.Themes.Default/DefaultTheme.paml index f1b5776f83..78f80308ea 100644 --- a/src/Perspex.Themes.Default/DefaultTheme.paml +++ b/src/Perspex.Themes.Default/DefaultTheme.paml @@ -17,6 +17,7 @@ + diff --git a/src/Perspex.Themes.Default/Perspex.Themes.Default.csproj b/src/Perspex.Themes.Default/Perspex.Themes.Default.csproj index cc61488af2..db8e0ce93f 100644 --- a/src/Perspex.Themes.Default/Perspex.Themes.Default.csproj +++ b/src/Perspex.Themes.Default/Perspex.Themes.Default.csproj @@ -193,6 +193,9 @@ Designer + + Designer +