fixed #431
This commit is contained in:
1 parent
da0c8c7bba
commit
b6909066a8
1 file changed
+121
-10
@@ -18,7 +18,7 @@ namespace HandyControl.Controls
|
||||
|
||||
public RelativePanel() => _childGraph = new Graph();
|
||||
|
||||
#region 容器对齐方式
|
||||
#region Panel alignment
|
||||
|
||||
public static readonly DependencyProperty AlignLeftWithPanelProperty = DependencyProperty.RegisterAttached(
|
||||
"AlignLeftWithPanel", typeof(bool), typeof(RelativePanel), new FrameworkPropertyMetadata(ValueBoxes.FalseBox, FrameworkPropertyMetadataOptions.AffectsRender));
|
||||
@@ -58,7 +58,7 @@ namespace HandyControl.Controls
|
||||
|
||||
#endregion
|
||||
|
||||
#region 元素间对齐方式
|
||||
#region Sibling alignment
|
||||
|
||||
public static readonly DependencyProperty AlignLeftWithProperty = DependencyProperty.RegisterAttached(
|
||||
"AlignLeftWith", typeof(UIElement), typeof(RelativePanel), new FrameworkPropertyMetadata(default(UIElement), FrameworkPropertyMetadataOptions.AffectsRender));
|
||||
@@ -102,7 +102,7 @@ namespace HandyControl.Controls
|
||||
|
||||
#endregion
|
||||
|
||||
#region 元素间位置关系
|
||||
#region Sibling positional
|
||||
|
||||
public static readonly DependencyProperty LeftOfProperty = DependencyProperty.RegisterAttached(
|
||||
"LeftOf", typeof(UIElement), typeof(RelativePanel), new FrameworkPropertyMetadata(default(UIElement), FrameworkPropertyMetadataOptions.AffectsRender));
|
||||
@@ -146,7 +146,7 @@ namespace HandyControl.Controls
|
||||
|
||||
#endregion
|
||||
|
||||
#region 居中对齐方式
|
||||
#region Center alignment
|
||||
|
||||
public static readonly DependencyProperty AlignHorizontalCenterWithPanelProperty = DependencyProperty.RegisterAttached(
|
||||
"AlignHorizontalCenterWithPanel", typeof(bool), typeof(RelativePanel), new FrameworkPropertyMetadata(ValueBoxes.FalseBox, FrameworkPropertyMetadataOptions.AffectsRender));
|
||||
@@ -190,8 +190,9 @@ namespace HandyControl.Controls
|
||||
|
||||
protected override Size MeasureOverride(Size availableSize)
|
||||
{
|
||||
_childGraph.Clear();
|
||||
#region Calc DesiredSize
|
||||
|
||||
_childGraph.Clear();
|
||||
foreach (UIElement child in InternalChildren)
|
||||
{
|
||||
if (child == null) continue;
|
||||
@@ -210,9 +211,19 @@ namespace HandyControl.Controls
|
||||
node.AlignHorizontalCenterWith = _childGraph.AddLink(node, GetAlignHorizontalCenterWith(child));
|
||||
node.AlignVerticalCenterWith = _childGraph.AddLink(node, GetAlignVerticalCenterWith(child));
|
||||
}
|
||||
|
||||
_childGraph.Measure(availableSize);
|
||||
return availableSize;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Calc AvailableSize
|
||||
|
||||
_childGraph.Reset();
|
||||
var boundingSize = _childGraph.GetBoundingSize(Width.IsNaN(), Height.IsNaN());
|
||||
_childGraph.Reset();
|
||||
_childGraph.Measure(boundingSize);
|
||||
return boundingSize;
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
protected override Size ArrangeOverride(Size arrangeSize)
|
||||
@@ -227,6 +238,14 @@ namespace HandyControl.Controls
|
||||
|
||||
public UIElement Element { get; }
|
||||
|
||||
public bool HorizontalOffsetFlag { get; set; }
|
||||
|
||||
public bool VerticalOffsetFlag { get; set; }
|
||||
|
||||
public Size BoundingSize { get; set; }
|
||||
|
||||
public Size OriginDesiredSize { get; set; }
|
||||
|
||||
public double Left { get; set; } = double.NaN;
|
||||
|
||||
public double Top { get; set; } = double.NaN;
|
||||
@@ -264,6 +283,78 @@ namespace HandyControl.Controls
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
Left = double.NaN;
|
||||
Top = double.NaN;
|
||||
Right = double.NaN;
|
||||
Bottom = double.NaN;
|
||||
Measured = false;
|
||||
}
|
||||
|
||||
public Size GetBoundingSize()
|
||||
{
|
||||
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
|
||||
@@ -282,6 +373,8 @@ namespace HandyControl.Controls
|
||||
_nodeDic.Clear();
|
||||
}
|
||||
|
||||
public void Reset() => _nodeDic.Values.Do(node => node.Reset());
|
||||
|
||||
public GraphNode AddLink(GraphNode from, UIElement to)
|
||||
{
|
||||
if (to == null) return null;
|
||||
@@ -329,7 +422,7 @@ namespace HandyControl.Controls
|
||||
* 该节点无任何依赖,所以从这里开始计算元素位置。
|
||||
* 因为无任何依赖,所以忽略同级元素
|
||||
*/
|
||||
if (!node.Measured && node.OutgoingNodes.Count == 0)
|
||||
if (!node.Measured && !node.OutgoingNodes.Any())
|
||||
{
|
||||
MeasureChild(node);
|
||||
continue;
|
||||
@@ -360,6 +453,8 @@ namespace HandyControl.Controls
|
||||
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);
|
||||
@@ -435,8 +530,8 @@ namespace HandyControl.Controls
|
||||
}
|
||||
}
|
||||
|
||||
node.Element.Measure(new Size(Math.Max(availableWidth, 0), Math.Max(availableHeight, 0)));
|
||||
var childSize = node.Element.DesiredSize;
|
||||
child.Measure(new Size(Math.Max(availableWidth, 0), Math.Max(availableHeight, 0)));
|
||||
var childSize = child.DesiredSize;
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -566,6 +661,22 @@ namespace HandyControl.Controls
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user