committed by
GitHub
41 changed files with 1453 additions and 164 deletions
@ -0,0 +1,60 @@ |
|||
<UserControl xmlns="https://github.com/avaloniaui" |
|||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
|||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" |
|||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" |
|||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" |
|||
x:Class="ControlCatalog.Pages.RelativePanelPage"> |
|||
<RelativePanel Width="620" Height="700" Margin="32"> |
|||
<Border Name="Rect1" Background="Red" Height="50" Width="50"> |
|||
<TextBlock Text="Rect1" Foreground="White" FontWeight="Bold" HorizontalAlignment="Center" VerticalAlignment="Center"/> |
|||
</Border> |
|||
<Border Name="Rect2" Background="Blue" Height="50" Width="50" RelativePanel.AlignHorizontalCenterWithPanel="True"> |
|||
<TextBlock Text="Rect2" Foreground="White" FontWeight="Bold" HorizontalAlignment="Center" VerticalAlignment="Center"/> |
|||
</Border> |
|||
<Border Name="Rect3" Background="Green" Height="50" Width="50" RelativePanel.AlignRightWithPanel="True"> |
|||
<TextBlock Text="Rect3" Foreground="White" FontWeight="Bold" HorizontalAlignment="Center" VerticalAlignment="Center"/> |
|||
</Border> |
|||
<Border Name="Rect4" Background="Red" Height="50" Width="50" RelativePanel.AlignBottomWithPanel="True"> |
|||
<TextBlock Text="Rect4" Foreground="White" FontWeight="Bold" HorizontalAlignment="Center" VerticalAlignment="Center"/> |
|||
</Border> |
|||
<Border Name="Rect5" Background="Blue" Height="50" Width="50" RelativePanel.AlignBottomWithPanel="True" RelativePanel.AlignHorizontalCenterWithPanel="True"> |
|||
<TextBlock Text="Rect5" Foreground="White" FontWeight="Bold" HorizontalAlignment="Center" VerticalAlignment="Center"/> |
|||
</Border> |
|||
<Border Name="Rect6" Background="Green" Height="50" Width="50" RelativePanel.AlignBottomWithPanel="True" RelativePanel.AlignRightWithPanel="True"> |
|||
<TextBlock Text="Rect6" Foreground="White" FontWeight="Bold" HorizontalAlignment="Center" VerticalAlignment="Center"/> |
|||
</Border> |
|||
<Border Name="Rect7" Background="Blue" Height="50" RelativePanel.RightOf="{Binding ElementName=Rect1}"> |
|||
<TextBlock Text="Rect7 (RightOf Rect1)" Padding="10,0" Foreground="White" FontWeight="Bold" HorizontalAlignment="Center" VerticalAlignment="Center"/> |
|||
</Border> |
|||
<Border Name="Rect8" Background="Green" Height="50" RelativePanel.Below="{Binding ElementName=Rect7}"> |
|||
<TextBlock Text="Rect8 (Below Rect7)" Padding="10,0" Foreground="White" FontWeight="Bold" HorizontalAlignment="Center" VerticalAlignment="Center"/> |
|||
</Border> |
|||
<Border Name="Rect9" Background="Blue" Height="140" Width="460" RelativePanel.AlignHorizontalCenterWithPanel="True" RelativePanel.AlignVerticalCenterWithPanel="True"> |
|||
<TextBlock Text="Rect9" Padding="10" Foreground="White" FontWeight="Bold" HorizontalAlignment="Center" VerticalAlignment="Top"/> |
|||
</Border> |
|||
<Border Name="Rect10" Background="Red" Width="50" RelativePanel.RightOf="{Binding ElementName=Rect9}" RelativePanel.AlignVerticalCenterWith="{Binding ElementName=Rect9}"> |
|||
<TextBlock Text="Rect14 (RightOf Rect9, AlignVerticalCenterWith Rect9)" Padding="10,0" Foreground="White" FontWeight="Bold" HorizontalAlignment="Center" VerticalAlignment="Center"> |
|||
<TextBlock.RenderTransform> |
|||
<TransformGroup> |
|||
<RotateTransform Angle="-90"/> |
|||
</TransformGroup> |
|||
</TextBlock.RenderTransform> |
|||
</TextBlock> |
|||
</Border> |
|||
<Border Name="Rect11" Background="Red" Height="50" RelativePanel.AlignBottomWith="{Binding ElementName=Rect9}" RelativePanel.AlignHorizontalCenterWith="{Binding ElementName=Rect9}"> |
|||
<TextBlock Text="Rect11 (AlignBottomWith Rect9, AlignHorizontalCenterWith Rect9)" Padding="10,0" Foreground="White" FontWeight="Bold" HorizontalAlignment="Center" VerticalAlignment="Center"/> |
|||
</Border> |
|||
<Border Name="Rect12" Background="Red" Height="50" RelativePanel.Below="{Binding ElementName=Rect8}" RelativePanel.AlignLeftWith="{Binding ElementName=Rect7}"> |
|||
<TextBlock Text="Rect12 (Below Rect8, AlignLeftWith Rect7)" Padding="10,0" Foreground="White" FontWeight="Bold" HorizontalAlignment="Center" VerticalAlignment="Center"/> |
|||
</Border> |
|||
<Border Name="Rect13" Background="Blue" Height="50" RelativePanel.Below="{Binding ElementName=Rect12}" RelativePanel.AlignRightWith="{Binding ElementName=Rect12}"> |
|||
<TextBlock Text="Rect13 (Below Rect12, AlignRightWith Rect12)" Padding="10,0" Foreground="White" FontWeight="Bold" HorizontalAlignment="Center" VerticalAlignment="Center"/> |
|||
</Border> |
|||
<Border Name="Rect14" Background="Green" Height="50" RelativePanel.Above="{Binding ElementName=Rect9}" RelativePanel.AlignRightWith="{Binding ElementName=Rect9}"> |
|||
<TextBlock Text="Rect14 (Above Rect9, AlignRightWith Rect9)" Padding="10,0" Foreground="White" FontWeight="Bold" HorizontalAlignment="Center" VerticalAlignment="Center"/> |
|||
</Border> |
|||
<Border Name="Rect15" Background="Red" Height="50" RelativePanel.LeftOf="{Binding ElementName=Rect2}" RelativePanel.AlignTopWith="{Binding ElementName=Rect9}"> |
|||
<TextBlock Text="Rect15 (LeftOf Rect2, AlignTopWith Rect9)" Padding="10,0" Foreground="White" FontWeight="Bold" HorizontalAlignment="Center" VerticalAlignment="Center"/> |
|||
</Border> |
|||
</RelativePanel> |
|||
</UserControl> |
|||
@ -0,0 +1,19 @@ |
|||
using Avalonia; |
|||
using Avalonia.Controls; |
|||
using Avalonia.Markup.Xaml; |
|||
|
|||
namespace ControlCatalog.Pages |
|||
{ |
|||
public class RelativePanelPage : UserControl |
|||
{ |
|||
public RelativePanelPage() |
|||
{ |
|||
this.InitializeComponent(); |
|||
} |
|||
|
|||
private void InitializeComponent() |
|||
{ |
|||
AvaloniaXamlLoader.Load(this); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,546 @@ |
|||
using Avalonia.Layout; |
|||
|
|||
#nullable enable |
|||
|
|||
namespace Avalonia.Controls |
|||
{ |
|||
public partial class RelativePanel |
|||
{ |
|||
private static void OnAlignPropertiesChanged(AvaloniaObject d, AvaloniaPropertyChangedEventArgs e) |
|||
{ |
|||
if (d is Layoutable layoutable && layoutable.Parent is Layoutable layoutableParent) |
|||
{ |
|||
layoutableParent.InvalidateArrange(); |
|||
} |
|||
} |
|||
|
|||
static RelativePanel() |
|||
{ |
|||
ClipToBoundsProperty.OverrideDefaultValue<RelativePanel>(true); |
|||
|
|||
AboveProperty.Changed.AddClassHandler<Layoutable>(OnAlignPropertiesChanged); |
|||
AlignBottomWithPanelProperty.Changed.AddClassHandler<Layoutable>(OnAlignPropertiesChanged); |
|||
AlignBottomWithProperty.Changed.AddClassHandler<Layoutable>(OnAlignPropertiesChanged); |
|||
AlignHorizontalCenterWithPanelProperty.Changed.AddClassHandler<Layoutable>(OnAlignPropertiesChanged); |
|||
AlignHorizontalCenterWithProperty.Changed.AddClassHandler<Layoutable>(OnAlignPropertiesChanged); |
|||
AlignLeftWithPanelProperty.Changed.AddClassHandler<Layoutable>(OnAlignPropertiesChanged); |
|||
AlignLeftWithProperty.Changed.AddClassHandler<Layoutable>(OnAlignPropertiesChanged); |
|||
AlignRightWithPanelProperty.Changed.AddClassHandler<Layoutable>(OnAlignPropertiesChanged); |
|||
AlignRightWithProperty.Changed.AddClassHandler<Layoutable>(OnAlignPropertiesChanged); |
|||
AlignTopWithPanelProperty.Changed.AddClassHandler<Layoutable>(OnAlignPropertiesChanged); |
|||
AlignTopWithProperty.Changed.AddClassHandler<Layoutable>(OnAlignPropertiesChanged); |
|||
AlignVerticalCenterWithPanelProperty.Changed.AddClassHandler<Layoutable>(OnAlignPropertiesChanged); |
|||
AlignVerticalCenterWithProperty.Changed.AddClassHandler<Layoutable>(OnAlignPropertiesChanged); |
|||
BelowProperty.Changed.AddClassHandler<Layoutable>(OnAlignPropertiesChanged); |
|||
LeftOfProperty.Changed.AddClassHandler<Layoutable>(OnAlignPropertiesChanged); |
|||
LeftOfProperty.Changed.AddClassHandler<Layoutable>(OnAlignPropertiesChanged); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the value of the RelativePanel.Above XAML attached property for the target element.
|
|||
/// </summary>
|
|||
/// <param name="obj">The object from which the property value is read.</param>
|
|||
/// <returns>
|
|||
/// The RelativePanel.Above XAML attached property value of the specified object.
|
|||
/// (The element to position this element above.)
|
|||
/// </returns>
|
|||
[ResolveByName] |
|||
public static object GetAbove(AvaloniaObject obj) |
|||
{ |
|||
return (object)obj.GetValue(AboveProperty); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Sets the value of the RelativePanel.Above XAML attached property for a target element.
|
|||
/// </summary>
|
|||
/// <param name="obj">The object to which the property value is written.</param>
|
|||
/// <param name="value">The value to set. (The element to position this element above.)</param>
|
|||
public static void SetAbove(AvaloniaObject obj, object value) |
|||
{ |
|||
obj.SetValue(AboveProperty, value); |
|||
} |
|||
|
|||
|
|||
/// <summary>
|
|||
/// Identifies the <see cref="RelativePanel.AboveProperty"/> XAML attached property.
|
|||
/// </summary>
|
|||
|
|||
public static readonly AttachedProperty<object> AboveProperty = |
|||
AvaloniaProperty.RegisterAttached<Layoutable, object>("Above", typeof(RelativePanel)); |
|||
|
|||
|
|||
/// <summary>
|
|||
/// Gets the value of the RelativePanel.AlignBottomWithPanel XAML attached property for the target element.
|
|||
/// </summary>
|
|||
/// <param name="obj">The object from which the property value is read.</param>
|
|||
/// <returns>
|
|||
/// The RelativePanel.AlignBottomWithPanel XAML attached property value of the specified
|
|||
/// object. (true to align this element's bottom edge with the panel's bottom edge;
|
|||
/// otherwise, false.)
|
|||
/// </returns>
|
|||
public static bool GetAlignBottomWithPanel(AvaloniaObject obj) |
|||
{ |
|||
return (bool)obj.GetValue(AlignBottomWithPanelProperty); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Sets the value of the RelativePanel.Above XAML attached property for a target element.
|
|||
/// </summary>
|
|||
/// <param name="obj">The object to which the property value is written.</param>
|
|||
/// <param name="value">
|
|||
/// The value to set. (true to align this element's bottom edge with the panel's
|
|||
/// bottom edge; otherwise, false.)
|
|||
/// </param>
|
|||
public static void SetAlignBottomWithPanel(AvaloniaObject obj, bool value) |
|||
{ |
|||
obj.SetValue(AlignBottomWithPanelProperty, value); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Identifies the <see cref="RelativePanel.AlignBottomWithPanelProperty"/> XAML attached property.
|
|||
/// </summary>
|
|||
public static readonly AttachedProperty<bool> AlignBottomWithPanelProperty = |
|||
AvaloniaProperty.RegisterAttached<Layoutable, bool>("AlignBottomWithPanel", typeof(RelativePanel)); |
|||
|
|||
/// <summary>
|
|||
/// Gets the value of the RelativePanel.AlignBottomWith XAML attached property for the target element.
|
|||
/// </summary>
|
|||
/// <param name="obj">The object from which the property value is read.</param>
|
|||
/// <returns>
|
|||
/// The RelativePanel.AlignBottomWith XAML attached property value of the specified object.
|
|||
/// (The element to align this element's bottom edge with.)
|
|||
/// </returns>
|
|||
[ResolveByName] |
|||
public static object GetAlignBottomWith(AvaloniaObject obj) |
|||
{ |
|||
return (object)obj.GetValue(AlignBottomWithProperty); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Sets the value of the RelativePanel.Above XAML attached property for a target element.
|
|||
/// </summary>
|
|||
/// <param name="obj">The object to which the property value is written.</param>
|
|||
/// <param name="value">The value to set. (The element to align this element's bottom edge with.)</param>
|
|||
public static void SetAlignBottomWith(AvaloniaObject obj, object value) |
|||
{ |
|||
obj.SetValue(AlignBottomWithProperty, value); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Identifies the <see cref="RelativePanel.AlignBottomWithProperty"/> XAML attached property.
|
|||
/// </summary>
|
|||
|
|||
public static readonly AttachedProperty<object> AlignBottomWithProperty = |
|||
AvaloniaProperty.RegisterAttached<Layoutable, object>("AlignBottomWith", typeof(RelativePanel)); |
|||
|
|||
/// <summary>
|
|||
/// Gets the value of the RelativePanel.AlignHorizontalCenterWithPanel XAML attached property for the target element.
|
|||
/// </summary>
|
|||
/// <param name="obj">The object from which the property value is read.</param>
|
|||
/// <returns>
|
|||
/// The RelativePanel.AlignHorizontalCenterWithPanel XAML attached property value
|
|||
/// of the specified object. (true to horizontally center this element in the panel;
|
|||
/// otherwise, false.)
|
|||
/// </returns>
|
|||
public static bool GetAlignHorizontalCenterWithPanel(AvaloniaObject obj) |
|||
{ |
|||
return (bool)obj.GetValue(AlignHorizontalCenterWithPanelProperty); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Sets the value of the RelativePanel.Above XAML attached property for a target element.
|
|||
/// </summary>
|
|||
/// <param name="obj">The object to which the property value is written.</param>
|
|||
/// <param name="value">
|
|||
/// The value to set. (true to horizontally center this element in the panel; otherwise,
|
|||
/// false.)
|
|||
/// </param>
|
|||
public static void SetAlignHorizontalCenterWithPanel(AvaloniaObject obj, bool value) |
|||
{ |
|||
obj.SetValue(AlignHorizontalCenterWithPanelProperty, value); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Identifies the <see cref="RelativePanel.AlignHorizontalCenterWithPanelProperty"/> XAML attached property.
|
|||
/// </summary>
|
|||
public static readonly AttachedProperty<bool> AlignHorizontalCenterWithPanelProperty = |
|||
AvaloniaProperty.RegisterAttached<Layoutable, bool>("AlignHorizontalCenterWithPanel", typeof(RelativePanel), false); |
|||
|
|||
/// <summary>
|
|||
/// Gets the value of the RelativePanel.AlignHorizontalCenterWith XAML attached property for the target element.
|
|||
/// </summary>
|
|||
/// <param name="obj">The object from which the property value is read.</param>
|
|||
/// <returns>
|
|||
/// The RelativePanel.AlignHorizontalCenterWith XAML attached property value of the
|
|||
/// specified object. (The element to align this element's horizontal center with.)
|
|||
/// </returns>
|
|||
[ResolveByName] |
|||
public static object GetAlignHorizontalCenterWith(AvaloniaObject obj) |
|||
{ |
|||
return (object)obj.GetValue(AlignHorizontalCenterWithProperty); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Sets the value of the RelativePanel.Above XAML attached property for a target element.
|
|||
/// </summary>
|
|||
/// <param name="obj">The object to which the property value is written.</param>
|
|||
/// <param name="value">The value to set. (The element to align this element's horizontal center with.)</param>
|
|||
public static void SetAlignHorizontalCenterWith(AvaloniaObject obj, object value) |
|||
{ |
|||
obj.SetValue(AlignHorizontalCenterWithProperty, value); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Identifies the <see cref="RelativePanel.AlignHorizontalCenterWithProperty"/> XAML attached property.
|
|||
/// </summary>
|
|||
|
|||
public static readonly AttachedProperty<object> AlignHorizontalCenterWithProperty = |
|||
AvaloniaProperty.RegisterAttached<Layoutable, object>("AlignHorizontalCenterWith", typeof(object), typeof(RelativePanel)); |
|||
|
|||
/// <summary>
|
|||
/// Gets the value of the RelativePanel.AlignLeftWithPanel XAML attached property for the target element.
|
|||
/// </summary>
|
|||
/// <param name="obj">The object from which the property value is read.</param>
|
|||
/// <returns>
|
|||
/// The RelativePanel.AlignLeftWithPanel XAML attached property value of the specified
|
|||
/// object. (true to align this element's left edge with the panel's left edge; otherwise,
|
|||
/// false.)
|
|||
/// </returns>
|
|||
public static bool GetAlignLeftWithPanel(AvaloniaObject obj) |
|||
{ |
|||
return (bool)obj.GetValue(AlignLeftWithPanelProperty); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Sets the value of the RelativePanel.Above XAML attached property for a target element.
|
|||
/// </summary>
|
|||
/// <param name="obj">The object to which the property value is written.</param>
|
|||
/// <param name="value">
|
|||
/// The value to set. (true to align this element's left edge with the panel's left
|
|||
/// edge; otherwise, false.)
|
|||
/// </param>
|
|||
public static void SetAlignLeftWithPanel(AvaloniaObject obj, bool value) |
|||
{ |
|||
obj.SetValue(AlignLeftWithPanelProperty, value); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Identifies the <see cref="RelativePanel.AlignLeftWithPanelProperty"/> XAML attached property.
|
|||
/// </summary>
|
|||
public static readonly AttachedProperty<bool> AlignLeftWithPanelProperty = |
|||
AvaloniaProperty.RegisterAttached<Layoutable, bool>("AlignLeftWithPanel", typeof(RelativePanel), false); |
|||
|
|||
|
|||
/// <summary>
|
|||
/// Gets the value of the RelativePanel.AlignLeftWith XAML attached property for the target element.
|
|||
/// </summary>
|
|||
/// <param name="obj">The object from which the property value is read.</param>
|
|||
/// <returns>
|
|||
/// The RelativePanel.AlignLeftWith XAML attached property value of the specified
|
|||
/// object. (The element to align this element's left edge with.)
|
|||
/// </returns>
|
|||
[ResolveByName] |
|||
public static object GetAlignLeftWith(AvaloniaObject obj) |
|||
{ |
|||
return (object)obj.GetValue(AlignLeftWithProperty); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Sets the value of the RelativePanel.Above XAML attached property for a target element.
|
|||
/// </summary>
|
|||
/// <param name="obj">The object to which the property value is written.</param>
|
|||
/// <param name="value">The value to set. (The element to align this element's left edge with.)</param>
|
|||
public static void SetAlignLeftWith(AvaloniaObject obj, object value) |
|||
{ |
|||
obj.SetValue(AlignLeftWithProperty, value); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Identifies the <see cref="RelativePanel.AlignLeftWithProperty"/> XAML attached property.
|
|||
/// </summary>
|
|||
|
|||
public static readonly AttachedProperty<object> AlignLeftWithProperty = |
|||
AvaloniaProperty.RegisterAttached<RelativePanel, Layoutable, object>("AlignLeftWith"); |
|||
|
|||
|
|||
/// <summary>
|
|||
/// Gets the value of the RelativePanel.AlignRightWithPanel XAML attached property for the target element.
|
|||
/// </summary>
|
|||
/// <param name="obj">The object from which the property value is read.</param>
|
|||
/// <returns>
|
|||
/// The RelativePanel.AlignRightWithPanel XAML attached property value of the specified
|
|||
/// object. (true to align this element's right edge with the panel's right edge;
|
|||
/// otherwise, false.)
|
|||
/// </returns>
|
|||
public static bool GetAlignRightWithPanel(AvaloniaObject obj) |
|||
{ |
|||
return (bool)obj.GetValue(AlignRightWithPanelProperty); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Sets the value of the RelativePanel.Above XAML attached property for a target element.
|
|||
/// </summary>
|
|||
/// <param name="obj">The object to which the property value is written.</param>
|
|||
/// <param name="value">
|
|||
/// The value to set. (true to align this element's right edge with the panel's right
|
|||
/// edge; otherwise, false.)
|
|||
/// </param>
|
|||
public static void SetAlignRightWithPanel(AvaloniaObject obj, bool value) |
|||
{ |
|||
obj.SetValue(AlignRightWithPanelProperty, value); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Identifies the <see cref="RelativePanel.AlignRightWithPanelProperty"/> XAML attached property.
|
|||
/// </summary>
|
|||
public static readonly AttachedProperty<bool> AlignRightWithPanelProperty = |
|||
AvaloniaProperty.RegisterAttached<RelativePanel, Layoutable, bool>("AlignRightWithPanel", false); |
|||
|
|||
/// <summary>
|
|||
/// Gets the value of the RelativePanel.AlignRightWith XAML attached property for the target element.
|
|||
/// </summary>
|
|||
/// <param name="obj">The object from which the property value is read.</param>
|
|||
/// <returns>
|
|||
/// The RelativePanel.AlignRightWith XAML attached property value of the specified
|
|||
/// object. (The element to align this element's right edge with.)
|
|||
/// </returns>
|
|||
[ResolveByName] |
|||
public static object GetAlignRightWith(AvaloniaObject obj) |
|||
{ |
|||
return (object)obj.GetValue(AlignRightWithProperty); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Sets the value of the RelativePanel.AlignRightWith XAML attached property for a target element.
|
|||
/// </summary>
|
|||
/// <param name="obj">The object to which the property value is written.</param>
|
|||
/// <param name="value">The value to set. (The element to align this element's right edge with.)</param>
|
|||
public static void SetAlignRightWith(AvaloniaObject obj, object value) |
|||
{ |
|||
obj.SetValue(AlignRightWithProperty, value); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Identifies the <see cref="RelativePanel.AlignRightWithProperty"/> XAML attached property.
|
|||
/// </summary>
|
|||
|
|||
public static readonly AttachedProperty<object> AlignRightWithProperty = |
|||
AvaloniaProperty.RegisterAttached<RelativePanel, Layoutable, object>("AlignRightWith"); |
|||
|
|||
/// <summary>
|
|||
/// Gets the value of the RelativePanel.AlignTopWithPanel XAML attached property for the target element.
|
|||
/// </summary>
|
|||
/// <param name="obj">The object from which the property value is read.</param>
|
|||
/// <returns>
|
|||
/// The RelativePanel.AlignTopWithPanel XAML attached property value of the specified
|
|||
/// object. (true to align this element's top edge with the panel's top edge; otherwise,
|
|||
/// false.)
|
|||
/// </returns>
|
|||
public static bool GetAlignTopWithPanel(AvaloniaObject obj) |
|||
{ |
|||
return (bool)obj.GetValue(AlignTopWithPanelProperty); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Sets the value of the RelativePanel.AlignTopWithPanel XAML attached property for a target element.
|
|||
/// </summary>
|
|||
/// <param name="obj">The object to which the property value is written.</param>
|
|||
/// <param name="value">
|
|||
/// The value to set. (true to align this element's top edge with the panel's top
|
|||
/// edge; otherwise, false.)
|
|||
/// </param>
|
|||
public static void SetAlignTopWithPanel(AvaloniaObject obj, bool value) |
|||
{ |
|||
obj.SetValue(AlignTopWithPanelProperty, value); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Identifies the <see cref="RelativePanel.AlignTopWithPanelProperty"/> XAML attached property.
|
|||
/// </summary>
|
|||
public static readonly AttachedProperty<bool> AlignTopWithPanelProperty = |
|||
AvaloniaProperty.RegisterAttached<RelativePanel, Layoutable, bool>("AlignTopWithPanel", false); |
|||
|
|||
/// <summary>
|
|||
/// Gets the value of the RelativePanel.AlignTopWith XAML attached property for the target element.
|
|||
/// </summary>
|
|||
/// <param name="obj">The object from which the property value is read.</param>
|
|||
/// <returns>The value to set. (The element to align this element's top edge with.)</returns>
|
|||
[ResolveByName] |
|||
public static object GetAlignTopWith(AvaloniaObject obj) |
|||
{ |
|||
return (object)obj.GetValue(AlignTopWithProperty); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Sets the value of the RelativePanel.AlignTopWith XAML attached property for a target element.
|
|||
/// </summary>
|
|||
/// <param name="obj">The object to which the property value is written.</param>
|
|||
/// <param name="value">The value to set. (The element to align this element's top edge with.)</param>
|
|||
public static void SetAlignTopWith(AvaloniaObject obj, object value) |
|||
{ |
|||
obj.SetValue(AlignTopWithProperty, value); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Identifies the <see cref="RelativePanel.AlignTopWithProperty"/> XAML attached property.
|
|||
/// </summary>
|
|||
|
|||
public static readonly AttachedProperty<object> AlignTopWithProperty = |
|||
AvaloniaProperty.RegisterAttached<RelativePanel, Layoutable, object>("AlignTopWith"); |
|||
|
|||
/// <summary>
|
|||
/// Gets the value of the RelativePanel.AlignVerticalCenterWithPanel XAML attached property for the target element.
|
|||
/// </summary>
|
|||
/// <param name="obj">The object from which the property value is read.</param>
|
|||
/// <returns>
|
|||
/// The RelativePanel.AlignVerticalCenterWithPanel XAML attached property value of
|
|||
/// the specified object. (true to vertically center this element in the panel; otherwise,
|
|||
/// false.)
|
|||
/// </returns>
|
|||
public static bool GetAlignVerticalCenterWithPanel(AvaloniaObject obj) |
|||
{ |
|||
return (bool)obj.GetValue(AlignVerticalCenterWithPanelProperty); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Sets the value of the RelativePanel.AlignVerticalCenterWithPanel XAML attached property for a target element.
|
|||
/// </summary>
|
|||
/// <param name="obj">The object to which the property value is written.</param>
|
|||
/// <param name="value">
|
|||
/// The value to set. (true to vertically center this element in the panel; otherwise,
|
|||
/// false.)
|
|||
/// </param>
|
|||
public static void SetAlignVerticalCenterWithPanel(AvaloniaObject obj, bool value) |
|||
{ |
|||
obj.SetValue(AlignVerticalCenterWithPanelProperty, value); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Identifies the <see cref="RelativePanel.AlignVerticalCenterWithPanelProperty"/> XAML attached property.
|
|||
/// </summary>
|
|||
public static readonly AttachedProperty<bool> AlignVerticalCenterWithPanelProperty = |
|||
AvaloniaProperty.RegisterAttached<RelativePanel, Layoutable, bool>("AlignVerticalCenterWithPanel", false); |
|||
|
|||
/// <summary>
|
|||
/// Gets the value of the RelativePanel.AlignVerticalCenterWith XAML attached property for the target element.
|
|||
/// </summary>
|
|||
/// <param name="obj">The object from which the property value is read.</param>
|
|||
/// <returns>The value to set. (The element to align this element's vertical center with.)</returns>
|
|||
[ResolveByName] |
|||
public static object GetAlignVerticalCenterWith(AvaloniaObject obj) |
|||
{ |
|||
return (object)obj.GetValue(AlignVerticalCenterWithProperty); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Sets the value of the RelativePanel.AlignVerticalCenterWith XAML attached property for a target element.
|
|||
/// </summary>
|
|||
/// <param name="obj">The object to which the property value is written.</param>
|
|||
/// <param name="value">The value to set. (The element to align this element's horizontal center with.)</param>
|
|||
|
|||
public static void SetAlignVerticalCenterWith(AvaloniaObject obj, object value) |
|||
{ |
|||
obj.SetValue(AlignVerticalCenterWithProperty, value); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Identifies the <see cref="RelativePanel.AlignVerticalCenterWithProperty"/> XAML attached property.
|
|||
/// </summary>
|
|||
public static readonly AttachedProperty<object> AlignVerticalCenterWithProperty = |
|||
AvaloniaProperty.RegisterAttached<RelativePanel, Layoutable, object>("AlignVerticalCenterWith"); |
|||
|
|||
/// <summary>
|
|||
/// Gets the value of the RelativePanel.Below XAML attached property for the target element.
|
|||
/// </summary>
|
|||
/// <param name="obj">The object from which the property value is read.</param>
|
|||
/// <returns>
|
|||
/// The RelativePanel.Below XAML attached property value of the specified object.
|
|||
/// (The element to position this element below.)
|
|||
/// </returns>
|
|||
[ResolveByName] |
|||
public static object GetBelow(AvaloniaObject obj) |
|||
{ |
|||
return (object)obj.GetValue(BelowProperty); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Sets the value of the RelativePanel.Above XAML attached property for a target element.
|
|||
/// </summary>
|
|||
/// <param name="obj">The object to which the property value is written.</param>
|
|||
/// <param name="value">The value to set. (The element to position this element below.)</param>
|
|||
|
|||
public static void SetBelow(AvaloniaObject obj, object value) |
|||
{ |
|||
obj.SetValue(BelowProperty, value); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Identifies the <see cref="RelativePanel.BelowProperty"/> XAML attached property.
|
|||
/// </summary>
|
|||
|
|||
public static readonly AttachedProperty<object> BelowProperty = |
|||
AvaloniaProperty.RegisterAttached<RelativePanel, Layoutable, object>("Below"); |
|||
|
|||
/// <summary>
|
|||
/// Gets the value of the RelativePanel.LeftOf XAML attached property for the target element.
|
|||
/// </summary>
|
|||
/// <param name="obj">The object from which the property value is read.</param>
|
|||
/// <returns>
|
|||
/// The RelativePanel.LeftOf XAML attached property value of the specified object.
|
|||
/// (The element to position this element to the left of.)
|
|||
/// </returns>
|
|||
[ResolveByName] |
|||
public static object GetLeftOf(AvaloniaObject obj) |
|||
{ |
|||
return (object)obj.GetValue(LeftOfProperty); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Sets the value of the RelativePanel.LeftOf XAML attached property for a target element.
|
|||
/// </summary>
|
|||
/// <param name="obj">The object to which the property value is written.</param>
|
|||
/// <param name="value">The value to set. (The element to position this element to the left of.)</param>
|
|||
public static void SetLeftOf(AvaloniaObject obj, object value) |
|||
{ |
|||
obj.SetValue(LeftOfProperty, value); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Identifies the <see cref="RelativePanel.LeftOfProperty"/> XAML attached property.
|
|||
/// </summary>
|
|||
|
|||
public static readonly AttachedProperty<object> LeftOfProperty = |
|||
AvaloniaProperty.RegisterAttached<RelativePanel, Layoutable, object>("LeftOf"); |
|||
|
|||
/// <summary>
|
|||
/// Gets the value of the RelativePanel.RightOf XAML attached property for the target element.
|
|||
/// </summary>
|
|||
/// <param name="obj">The object from which the property value is read.</param>
|
|||
/// <returns>
|
|||
/// The RelativePanel.RightOf XAML attached property value of the specified object.
|
|||
/// (The element to position this element to the right of.)
|
|||
/// </returns>
|
|||
[ResolveByName] |
|||
public static object GetRightOf(AvaloniaObject obj) |
|||
{ |
|||
return (object)obj.GetValue(RightOfProperty); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Sets the value of the RelativePanel.RightOf XAML attached property for a target element.
|
|||
/// </summary>
|
|||
/// <param name="obj">The object to which the property value is written.</param>
|
|||
/// <param name="value">The value to set. (The element to position this element to the right of.)</param>
|
|||
public static void SetRightOf(AvaloniaObject obj, object value) |
|||
{ |
|||
obj.SetValue(RightOfProperty, value); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Identifies the <see cref="RelativePanel.RightOfProperty"/> XAML attached property.
|
|||
/// </summary>
|
|||
|
|||
public static readonly AttachedProperty<object> RightOfProperty = |
|||
AvaloniaProperty.RegisterAttached<RelativePanel, Layoutable, object>("RightOf"); |
|||
} |
|||
} |
|||
@ -0,0 +1,353 @@ |
|||
/// Ported from https://github.com/HandyOrg/HandyControl/blob/master/src/Shared/HandyControl_Shared/Controls/Panel/RelativePanel.cs
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using Avalonia.Layout; |
|||
|
|||
#nullable enable |
|||
|
|||
namespace Avalonia.Controls |
|||
{ |
|||
public partial class RelativePanel : Panel |
|||
{ |
|||
private readonly Graph _childGraph; |
|||
|
|||
public RelativePanel() => _childGraph = new Graph(); |
|||
|
|||
protected override Size MeasureOverride(Size availableSize) |
|||
{ |
|||
foreach (var child in Children) |
|||
{ |
|||
child?.Measure(availableSize); |
|||
} |
|||
|
|||
return availableSize; |
|||
} |
|||
|
|||
protected override Size ArrangeOverride(Size arrangeSize) |
|||
{ |
|||
_childGraph.Reset(arrangeSize); |
|||
|
|||
foreach (var child in Children.OfType<Layoutable>()) |
|||
{ |
|||
if (child == null) |
|||
continue; |
|||
|
|||
var node = _childGraph.AddNode(child); |
|||
|
|||
node.AlignLeftWithNode = _childGraph.AddLink(node, GetDependencyElement(AlignLeftWithProperty, child)); |
|||
node.AlignTopWithNode = _childGraph.AddLink(node, GetDependencyElement(AlignTopWithProperty, child)); |
|||
node.AlignRightWithNode = _childGraph.AddLink(node, GetDependencyElement(AlignRightWithProperty, child)); |
|||
node.AlignBottomWithNode = _childGraph.AddLink(node, GetDependencyElement(AlignBottomWithProperty, child)); |
|||
|
|||
node.LeftOfNode = _childGraph.AddLink(node, GetDependencyElement(LeftOfProperty, child)); |
|||
node.AboveNode = _childGraph.AddLink(node, GetDependencyElement(AboveProperty, child)); |
|||
node.RightOfNode = _childGraph.AddLink(node, GetDependencyElement(RightOfProperty, child)); |
|||
node.BelowNode = _childGraph.AddLink(node, GetDependencyElement(BelowProperty, child)); |
|||
|
|||
node.AlignHorizontalCenterWith = _childGraph.AddLink(node, GetDependencyElement(AlignHorizontalCenterWithProperty, child)); |
|||
node.AlignVerticalCenterWith = _childGraph.AddLink(node, GetDependencyElement(AlignVerticalCenterWithProperty, child)); |
|||
} |
|||
|
|||
if (_childGraph.CheckCyclic()) |
|||
{ |
|||
throw new Exception("RelativePanel error: Circular dependency detected. Layout could not complete."); |
|||
} |
|||
|
|||
var size = new Size(); |
|||
|
|||
foreach (var child in Children) |
|||
{ |
|||
if (child.Bounds.Bottom > size.Height) |
|||
{ |
|||
size = size.WithHeight(child.Bounds.Bottom); |
|||
} |
|||
|
|||
if (child.Bounds.Right > size.Width) |
|||
{ |
|||
size = size.WithWidth(child.Bounds.Right); |
|||
} |
|||
} |
|||
|
|||
if (VerticalAlignment == VerticalAlignment.Stretch) |
|||
{ |
|||
size = size.WithHeight(arrangeSize.Height); |
|||
} |
|||
|
|||
if (HorizontalAlignment == HorizontalAlignment.Stretch) |
|||
{ |
|||
size = size.WithWidth(arrangeSize.Width); |
|||
} |
|||
|
|||
return size; |
|||
} |
|||
|
|||
private Layoutable? GetDependencyElement(AvaloniaProperty property, AvaloniaObject child) |
|||
{ |
|||
var dependency = child.GetValue(property); |
|||
|
|||
if (dependency is Layoutable layoutable) |
|||
{ |
|||
if (Children.Contains((ILayoutable)layoutable)) |
|||
return layoutable; |
|||
|
|||
throw new ArgumentException($"RelativePanel error: Element does not exist in the current context: {property.Name}"); |
|||
} |
|||
|
|||
return null; |
|||
} |
|||
|
|||
private class GraphNode |
|||
{ |
|||
public Point Position { get; set; } |
|||
|
|||
public bool Arranged { get; set; } |
|||
|
|||
public Layoutable Element { get; } |
|||
|
|||
public HashSet<GraphNode> OutgoingNodes { get; } |
|||
|
|||
public GraphNode? AlignLeftWithNode { get; set; } |
|||
|
|||
public GraphNode? AlignTopWithNode { get; set; } |
|||
|
|||
public GraphNode? AlignRightWithNode { get; set; } |
|||
|
|||
public GraphNode? AlignBottomWithNode { get; set; } |
|||
|
|||
public GraphNode? LeftOfNode { get; set; } |
|||
|
|||
public GraphNode? AboveNode { get; set; } |
|||
|
|||
public GraphNode? RightOfNode { get; set; } |
|||
|
|||
public GraphNode? BelowNode { get; set; } |
|||
|
|||
public GraphNode? AlignHorizontalCenterWith { get; set; } |
|||
|
|||
public GraphNode? AlignVerticalCenterWith { get; set; } |
|||
|
|||
public GraphNode(Layoutable element) |
|||
{ |
|||
OutgoingNodes = new HashSet<GraphNode>(); |
|||
Element = element; |
|||
} |
|||
} |
|||
|
|||
private class Graph |
|||
{ |
|||
private readonly Dictionary<AvaloniaObject, GraphNode> _nodeDic; |
|||
|
|||
private Size _arrangeSize; |
|||
|
|||
public Graph() |
|||
{ |
|||
_nodeDic = new Dictionary<AvaloniaObject, GraphNode>(); |
|||
} |
|||
|
|||
public GraphNode? AddLink(GraphNode from, Layoutable? to) |
|||
{ |
|||
if (to == null) |
|||
return null; |
|||
|
|||
GraphNode nodeTo; |
|||
if (_nodeDic.ContainsKey(to)) |
|||
{ |
|||
nodeTo = _nodeDic[to]; |
|||
} |
|||
else |
|||
{ |
|||
nodeTo = new GraphNode(to); |
|||
_nodeDic[to] = nodeTo; |
|||
} |
|||
|
|||
from.OutgoingNodes.Add(nodeTo); |
|||
return nodeTo; |
|||
} |
|||
|
|||
public GraphNode AddNode(Layoutable value) |
|||
{ |
|||
if (!_nodeDic.ContainsKey(value)) |
|||
{ |
|||
var node = new GraphNode(value); |
|||
_nodeDic.Add(value, node); |
|||
return node; |
|||
} |
|||
|
|||
return _nodeDic[value]; |
|||
} |
|||
|
|||
public void Reset(Size arrangeSize) |
|||
{ |
|||
_arrangeSize = arrangeSize; |
|||
_nodeDic.Clear(); |
|||
} |
|||
|
|||
public bool CheckCyclic() => CheckCyclic(_nodeDic.Values, null); |
|||
|
|||
private bool CheckCyclic(IEnumerable<GraphNode> nodes, HashSet<Layoutable>? set) |
|||
{ |
|||
set ??= new HashSet<Layoutable>(); |
|||
|
|||
foreach (var node in nodes) |
|||
{ |
|||
if (!node.Arranged && node.OutgoingNodes.Count == 0) |
|||
{ |
|||
ArrangeChild(node, true); |
|||
continue; |
|||
} |
|||
|
|||
if (node.OutgoingNodes.All(item => item.Arranged)) |
|||
{ |
|||
ArrangeChild(node); |
|||
continue; |
|||
} |
|||
|
|||
if (!set.Add(node.Element)) |
|||
return true; |
|||
|
|||
return CheckCyclic(node.OutgoingNodes, set); |
|||
} |
|||
|
|||
return false; |
|||
} |
|||
|
|||
private void ArrangeChild(GraphNode node, bool ignoneSibling = false) |
|||
{ |
|||
var child = node.Element; |
|||
var childSize = child.DesiredSize; |
|||
var childPos = new Point(); |
|||
|
|||
if (GetAlignHorizontalCenterWithPanel(child)) |
|||
{ |
|||
childPos = childPos.WithX((_arrangeSize.Width - childSize.Width) / 2); |
|||
} |
|||
|
|||
if (GetAlignVerticalCenterWithPanel(child)) |
|||
{ |
|||
childPos = childPos.WithY((_arrangeSize.Height - childSize.Height) / 2); |
|||
} |
|||
|
|||
var alignLeftWithPanel = GetAlignLeftWithPanel(child); |
|||
var alignTopWithPanel = GetAlignTopWithPanel(child); |
|||
var alignRightWithPanel = GetAlignRightWithPanel(child); |
|||
var alignBottomWithPanel = GetAlignBottomWithPanel(child); |
|||
|
|||
if (!ignoneSibling) |
|||
{ |
|||
if (node.LeftOfNode != null) |
|||
{ |
|||
childPos = childPos.WithX(node.LeftOfNode.Position.X - childSize.Width); |
|||
} |
|||
|
|||
if (node.AboveNode != null) |
|||
{ |
|||
childPos = childPos.WithY(node.AboveNode.Position.Y - childSize.Height); |
|||
} |
|||
|
|||
if (node.RightOfNode != null) |
|||
{ |
|||
childPos = childPos.WithX(node.RightOfNode.Position.X + node.RightOfNode.Element.DesiredSize.Width); |
|||
} |
|||
|
|||
if (node.BelowNode != null) |
|||
{ |
|||
childPos = childPos.WithY(node.BelowNode.Position.Y + node.BelowNode.Element.DesiredSize.Height); |
|||
} |
|||
|
|||
if (node.AlignHorizontalCenterWith != null) |
|||
{ |
|||
childPos = childPos.WithX(node.AlignHorizontalCenterWith.Position.X + |
|||
(node.AlignHorizontalCenterWith.Element.DesiredSize.Width - childSize.Width) / 2); |
|||
} |
|||
|
|||
if (node.AlignVerticalCenterWith != null) |
|||
{ |
|||
childPos = childPos.WithY(node.AlignVerticalCenterWith.Position.Y + |
|||
(node.AlignVerticalCenterWith.Element.DesiredSize.Height - childSize.Height) / 2); |
|||
} |
|||
|
|||
if (node.AlignLeftWithNode != null) |
|||
{ |
|||
childPos = childPos.WithX(node.AlignLeftWithNode.Position.X); |
|||
} |
|||
|
|||
if (node.AlignTopWithNode != null) |
|||
{ |
|||
childPos = childPos.WithY(node.AlignTopWithNode.Position.Y); |
|||
} |
|||
|
|||
if (node.AlignRightWithNode != null) |
|||
{ |
|||
childPos = childPos.WithX(node.AlignRightWithNode.Element.DesiredSize.Width + node.AlignRightWithNode.Position.X - childSize.Width); |
|||
} |
|||
|
|||
if (node.AlignBottomWithNode != null) |
|||
{ |
|||
childPos = childPos.WithY(node.AlignBottomWithNode.Element.DesiredSize.Height + node.AlignBottomWithNode.Position.Y - childSize.Height); |
|||
} |
|||
} |
|||
|
|||
if (alignLeftWithPanel) |
|||
{ |
|||
if (node.AlignRightWithNode != null) |
|||
{ |
|||
childPos = childPos.WithX((node.AlignRightWithNode.Element.DesiredSize.Width + node.AlignRightWithNode.Position.X - childSize.Width) / 2); |
|||
} |
|||
else |
|||
{ |
|||
childPos = childPos.WithX(0); |
|||
} |
|||
} |
|||
|
|||
if (alignTopWithPanel) |
|||
{ |
|||
if (node.AlignBottomWithNode != null) |
|||
{ |
|||
childPos = childPos.WithY((node.AlignBottomWithNode.Element.DesiredSize.Height + node.AlignBottomWithNode.Position.Y - childSize.Height) / 2); |
|||
} |
|||
else |
|||
{ |
|||
childPos = childPos.WithY(0); |
|||
} |
|||
} |
|||
|
|||
if (alignRightWithPanel) |
|||
{ |
|||
if (alignLeftWithPanel) |
|||
{ |
|||
childPos = childPos.WithX((_arrangeSize.Width - childSize.Width) / 2); |
|||
} |
|||
else if (node.AlignLeftWithNode == null) |
|||
{ |
|||
childPos = childPos.WithX(_arrangeSize.Width - childSize.Width); |
|||
} |
|||
else |
|||
{ |
|||
childPos = childPos.WithX((_arrangeSize.Width + node.AlignLeftWithNode.Position.X - childSize.Width) / 2); |
|||
} |
|||
} |
|||
|
|||
if (alignBottomWithPanel) |
|||
{ |
|||
if (alignTopWithPanel) |
|||
{ |
|||
childPos = childPos.WithY((_arrangeSize.Height - childSize.Height) / 2); |
|||
} |
|||
else if (node.AlignTopWithNode == null) |
|||
{ |
|||
childPos = childPos.WithY(_arrangeSize.Height - childSize.Height); |
|||
} |
|||
else |
|||
{ |
|||
childPos = childPos.WithY((_arrangeSize.Height + node.AlignTopWithNode.Position.Y - childSize.Height) / 2); |
|||
} |
|||
} |
|||
|
|||
child.Arrange(new Rect(childPos.X, childPos.Y, childSize.Width, childSize.Height)); |
|||
node.Position = childPos; |
|||
node.Arranged = true; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,9 @@ |
|||
using System; |
|||
|
|||
namespace Avalonia.Controls |
|||
{ |
|||
public class ResolveByNameAttribute : Attribute |
|||
{ |
|||
|
|||
} |
|||
} |
|||
@ -0,0 +1,36 @@ |
|||
using System; |
|||
using Avalonia.Controls; |
|||
using Avalonia.Data.Core; |
|||
|
|||
#nullable enable |
|||
|
|||
namespace Avalonia.Markup.Xaml.MarkupExtensions |
|||
{ |
|||
public class ResolveByNameExtension |
|||
{ |
|||
public ResolveByNameExtension(string name) |
|||
{ |
|||
Name = name; |
|||
} |
|||
|
|||
public string Name { get; } |
|||
|
|||
public object? ProvideValue(IServiceProvider serviceProvider) |
|||
{ |
|||
var nameScope = serviceProvider.GetService<INameScope>(); |
|||
|
|||
var value = nameScope.FindAsync(Name); |
|||
|
|||
if(value.IsCompleted) |
|||
return value.GetResult(); |
|||
|
|||
var provideValueTarget = serviceProvider.GetService<IProvideValueTarget>(); |
|||
var target = provideValueTarget.TargetObject; |
|||
|
|||
if (provideValueTarget.TargetProperty is IPropertyInfo property) |
|||
value.OnCompleted(() => property.Set(target, value.GetResult())); |
|||
|
|||
return null; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,49 @@ |
|||
using System.Collections; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using XamlX.Ast; |
|||
using XamlX.Transform; |
|||
using XamlX.TypeSystem; |
|||
|
|||
#nullable enable |
|||
namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers |
|||
{ |
|||
class AvaloniaXamlIlResolveByNameMarkupExtensionReplacer : IXamlAstTransformer |
|||
{ |
|||
public IXamlAstNode Transform(AstTransformationContext context, IXamlAstNode node) |
|||
{ |
|||
if (!(node is XamlAstXamlPropertyValueNode propertyValueNode)) return node; |
|||
|
|||
if (!(propertyValueNode.Property is XamlAstClrProperty clrProperty)) return node; |
|||
|
|||
IEnumerable<IXamlCustomAttribute> attributes = propertyValueNode.Property.GetClrProperty().CustomAttributes; |
|||
|
|||
if (propertyValueNode.Property is XamlAstClrProperty referenceNode && |
|||
referenceNode.Getter != null) |
|||
{ |
|||
attributes = attributes.Concat(referenceNode.Getter.CustomAttributes); |
|||
} |
|||
|
|||
if (attributes.All(attribute => attribute.Type.FullName != "Avalonia.Controls.ResolveByNameAttribute")) |
|||
return node; |
|||
|
|||
if (propertyValueNode.Values.Count != 1 || !(propertyValueNode.Values.First() is XamlAstTextNode)) |
|||
return node; |
|||
|
|||
var newNode = new XamlAstObjectNode( |
|||
propertyValueNode.Values[0], |
|||
new XamlAstClrTypeReference(propertyValueNode.Values[0], |
|||
context.GetAvaloniaTypes().ResolveByNameExtension, true)) |
|||
{ |
|||
Arguments = new List<IXamlAstValueNode> { propertyValueNode.Values[0] } |
|||
}; |
|||
|
|||
if (XamlTransformHelpers.TryConvertMarkupExtension(context, newNode, out var extensionNode)) |
|||
{ |
|||
propertyValueNode.Values[0] = extensionNode; |
|||
} |
|||
|
|||
return node; |
|||
} |
|||
} |
|||
} |
|||
@ -1 +1 @@ |
|||
Subproject commit 0028377ce7c7dc21f9fe71b45f62a95991b1ab58 |
|||
Subproject commit 7b8b3013bd42e1992838a525c991f44191da55be |
|||
@ -0,0 +1,59 @@ |
|||
using Avalonia.Controls.Shapes; |
|||
using Xunit; |
|||
|
|||
namespace Avalonia.Controls.UnitTests |
|||
{ |
|||
public class RelativePanelTests |
|||
{ |
|||
[Fact] |
|||
public void Lays_Out_1_Child_Next_the_other() |
|||
{ |
|||
var rect1 = new Rectangle { Height = 20, Width = 20 }; |
|||
var rect2 = new Rectangle { Height = 20, Width = 20 }; |
|||
|
|||
var target = new RelativePanel |
|||
{ |
|||
VerticalAlignment = Layout.VerticalAlignment.Top, |
|||
HorizontalAlignment = Layout.HorizontalAlignment.Left, |
|||
Children = |
|||
{ |
|||
rect1, rect2 |
|||
} |
|||
}; |
|||
|
|||
RelativePanel.SetAlignLeftWithPanel(rect1 , true); |
|||
RelativePanel.SetRightOf(rect2, rect1); |
|||
target.Measure(new Size(400, 400)); |
|||
target.Arrange(new Rect(target.DesiredSize)); |
|||
|
|||
Assert.Equal(new Size(40, 20), target.Bounds.Size); |
|||
Assert.Equal(new Rect(0, 0, 20, 20), target.Children[0].Bounds); |
|||
Assert.Equal(new Rect(20, 0, 20, 20), target.Children[1].Bounds); |
|||
} |
|||
|
|||
public void Lays_Out_1_Child_Below_the_other() |
|||
{ |
|||
var rect1 = new Rectangle { Height = 20, Width = 20 }; |
|||
var rect2 = new Rectangle { Height = 20, Width = 20 }; |
|||
|
|||
var target = new RelativePanel |
|||
{ |
|||
VerticalAlignment = Layout.VerticalAlignment.Top, |
|||
HorizontalAlignment = Layout.HorizontalAlignment.Left, |
|||
Children = |
|||
{ |
|||
rect1, rect2 |
|||
} |
|||
}; |
|||
|
|||
RelativePanel.SetAlignLeftWithPanel(rect1, true); |
|||
RelativePanel.SetBelow(rect2, rect1); |
|||
target.Measure(new Size(400, 400)); |
|||
target.Arrange(new Rect(target.DesiredSize)); |
|||
|
|||
Assert.Equal(new Size(20, 40), target.Bounds.Size); |
|||
Assert.Equal(new Rect(0, 0, 20, 20), target.Children[0].Bounds); |
|||
Assert.Equal(new Rect(0, 20, 20, 20), target.Children[1].Bounds); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,37 @@ |
|||
using System.Linq; |
|||
using Avalonia.Utilities; |
|||
using Xunit; |
|||
|
|||
namespace Avalonia.Visuals.UnitTests.Utilities |
|||
{ |
|||
public class ReadOnlySpanTests |
|||
{ |
|||
[Fact] |
|||
public void Should_Skip() |
|||
{ |
|||
var buffer = new[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; |
|||
|
|||
var slice = new ReadOnlySlice<int>(buffer); |
|||
|
|||
var skipped = slice.Skip(2); |
|||
|
|||
var expected = buffer.Skip(2); |
|||
|
|||
Assert.Equal(expected, skipped); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_Take() |
|||
{ |
|||
var buffer = new[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; |
|||
|
|||
var slice = new ReadOnlySlice<int>(buffer); |
|||
|
|||
var taken = slice.Take(8); |
|||
|
|||
var expected = buffer.Take(8); |
|||
|
|||
Assert.Equal(expected, taken); |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue