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> </Style>
</UserControl.Styles> </UserControl.Styles>
<StackPanel> <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="Minimum" Value="{Binding #range.Minimum, Mode=TwoWay}" />
<u:NumericDoubleUpDown InnerLeftContent="Maximum" Value="{Binding #range.Maximum, Mode=TwoWay}" /> <u:NumericDoubleUpDown InnerLeftContent="Maximum" Value="{Binding #range.Maximum, Mode=TwoWay}" />
<u:NumericDoubleUpDown InnerLeftContent="LowerValue" Value="{Binding #range.LowerValue, Mode=TwoWay}" /> <u:NumericDoubleUpDown InnerLeftContent="LowerValue" Value="{Binding #range.LowerValue, Mode=TwoWay}" />

View File

@@ -5,46 +5,198 @@
<!-- Add Resources Here --> <!-- Add Resources Here -->
<ControlTheme x:Key="{x:Type u:RangeSlider}" TargetType="u:RangeSlider"> <ControlTheme x:Key="{x:Type u:RangeSlider}" TargetType="u:RangeSlider">
<Setter Property="TrackWidth" Value="8" /> <Setter Property="TrackWidth" Value="8" />
<Setter Property="Template"> <Style Selector="^:horizontal">
<ControlTemplate TargetType="u:RangeSlider"> <Setter Property="Template">
<u:RangeTrack <ControlTemplate TargetType="u:RangeSlider">
Name="{x:Static u:RangeSlider.PART_Track}" <DataValidationErrors>
LowerValue="{Binding LowerValue, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}" <Grid
Maximum="{Binding Maximum, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}" x:Name="SliderContainer"
Minimum="{Binding Minimum, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}" Margin="{TemplateBinding Padding}"
UpperValue="{Binding UpperValue, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}"> Background="Transparent"
<u:RangeTrack.LowerSection> RowDefinitions="Auto,Auto,Auto">
<Border <Grid.Styles>
Height="{TemplateBinding TrackWidth}" <Style Selector="TickBar">
Background="Gray" <Setter Property="ReservedSpace" Value="{Binding #PART_Track.LowerThumb.Bounds}" />
CornerRadius="100" /> </Style>
</u:RangeTrack.LowerSection> </Grid.Styles>
<u:RangeTrack.LowerThumb> <TickBar
<Thumb Name="TopTickBar"
Width="16" Grid.Row="0"
Height="16" Height="{DynamicResource SliderTickHorizontalHeight}"
Theme="{DynamicResource SliderThumbTheme}" /> Margin="0,0,0,4"
</u:RangeTrack.LowerThumb> VerticalAlignment="Bottom"
<u:RangeTrack.InnerSection> Fill="{DynamicResource SliderTickForeground}"
<Border IsVisible="False"
Height="{TemplateBinding TrackWidth}" Maximum="{TemplateBinding u:RangeSlider.Maximum}"
Background="Blue" Minimum="{TemplateBinding u:RangeSlider.Minimum}"
CornerRadius="100" /> Orientation="{TemplateBinding u:RangeSlider.Orientation}"
</u:RangeTrack.InnerSection> Placement="Top"
<u:RangeTrack.UpperThumb> TickFrequency="{TemplateBinding u:RangeSlider.TickFrequency}"
<Thumb Ticks="{TemplateBinding Ticks}" />
Width="16" <TickBar
Height="16" Name="BottomTickBar"
Theme="{DynamicResource SliderThumbTheme}" /> Grid.Row="2"
</u:RangeTrack.UpperThumb> Height="{DynamicResource SliderTickHorizontalHeight}"
<u:RangeTrack.UpperSection> Margin="0,4,0,0"
<Border VerticalAlignment="Top"
Height="{TemplateBinding TrackWidth}" Fill="{DynamicResource SliderTickForeground}"
Background="Gray" IsVisible="False"
CornerRadius="100" /> Maximum="{TemplateBinding u:RangeSlider.Maximum}"
</u:RangeTrack.UpperSection> Minimum="{TemplateBinding u:RangeSlider.Minimum}"
</u:RangeTrack> Orientation="{TemplateBinding u:RangeSlider.Orientation}"
</ControlTemplate> Placement="Bottom"
</Setter> 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}"
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="^: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> </ControlTheme>
</ResourceDictionary> </ResourceDictionary>

View File

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