|
|
|
@ -4,7 +4,11 @@ |
|
|
|
// Licensed to The Avalonia Project under MIT License, courtesy of The .NET Foundation.
|
|
|
|
|
|
|
|
using System; |
|
|
|
using System.Collections.Generic; |
|
|
|
using System.Linq; |
|
|
|
using Avalonia.Controls.Primitives; |
|
|
|
using Avalonia.Input; |
|
|
|
using Avalonia.Interactivity; |
|
|
|
using Avalonia.Layout; |
|
|
|
|
|
|
|
namespace Avalonia.Controls |
|
|
|
@ -12,7 +16,7 @@ namespace Avalonia.Controls |
|
|
|
/// <summary>
|
|
|
|
/// A panel which lays out its children horizontally or vertically.
|
|
|
|
/// </summary>
|
|
|
|
public class StackPanel : Panel, INavigableContainer |
|
|
|
public class StackPanel : Panel, INavigableContainer, IScrollSnapPointsInfo |
|
|
|
{ |
|
|
|
/// <summary>
|
|
|
|
/// Defines the <see cref="Spacing"/> property.
|
|
|
|
@ -26,6 +30,34 @@ namespace Avalonia.Controls |
|
|
|
public static readonly StyledProperty<Orientation> OrientationProperty = |
|
|
|
StackLayout.OrientationProperty.AddOwner<StackPanel>(); |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Defines the <see cref="AreHorizontalSnapPointsRegular"/> property.
|
|
|
|
/// </summary>
|
|
|
|
public static readonly StyledProperty<bool> AreHorizontalSnapPointsRegularProperty = |
|
|
|
AvaloniaProperty.Register<StackPanel, bool>(nameof(AreHorizontalSnapPointsRegular)); |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Defines the <see cref="AreVerticalSnapPointsRegular"/> property.
|
|
|
|
/// </summary>
|
|
|
|
public static readonly StyledProperty<bool> AreVerticalSnapPointsRegularProperty = |
|
|
|
AvaloniaProperty.Register<StackPanel, bool>(nameof(AreVerticalSnapPointsRegular)); |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Defines the <see cref="HorizontalSnapPointsChanged"/> event.
|
|
|
|
/// </summary>
|
|
|
|
public static readonly RoutedEvent<RoutedEventArgs> HorizontalSnapPointsChangedEvent = |
|
|
|
RoutedEvent.Register<StackPanel, RoutedEventArgs>( |
|
|
|
nameof(HorizontalSnapPointsChanged), |
|
|
|
RoutingStrategies.Bubble); |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Defines the <see cref="VerticalSnapPointsChanged"/> event.
|
|
|
|
/// </summary>
|
|
|
|
public static readonly RoutedEvent<RoutedEventArgs> VerticalSnapPointsChangedEvent = |
|
|
|
RoutedEvent.Register<StackPanel, RoutedEventArgs>( |
|
|
|
nameof(VerticalSnapPointsChanged), |
|
|
|
RoutingStrategies.Bubble); |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Initializes static members of the <see cref="StackPanel"/> class.
|
|
|
|
/// </summary>
|
|
|
|
@ -53,6 +85,31 @@ namespace Avalonia.Controls |
|
|
|
set { SetValue(OrientationProperty, value); } |
|
|
|
} |
|
|
|
|
|
|
|
public event EventHandler<RoutedEventArgs>? HorizontalSnapPointsChanged |
|
|
|
{ |
|
|
|
add => AddHandler(HorizontalSnapPointsChangedEvent, value); |
|
|
|
remove => RemoveHandler(HorizontalSnapPointsChangedEvent, value); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public event EventHandler<RoutedEventArgs>? VerticalSnapPointsChanged |
|
|
|
{ |
|
|
|
add => AddHandler(VerticalSnapPointsChangedEvent, value); |
|
|
|
remove => RemoveHandler(VerticalSnapPointsChangedEvent, value); |
|
|
|
} |
|
|
|
|
|
|
|
public bool AreHorizontalSnapPointsRegular |
|
|
|
{ |
|
|
|
get { return GetValue(AreHorizontalSnapPointsRegularProperty); } |
|
|
|
set { SetValue(AreHorizontalSnapPointsRegularProperty, value); } |
|
|
|
} |
|
|
|
|
|
|
|
public bool AreVerticalSnapPointsRegular |
|
|
|
{ |
|
|
|
get { return GetValue(AreVerticalSnapPointsRegularProperty); } |
|
|
|
set { SetValue(AreVerticalSnapPointsRegularProperty, value); } |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Gets the next control in the specified direction.
|
|
|
|
/// </summary>
|
|
|
|
@ -274,6 +331,8 @@ namespace Avalonia.Controls |
|
|
|
ArrangeChild(child, rcChild, finalSize, Orientation); |
|
|
|
} |
|
|
|
|
|
|
|
RaiseEvent(new RoutedEventArgs(Orientation == Orientation.Horizontal ? HorizontalSnapPointsChangedEvent : VerticalSnapPointsChangedEvent)); |
|
|
|
|
|
|
|
return finalSize; |
|
|
|
} |
|
|
|
|
|
|
|
@ -285,5 +344,122 @@ namespace Avalonia.Controls |
|
|
|
{ |
|
|
|
child.Arrange(rect); |
|
|
|
} |
|
|
|
|
|
|
|
public IReadOnlyList<double> GetIrregularSnapPoints(Orientation orientation, SnapPointsAlignment snapPointsAlignment) |
|
|
|
{ |
|
|
|
var snapPoints = new List<double>(); |
|
|
|
|
|
|
|
switch (orientation) |
|
|
|
{ |
|
|
|
case Orientation.Horizontal: |
|
|
|
if (AreHorizontalSnapPointsRegular) |
|
|
|
throw new InvalidOperationException(); |
|
|
|
if (Orientation == Orientation.Horizontal) |
|
|
|
{ |
|
|
|
foreach(var child in VisualChildren) |
|
|
|
{ |
|
|
|
double snapPoint = 0; |
|
|
|
|
|
|
|
switch (snapPointsAlignment) |
|
|
|
{ |
|
|
|
case SnapPointsAlignment.Near: |
|
|
|
snapPoint = child.Bounds.Left; |
|
|
|
break; |
|
|
|
case SnapPointsAlignment.Center: |
|
|
|
snapPoint = child.Bounds.Center.X; |
|
|
|
break; |
|
|
|
case SnapPointsAlignment.Far: |
|
|
|
snapPoint = child.Bounds.Right; |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
snapPoints.Add(snapPoint); |
|
|
|
} |
|
|
|
} |
|
|
|
break; |
|
|
|
case Orientation.Vertical: |
|
|
|
if (AreVerticalSnapPointsRegular) |
|
|
|
throw new InvalidOperationException(); |
|
|
|
if (Orientation == Orientation.Vertical) |
|
|
|
{ |
|
|
|
foreach (var child in VisualChildren) |
|
|
|
{ |
|
|
|
double snapPoint = 0; |
|
|
|
|
|
|
|
switch (snapPointsAlignment) |
|
|
|
{ |
|
|
|
case SnapPointsAlignment.Near: |
|
|
|
snapPoint = child.Bounds.Top; |
|
|
|
break; |
|
|
|
case SnapPointsAlignment.Center: |
|
|
|
snapPoint = child.Bounds.Center.Y; |
|
|
|
break; |
|
|
|
case SnapPointsAlignment.Far: |
|
|
|
snapPoint = child.Bounds.Bottom; |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
snapPoints.Add(snapPoint); |
|
|
|
} |
|
|
|
} |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
return snapPoints; |
|
|
|
} |
|
|
|
|
|
|
|
public double GetRegularSnapPoints(Orientation orientation, SnapPointsAlignment snapPointsAlignment, out double offset) |
|
|
|
{ |
|
|
|
offset = 0f; |
|
|
|
var firstChild = VisualChildren.FirstOrDefault(); |
|
|
|
|
|
|
|
if(firstChild == null) |
|
|
|
{ |
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
double snapPoint = 0; |
|
|
|
|
|
|
|
switch (Orientation) |
|
|
|
{ |
|
|
|
case Orientation.Horizontal: |
|
|
|
if (!AreHorizontalSnapPointsRegular) |
|
|
|
throw new InvalidOperationException(); |
|
|
|
|
|
|
|
snapPoint = firstChild.Bounds.Width; |
|
|
|
switch (snapPointsAlignment) |
|
|
|
{ |
|
|
|
case SnapPointsAlignment.Near: |
|
|
|
offset = firstChild.Bounds.Left; |
|
|
|
break; |
|
|
|
case SnapPointsAlignment.Center: |
|
|
|
offset = firstChild.Bounds.Center.X; |
|
|
|
break; |
|
|
|
case SnapPointsAlignment.Far: |
|
|
|
offset = firstChild.Bounds.Right; |
|
|
|
break; |
|
|
|
} |
|
|
|
break; |
|
|
|
case Orientation.Vertical: |
|
|
|
if (!AreVerticalSnapPointsRegular) |
|
|
|
throw new InvalidOperationException(); |
|
|
|
snapPoint = firstChild.Bounds.Height; |
|
|
|
switch (snapPointsAlignment) |
|
|
|
{ |
|
|
|
case SnapPointsAlignment.Near: |
|
|
|
offset = firstChild.Bounds.Top; |
|
|
|
break; |
|
|
|
case SnapPointsAlignment.Center: |
|
|
|
offset = firstChild.Bounds.Center.Y; |
|
|
|
break; |
|
|
|
case SnapPointsAlignment.Far: |
|
|
|
offset = firstChild.Bounds.Bottom; |
|
|
|
break; |
|
|
|
} |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
return snapPoint; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|