// 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.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(TickFrequency), 0.0); // Slider required parts private Track _track; /// /// Initializes static members of the class. /// static Slider() { PseudoClass(OrientationProperty, o => o == Perspex.Controls.Orientation.Vertical, ":vertical"); PseudoClass(OrientationProperty, o => o == Perspex.Controls.Orientation.Horizontal, ":horizontal"); 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; } } }