committed by
GitHub
5 changed files with 202 additions and 48 deletions
@ -0,0 +1,64 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Globalization; |
|||
using Avalonia.Controls.Primitives; |
|||
using Avalonia.Data.Converters; |
|||
using Avalonia.Utilities; |
|||
|
|||
namespace Avalonia.Controls.Converters |
|||
{ |
|||
public class MenuScrollingVisibilityConverter : IMultiValueConverter |
|||
{ |
|||
public static readonly MenuScrollingVisibilityConverter Instance = new MenuScrollingVisibilityConverter(); |
|||
|
|||
public object Convert(IList<object> values, Type targetType, object parameter, CultureInfo culture) |
|||
{ |
|||
if (parameter == null || |
|||
values == null || |
|||
values.Count != 4 || |
|||
!(values[0] is ScrollBarVisibility visiblity) || |
|||
!(values[1] is double offset) || |
|||
!(values[2] is double extent) || |
|||
!(values[3] is double viewport)) |
|||
{ |
|||
return AvaloniaProperty.UnsetValue; |
|||
} |
|||
|
|||
if (visiblity == ScrollBarVisibility.Auto) |
|||
{ |
|||
if (extent == viewport) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
double target; |
|||
|
|||
if (parameter is double d) |
|||
{ |
|||
target = d; |
|||
} |
|||
else if (parameter is string s) |
|||
{ |
|||
target = double.Parse(s, NumberFormatInfo.InvariantInfo); |
|||
} |
|||
else |
|||
{ |
|||
return AvaloniaProperty.UnsetValue; |
|||
} |
|||
|
|||
// Calculate the percent so that we can see if we are near the edge of the range
|
|||
double percent = MathUtilities.Clamp(offset * 100.0 / (extent - viewport), 0, 100); |
|||
|
|||
if (MathUtilities.AreClose(percent, target)) |
|||
{ |
|||
// We are at the end of the range, so no need for this button to be shown
|
|||
return false; |
|||
} |
|||
|
|||
return true; |
|||
} |
|||
|
|||
return false; |
|||
} |
|||
} |
|||
} |
|||
@ -1,47 +1,105 @@ |
|||
<Style xmlns="https://github.com/avaloniaui" Selector="ScrollViewer"> |
|||
<Setter Property="Background" |
|||
Value="Transparent" /> |
|||
<Setter Property="Template"> |
|||
<ControlTemplate> |
|||
<Grid ColumnDefinitions="*,Auto" RowDefinitions="*,Auto"> |
|||
<ScrollContentPresenter Name="PART_ContentPresenter" |
|||
Background="{TemplateBinding Background}" |
|||
CanHorizontallyScroll="{TemplateBinding CanHorizontallyScroll}" |
|||
CanVerticallyScroll="{TemplateBinding CanVerticallyScroll}" |
|||
Content="{TemplateBinding Content}" |
|||
Extent="{TemplateBinding Extent, Mode=TwoWay}" |
|||
Margin="{TemplateBinding Padding}" |
|||
Offset="{TemplateBinding Offset, Mode=TwoWay}" |
|||
Viewport="{TemplateBinding Viewport, Mode=TwoWay}"> |
|||
<ScrollContentPresenter.GestureRecognizers> |
|||
<ScrollGestureRecognizer |
|||
CanHorizontallyScroll="{TemplateBinding CanHorizontallyScroll}" |
|||
CanVerticallyScroll="{TemplateBinding CanVerticallyScroll}" |
|||
<Styles xmlns="https://github.com/avaloniaui" |
|||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
|||
xmlns:converters="clr-namespace:Avalonia.Controls.Converters;assembly=Avalonia.Controls"> |
|||
<Style Selector="ScrollViewer"> |
|||
<Setter Property="Background" |
|||
Value="Transparent" /> |
|||
<Setter Property="Template"> |
|||
<ControlTemplate> |
|||
<Grid ColumnDefinitions="*,Auto" RowDefinitions="*,Auto"> |
|||
<ScrollContentPresenter Name="PART_ContentPresenter" |
|||
Background="{TemplateBinding Background}" |
|||
CanHorizontallyScroll="{TemplateBinding CanHorizontallyScroll}" |
|||
CanVerticallyScroll="{TemplateBinding CanVerticallyScroll}" |
|||
Content="{TemplateBinding Content}" |
|||
Extent="{TemplateBinding Extent, Mode=TwoWay}" |
|||
Margin="{TemplateBinding Padding}" |
|||
Offset="{TemplateBinding Offset, Mode=TwoWay}" |
|||
Viewport="{TemplateBinding Viewport, Mode=TwoWay}"> |
|||
<ScrollContentPresenter.GestureRecognizers> |
|||
<ScrollGestureRecognizer |
|||
CanHorizontallyScroll="{TemplateBinding CanHorizontallyScroll}" |
|||
CanVerticallyScroll="{TemplateBinding CanVerticallyScroll}" |
|||
/> |
|||
</ScrollContentPresenter.GestureRecognizers> |
|||
</ScrollContentPresenter> |
|||
<ScrollBar Name="horizontalScrollBar" |
|||
Orientation="Horizontal" |
|||
LargeChange="{Binding LargeChange.Width, RelativeSource={RelativeSource TemplatedParent}}" |
|||
SmallChange="{Binding SmallChange.Width, RelativeSource={RelativeSource TemplatedParent}}" |
|||
Maximum="{TemplateBinding HorizontalScrollBarMaximum}" |
|||
Value="{TemplateBinding HorizontalScrollBarValue, Mode=TwoWay}" |
|||
ViewportSize="{TemplateBinding HorizontalScrollBarViewportSize}" |
|||
Visibility="{TemplateBinding HorizontalScrollBarVisibility}" |
|||
Grid.Row="1" |
|||
Focusable="False"/> |
|||
<ScrollBar Name="verticalScrollBar" |
|||
Orientation="Vertical" |
|||
LargeChange="{Binding LargeChange.Height, RelativeSource={RelativeSource TemplatedParent}}" |
|||
SmallChange="{Binding SmallChange.Height, RelativeSource={RelativeSource TemplatedParent}}" |
|||
Maximum="{TemplateBinding VerticalScrollBarMaximum}" |
|||
Value="{TemplateBinding VerticalScrollBarValue, Mode=TwoWay}" |
|||
ViewportSize="{TemplateBinding VerticalScrollBarViewportSize}" |
|||
Visibility="{TemplateBinding VerticalScrollBarVisibility}" |
|||
Grid.Column="1" |
|||
Focusable="False"/> |
|||
<Panel Grid.Row="1" Grid.Column="1" Background="{DynamicResource ThemeControlMidBrush}"/> |
|||
</Grid> |
|||
</ControlTemplate> |
|||
</Setter> |
|||
</Style> |
|||
</ScrollContentPresenter.GestureRecognizers> |
|||
</ScrollContentPresenter> |
|||
<ScrollBar Name="horizontalScrollBar" |
|||
Orientation="Horizontal" |
|||
LargeChange="{Binding LargeChange.Width, RelativeSource={RelativeSource TemplatedParent}}" |
|||
SmallChange="{Binding SmallChange.Width, RelativeSource={RelativeSource TemplatedParent}}" |
|||
Maximum="{TemplateBinding HorizontalScrollBarMaximum}" |
|||
Value="{TemplateBinding HorizontalScrollBarValue, Mode=TwoWay}" |
|||
ViewportSize="{TemplateBinding HorizontalScrollBarViewportSize}" |
|||
Visibility="{TemplateBinding HorizontalScrollBarVisibility}" |
|||
Grid.Row="1" |
|||
Focusable="False"/> |
|||
<ScrollBar Name="verticalScrollBar" |
|||
Orientation="Vertical" |
|||
LargeChange="{Binding LargeChange.Height, RelativeSource={RelativeSource TemplatedParent}}" |
|||
SmallChange="{Binding SmallChange.Height, RelativeSource={RelativeSource TemplatedParent}}" |
|||
Maximum="{TemplateBinding VerticalScrollBarMaximum}" |
|||
Value="{TemplateBinding VerticalScrollBarValue, Mode=TwoWay}" |
|||
ViewportSize="{TemplateBinding VerticalScrollBarViewportSize}" |
|||
Visibility="{TemplateBinding VerticalScrollBarVisibility}" |
|||
Grid.Column="1" |
|||
Focusable="False"/> |
|||
<Panel Grid.Row="1" Grid.Column="1" Background="{DynamicResource ThemeControlMidBrush}"/> |
|||
</Grid> |
|||
</ControlTemplate> |
|||
</Setter> |
|||
</Style> |
|||
|
|||
<Style Selector="ScrollViewer.menuscroller"> |
|||
<Setter Property="Template"> |
|||
<ControlTemplate> |
|||
<DockPanel> |
|||
<RepeatButton DockPanel.Dock="Top" |
|||
BorderThickness="0" |
|||
Background="Transparent" |
|||
Command="{Binding LineUp, RelativeSource={RelativeSource TemplatedParent}}"> |
|||
<RepeatButton.IsVisible> |
|||
<MultiBinding Converter="{x:Static converters:MenuScrollingVisibilityConverter.Instance}" |
|||
ConverterParameter="0"> |
|||
<Binding RelativeSource="{RelativeSource TemplatedParent}" Path="VerticalScrollBarVisibility"/> |
|||
<Binding RelativeSource="{RelativeSource TemplatedParent}" Path="Offset.Y"/> |
|||
<Binding RelativeSource="{RelativeSource TemplatedParent}" Path="Extent.Height"/> |
|||
<Binding RelativeSource="{RelativeSource TemplatedParent}" Path="Viewport.Height"/> |
|||
</MultiBinding> |
|||
</RepeatButton.IsVisible> |
|||
<Path Data="M 0 4 L 8 4 L 4 0 Z"/> |
|||
</RepeatButton> |
|||
<RepeatButton DockPanel.Dock="Bottom" |
|||
BorderThickness="0" |
|||
Background="Transparent" |
|||
Command="{Binding LineDown, RelativeSource={RelativeSource TemplatedParent}}"> |
|||
<RepeatButton.IsVisible> |
|||
<MultiBinding Converter="{x:Static converters:MenuScrollingVisibilityConverter.Instance}" |
|||
ConverterParameter="100"> |
|||
<Binding RelativeSource="{RelativeSource TemplatedParent}" Path="VerticalScrollBarVisibility"/> |
|||
<Binding RelativeSource="{RelativeSource TemplatedParent}" Path="Offset.Y"/> |
|||
<Binding RelativeSource="{RelativeSource TemplatedParent}" Path="Extent.Height"/> |
|||
<Binding RelativeSource="{RelativeSource TemplatedParent}" Path="Viewport.Height"/> |
|||
</MultiBinding> |
|||
</RepeatButton.IsVisible> |
|||
<Path Data="M 0 0 L 4 4 L 8 0 Z"/> |
|||
</RepeatButton> |
|||
<ScrollContentPresenter Name="PART_ContentPresenter" |
|||
CanHorizontallyScroll="{TemplateBinding CanHorizontallyScroll}" |
|||
CanVerticallyScroll="{TemplateBinding CanVerticallyScroll}" |
|||
Content="{TemplateBinding Content}" |
|||
Extent="{TemplateBinding Extent, Mode=TwoWay}" |
|||
Margin="{TemplateBinding Padding}" |
|||
Offset="{TemplateBinding Offset, Mode=TwoWay}" |
|||
Viewport="{TemplateBinding Viewport, Mode=TwoWay}"/> |
|||
</DockPanel> |
|||
</ControlTemplate> |
|||
</Setter> |
|||
</Style> |
|||
<Style Selector="ScrollViewer.menuscroller /template/ RepeatButton > Path"> |
|||
<Setter Property="Fill" Value="{DynamicResource ThemeForegroundLowBrush}" /> |
|||
</Style> |
|||
|
|||
<Style Selector="ScrollViewer.menuscroller /template/ RepeatButton:pointerover > Path"> |
|||
<Setter Property="Fill" Value="{DynamicResource ThemeAccentBrush}" /> |
|||
</Style> |
|||
</Styles> |
|||
|
|||
Loading…
Reference in new issue