123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696 |
- //reference doc : https://docs.microsoft.com/en-us/uwp/api/Windows.UI.Xaml.Controls.RelativePanel
- using System;
- using System.Collections.Generic;
- using System.ComponentModel;
- using System.Linq;
- using System.Windows;
- using System.Windows.Controls;
- using System.Windows.Markup;
- using HandyControl.Data;
- using HandyControl.Tools.Extension;
- namespace HandyControl.Controls;
- public class RelativePanel : Panel
- {
- private readonly Graph _childGraph;
- public RelativePanel() => _childGraph = new Graph();
- #region Panel alignment
- public static readonly DependencyProperty AlignLeftWithPanelProperty = DependencyProperty.RegisterAttached(
- "AlignLeftWithPanel", typeof(bool), typeof(RelativePanel), new FrameworkPropertyMetadata(ValueBoxes.FalseBox, FrameworkPropertyMetadataOptions.AffectsRender));
- public static void SetAlignLeftWithPanel(DependencyObject element, bool value)
- => element.SetValue(AlignLeftWithPanelProperty, ValueBoxes.BooleanBox(value));
- public static bool GetAlignLeftWithPanel(DependencyObject element)
- => (bool) element.GetValue(AlignLeftWithPanelProperty);
- public static readonly DependencyProperty AlignTopWithPanelProperty = DependencyProperty.RegisterAttached(
- "AlignTopWithPanel", typeof(bool), typeof(RelativePanel), new FrameworkPropertyMetadata(ValueBoxes.FalseBox, FrameworkPropertyMetadataOptions.AffectsRender));
- public static void SetAlignTopWithPanel(DependencyObject element, bool value)
- => element.SetValue(AlignTopWithPanelProperty, ValueBoxes.BooleanBox(value));
- public static bool GetAlignTopWithPanel(DependencyObject element)
- => (bool) element.GetValue(AlignTopWithPanelProperty);
- public static readonly DependencyProperty AlignRightWithPanelProperty = DependencyProperty.RegisterAttached(
- "AlignRightWithPanel", typeof(bool), typeof(RelativePanel), new FrameworkPropertyMetadata(ValueBoxes.FalseBox, FrameworkPropertyMetadataOptions.AffectsRender));
- public static void SetAlignRightWithPanel(DependencyObject element, bool value)
- => element.SetValue(AlignRightWithPanelProperty, ValueBoxes.BooleanBox(value));
- public static bool GetAlignRightWithPanel(DependencyObject element)
- => (bool) element.GetValue(AlignRightWithPanelProperty);
- public static readonly DependencyProperty AlignBottomWithPanelProperty = DependencyProperty.RegisterAttached(
- "AlignBottomWithPanel", typeof(bool), typeof(RelativePanel), new FrameworkPropertyMetadata(ValueBoxes.FalseBox, FrameworkPropertyMetadataOptions.AffectsRender));
- public static void SetAlignBottomWithPanel(DependencyObject element, bool value)
- => element.SetValue(AlignBottomWithPanelProperty, ValueBoxes.BooleanBox(value));
- public static bool GetAlignBottomWithPanel(DependencyObject element)
- => (bool) element.GetValue(AlignBottomWithPanelProperty);
- #endregion
- #region Sibling alignment
- public static readonly DependencyProperty AlignLeftWithProperty = DependencyProperty.RegisterAttached(
- "AlignLeftWith", typeof(UIElement), typeof(RelativePanel), new FrameworkPropertyMetadata(default(UIElement), FrameworkPropertyMetadataOptions.AffectsRender));
- public static void SetAlignLeftWith(DependencyObject element, UIElement value)
- => element.SetValue(AlignLeftWithProperty, value);
- [TypeConverter(typeof(NameReferenceConverter))]
- public static UIElement GetAlignLeftWith(DependencyObject element)
- => (UIElement) element.GetValue(AlignLeftWithProperty);
- public static readonly DependencyProperty AlignTopWithProperty = DependencyProperty.RegisterAttached(
- "AlignTopWith", typeof(UIElement), typeof(RelativePanel), new FrameworkPropertyMetadata(default(UIElement), FrameworkPropertyMetadataOptions.AffectsRender));
- public static void SetAlignTopWith(DependencyObject element, UIElement value)
- => element.SetValue(AlignTopWithProperty, value);
- [TypeConverter(typeof(NameReferenceConverter))]
- public static UIElement GetAlignTopWith(DependencyObject element)
- => (UIElement) element.GetValue(AlignTopWithProperty);
- public static readonly DependencyProperty AlignRightWithProperty = DependencyProperty.RegisterAttached(
- "AlignRightWith", typeof(UIElement), typeof(RelativePanel), new FrameworkPropertyMetadata(default(UIElement), FrameworkPropertyMetadataOptions.AffectsRender));
- public static void SetAlignRightWith(DependencyObject element, UIElement value)
- => element.SetValue(AlignRightWithProperty, value);
- [TypeConverter(typeof(NameReferenceConverter))]
- public static UIElement GetAlignRightWith(DependencyObject element)
- => (UIElement) element.GetValue(AlignRightWithProperty);
- public static readonly DependencyProperty AlignBottomWithProperty = DependencyProperty.RegisterAttached(
- "AlignBottomWith", typeof(UIElement), typeof(RelativePanel), new FrameworkPropertyMetadata(default(UIElement), FrameworkPropertyMetadataOptions.AffectsRender));
- public static void SetAlignBottomWith(DependencyObject element, UIElement value)
- => element.SetValue(AlignBottomWithProperty, value);
- [TypeConverter(typeof(NameReferenceConverter))]
- public static UIElement GetAlignBottomWith(DependencyObject element)
- => (UIElement) element.GetValue(AlignBottomWithProperty);
- #endregion
- #region Sibling positional
- public static readonly DependencyProperty LeftOfProperty = DependencyProperty.RegisterAttached(
- "LeftOf", typeof(UIElement), typeof(RelativePanel), new FrameworkPropertyMetadata(default(UIElement), FrameworkPropertyMetadataOptions.AffectsRender));
- public static void SetLeftOf(DependencyObject element, UIElement value)
- => element.SetValue(LeftOfProperty, value);
- [TypeConverter(typeof(NameReferenceConverter))]
- public static UIElement GetLeftOf(DependencyObject element)
- => (UIElement) element.GetValue(LeftOfProperty);
- public static readonly DependencyProperty AboveProperty = DependencyProperty.RegisterAttached(
- "Above", typeof(UIElement), typeof(RelativePanel), new FrameworkPropertyMetadata(default(UIElement), FrameworkPropertyMetadataOptions.AffectsRender));
- public static void SetAbove(DependencyObject element, UIElement value)
- => element.SetValue(AboveProperty, value);
- [TypeConverter(typeof(NameReferenceConverter))]
- public static UIElement GetAbove(DependencyObject element)
- => (UIElement) element.GetValue(AboveProperty);
- public static readonly DependencyProperty RightOfProperty = DependencyProperty.RegisterAttached(
- "RightOf", typeof(UIElement), typeof(RelativePanel), new FrameworkPropertyMetadata(default(UIElement), FrameworkPropertyMetadataOptions.AffectsRender));
- public static void SetRightOf(DependencyObject element, UIElement value)
- => element.SetValue(RightOfProperty, value);
- [TypeConverter(typeof(NameReferenceConverter))]
- public static UIElement GetRightOf(DependencyObject element)
- => (UIElement) element.GetValue(RightOfProperty);
- public static readonly DependencyProperty BelowProperty = DependencyProperty.RegisterAttached(
- "Below", typeof(UIElement), typeof(RelativePanel), new FrameworkPropertyMetadata(default(UIElement), FrameworkPropertyMetadataOptions.AffectsRender));
- public static void SetBelow(DependencyObject element, UIElement value)
- => element.SetValue(BelowProperty, value);
- [TypeConverter(typeof(NameReferenceConverter))]
- public static UIElement GetBelow(DependencyObject element)
- => (UIElement) element.GetValue(BelowProperty);
- #endregion
- #region Center alignment
- public static readonly DependencyProperty AlignHorizontalCenterWithPanelProperty = DependencyProperty.RegisterAttached(
- "AlignHorizontalCenterWithPanel", typeof(bool), typeof(RelativePanel), new FrameworkPropertyMetadata(ValueBoxes.FalseBox, FrameworkPropertyMetadataOptions.AffectsRender));
- public static void SetAlignHorizontalCenterWithPanel(DependencyObject element, bool value)
- => element.SetValue(AlignHorizontalCenterWithPanelProperty, ValueBoxes.BooleanBox(value));
- public static bool GetAlignHorizontalCenterWithPanel(DependencyObject element)
- => (bool) element.GetValue(AlignHorizontalCenterWithPanelProperty);
- public static readonly DependencyProperty AlignVerticalCenterWithPanelProperty = DependencyProperty.RegisterAttached(
- "AlignVerticalCenterWithPanel", typeof(bool), typeof(RelativePanel), new FrameworkPropertyMetadata(ValueBoxes.FalseBox, FrameworkPropertyMetadataOptions.AffectsRender));
- public static void SetAlignVerticalCenterWithPanel(DependencyObject element, bool value)
- => element.SetValue(AlignVerticalCenterWithPanelProperty, ValueBoxes.BooleanBox(value));
- public static bool GetAlignVerticalCenterWithPanel(DependencyObject element)
- => (bool) element.GetValue(AlignVerticalCenterWithPanelProperty);
- public static readonly DependencyProperty AlignHorizontalCenterWithProperty = DependencyProperty.RegisterAttached(
- "AlignHorizontalCenterWith", typeof(UIElement), typeof(RelativePanel), new FrameworkPropertyMetadata(default(UIElement), FrameworkPropertyMetadataOptions.AffectsRender));
- public static void SetAlignHorizontalCenterWith(DependencyObject element, UIElement value)
- => element.SetValue(AlignHorizontalCenterWithProperty, value);
- [TypeConverter(typeof(NameReferenceConverter))]
- public static UIElement GetAlignHorizontalCenterWith(DependencyObject element)
- => (UIElement) element.GetValue(AlignHorizontalCenterWithProperty);
- public static readonly DependencyProperty AlignVerticalCenterWithProperty = DependencyProperty.RegisterAttached(
- "AlignVerticalCenterWith", typeof(UIElement), typeof(RelativePanel), new FrameworkPropertyMetadata(default(UIElement), FrameworkPropertyMetadataOptions.AffectsRender));
- public static void SetAlignVerticalCenterWith(DependencyObject element, UIElement value)
- => element.SetValue(AlignVerticalCenterWithProperty, value);
- [TypeConverter(typeof(NameReferenceConverter))]
- public static UIElement GetAlignVerticalCenterWith(DependencyObject element)
- => (UIElement) element.GetValue(AlignVerticalCenterWithProperty);
- #endregion
- protected override Size MeasureOverride(Size availableSize)
- {
- #region Calc DesiredSize
- _childGraph.Clear();
- foreach (UIElement child in InternalChildren)
- {
- if (child == null) continue;
- var node = _childGraph.AddNode(child);
- node.AlignLeftWithNode = _childGraph.AddLink(node, GetAlignLeftWith(child));
- node.AlignTopWithNode = _childGraph.AddLink(node, GetAlignTopWith(child));
- node.AlignRightWithNode = _childGraph.AddLink(node, GetAlignRightWith(child));
- node.AlignBottomWithNode = _childGraph.AddLink(node, GetAlignBottomWith(child));
- node.LeftOfNode = _childGraph.AddLink(node, GetLeftOf(child));
- node.AboveNode = _childGraph.AddLink(node, GetAbove(child));
- node.RightOfNode = _childGraph.AddLink(node, GetRightOf(child));
- node.BelowNode = _childGraph.AddLink(node, GetBelow(child));
- node.AlignHorizontalCenterWith = _childGraph.AddLink(node, GetAlignHorizontalCenterWith(child));
- node.AlignVerticalCenterWith = _childGraph.AddLink(node, GetAlignVerticalCenterWith(child));
- }
- _childGraph.Measure(availableSize);
- #endregion
- #region Calc AvailableSize
- _childGraph.Reset(false);
- var calcWidth = Width.IsNaN() && HorizontalAlignment != HorizontalAlignment.Stretch;
- var calcHeight = Height.IsNaN() && VerticalAlignment != VerticalAlignment.Stretch;
- var boundingSize = _childGraph.GetBoundingSize(calcWidth, calcHeight);
- _childGraph.Reset();
- _childGraph.Measure(boundingSize);
- return boundingSize;
- #endregion
- }
- protected override Size ArrangeOverride(Size arrangeSize)
- {
- _childGraph.GetNodes().Do(node => node.Arrange(arrangeSize));
- return arrangeSize;
- }
- private class GraphNode
- {
- public bool Measured { get; set; }
- public UIElement Element { get; }
- private bool HorizontalOffsetFlag { get; set; }
- private bool VerticalOffsetFlag { get; set; }
- private Size BoundingSize { get; set; }
- public Size OriginDesiredSize { get; set; }
- public double Left { get; set; } = double.NaN;
- public double Top { get; set; } = double.NaN;
- public double Right { get; set; } = double.NaN;
- public double Bottom { get; set; } = double.NaN;
- 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(UIElement element)
- {
- OutgoingNodes = new HashSet<GraphNode>();
- Element = element;
- }
- public void Arrange(Size arrangeSize) => Element.Arrange(new Rect(Left, Top, Math.Max(arrangeSize.Width - Left - Right, 0), Math.Max(arrangeSize.Height - Top - Bottom, 0)));
- public void Reset(bool clearPos)
- {
- if (clearPos)
- {
- Left = double.NaN;
- Top = double.NaN;
- Right = double.NaN;
- Bottom = double.NaN;
- }
- Measured = false;
- }
- public Size GetBoundingSize()
- {
- if (Left < 0 || Top < 0) return default;
- if (Measured) return BoundingSize;
- if (!OutgoingNodes.Any())
- {
- BoundingSize = Element.DesiredSize;
- Measured = true;
- }
- else
- {
- BoundingSize = GetBoundingSize(this, Element.DesiredSize, OutgoingNodes);
- Measured = true;
- }
- return BoundingSize;
- }
- private static Size GetBoundingSize(GraphNode prevNode, Size prevSize, IEnumerable<GraphNode> nodes)
- {
- foreach (var node in nodes)
- {
- if (node.Measured || !node.OutgoingNodes.Any())
- {
- if (prevNode.LeftOfNode != null && prevNode.LeftOfNode == node ||
- prevNode.RightOfNode != null && prevNode.RightOfNode == node)
- {
- prevSize.Width += node.BoundingSize.Width;
- if (GetAlignHorizontalCenterWithPanel(node.Element) || node.HorizontalOffsetFlag)
- {
- prevSize.Width += prevNode.OriginDesiredSize.Width;
- prevNode.HorizontalOffsetFlag = true;
- }
- if (node.VerticalOffsetFlag)
- {
- prevNode.VerticalOffsetFlag = true;
- }
- }
- if (prevNode.AboveNode != null && prevNode.AboveNode == node ||
- prevNode.BelowNode != null && prevNode.BelowNode == node)
- {
- prevSize.Height += node.BoundingSize.Height;
- if (GetAlignVerticalCenterWithPanel(node.Element) || node.VerticalOffsetFlag)
- {
- prevSize.Height += prevNode.OriginDesiredSize.Height;
- prevNode.VerticalOffsetFlag = true;
- }
- if (node.HorizontalOffsetFlag)
- {
- prevNode.HorizontalOffsetFlag = true;
- }
- }
- }
- else
- {
- return GetBoundingSize(node, prevSize, node.OutgoingNodes);
- }
- }
- return prevSize;
- }
- }
- private class Graph
- {
- private readonly Dictionary<DependencyObject, GraphNode> _nodeDic;
- private Size AvailableSize { get; set; }
- public Graph() => _nodeDic = new Dictionary<DependencyObject, GraphNode>();
- public IEnumerable<GraphNode> GetNodes() => _nodeDic.Values;
- public void Clear()
- {
- AvailableSize = new Size();
- _nodeDic.Clear();
- }
- public void Reset(bool clearPos = true) => _nodeDic.Values.Do(node => node.Reset(clearPos));
- public GraphNode AddLink(GraphNode from, UIElement 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(UIElement value)
- {
- if (!_nodeDic.ContainsKey(value))
- {
- var node = new GraphNode(value);
- _nodeDic.Add(value, node);
- return node;
- }
- return _nodeDic[value];
- }
- public void Measure(Size availableSize)
- {
- AvailableSize = EnsureValidSize(availableSize);
- Measure(_nodeDic.Values, null);
- }
- private static Size EnsureValidSize(Size size)
- {
- var width = double.IsInfinity(size.Width) ? 0 : size.Width;
- var height = double.IsInfinity(size.Height) ? 0 : size.Height;
- return new Size(width, height);
- }
- private void Measure(IEnumerable<GraphNode> nodes, HashSet<DependencyObject> set)
- {
- set ??= new HashSet<DependencyObject>();
- foreach (var node in nodes)
- {
- /*
- * 该节点无任何依赖,所以从这里开始计算元素位置。
- * 因为无任何依赖,所以忽略同级元素
- */
- if (!node.Measured && !node.OutgoingNodes.Any())
- {
- MeasureChild(node);
- continue;
- }
- // 判断依赖元素是否全部排列完毕
- if (node.OutgoingNodes.All(item => item.Measured))
- {
- MeasureChild(node);
- continue;
- }
- // 判断是否有循环
- if (!set.Add(node.Element)) throw new Exception("RelativePanel error: Circular dependency detected. Layout could not complete.");
- // 没有循环,且有依赖,则继续往下
- Measure(node.OutgoingNodes, set);
- if (!node.Measured)
- {
- MeasureChild(node);
- }
- }
- }
- private void MeasureChild(GraphNode node)
- {
- var child = node.Element;
- child.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
- node.OriginDesiredSize = child.DesiredSize;
- var alignLeftWithPanel = GetAlignLeftWithPanel(child);
- var alignTopWithPanel = GetAlignTopWithPanel(child);
- var alignRightWithPanel = GetAlignRightWithPanel(child);
- var alignBottomWithPanel = GetAlignBottomWithPanel(child);
- #region Panel alignment
- if (alignLeftWithPanel) node.Left = 0;
- if (alignTopWithPanel) node.Top = 0;
- if (alignRightWithPanel) node.Right = 0;
- if (alignBottomWithPanel) node.Bottom = 0;
- #endregion
- #region Sibling alignment
- if (node.AlignLeftWithNode != null)
- {
- node.Left = node.Left.IsNaN() ? node.AlignLeftWithNode.Left : node.AlignLeftWithNode.Left * 0.5;
- }
- if (node.AlignTopWithNode != null)
- {
- node.Top = node.Top.IsNaN() ? node.AlignTopWithNode.Top : node.AlignTopWithNode.Top * 0.5;
- }
- if (node.AlignRightWithNode != null)
- {
- node.Right = node.Right.IsNaN()
- ? node.AlignRightWithNode.Right
- : node.AlignRightWithNode.Right * 0.5;
- }
- if (node.AlignBottomWithNode != null)
- {
- node.Bottom = node.Bottom.IsNaN()
- ? node.AlignBottomWithNode.Bottom
- : node.AlignBottomWithNode.Bottom * 0.5;
- }
- #endregion
- #region Measure
- var availableHeight = AvailableSize.Height - node.Top - node.Bottom;
- if (availableHeight.IsNaN())
- {
- availableHeight = AvailableSize.Height;
- if (!node.Top.IsNaN() && node.Bottom.IsNaN())
- {
- availableHeight -= node.Top;
- }
- else if (node.Top.IsNaN() && !node.Bottom.IsNaN())
- {
- availableHeight -= node.Bottom;
- }
- }
- var availableWidth = AvailableSize.Width - node.Left - node.Right;
- if (availableWidth.IsNaN())
- {
- availableWidth = AvailableSize.Width;
- if (!node.Left.IsNaN() && node.Right.IsNaN())
- {
- availableWidth -= node.Left;
- }
- else if (node.Left.IsNaN() && !node.Right.IsNaN())
- {
- availableWidth -= node.Right;
- }
- }
- child.Measure(new Size(Math.Max(availableWidth, 0), Math.Max(availableHeight, 0)));
- var childSize = child.DesiredSize;
- #endregion
- #region Sibling positional
- if (node.LeftOfNode != null && node.Left.IsNaN())
- {
- node.Left = node.LeftOfNode.Left - childSize.Width;
- }
- if (node.AboveNode != null && node.Top.IsNaN())
- {
- node.Top = node.AboveNode.Top - childSize.Height;
- }
- if (node.RightOfNode != null)
- {
- if (node.Right.IsNaN())
- {
- node.Right = node.RightOfNode.Right - childSize.Width;
- }
- if (node.Left.IsNaN())
- {
- node.Left = AvailableSize.Width - node.RightOfNode.Right;
- }
- }
- if (node.BelowNode != null)
- {
- if (node.Bottom.IsNaN())
- {
- node.Bottom = node.BelowNode.Bottom - childSize.Height;
- }
- if (node.Top.IsNaN())
- {
- node.Top = AvailableSize.Height - node.BelowNode.Bottom;
- }
- }
- #endregion
- #region Sibling-center alignment
- if (node.AlignHorizontalCenterWith != null)
- {
- var halfWidthLeft = (AvailableSize.Width + node.AlignHorizontalCenterWith.Left - node.AlignHorizontalCenterWith.Right - childSize.Width) * 0.5;
- var halfWidthRight = (AvailableSize.Width - node.AlignHorizontalCenterWith.Left + node.AlignHorizontalCenterWith.Right - childSize.Width) * 0.5;
- if (node.Left.IsNaN()) node.Left = halfWidthLeft;
- else node.Left = (node.Left + halfWidthLeft) * 0.5;
- if (node.Right.IsNaN()) node.Right = halfWidthRight;
- else node.Right = (node.Right + halfWidthRight) * 0.5;
- }
- if (node.AlignVerticalCenterWith != null)
- {
- var halfHeightTop = (AvailableSize.Height + node.AlignVerticalCenterWith.Top - node.AlignVerticalCenterWith.Bottom - childSize.Height) * 0.5;
- var halfHeightBottom = (AvailableSize.Height - node.AlignVerticalCenterWith.Top + node.AlignVerticalCenterWith.Bottom - childSize.Height) * 0.5;
- if (node.Top.IsNaN()) node.Top = halfHeightTop;
- else node.Top = (node.Top + halfHeightTop) * 0.5;
- if (node.Bottom.IsNaN()) node.Bottom = halfHeightBottom;
- else node.Bottom = (node.Bottom + halfHeightBottom) * 0.5;
- }
- #endregion
- #region Panel-center alignment
- if (GetAlignHorizontalCenterWithPanel(child))
- {
- var halfSubWidth = (AvailableSize.Width - childSize.Width) * 0.5;
- if (node.Left.IsNaN()) node.Left = halfSubWidth;
- else node.Left = (node.Left + halfSubWidth) * 0.5;
- if (node.Right.IsNaN()) node.Right = halfSubWidth;
- else node.Right = (node.Right + halfSubWidth) * 0.5;
- }
- if (GetAlignVerticalCenterWithPanel(child))
- {
- var halfSubHeight = (AvailableSize.Height - childSize.Height) * 0.5;
- if (node.Top.IsNaN()) node.Top = halfSubHeight;
- else node.Top = (node.Top + halfSubHeight) * 0.5;
- if (node.Bottom.IsNaN()) node.Bottom = halfSubHeight;
- else node.Bottom = (node.Bottom + halfSubHeight) * 0.5;
- }
- #endregion
- if (node.Left.IsNaN())
- {
- if (!node.Right.IsNaN())
- node.Left = AvailableSize.Width - node.Right - childSize.Width;
- else
- {
- node.Left = 0;
- node.Right = AvailableSize.Width - childSize.Width;
- }
- }
- else if (!node.Left.IsNaN() && node.Right.IsNaN())
- {
- node.Right = AvailableSize.Width - node.Left - childSize.Width;
- }
- if (node.Top.IsNaN())
- {
- if (!node.Bottom.IsNaN())
- node.Top = AvailableSize.Height - node.Bottom - childSize.Height;
- else
- {
- node.Top = 0;
- node.Bottom = AvailableSize.Height - childSize.Height;
- }
- }
- else if (!node.Top.IsNaN() && node.Bottom.IsNaN())
- {
- node.Bottom = AvailableSize.Height - node.Top - childSize.Height;
- }
- node.Measured = true;
- }
- public Size GetBoundingSize(bool calcWidth, bool calcHeight)
- {
- var boundingSize = new Size();
- foreach (var node in _nodeDic.Values)
- {
- var size = node.GetBoundingSize();
- boundingSize.Width = Math.Max(boundingSize.Width, size.Width);
- boundingSize.Height = Math.Max(boundingSize.Height, size.Height);
- }
- boundingSize.Width = calcWidth ? boundingSize.Width : AvailableSize.Width;
- boundingSize.Height = calcHeight ? boundingSize.Height : AvailableSize.Height;
- return boundingSize;
- }
- }
- }
|