You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
554 lines
25 KiB
554 lines
25 KiB
// (c) Copyright Microsoft Corporation.
|
|
// This source is subject to the Microsoft Public License (Ms-PL).
|
|
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
|
|
// All other rights reserved.
|
|
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics.CodeAnalysis;
|
|
using System.Globalization;
|
|
using System.Linq;
|
|
using System.Windows.Media;
|
|
|
|
namespace System.Windows.Controls.DataVisualization.Charting.Primitives
|
|
{
|
|
/// <summary>
|
|
/// Defines an area where you can arrange child elements either horizontally
|
|
/// or vertically, relative to each other.
|
|
/// </summary>
|
|
/// <QualityBand>Preview</QualityBand>
|
|
public class EdgePanel : Panel
|
|
{
|
|
/// <summary>
|
|
/// The maximum number of iterations.
|
|
/// </summary>
|
|
private const int MaximumIterations = 10;
|
|
|
|
/// <summary>
|
|
/// A flag that ignores a property change when set.
|
|
/// </summary>
|
|
private static bool _ignorePropertyChange;
|
|
|
|
#region public attached Edge Edge
|
|
/// <summary>
|
|
/// Gets the value of the Edge attached property for a specified
|
|
/// UIElement.
|
|
/// </summary>
|
|
/// <param name="element">
|
|
/// The element from which the property value is read.
|
|
/// </param>
|
|
/// <returns>The Edge property value for the element.</returns>
|
|
[SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters", Justification = "EdgePanel only has UIElement children")]
|
|
public static Edge GetEdge(UIElement element)
|
|
{
|
|
if (element == null)
|
|
{
|
|
throw new ArgumentNullException("element");
|
|
}
|
|
return (Edge)element.GetValue(EdgeProperty);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Sets the value of the Edge attached property to a specified element.
|
|
/// </summary>
|
|
/// <param name="element">
|
|
/// The element to which the attached property is written.
|
|
/// </param>
|
|
/// <param name="edge">The needed Edge value.</param>
|
|
[SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters", Justification = "EdgePanel only has UIElement children")]
|
|
public static void SetEdge(UIElement element, Edge edge)
|
|
{
|
|
if (element == null)
|
|
{
|
|
throw new ArgumentNullException("element");
|
|
}
|
|
element.SetValue(EdgeProperty, edge);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Identifies the Edge dependency property.
|
|
/// </summary>
|
|
public static readonly DependencyProperty EdgeProperty =
|
|
DependencyProperty.RegisterAttached(
|
|
"Edge",
|
|
typeof(Edge),
|
|
typeof(EdgePanel),
|
|
new PropertyMetadata(Edge.Center, OnEdgePropertyChanged));
|
|
|
|
/// <summary>
|
|
/// EdgeProperty property changed handler.
|
|
/// </summary>
|
|
/// <param name="d">UIElement that changed its Edge.</param>
|
|
/// <param name="e">Event arguments.</param>
|
|
[SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly", Justification = "Almost always set from the attached property CLR setter.")]
|
|
private static void OnEdgePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
|
{
|
|
// Ignore the change if requested
|
|
if (_ignorePropertyChange)
|
|
{
|
|
_ignorePropertyChange = false;
|
|
return;
|
|
}
|
|
|
|
UIElement element = (UIElement)d;
|
|
Edge value = (Edge)e.NewValue;
|
|
|
|
// Validate the Edge property
|
|
if ((value != Edge.Left) &&
|
|
(value != Edge.Top) &&
|
|
(value != Edge.Right) &&
|
|
(value != Edge.Center) &&
|
|
(value != Edge.Bottom))
|
|
{
|
|
// Reset the property to its original state before throwing
|
|
_ignorePropertyChange = true;
|
|
element.SetValue(EdgeProperty, (Edge)e.OldValue);
|
|
|
|
string message = string.Format(
|
|
CultureInfo.InvariantCulture,
|
|
Properties.Resources.EdgePanel_OnEdgePropertyChanged,
|
|
value);
|
|
|
|
throw new ArgumentException(message, "value");
|
|
}
|
|
|
|
// Cause the EdgePanel to update its layout when a child changes
|
|
EdgePanel panel = VisualTreeHelper.GetParent(element) as EdgePanel;
|
|
if (panel != null)
|
|
{
|
|
panel.InvalidateMeasure();
|
|
}
|
|
}
|
|
#endregion public attached Edge Edge
|
|
|
|
/// <summary>
|
|
/// Initializes a new instance of the EdgePanel class.
|
|
/// </summary>
|
|
public EdgePanel()
|
|
{
|
|
this.SizeChanged += new SizeChangedEventHandler(EdgePanelSizeChanged);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Invalidate measure when edge panel is resized.
|
|
/// </summary>
|
|
/// <param name="sender">The source of the event.</param>
|
|
/// <param name="e">Information about the event.</param>
|
|
private void EdgePanelSizeChanged(object sender, SizeChangedEventArgs e)
|
|
{
|
|
InvalidateMeasure();
|
|
}
|
|
|
|
/// <summary>
|
|
/// The left rectangle in which to render left elements.
|
|
/// </summary>
|
|
private Rect _leftRect;
|
|
|
|
/// <summary>
|
|
/// The right rectangle in which to render right elements.
|
|
/// </summary>
|
|
private Rect _rightRect;
|
|
|
|
/// <summary>
|
|
/// The top rectangle in which to render top elements.
|
|
/// </summary>
|
|
private Rect _topRect;
|
|
|
|
/// <summary>
|
|
/// The bottom rectangle in which to render bottom elements.
|
|
/// </summary>
|
|
private Rect _bottomRect;
|
|
|
|
/// <summary>
|
|
/// Measures the children of a EdgePanel in anticipation of arranging
|
|
/// them during the ArrangeOverride pass.
|
|
/// </summary>
|
|
/// <param name="constraint">A maximum Size to not exceed.</param>
|
|
/// <returns>The desired size of the EdgePanel.</returns>
|
|
[SuppressMessage("Microsoft.Maintainability", "CA1505:AvoidUnmaintainableCode", Justification = "Code is by nature difficult to refactor into several methods.")]
|
|
[SuppressMessage("Microsoft.Naming", "CA1725:ParameterNamesShouldMatchBaseDeclaration", MessageId = "0#", Justification = "Compat with WPF.")]
|
|
[SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity", Justification = "Splitting up method will make it more difficult to understand.")]
|
|
protected override Size MeasureOverride(Size constraint)
|
|
{
|
|
constraint = new Size(this.ActualWidth, this.ActualHeight);
|
|
|
|
IList<UIElement> leftElements = this.Children.OfType<UIElement>().Where(element => GetEdge(element) == Edge.Left).ToList();
|
|
IList<UIElement> rightElements = this.Children.OfType<UIElement>().Where(element => GetEdge(element) == Edge.Right).ToList();
|
|
IList<UIElement> bottomElements = this.Children.OfType<UIElement>().Where(element => GetEdge(element) == Edge.Bottom).ToList();
|
|
IList<UIElement> topElements = this.Children.OfType<UIElement>().Where(element => GetEdge(element) == Edge.Top).ToList();
|
|
|
|
Rect totalRect = SafeCreateRect(0, 0, constraint.Width, constraint.Height);
|
|
|
|
_leftRect = (leftElements.Count > 0) ? totalRect : Rect.Empty;
|
|
_bottomRect = (bottomElements.Count > 0) ? totalRect : Rect.Empty;
|
|
_rightRect = (rightElements.Count > 0) ? totalRect : Rect.Empty;
|
|
_topRect = (topElements.Count > 0) ? totalRect : Rect.Empty;
|
|
|
|
double rightAxesWidth = 0.0;
|
|
double leftAxesWidth = 0.0;
|
|
double topAxesHeight = 0.0;
|
|
double bottomAxesHeight = 0.0;
|
|
|
|
double maxRightRequestedWidth = 0;
|
|
double maxLeftRequestedWidth = 0;
|
|
double maxTopRequestedHeight = 0;
|
|
double maxBottomRequestedHeight = 0;
|
|
|
|
double previousRightAxesWidth = rightAxesWidth;
|
|
double previousLeftAxesWidth = leftAxesWidth;
|
|
double previousTopAxesHeight = topAxesHeight;
|
|
double previousBottomAxesHeight = bottomAxesHeight;
|
|
|
|
int iterations = 0;
|
|
// Measure each of the Children
|
|
while (true)
|
|
{
|
|
// Measure the children using the rectangle regions.
|
|
if (rightElements.Count > 0)
|
|
{
|
|
Size rightSize = new Size(constraint.Width, _rightRect.Height);
|
|
foreach (UIElement rightUIElement in rightElements)
|
|
{
|
|
rightUIElement.Measure(rightSize);
|
|
}
|
|
|
|
previousRightAxesWidth = rightAxesWidth;
|
|
rightAxesWidth = rightElements.Select(axis => axis.DesiredSize.Width).SumOrDefault();
|
|
maxRightRequestedWidth = Math.Max(maxRightRequestedWidth, rightAxesWidth);
|
|
_rightRect =
|
|
SafeCreateRect(
|
|
constraint.Width - rightAxesWidth,
|
|
_rightRect.Top,
|
|
rightAxesWidth,
|
|
_rightRect.Height);
|
|
}
|
|
|
|
if (topElements.Count > 0)
|
|
{
|
|
Size topSize = new Size(_topRect.Width, constraint.Height);
|
|
foreach (UIElement topUIElement in topElements)
|
|
{
|
|
topUIElement.Measure(topSize);
|
|
}
|
|
|
|
previousTopAxesHeight = topAxesHeight;
|
|
topAxesHeight = topElements.Select(axis => axis.DesiredSize.Height).SumOrDefault();
|
|
maxTopRequestedHeight = Math.Max(maxTopRequestedHeight, topAxesHeight);
|
|
_topRect =
|
|
SafeCreateRect(
|
|
_topRect.Left,
|
|
_topRect.Top,
|
|
_topRect.Width,
|
|
topAxesHeight);
|
|
}
|
|
|
|
if (leftElements.Count > 0)
|
|
{
|
|
Size leftSize = new Size(constraint.Width, _leftRect.Height);
|
|
foreach (UIElement leftUIElement in leftElements)
|
|
{
|
|
leftUIElement.Measure(leftSize);
|
|
}
|
|
|
|
previousLeftAxesWidth = leftAxesWidth;
|
|
leftAxesWidth = leftElements.Select(axis => axis.DesiredSize.Width).SumOrDefault();
|
|
maxLeftRequestedWidth = Math.Max(maxLeftRequestedWidth, leftAxesWidth);
|
|
_leftRect =
|
|
SafeCreateRect(
|
|
_leftRect.Left,
|
|
_leftRect.Top,
|
|
leftElements.Select(axis => axis.DesiredSize.Width).SumOrDefault(),
|
|
_leftRect.Height);
|
|
}
|
|
|
|
if (bottomElements.Count > 0)
|
|
{
|
|
Size bottomSize = new Size(_bottomRect.Width, constraint.Height);
|
|
foreach (UIElement bottomUIElement in bottomElements)
|
|
{
|
|
bottomUIElement.Measure(bottomSize);
|
|
}
|
|
|
|
previousBottomAxesHeight = bottomAxesHeight;
|
|
bottomAxesHeight = bottomElements.Select(axis => axis.DesiredSize.Height).SumOrDefault();
|
|
maxBottomRequestedHeight = Math.Max(maxBottomRequestedHeight, bottomAxesHeight);
|
|
_bottomRect =
|
|
SafeCreateRect(
|
|
_bottomRect.Left,
|
|
constraint.Height - bottomAxesHeight,
|
|
_bottomRect.Width,
|
|
bottomAxesHeight);
|
|
}
|
|
|
|
// Ensuring that parallel axes don't collide
|
|
Rect leftRightCollisionRect = _leftRect;
|
|
leftRightCollisionRect.Intersect(_rightRect);
|
|
|
|
Rect topBottomCollisionRect = _topRect;
|
|
topBottomCollisionRect.Intersect(_bottomRect);
|
|
|
|
if (!leftRightCollisionRect.IsEmptyOrHasNoSize() || !topBottomCollisionRect.IsEmptyOrHasNoSize())
|
|
{
|
|
return new Size();
|
|
}
|
|
|
|
// Resolving perpendicular axes collisions
|
|
Rect leftTopCollisionRect = _leftRect;
|
|
leftTopCollisionRect.Intersect(_topRect);
|
|
|
|
Rect rightTopCollisionRect = _rightRect;
|
|
rightTopCollisionRect.Intersect(_topRect);
|
|
|
|
Rect leftBottomCollisionRect = _leftRect;
|
|
leftBottomCollisionRect.Intersect(_bottomRect);
|
|
|
|
Rect rightBottomCollisionRect = _rightRect;
|
|
rightBottomCollisionRect.Intersect(_bottomRect);
|
|
|
|
if (leftBottomCollisionRect.IsEmptyOrHasNoSize()
|
|
&& rightBottomCollisionRect.IsEmptyOrHasNoSize()
|
|
&& leftTopCollisionRect.IsEmptyOrHasNoSize()
|
|
&& rightTopCollisionRect.IsEmptyOrHasNoSize()
|
|
&& previousBottomAxesHeight == bottomAxesHeight
|
|
&& previousLeftAxesWidth == leftAxesWidth
|
|
&& previousRightAxesWidth == rightAxesWidth
|
|
&& previousTopAxesHeight == topAxesHeight)
|
|
{
|
|
break;
|
|
}
|
|
|
|
if (iterations == MaximumIterations)
|
|
{
|
|
_leftRect = SafeCreateRect(0, maxTopRequestedHeight, maxLeftRequestedWidth, (constraint.Height - maxTopRequestedHeight) - maxBottomRequestedHeight);
|
|
_rightRect = SafeCreateRect(constraint.Width - maxRightRequestedWidth, maxTopRequestedHeight, maxRightRequestedWidth, (constraint.Height - maxTopRequestedHeight) - maxBottomRequestedHeight);
|
|
_bottomRect = SafeCreateRect(maxLeftRequestedWidth, constraint.Height - maxBottomRequestedHeight, (constraint.Width - maxLeftRequestedWidth) - maxRightRequestedWidth, maxBottomRequestedHeight);
|
|
_topRect = SafeCreateRect(maxLeftRequestedWidth, 0, (constraint.Width - maxLeftRequestedWidth) - maxRightRequestedWidth, maxTopRequestedHeight);
|
|
|
|
foreach (UIElement leftElement in leftElements)
|
|
{
|
|
leftElement.Measure(new Size(_leftRect.Width, _leftRect.Height));
|
|
}
|
|
|
|
foreach (UIElement rightElement in rightElements)
|
|
{
|
|
rightElement.Measure(new Size(_rightRect.Width, _rightRect.Height));
|
|
}
|
|
|
|
foreach (UIElement bottomElement in bottomElements)
|
|
{
|
|
bottomElement.Measure(new Size(_bottomRect.Width, _bottomRect.Height));
|
|
}
|
|
|
|
foreach (UIElement topElement in topElements)
|
|
{
|
|
topElement.Measure(new Size(_topRect.Width, _topRect.Height));
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (!leftBottomCollisionRect.IsEmptyOrHasNoSize())
|
|
{
|
|
_leftRect =
|
|
SafeCreateRect(
|
|
_leftRect.Left,
|
|
_leftRect.Top,
|
|
_leftRect.Width,
|
|
_leftRect.Height - leftBottomCollisionRect.Height);
|
|
|
|
_bottomRect =
|
|
SafeCreateRect(
|
|
_bottomRect.Left + leftBottomCollisionRect.Width,
|
|
_bottomRect.Top,
|
|
_bottomRect.Width - leftBottomCollisionRect.Width,
|
|
_bottomRect.Height);
|
|
}
|
|
|
|
if (!leftTopCollisionRect.IsEmptyOrHasNoSize())
|
|
{
|
|
_leftRect =
|
|
SafeCreateRect(
|
|
_leftRect.Left,
|
|
_leftRect.Top + leftTopCollisionRect.Height,
|
|
_leftRect.Width,
|
|
_leftRect.Height - leftTopCollisionRect.Height);
|
|
|
|
_topRect =
|
|
SafeCreateRect(
|
|
_topRect.Left + leftTopCollisionRect.Width,
|
|
_topRect.Top,
|
|
_topRect.Width - leftTopCollisionRect.Width,
|
|
_topRect.Height);
|
|
}
|
|
|
|
if (!rightBottomCollisionRect.IsEmptyOrHasNoSize())
|
|
{
|
|
_rightRect =
|
|
SafeCreateRect(
|
|
_rightRect.Left,
|
|
_rightRect.Top,
|
|
_rightRect.Width,
|
|
_rightRect.Height - rightBottomCollisionRect.Height);
|
|
|
|
_bottomRect =
|
|
SafeCreateRect(
|
|
_bottomRect.Left,
|
|
_bottomRect.Top,
|
|
_bottomRect.Width - rightBottomCollisionRect.Width,
|
|
_bottomRect.Height);
|
|
}
|
|
|
|
if (!rightTopCollisionRect.IsEmptyOrHasNoSize())
|
|
{
|
|
_rightRect =
|
|
SafeCreateRect(
|
|
_rightRect.Left,
|
|
_rightRect.Top + rightTopCollisionRect.Height,
|
|
_rightRect.Width,
|
|
_rightRect.Height - rightTopCollisionRect.Height);
|
|
|
|
_topRect =
|
|
SafeCreateRect(
|
|
_topRect.Left,
|
|
_topRect.Top,
|
|
_topRect.Width - rightTopCollisionRect.Width,
|
|
_topRect.Height);
|
|
}
|
|
|
|
// Bring axis measure rectangles together if there are gaps
|
|
// between them.
|
|
if (!_leftRect.IsEmpty)
|
|
{
|
|
_leftRect =
|
|
new Rect(
|
|
new Point(_leftRect.Left, _topRect.BottomOrDefault(0)),
|
|
new Point(_leftRect.Right, _bottomRect.TopOrDefault(constraint.Height)));
|
|
}
|
|
|
|
if (!_rightRect.IsEmpty)
|
|
{
|
|
_rightRect =
|
|
new Rect(
|
|
new Point(_rightRect.Left, _topRect.BottomOrDefault(0)),
|
|
new Point(_rightRect.Right, _bottomRect.TopOrDefault(constraint.Height)));
|
|
}
|
|
|
|
if (!_bottomRect.IsEmpty)
|
|
{
|
|
_bottomRect =
|
|
new Rect(
|
|
new Point(_leftRect.RightOrDefault(0), _bottomRect.Top),
|
|
new Point(_rightRect.LeftOrDefault(constraint.Width), _bottomRect.Bottom));
|
|
}
|
|
|
|
if (!_topRect.IsEmpty)
|
|
{
|
|
_topRect =
|
|
new Rect(
|
|
new Point(_leftRect.RightOrDefault(0), _topRect.Top),
|
|
new Point(_rightRect.LeftOrDefault(constraint.Width), _topRect.Bottom));
|
|
}
|
|
|
|
iterations++;
|
|
}
|
|
|
|
Size centerSize =
|
|
new Size(
|
|
(constraint.Width - _leftRect.WidthOrDefault(0)) - _rightRect.WidthOrDefault(0),
|
|
(constraint.Height - _topRect.HeightOrDefault(0)) - _bottomRect.HeightOrDefault(0));
|
|
|
|
foreach (UIElement element in Children.OfType<UIElement>().Where(child => GetEdge(child) == Edge.Center))
|
|
{
|
|
element.Measure(centerSize);
|
|
}
|
|
|
|
return new Size();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Arranges the content (child elements) of a EdgePanel element.
|
|
/// </summary>
|
|
/// <param name="arrangeSize">
|
|
/// The Size the EdgePanel uses to arrange its child elements.
|
|
/// </param>
|
|
/// <returns>The arranged size of the EdgePanel.</returns>
|
|
[SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity", Justification = "Splitting up method will make it more difficult to understand.")]
|
|
[SuppressMessage("Microsoft.Naming", "CA1725:ParameterNamesShouldMatchBaseDeclaration", MessageId = "0#", Justification = "Compat with WPF.")]
|
|
protected override Size ArrangeOverride(Size arrangeSize)
|
|
{
|
|
if (arrangeSize.Width == 0 || arrangeSize.Height == 0 || !ValueHelper.CanGraph(arrangeSize.Width) || !ValueHelper.CanGraph(arrangeSize.Height))
|
|
{
|
|
return arrangeSize;
|
|
}
|
|
|
|
IList<UIElement> leftElements = this.Children.OfType<UIElement>().Where(element => GetEdge(element) == Edge.Left).ToList();
|
|
IList<UIElement> rightElements = this.Children.OfType<UIElement>().Where(element => GetEdge(element) == Edge.Right).ToList();
|
|
IList<UIElement> bottomElements = this.Children.OfType<UIElement>().Where(element => GetEdge(element) == Edge.Bottom).ToList();
|
|
IList<UIElement> topElements = this.Children.OfType<UIElement>().Where(element => GetEdge(element) == Edge.Top).ToList();
|
|
|
|
if (!_bottomRect.IsEmpty)
|
|
{
|
|
double workingHeight = _bottomRect.Top;
|
|
foreach (UIElement bottomUIElement in bottomElements)
|
|
{
|
|
bottomUIElement.Arrange(SafeCreateRect(_leftRect.RightOrDefault(0), workingHeight, (arrangeSize.Width - _leftRect.WidthOrDefault(0)) - _rightRect.WidthOrDefault(0), bottomUIElement.DesiredSize.Height));
|
|
workingHeight += bottomUIElement.DesiredSize.Height;
|
|
}
|
|
}
|
|
if (!_topRect.IsEmpty)
|
|
{
|
|
double workingTop = _topRect.Bottom;
|
|
foreach (UIElement topUIElement in topElements)
|
|
{
|
|
workingTop -= topUIElement.DesiredSize.Height;
|
|
topUIElement.Arrange(SafeCreateRect(_leftRect.RightOrDefault(0), workingTop, (arrangeSize.Width - _leftRect.WidthOrDefault(0)) - _rightRect.WidthOrDefault(0), topUIElement.DesiredSize.Height));
|
|
}
|
|
}
|
|
|
|
if (!_rightRect.IsEmpty)
|
|
{
|
|
double workingRight = _rightRect.Left;
|
|
foreach (UIElement rightUIElement in rightElements)
|
|
{
|
|
rightUIElement.Arrange(SafeCreateRect(workingRight, _topRect.BottomOrDefault(0), rightUIElement.DesiredSize.Width, (arrangeSize.Height - _bottomRect.HeightOrDefault(0)) - _topRect.HeightOrDefault(0)));
|
|
workingRight += rightUIElement.DesiredSize.Width;
|
|
}
|
|
}
|
|
|
|
if (!_leftRect.IsEmpty)
|
|
{
|
|
double workingLeft = _leftRect.Right;
|
|
foreach (UIElement leftUIElement in leftElements)
|
|
{
|
|
workingLeft -= leftUIElement.DesiredSize.Width;
|
|
Rect leftRect = SafeCreateRect(workingLeft, _topRect.BottomOrDefault(0), leftUIElement.DesiredSize.Width, (arrangeSize.Height - _bottomRect.HeightOrDefault(0)) - _topRect.HeightOrDefault(0));
|
|
leftUIElement.Arrange(leftRect);
|
|
}
|
|
}
|
|
|
|
Rect centerRect = SafeCreateRect(
|
|
_leftRect.RightOrDefault(0),
|
|
_topRect.BottomOrDefault(0),
|
|
((arrangeSize.Width - _leftRect.WidthOrDefault(0)) - _rightRect.WidthOrDefault(0)),
|
|
((arrangeSize.Height - _topRect.HeightOrDefault(0)) - _bottomRect.HeightOrDefault(0)));
|
|
|
|
foreach (UIElement element in Children.OfType<UIElement>().Where(child => GetEdge(child) == Edge.Center))
|
|
{
|
|
element.Arrange(centerRect);
|
|
}
|
|
|
|
return arrangeSize;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creates a Rect safely by forcing width/height to be valid.
|
|
/// </summary>
|
|
/// <param name="left">Rect left parameter.</param>
|
|
/// <param name="top">Rect top parameter.</param>
|
|
/// <param name="width">Rect width parameter.</param>
|
|
/// <param name="height">Rect height parameter.</param>
|
|
/// <returns>New Rect struct.</returns>
|
|
private static Rect SafeCreateRect(double left, double top, double width, double height)
|
|
{
|
|
return new Rect(left, top, Math.Max(0.0, width), Math.Max(0.0, height));
|
|
}
|
|
}
|
|
}
|