feat: enable tick visual.

This commit is contained in:
rabbitism
2024-01-19 19:12:33 +08:00
parent 33543c7ebf
commit 48bdb2cfb9
3 changed files with 209 additions and 64 deletions

View File

@@ -12,7 +12,7 @@
</Style>
</UserControl.Styles>
<StackPanel>
<u:RangeSlider Name="range" Height="24" TickFrequency="5" IsSnapToTick="True"/>
<u:RangeSlider Name="range" TickFrequency="5" IsSnapToTick="True" TickPlacement="TopLeft"/>
<u:NumericDoubleUpDown InnerLeftContent="Minimum" Value="{Binding #range.Minimum, Mode=TwoWay}" />
<u:NumericDoubleUpDown InnerLeftContent="Maximum" Value="{Binding #range.Maximum, Mode=TwoWay}" />
<u:NumericDoubleUpDown InnerLeftContent="LowerValue" Value="{Binding #range.LowerValue, Mode=TwoWay}" />

View File

@@ -5,10 +5,53 @@
<!-- Add Resources Here -->
<ControlTheme x:Key="{x:Type u:RangeSlider}" TargetType="u:RangeSlider">
<Setter Property="TrackWidth" Value="8" />
<Style Selector="^:horizontal">
<Setter Property="Template">
<ControlTemplate TargetType="u:RangeSlider">
<DataValidationErrors>
<Grid
x:Name="SliderContainer"
Margin="{TemplateBinding Padding}"
Background="Transparent"
RowDefinitions="Auto,Auto,Auto">
<Grid.Styles>
<Style Selector="TickBar">
<Setter Property="ReservedSpace" Value="{Binding #PART_Track.LowerThumb.Bounds}" />
</Style>
</Grid.Styles>
<TickBar
Name="TopTickBar"
Grid.Row="0"
Height="{DynamicResource SliderTickHorizontalHeight}"
Margin="0,0,0,4"
VerticalAlignment="Bottom"
Fill="{DynamicResource SliderTickForeground}"
IsVisible="False"
Maximum="{TemplateBinding u:RangeSlider.Maximum}"
Minimum="{TemplateBinding u:RangeSlider.Minimum}"
Orientation="{TemplateBinding u:RangeSlider.Orientation}"
Placement="Top"
TickFrequency="{TemplateBinding u:RangeSlider.TickFrequency}"
Ticks="{TemplateBinding Ticks}" />
<TickBar
Name="BottomTickBar"
Grid.Row="2"
Height="{DynamicResource SliderTickHorizontalHeight}"
Margin="0,4,0,0"
VerticalAlignment="Top"
Fill="{DynamicResource SliderTickForeground}"
IsVisible="False"
Maximum="{TemplateBinding u:RangeSlider.Maximum}"
Minimum="{TemplateBinding u:RangeSlider.Minimum}"
Orientation="{TemplateBinding u:RangeSlider.Orientation}"
Placement="Bottom"
TickFrequency="{TemplateBinding u:RangeSlider.TickFrequency}"
Ticks="{TemplateBinding Ticks}" />
<u:RangeTrack
Name="{x:Static u:RangeSlider.PART_Track}"
Grid.Row="1"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
LowerValue="{Binding LowerValue, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}"
Maximum="{Binding Maximum, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}"
Minimum="{Binding Minimum, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}"
@@ -44,7 +87,116 @@
CornerRadius="100" />
</u:RangeTrack.UpperSection>
</u:RangeTrack>
</Grid>
</DataValidationErrors>
</ControlTemplate>
</Setter>
</Style>
<Style Selector="^:vertical">
<Setter Property="Template">
<ControlTemplate TargetType="u:RangeSlider">
<DataValidationErrors>
<Grid
x:Name="SliderContainer"
Margin="{TemplateBinding Padding}"
Background="{DynamicResource SliderContainerBackground}"
ColumnDefinitions="Auto,Auto,Auto">
<Grid.Styles>
<Style Selector="TickBar">
<Setter Property="ReservedSpace" Value="{Binding #PART_Track.LowerThumb.Bounds}" />
</Style>
</Grid.Styles>
<TickBar
Name="LeftTickBar"
Grid.Column="0"
Width="{DynamicResource SliderTickVerticalWidth}"
Margin="0,0,4,0"
HorizontalAlignment="Right"
Fill="{DynamicResource SliderTickForeground}"
IsVisible="False"
Maximum="{TemplateBinding u:RangeSlider.Maximum}"
Minimum="{TemplateBinding u:RangeSlider.Minimum}"
Orientation="{TemplateBinding u:RangeSlider.Orientation}"
Placement="Left"
TickFrequency="{TemplateBinding u:RangeSlider.TickFrequency}"
Ticks="{TemplateBinding Ticks}" />
<TickBar
Name="RightTickBar"
Grid.Column="2"
Width="{DynamicResource SliderTickVerticalWidth}"
Margin="4,0,0,0"
HorizontalAlignment="Left"
Fill="{DynamicResource SliderTickForeground}"
IsVisible="False"
Maximum="{TemplateBinding u:RangeSlider.Maximum}"
Minimum="{TemplateBinding u:RangeSlider.Minimum}"
Orientation="{TemplateBinding u:RangeSlider.Orientation}"
Placement="Right"
TickFrequency="{TemplateBinding u:RangeSlider.TickFrequency}"
Ticks="{TemplateBinding Ticks}" />
<u:RangeTrack
Name="{x:Static u:RangeSlider.PART_Track}"
Grid.Column="1"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
LowerValue="{Binding LowerValue, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}"
Maximum="{Binding Maximum, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}"
Minimum="{Binding Minimum, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}"
UpperValue="{Binding UpperValue, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}">
<u:RangeTrack.LowerSection>
<Border
Height="{TemplateBinding TrackWidth}"
Background="Gray"
CornerRadius="100" />
</u:RangeTrack.LowerSection>
<u:RangeTrack.LowerThumb>
<Thumb
Width="16"
Height="16"
Theme="{DynamicResource SliderThumbTheme}" />
</u:RangeTrack.LowerThumb>
<u:RangeTrack.InnerSection>
<Border
Height="{TemplateBinding TrackWidth}"
Background="Blue"
CornerRadius="100" />
</u:RangeTrack.InnerSection>
<u:RangeTrack.UpperThumb>
<Thumb
Width="16"
Height="16"
Theme="{DynamicResource SliderThumbTheme}" />
</u:RangeTrack.UpperThumb>
<u:RangeTrack.UpperSection>
<Border
Height="{TemplateBinding TrackWidth}"
Background="Gray"
CornerRadius="100" />
</u:RangeTrack.UpperSection>
</u:RangeTrack>
</Grid>
</DataValidationErrors>
</ControlTemplate>
</Setter>
</Style>
<Style Selector="^[TickPlacement=TopLeft] /template/ TickBar#LeftTickBar, ^[TickPlacement=Outside] /template/ TickBar#LeftTickBar">
<Setter Property="IsVisible" Value="True" />
</Style>
<Style Selector="^[TickPlacement=TopLeft] /template/ TickBar#TopTickBar, ^[TickPlacement=Outside] /template/ TickBar#TopTickBar">
<Setter Property="IsVisible" Value="True" />
</Style>
<Style Selector="^[TickPlacement=BottomRight] /template/ TickBar#BottomTickBar, ^[TickPlacement=Outside] /template/ TickBar#BottomTickBar">
<Setter Property="IsVisible" Value="True" />
</Style>
<Style Selector="^[TickPlacement=BottomRight] /template/ TickBar#RightTickBar, ^[TickPlacement=Outside] /template/ TickBar#RightTickBar">
<Setter Property="IsVisible" Value="True" />
</Style>
<Style Selector="^:error /template/ Thumb#thumb">
<Setter Property="BorderBrush" Value="{DynamicResource DataValidationErrorsSelectedBorderBrush}" />
</Style>
</ControlTheme>
</ResourceDictionary>

View File

@@ -17,8 +17,8 @@ namespace Ursa.Controls;
public class RangeSlider: TemplatedControl
{
public const string PART_Track = "PART_Track";
private const string PC_Horizontal= "horizontal";
private const string PC_Vertical = "vertical";
private const string PC_Horizontal= ":horizontal";
private const string PC_Vertical = ":vertical";
private RangeTrack? _track;
private bool _isDragging;
@@ -129,11 +129,15 @@ public class RangeSlider: TemplatedControl
UpperValueProperty.OverrideDefaultValue<RangeSlider>(100);
}
public RangeSlider()
{
UpdatePseudoClasses(Orientation);
}
private void OnOrientationChanged(AvaloniaPropertyChangedEventArgs<Orientation> args)
{
var value = args.NewValue.Value;
PseudoClasses.Set(PC_Horizontal, value == Orientation.Horizontal);
PseudoClasses.Set(PC_Vertical, value == Orientation.Vertical);
UpdatePseudoClasses(value);
}
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
@@ -146,10 +150,10 @@ public class RangeSlider: TemplatedControl
_pointerMoveDisposable = this.AddDisposableHandler(PointerMovedEvent, PointerMove, RoutingStrategies.Tunnel);
_pointerPressedDisposable = this.AddDisposableHandler(PointerPressedEvent, PointerPress, RoutingStrategies.Tunnel);
_pointerReleasedDisposable = this.AddDisposableHandler(PointerReleasedEvent, PointerRelease, RoutingStrategies.Tunnel);
}
private Thumb? _currentThumb;
private void PointerPress(object sender, PointerPressedEventArgs e)
{
if (e.GetCurrentPoint(this).Properties.IsLeftButtonPressed)
@@ -266,22 +270,11 @@ public class RangeSlider: TemplatedControl
var range = Maximum - Minimum;
var finalValue = ratio * range + Minimum;
return finalValue;
/*
var trackLength = _track.GetTrackLength();
var thumbLength = _track.GetThumbLength() * 0.5;
if(pointPosition < thumbLength * 0.5)
return isHorizontal? Minimum : Maximum;
if (pointPosition > trackLength - thumbLength * 0.5)
return isHorizontal? Maximum : Minimum;
trackLength -= thumbLength * 2;
pointPosition = MathUtilities.Clamp(pointPosition / trackLength, 0.0, 1.0);
var invert = isHorizontal
? IsDirectionReversed ? 1.0 : 0
: IsDirectionReversed ? 0 : 1.0;
var calValue = Math.Abs(invert - pointPosition);
var range = Maximum - Minimum;
var finalValue = calValue * range + Minimum;
return finalValue;
*/
}
private void UpdatePseudoClasses(Orientation o)
{
this.PseudoClasses.Set(PC_Vertical, o == Orientation.Vertical);
this.PseudoClasses.Set(PC_Horizontal, o == Orientation.Horizontal);
}
}