diff --git a/src/Avalonia.Controls/Converters/MenuScrollingVisibilityConverter.cs b/src/Avalonia.Controls/Converters/MenuScrollingVisibilityConverter.cs new file mode 100644 index 0000000000..e6420fe342 --- /dev/null +++ b/src/Avalonia.Controls/Converters/MenuScrollingVisibilityConverter.cs @@ -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 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; + } + } +} diff --git a/src/Avalonia.Controls/ScrollViewer.cs b/src/Avalonia.Controls/ScrollViewer.cs index c3f0dc0056..813d6967c3 100644 --- a/src/Avalonia.Controls/ScrollViewer.cs +++ b/src/Avalonia.Controls/ScrollViewer.cs @@ -387,6 +387,38 @@ namespace Avalonia.Controls /// IControl IScrollAnchorProvider.CurrentAnchor => null; // TODO: Implement + /// + /// Scrolls the content up one line. + /// + public void LineUp() + { + Offset -= new Vector(0, _smallChange.Height); + } + + /// + /// Scrolls the content down one line. + /// + public void LineDown() + { + Offset += new Vector(0, _smallChange.Height); + } + + /// + /// Scrolls the content left one line. + /// + public void LineLeft() + { + Offset -= new Vector(_smallChange.Width, 0); + } + + /// + /// Scrolls the content right one line. + /// + public void LineRight() + { + Offset += new Vector(_smallChange.Width, 0); + } + /// /// Scrolls to the top-left corner of the content. /// diff --git a/src/Avalonia.Themes.Default/ContextMenu.xaml b/src/Avalonia.Themes.Default/ContextMenu.xaml index 75f8f7c23d..9b84253c8a 100644 --- a/src/Avalonia.Themes.Default/ContextMenu.xaml +++ b/src/Avalonia.Themes.Default/ContextMenu.xaml @@ -10,7 +10,7 @@ BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Padding="{TemplateBinding Padding}"> - + - + - - - - - - - + + + + + + + + + + + + + + + +