5 changed files with 229 additions and 0 deletions
@ -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 |
|||
{ |
|||
/// <summary>
|
|||
/// A control that lets the user select from a range of values by moving a Thumb control along a Track.
|
|||
/// </summary>
|
|||
public class Slider : RangeBase |
|||
{ |
|||
/// <summary>
|
|||
/// Defines the <see cref="Orientation"/> property.
|
|||
/// </summary>
|
|||
public static readonly StyledProperty<Orientation> OrientationProperty = |
|||
PerspexProperty.Register<Slider, Orientation>(nameof(Orientation), Orientation.Horizontal); |
|||
|
|||
/// <summary>
|
|||
/// Defines the <see cref="IsSnapToTickEnabled"/> property.
|
|||
/// </summary>
|
|||
public static readonly StyledProperty<bool> IsSnapToTickEnabledProperty = |
|||
PerspexProperty.Register<Slider, bool>(nameof(IsSnapToTickEnabled), false); |
|||
|
|||
/// <summary>
|
|||
/// Defines the <see cref="TickFrequency"/> property.
|
|||
/// </summary>
|
|||
public static readonly StyledProperty<double> TickFrequencyProperty = |
|||
PerspexProperty.Register<Slider, double>(nameof(TickFrequencyProperty), 0.0); |
|||
|
|||
// Slider required parts
|
|||
private Track _track; |
|||
|
|||
/// <summary>
|
|||
/// Initializes static members of the <see cref="Slider"/> class.
|
|||
/// </summary>
|
|||
static Slider() |
|||
{ |
|||
Thumb.DragStartedEvent.AddClassHandler<Slider>(x => x.OnThumbDragStarted, RoutingStrategies.Bubble); |
|||
Thumb.DragDeltaEvent.AddClassHandler<Slider>(x => x.OnThumbDragDelta, RoutingStrategies.Bubble); |
|||
Thumb.DragCompletedEvent.AddClassHandler<Slider>(x => x.OnThumbDragCompleted, RoutingStrategies.Bubble); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Instantiates a new instance of the <see cref="Slider"/> class.
|
|||
/// </summary>
|
|||
public Slider() |
|||
{ |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the orientation of a <see cref="Slider"/>.
|
|||
/// </summary>
|
|||
public Orientation Orientation |
|||
{ |
|||
get { return GetValue(OrientationProperty); } |
|||
set { SetValue(OrientationProperty, value); } |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets a value that indicates whether the <see cref="Slider"/> automatically moves the <see cref="Thumb"/> to the closest tick mark.
|
|||
/// </summary>
|
|||
public bool IsSnapToTickEnabled |
|||
{ |
|||
get { return GetValue(IsSnapToTickEnabledProperty); } |
|||
set { SetValue(IsSnapToTickEnabledProperty, value); } |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the interval between tick marks.
|
|||
/// </summary>
|
|||
public double TickFrequency |
|||
{ |
|||
get { return GetValue(TickFrequencyProperty); } |
|||
set { SetValue(TickFrequencyProperty, value); } |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
protected override void OnTemplateApplied(TemplateAppliedEventArgs e) |
|||
{ |
|||
_track = e.NameScope.Get<Track>("PART_Track"); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Called when user start dragging the <see cref="Thumb"/>.
|
|||
/// </summary>
|
|||
/// <param name="e"></param>
|
|||
protected virtual void OnThumbDragStarted(VectorEventArgs e) |
|||
{ |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Called when user dragging the <see cref="Thumb"/>.
|
|||
/// </summary>
|
|||
/// <param name="e"></param>
|
|||
protected virtual void OnThumbDragDelta(VectorEventArgs e) |
|||
{ |
|||
Thumb thumb = e.Source as Thumb; |
|||
if (thumb != null && _track.Thumb == thumb) |
|||
{ |
|||
MoveToNextTick(_track.Value); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Called when user stop dragging the <see cref="Thumb"/>.
|
|||
/// </summary>
|
|||
/// <param name="e"></param>
|
|||
protected virtual void OnThumbDragCompleted(VectorEventArgs e) |
|||
{ |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Searches for the closest tick and sets Value to that tick.
|
|||
/// </summary>
|
|||
/// <param name="value">Value that want to snap to closest Tick.</param>
|
|||
private void MoveToNextTick(double value) |
|||
{ |
|||
double next = SnapToTick(Math.Max(Minimum, Math.Min(Maximum, value))); |
|||
if (next != value) |
|||
{ |
|||
Value = next; |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Snap the input 'value' to the closest tick.
|
|||
/// </summary>
|
|||
/// <param name="value">Value that want to snap to closest Tick.</param>
|
|||
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; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,78 @@ |
|||
<Styles xmlns="https://github.com/perspex"> |
|||
<Style Selector="Slider[Orientation=Horizontal]"> |
|||
<Setter Property="MinWidth" Value="104"/> |
|||
<Setter Property="MinHeight" Value="21"/> |
|||
<Setter Property="Template"> |
|||
<ControlTemplate> |
|||
<Grid> |
|||
<Grid.RowDefinitions> |
|||
<RowDefinition Height="Auto"/> |
|||
<RowDefinition Height="Auto" |
|||
MinHeight="26" /> |
|||
<RowDefinition Height="Auto"/> |
|||
</Grid.RowDefinitions> |
|||
<Border Name="TrackBackground" |
|||
Grid.Row="1" |
|||
Height="4" |
|||
Margin="10,0" |
|||
VerticalAlignment="Center"/> |
|||
<Track Name="PART_Track" Grid.Row="1"> |
|||
<Thumb MinWidth="26" MinHeight="26"> |
|||
<Thumb.Template> |
|||
<ControlTemplate> |
|||
<Grid> |
|||
<Ellipse Width="26" Height="26" Fill="#5534b4e3"/> |
|||
<Ellipse Width="10" Height="10" Fill="#FF34b4e3"/> |
|||
</Grid> |
|||
</ControlTemplate> |
|||
</Thumb.Template> |
|||
</Thumb> |
|||
</Track> |
|||
</Grid> |
|||
</ControlTemplate> |
|||
</Setter> |
|||
</Style> |
|||
<Style Selector="Slider[Orientation=Vertical]"> |
|||
<Setter Property="MinWidth" Value="21" /> |
|||
<Setter Property="MinHeight" Value="104"/> |
|||
<Setter Property="Template"> |
|||
<ControlTemplate> |
|||
<Grid> |
|||
<Grid.ColumnDefinitions> |
|||
<ColumnDefinition Width="Auto"/> |
|||
<ColumnDefinition Width="Auto" |
|||
MinWidth="26"/> |
|||
<ColumnDefinition Width="Auto"/> |
|||
</Grid.ColumnDefinitions> |
|||
<Border Name="TrackBackground" |
|||
Grid.Column="1" |
|||
Width="4" |
|||
Margin="0,10" |
|||
HorizontalAlignment="Center"/> |
|||
<Track Name="PART_Track" Grid.Column="1"> |
|||
<Thumb MinWidth="26" MinHeight="26"> |
|||
<Thumb.Template> |
|||
<ControlTemplate> |
|||
<Grid> |
|||
<Ellipse Width="26" Height="26" Fill="#5534b4e3"/> |
|||
<Ellipse Width="10" Height="10" Fill="#FF34b4e3"/> |
|||
</Grid> |
|||
</ControlTemplate> |
|||
</Thumb.Template> |
|||
</Thumb> |
|||
</Track> |
|||
</Grid> |
|||
</ControlTemplate> |
|||
</Setter> |
|||
</Style> |
|||
<Style Selector="Slider /template/ Track#PART_Track"> |
|||
<Setter Property="Minimum" Value="{TemplateBinding Minimum}"/> |
|||
<Setter Property="Maximum" Value="{TemplateBinding Maximum}"/> |
|||
<Setter Property="Value" Value="{TemplateBinding Path=Value, Mode=TwoWay}"/> |
|||
<Setter Property="Orientation" Value="{TemplateBinding Orientation}"/> |
|||
</Style> |
|||
<Style Selector="Slider /template/ Border#TrackBackground"> |
|||
<Setter Property="BorderThickness" Value="2"/> |
|||
<Setter Property="BorderBrush" Value="LightGray"/> |
|||
</Style> |
|||
</Styles> |
|||
Loading…
Reference in new issue