2 changed files with 935 additions and 0 deletions
@ -0,0 +1,511 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Text; |
|||
|
|||
namespace Avalonia.Controls |
|||
{ |
|||
public partial class RelativePanel |
|||
{ |
|||
private static void OnAlignPropertiesChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) |
|||
{ |
|||
var elm = d as FrameworkElement; |
|||
if (elm.Parent is FrameworkElement) |
|||
((FrameworkElement)elm.Parent).InvalidateArrange(); |
|||
} |
|||
|
|||
/// <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>
|
|||
[TypeConverter(typeof(NameReferenceConverter))] |
|||
public static object GetAbove(DependencyObject 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(DependencyObject obj, object value) |
|||
{ |
|||
obj.SetValue(AboveProperty, value); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Identifies the <see cref="RelativePanel.AboveProperty"/> XAML attached property.
|
|||
/// </summary>
|
|||
public static readonly DependencyProperty AboveProperty = |
|||
DependencyProperty.RegisterAttached("Above", typeof(object), typeof(RelativePanel), new PropertyMetadata(null, OnAlignPropertiesChanged)); |
|||
|
|||
|
|||
/// <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(DependencyObject 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(DependencyObject obj, bool value) |
|||
{ |
|||
obj.SetValue(AlignBottomWithPanelProperty, value); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Identifies the <see cref="RelativePanel.AlignBottomWithPanelProperty"/> XAML attached property.
|
|||
/// </summary>
|
|||
public static readonly DependencyProperty AlignBottomWithPanelProperty = |
|||
DependencyProperty.RegisterAttached("AlignBottomWithPanel", typeof(bool), typeof(RelativePanel), new PropertyMetadata(false, OnAlignPropertiesChanged)); |
|||
|
|||
/// <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>
|
|||
[TypeConverter(typeof(NameReferenceConverter))] |
|||
public static object GetAlignBottomWith(DependencyObject 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(DependencyObject obj, object value) |
|||
{ |
|||
obj.SetValue(AlignBottomWithProperty, value); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Identifies the <see cref="RelativePanel.AlignBottomWithProperty"/> XAML attached property.
|
|||
/// </summary>
|
|||
public static readonly DependencyProperty AlignBottomWithProperty = |
|||
DependencyProperty.RegisterAttached("AlignBottomWith", typeof(object), typeof(RelativePanel), new PropertyMetadata(null, OnAlignPropertiesChanged)); |
|||
|
|||
/// <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(DependencyObject 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(DependencyObject obj, bool value) |
|||
{ |
|||
obj.SetValue(AlignHorizontalCenterWithPanelProperty, value); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Identifies the <see cref="RelativePanel.AlignHorizontalCenterWithPanelProperty"/> XAML attached property.
|
|||
/// </summary>
|
|||
public static readonly DependencyProperty AlignHorizontalCenterWithPanelProperty = |
|||
DependencyProperty.RegisterAttached("AlignHorizontalCenterWithPanel", typeof(bool), typeof(RelativePanel), new PropertyMetadata(false, OnAlignPropertiesChanged)); |
|||
|
|||
/// <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>
|
|||
[TypeConverter(typeof(NameReferenceConverter))] |
|||
public static object GetAlignHorizontalCenterWith(DependencyObject 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(DependencyObject obj, object value) |
|||
{ |
|||
obj.SetValue(AlignHorizontalCenterWithProperty, value); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Identifies the <see cref="RelativePanel.AlignHorizontalCenterWithProperty"/> XAML attached property.
|
|||
/// </summary>
|
|||
public static readonly DependencyProperty AlignHorizontalCenterWithProperty = |
|||
DependencyProperty.RegisterAttached("AlignHorizontalCenterWith", typeof(object), typeof(RelativePanel), new PropertyMetadata(null, OnAlignPropertiesChanged)); |
|||
|
|||
/// <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(DependencyObject 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(DependencyObject obj, bool value) |
|||
{ |
|||
obj.SetValue(AlignLeftWithPanelProperty, value); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Identifies the <see cref="RelativePanel.AlignLeftWithPanelProperty"/> XAML attached property.
|
|||
/// </summary>
|
|||
public static readonly DependencyProperty AlignLeftWithPanelProperty = |
|||
DependencyProperty.RegisterAttached("AlignLeftWithPanel", typeof(bool), typeof(RelativePanel), new PropertyMetadata(false, OnAlignPropertiesChanged)); |
|||
|
|||
|
|||
/// <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>
|
|||
[TypeConverter(typeof(NameReferenceConverter))] |
|||
public static object GetAlignLeftWith(DependencyObject 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(DependencyObject obj, object value) |
|||
{ |
|||
obj.SetValue(AlignLeftWithProperty, value); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Identifies the <see cref="RelativePanel.AlignLeftWithProperty"/> XAML attached property.
|
|||
/// </summary>
|
|||
public static readonly DependencyProperty AlignLeftWithProperty = |
|||
DependencyProperty.RegisterAttached("AlignLeftWith", typeof(object), typeof(RelativePanel), new PropertyMetadata(null, OnAlignPropertiesChanged)); |
|||
|
|||
|
|||
/// <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(DependencyObject 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(DependencyObject obj, bool value) |
|||
{ |
|||
obj.SetValue(AlignRightWithPanelProperty, value); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Identifies the <see cref="RelativePanel.AlignRightWithPanelProperty"/> XAML attached property.
|
|||
/// </summary>
|
|||
public static readonly DependencyProperty AlignRightWithPanelProperty = |
|||
DependencyProperty.RegisterAttached("AlignRightWithPanel", typeof(bool), typeof(RelativePanel), new PropertyMetadata(false, OnAlignPropertiesChanged)); |
|||
|
|||
/// <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>
|
|||
[TypeConverter(typeof(NameReferenceConverter))] |
|||
public static object GetAlignRightWith(DependencyObject 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(DependencyObject obj, object value) |
|||
{ |
|||
obj.SetValue(AlignRightWithProperty, value); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Identifies the <see cref="RelativePanel.AlignRightWithProperty"/> XAML attached property.
|
|||
/// </summary>
|
|||
public static readonly DependencyProperty AlignRightWithProperty = |
|||
DependencyProperty.RegisterAttached("AlignRightWith", typeof(object), typeof(RelativePanel), new PropertyMetadata(null, OnAlignPropertiesChanged)); |
|||
|
|||
/// <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(DependencyObject 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(DependencyObject obj, bool value) |
|||
{ |
|||
obj.SetValue(AlignTopWithPanelProperty, value); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Identifies the <see cref="RelativePanel.AlignTopWithPanelProperty"/> XAML attached property.
|
|||
/// </summary>
|
|||
public static readonly DependencyProperty AlignTopWithPanelProperty = |
|||
DependencyProperty.RegisterAttached("AlignTopWithPanel", typeof(bool), typeof(RelativePanel), new PropertyMetadata(false, OnAlignPropertiesChanged)); |
|||
|
|||
/// <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>
|
|||
[TypeConverter(typeof(NameReferenceConverter))] |
|||
public static object GetAlignTopWith(DependencyObject 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(DependencyObject obj, object value) |
|||
{ |
|||
obj.SetValue(AlignTopWithProperty, value); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Identifies the <see cref="RelativePanel.AlignTopWithProperty"/> XAML attached property.
|
|||
/// </summary>
|
|||
public static readonly DependencyProperty AlignTopWithProperty = |
|||
DependencyProperty.RegisterAttached("AlignTopWith", typeof(object), typeof(RelativePanel), new PropertyMetadata(null, OnAlignPropertiesChanged)); |
|||
|
|||
/// <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(DependencyObject 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(DependencyObject obj, bool value) |
|||
{ |
|||
obj.SetValue(AlignVerticalCenterWithPanelProperty, value); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Identifies the <see cref="RelativePanel.AlignVerticalCenterWithPanelProperty"/> XAML attached property.
|
|||
/// </summary>
|
|||
public static readonly DependencyProperty AlignVerticalCenterWithPanelProperty = |
|||
DependencyProperty.RegisterAttached("AlignVerticalCenterWithPanel", typeof(bool), typeof(RelativePanel), new PropertyMetadata(false, OnAlignPropertiesChanged)); |
|||
|
|||
/// <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>
|
|||
[TypeConverter(typeof(NameReferenceConverter))] |
|||
public static object GetAlignVerticalCenterWith(DependencyObject 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(DependencyObject obj, object value) |
|||
{ |
|||
obj.SetValue(AlignVerticalCenterWithProperty, value); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Identifies the <see cref="RelativePanel.AlignVerticalCenterWithProperty"/> XAML attached property.
|
|||
/// </summary>
|
|||
public static readonly DependencyProperty AlignVerticalCenterWithProperty = |
|||
DependencyProperty.RegisterAttached("AlignVerticalCenterWith", typeof(object), typeof(RelativePanel), new PropertyMetadata(null, OnAlignPropertiesChanged)); |
|||
|
|||
/// <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>
|
|||
[TypeConverter(typeof(NameReferenceConverter))] |
|||
public static object GetBelow(DependencyObject 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(DependencyObject obj, object value) |
|||
{ |
|||
obj.SetValue(BelowProperty, value); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Identifies the <see cref="RelativePanel.BelowProperty"/> XAML attached property.
|
|||
/// </summary>
|
|||
public static readonly DependencyProperty BelowProperty = |
|||
DependencyProperty.RegisterAttached("Below", typeof(object), typeof(RelativePanel), new PropertyMetadata(null, OnAlignPropertiesChanged)); |
|||
|
|||
/// <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>
|
|||
[TypeConverter(typeof(NameReferenceConverter))] |
|||
public static object GetLeftOf(DependencyObject 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(DependencyObject obj, object value) |
|||
{ |
|||
obj.SetValue(LeftOfProperty, value); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Identifies the <see cref="RelativePanel.LeftOfProperty"/> XAML attached property.
|
|||
/// </summary>
|
|||
public static readonly DependencyProperty LeftOfProperty = |
|||
DependencyProperty.RegisterAttached("LeftOf", typeof(object), typeof(RelativePanel), new PropertyMetadata(null, OnAlignPropertiesChanged)); |
|||
|
|||
/// <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>
|
|||
[TypeConverter(typeof(NameReferenceConverter))] |
|||
public static object GetRightOf(DependencyObject 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(DependencyObject obj, object value) |
|||
{ |
|||
obj.SetValue(RightOfProperty, value); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Identifies the <see cref="RelativePanel.RightOfProperty"/> XAML attached property.
|
|||
/// </summary>
|
|||
public static readonly DependencyProperty RightOfProperty = |
|||
DependencyProperty.RegisterAttached("RightOf", typeof(object), typeof(RelativePanel), new PropertyMetadata(null, OnAlignPropertiesChanged)); |
|||
} |
|||
} |
|||
@ -0,0 +1,424 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Text; |
|||
|
|||
namespace Avalonia.Controls |
|||
{ |
|||
/// <summary>
|
|||
/// Defines an area within which you can position and align child objects in relation
|
|||
/// to each other or the parent panel.
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// <para><b>Default position</b></para>
|
|||
/// <para>By default, any unconstrained element declared as a child of the RelativePanel is given the entire
|
|||
/// available space and positioned at the(0, 0) coordinates(upper left corner) of the panel.So, if you
|
|||
/// are positioning a second element relative to an unconstrained element, keep in mind that the second
|
|||
/// element might get pushed out of the panel.
|
|||
/// </para>
|
|||
///<para><b>Conflicting relationships</b></para>
|
|||
/// <para>
|
|||
/// If you set multiple relationships that target the same edge of an element, you might have conflicting
|
|||
/// relationships in your layout as a result.When this happens, the relationships are applied in the
|
|||
/// following order of priority:
|
|||
/// • Panel alignment relationships (AlignTopWithPanel, AlignLeftWithPanel, …) are applied first.
|
|||
/// • Sibling alignment relationships(AlignTopWith, AlignLeftWith, …) are applied second.
|
|||
/// • Sibling positional relationships(Above, Below, RightOf, LeftOf) are applied last.
|
|||
/// </para>
|
|||
/// <para>
|
|||
/// The panel-center alignment properties(AlignVerticalCenterWith, AlignHorizontalCenterWithPanel, ...) are
|
|||
/// typically used independently of other constraints and are applied if there is no conflict.
|
|||
///</para>
|
|||
/// <para>
|
|||
/// The HorizontalAlignment and VerticalAlignment properties on UI elements are applied after relationship
|
|||
/// properties are evaluated and applied. These properties control the placement of the element within the
|
|||
/// available size for the element, if the desired size is smaller than the available size.
|
|||
/// </para>
|
|||
/// </remarks>
|
|||
public partial class RelativePanel : Panel |
|||
{ |
|||
// Dependency property for storing intermediate arrange state on the children
|
|||
private static readonly DependencyProperty ArrangeStateProperty = |
|||
DependencyProperty.Register("ArrangeState", typeof(double[]), typeof(RelativePanel), new PropertyMetadata(null)); |
|||
|
|||
/// <summary>
|
|||
/// When overridden in a derived class, measures the size in layout required for
|
|||
/// child elements and determines a size for the System.Windows.FrameworkElement-derived
|
|||
/// class.</summary>
|
|||
/// <param name="availableSize">
|
|||
/// The available size that this element can give to child elements. Infinity can
|
|||
/// be specified as a value to indicate that the element will size to whatever content
|
|||
/// is available.
|
|||
/// </param>
|
|||
/// <returns>
|
|||
/// The size that this element determines it needs during layout, based on its calculations
|
|||
/// of child element sizes.
|
|||
/// </returns>
|
|||
protected override Size MeasureOverride(Size availableSize) |
|||
{ |
|||
foreach (var child in Children.OfType<FrameworkElement>()) |
|||
{ |
|||
child.Measure(availableSize); |
|||
} |
|||
foreach (var item in CalculateLocations(availableSize)) |
|||
{ |
|||
if (item.Item2.Size.Width < item.Item1.DesiredSize.Width || item.Item2.Size.Height < item.Item1.DesiredSize.Height) |
|||
item.Item1.Measure(item.Item2.Size); |
|||
} |
|||
return base.MeasureOverride(availableSize); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// When overridden in a derived class, positions child elements and determines a
|
|||
/// size for a System.Windows.FrameworkElement derived class.
|
|||
/// </summary>
|
|||
/// <param name="finalSize">
|
|||
/// The final area within the parent that this element should use to arrange itself
|
|||
/// and its children.
|
|||
/// </param>
|
|||
/// <returns>The actual size used.</returns>
|
|||
protected override Size ArrangeOverride(Size finalSize) |
|||
{ |
|||
foreach (var item in CalculateLocations(finalSize)) |
|||
item.Item1.Arrange(item.Item2); |
|||
return base.ArrangeOverride(finalSize); |
|||
} |
|||
|
|||
private IEnumerable<Tuple<UIElement, Rect>> CalculateLocations(Size finalSize) |
|||
{ |
|||
//List of margins for each element between the element and panel (left, top, right, bottom)
|
|||
List<double[]> arranges = new List<double[]>(Children.Count); |
|||
//First pass aligns all sides that aren't constrained by other elements
|
|||
int arrangedCount = 0; |
|||
foreach (var child in Children.OfType<UIElement>()) |
|||
{ |
|||
//NaN means the arrange value is not constrained yet for that side
|
|||
double[] rect = new[] { double.NaN, double.NaN, double.NaN, double.NaN }; |
|||
arranges.Add(rect); |
|||
child.SetValue(ArrangeStateProperty, rect); |
|||
|
|||
//Align with panels always wins, so do these first, or if no constraints are set at all set margin to 0
|
|||
|
|||
//Left side
|
|||
if (GetAlignLeftWithPanel(child)) |
|||
{ |
|||
rect[0] = 0; |
|||
} |
|||
else if ( |
|||
child.GetValue(AlignLeftWithProperty) == null && |
|||
child.GetValue(RightOfProperty) == null && |
|||
child.GetValue(AlignHorizontalCenterWithProperty) == null && |
|||
!GetAlignHorizontalCenterWithPanel(child)) |
|||
{ |
|||
if (GetAlignRightWithPanel(child)) |
|||
rect[0] = finalSize.Width - child.DesiredSize.Width; |
|||
else if (child.GetValue(AlignRightWithProperty) == null && child.GetValue(AlignHorizontalCenterWithProperty) == null && child.GetValue(LeftOfProperty) == null) |
|||
rect[0] = 0; //default fallback to 0
|
|||
} |
|||
|
|||
//Top side
|
|||
if (GetAlignTopWithPanel(child)) |
|||
{ |
|||
rect[1] = 0; |
|||
} |
|||
else if ( |
|||
child.GetValue(AlignTopWithProperty) == null && |
|||
child.GetValue(BelowProperty) == null && |
|||
child.GetValue(AlignVerticalCenterWithProperty) == null && |
|||
!GetAlignVerticalCenterWithPanel(child)) |
|||
{ |
|||
if (GetAlignBottomWithPanel(child)) |
|||
rect[1] = finalSize.Height - child.DesiredSize.Height; |
|||
else if (child.GetValue(AlignBottomWithProperty) == null && child.GetValue(AlignVerticalCenterWithProperty) == null && child.GetValue(AboveProperty) == null) |
|||
rect[1] = 0; //default fallback to 0
|
|||
} |
|||
|
|||
//Right side
|
|||
if (GetAlignRightWithPanel(child)) |
|||
{ |
|||
rect[2] = 0; |
|||
} |
|||
else if (!double.IsNaN(rect[0]) && |
|||
child.GetValue(AlignRightWithProperty) == null && |
|||
child.GetValue(LeftOfProperty) == null && |
|||
child.GetValue(AlignHorizontalCenterWithProperty) == null && |
|||
!GetAlignHorizontalCenterWithPanel(child)) |
|||
{ |
|||
rect[2] = finalSize.Width - rect[0] - child.DesiredSize.Width; |
|||
} |
|||
|
|||
//Bottom side
|
|||
if (GetAlignBottomWithPanel(child)) |
|||
rect[3] = 0; |
|||
else if (!double.IsNaN(rect[1]) && |
|||
(child.GetValue(AlignBottomWithProperty) == null && |
|||
child.GetValue(AboveProperty) == null) && |
|||
child.GetValue(AlignVerticalCenterWithProperty) == null && |
|||
!GetAlignVerticalCenterWithPanel(child)) |
|||
{ |
|||
rect[3] = finalSize.Height - rect[1] - child.DesiredSize.Height; |
|||
} |
|||
|
|||
if (!double.IsNaN(rect[0]) && !double.IsNaN(rect[1]) && |
|||
!double.IsNaN(rect[2]) && !double.IsNaN(rect[3])) |
|||
arrangedCount++; |
|||
} |
|||
int i = 0; |
|||
//Run iterative layout passes
|
|||
while (arrangedCount < Children.Count) |
|||
{ |
|||
bool valueChanged = false; |
|||
i = 0; |
|||
foreach (var child in Children.OfType<UIElement>()) |
|||
{ |
|||
double[] rect = arranges[i++]; |
|||
|
|||
if (!double.IsNaN(rect[0]) && !double.IsNaN(rect[1]) && |
|||
!double.IsNaN(rect[2]) && !double.IsNaN(rect[3])) |
|||
continue; //Control is fully arranged
|
|||
|
|||
//Calculate left side
|
|||
if (double.IsNaN(rect[0])) |
|||
{ |
|||
var alignLeftWith = GetDependencyElement(RelativePanel.AlignLeftWithProperty, child); |
|||
if (alignLeftWith != null) |
|||
{ |
|||
double[] r = (double[])alignLeftWith.GetValue(ArrangeStateProperty); |
|||
if (!double.IsNaN(r[0])) |
|||
{ |
|||
rect[0] = r[0]; |
|||
valueChanged = true; |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
var rightOf = GetDependencyElement(RelativePanel.RightOfProperty, child); |
|||
if (rightOf != null) |
|||
{ |
|||
double[] r = (double[])rightOf.GetValue(ArrangeStateProperty); |
|||
if (!double.IsNaN(r[2])) |
|||
{ |
|||
rect[0] = finalSize.Width - r[2]; |
|||
valueChanged = true; |
|||
} |
|||
} |
|||
else if (!double.IsNaN(rect[2])) |
|||
{ |
|||
rect[0] = finalSize.Width - rect[2] - child.DesiredSize.Width; |
|||
valueChanged = true; |
|||
} |
|||
} |
|||
} |
|||
//Calculate top side
|
|||
if (double.IsNaN(rect[1])) |
|||
{ |
|||
var alignTopWith = GetDependencyElement(RelativePanel.AlignTopWithProperty, child); |
|||
if (alignTopWith != null) |
|||
{ |
|||
double[] r = (double[])alignTopWith.GetValue(ArrangeStateProperty); |
|||
if (!double.IsNaN(r[1])) |
|||
{ |
|||
rect[1] = r[1]; |
|||
valueChanged = true; |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
var below = GetDependencyElement(RelativePanel.BelowProperty, child); |
|||
if (below != null) |
|||
{ |
|||
double[] r = (double[])below.GetValue(ArrangeStateProperty); |
|||
if (!double.IsNaN(r[3])) |
|||
{ |
|||
rect[1] = finalSize.Height - r[3]; |
|||
valueChanged = true; |
|||
} |
|||
} |
|||
else if (!double.IsNaN(rect[3])) |
|||
{ |
|||
rect[1] = finalSize.Height - rect[3] - child.DesiredSize.Height; |
|||
valueChanged = true; |
|||
} |
|||
} |
|||
} |
|||
//Calculate right side
|
|||
if (double.IsNaN(rect[2])) |
|||
{ |
|||
var alignRightWith = GetDependencyElement(RelativePanel.AlignRightWithProperty, child); |
|||
if (alignRightWith != null) |
|||
{ |
|||
double[] r = (double[])alignRightWith.GetValue(ArrangeStateProperty); |
|||
if (!double.IsNaN(r[2])) |
|||
{ |
|||
rect[2] = r[2]; |
|||
if (double.IsNaN(rect[0])) |
|||
{ |
|||
if (child.GetValue(RelativePanel.AlignLeftWithProperty) == null) |
|||
{ |
|||
rect[0] = rect[2] + child.DesiredSize.Width; |
|||
valueChanged = true; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
var leftOf = GetDependencyElement(RelativePanel.LeftOfProperty, child); |
|||
if (leftOf != null) |
|||
{ |
|||
double[] r = (double[])leftOf.GetValue(ArrangeStateProperty); |
|||
if (!double.IsNaN(r[0])) |
|||
{ |
|||
rect[2] = finalSize.Width - r[0]; |
|||
valueChanged = true; |
|||
} |
|||
} |
|||
else if (!double.IsNaN(rect[0])) |
|||
{ |
|||
rect[2] = finalSize.Width - rect[0] - child.DesiredSize.Width; |
|||
valueChanged = true; |
|||
} |
|||
} |
|||
} |
|||
//Calculate bottom side
|
|||
if (double.IsNaN(rect[3])) |
|||
{ |
|||
var alignBottomWith = GetDependencyElement(RelativePanel.AlignBottomWithProperty, child); |
|||
if (alignBottomWith != null) |
|||
{ |
|||
double[] r = (double[])alignBottomWith.GetValue(ArrangeStateProperty); |
|||
if (!double.IsNaN(r[3])) |
|||
{ |
|||
rect[3] = r[3]; |
|||
valueChanged = true; |
|||
if (double.IsNaN(rect[1])) |
|||
{ |
|||
if (child.GetValue(RelativePanel.AlignTopWithProperty) == null) |
|||
{ |
|||
rect[1] = finalSize.Height - rect[3] - child.DesiredSize.Height; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
var above = GetDependencyElement(RelativePanel.AboveProperty, child); |
|||
if (above != null) |
|||
{ |
|||
double[] r = (double[])above.GetValue(ArrangeStateProperty); |
|||
if (!double.IsNaN(r[1])) |
|||
{ |
|||
rect[3] = finalSize.Height - r[1]; |
|||
valueChanged = true; |
|||
} |
|||
} |
|||
else if (!double.IsNaN(rect[1])) |
|||
{ |
|||
rect[3] = finalSize.Height - rect[1] - child.DesiredSize.Height; |
|||
valueChanged = true; |
|||
} |
|||
} |
|||
} |
|||
//Calculate horizontal alignment
|
|||
if (double.IsNaN(rect[0]) && double.IsNaN(rect[2])) |
|||
{ |
|||
var alignHorizontalCenterWith = GetDependencyElement(RelativePanel.AlignHorizontalCenterWithProperty, child); |
|||
if (alignHorizontalCenterWith != null) |
|||
{ |
|||
double[] r = (double[])alignHorizontalCenterWith.GetValue(ArrangeStateProperty); |
|||
if (!double.IsNaN(r[0]) && !double.IsNaN(r[2])) |
|||
{ |
|||
rect[0] = r[0] + (finalSize.Width - r[2] - r[0]) * .5 - child.DesiredSize.Width * .5; |
|||
rect[2] = finalSize.Width - rect[0] - child.DesiredSize.Width; |
|||
valueChanged = true; |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
if (GetAlignHorizontalCenterWithPanel(child)) |
|||
{ |
|||
var roomToSpare = finalSize.Width - child.DesiredSize.Width; |
|||
rect[0] = roomToSpare * .5; |
|||
rect[2] = roomToSpare * .5; |
|||
valueChanged = true; |
|||
} |
|||
} |
|||
} |
|||
|
|||
//Calculate vertical alignment
|
|||
if (double.IsNaN(rect[1]) && double.IsNaN(rect[3])) |
|||
{ |
|||
var alignVerticalCenterWith = GetDependencyElement(RelativePanel.AlignVerticalCenterWithProperty, child); |
|||
if (alignVerticalCenterWith != null) |
|||
{ |
|||
double[] r = (double[])alignVerticalCenterWith.GetValue(ArrangeStateProperty); |
|||
if (!double.IsNaN(r[1]) && !double.IsNaN(r[3])) |
|||
{ |
|||
rect[1] = r[1] + (finalSize.Height - r[3] - r[1]) * .5 - child.DesiredSize.Height * .5; |
|||
rect[3] = finalSize.Height - rect[1] - child.DesiredSize.Height; |
|||
valueChanged = true; |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
if (GetAlignVerticalCenterWithPanel(child)) |
|||
{ |
|||
var roomToSpare = finalSize.Height - child.DesiredSize.Height; |
|||
rect[1] = roomToSpare * .5; |
|||
rect[3] = roomToSpare * .5; |
|||
valueChanged = true; |
|||
} |
|||
} |
|||
} |
|||
|
|||
|
|||
//if panel is now fully arranged, increase the counter
|
|||
if (!double.IsNaN(rect[0]) && !double.IsNaN(rect[1]) && |
|||
!double.IsNaN(rect[2]) && !double.IsNaN(rect[3])) |
|||
arrangedCount++; |
|||
} |
|||
if (!valueChanged) |
|||
{ |
|||
//If a layout pass didn't increase number of arranged elements,
|
|||
//there must be a circular dependency
|
|||
throw new ArgumentException("RelativePanel error: Circular dependency detected. Layout could not complete"); |
|||
} |
|||
} |
|||
|
|||
i = 0; |
|||
//Arrange iterations complete - Apply the results to the child elements
|
|||
foreach (var child in Children.OfType<UIElement>()) |
|||
{ |
|||
double[] rect = arranges[i++]; |
|||
//Measure child again with the new calculated available size
|
|||
//this helps for instance textblocks to reflow the text wrapping
|
|||
//We should probably have done this during the measure step but it would cause a more expensive
|
|||
//measure+arrange layout cycle
|
|||
//if(child is TextBlock)
|
|||
// child.Measure(new Size(Math.Max(0, finalSize.Width - rect[2] - rect[0]), Math.Max(0, finalSize.Height - rect[3] - rect[1])));
|
|||
|
|||
//if(child is TextBlock tb)
|
|||
//{
|
|||
// tb.ArrangeOverride(new Rect(rect[0], rect[1], Math.Max(0, finalSize.Width - rect[2] - rect[0]), Math.Max(0, finalSize.Height - rect[3] - rect[1])));
|
|||
//}
|
|||
//else
|
|||
yield return new Tuple<UIElement, Rect>(child, new Rect(rect[0], rect[1], Math.Max(0, finalSize.Width - rect[2] - rect[0]), Math.Max(0, finalSize.Height - rect[3] - rect[1]))); |
|||
} |
|||
} |
|||
|
|||
//Gets the element that's referred to in the alignment attached properties
|
|||
private UIElement GetDependencyElement(DependencyProperty property, DependencyObject child) |
|||
{ |
|||
var dependency = child.GetValue(property); |
|||
if (dependency == null) |
|||
return null; |
|||
if (dependency is UIElement) |
|||
{ |
|||
if (Children.Contains((UIElement)dependency)) |
|||
return (UIElement)dependency; |
|||
throw new ArgumentException(string.Format("RelativePanel error: Element does not exist in the current context", property.Name)); |
|||
} |
|||
|
|||
throw new ArgumentException("RelativePanel error: Value must be of type UIElement"); |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue