Browse Source

Merge pull request #3119 from AvaloniaUI/fixes/3095-visualnode-wrong-parent

Ensure VisualNode has correct parent.
release/0.9.0-preview2
danwalmsley 6 years ago
committed by Dan Walmsley
parent
commit
ccb8aa0dae
  1. 15
      src/Avalonia.Visuals/Rendering/SceneGraph/SceneBuilder.cs
  2. 10
      src/Avalonia.Visuals/Rendering/SceneGraph/VisualNode.cs
  3. 12
      tests/Avalonia.Visuals.UnitTests/Rendering/SceneGraph/DeferredDrawingContextImplTests.cs
  4. 3
      tests/Avalonia.Visuals.UnitTests/Rendering/SceneGraph/SceneBuilderTests.cs
  5. 8
      tests/Avalonia.Visuals.UnitTests/Rendering/SceneGraph/VisualNodeTests.cs

15
src/Avalonia.Visuals/Rendering/SceneGraph/SceneBuilder.cs

@ -148,6 +148,19 @@ namespace Avalonia.Rendering.SceneGraph
return (VisualNode)node;
}
private static object GetOrCreateChildNode(Scene scene, IVisual child, VisualNode parent)
{
var result = (VisualNode)scene.FindNode(child);
if (result != null && result.Parent != parent)
{
Deindex(scene, result);
result = null;
}
return result ?? CreateNode(scene, child, parent);
}
private static void Update(DrawingContext context, Scene scene, VisualNode node, Rect clip, bool forceRecurse)
{
var visual = node.Visual;
@ -231,7 +244,7 @@ namespace Avalonia.Rendering.SceneGraph
{
foreach (var child in visual.VisualChildren.OrderBy(x => x, ZIndexComparer.Instance))
{
var childNode = scene.FindNode(child) ?? CreateNode(scene, child, node);
var childNode = GetOrCreateChildNode(scene, child, node);
Update(context, scene, (VisualNode)childNode, clip, forceRecurse);
}

10
src/Avalonia.Visuals/Rendering/SceneGraph/VisualNode.cs

@ -119,6 +119,11 @@ namespace Avalonia.Rendering.SceneGraph
throw new ObjectDisposedException("Visual node for {node.Visual}");
}
if (child.Parent != this)
{
throw new AvaloniaInternalException("VisualNode added to wrong parent.");
}
EnsureChildrenCreated();
_children.Add(child);
}
@ -155,6 +160,11 @@ namespace Avalonia.Rendering.SceneGraph
throw new ObjectDisposedException("Visual node for {node.Visual}");
}
if (node.Parent != this)
{
throw new AvaloniaInternalException("VisualNode added to wrong parent.");
}
EnsureChildrenCreated();
_children[index] = node;
}

12
tests/Avalonia.Visuals.UnitTests/Rendering/SceneGraph/DeferredDrawingContextImplTests.cs

@ -17,7 +17,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph
public void Should_Add_VisualNode()
{
var parent = new VisualNode(new TestRoot(), null);
var child = new VisualNode(Mock.Of<IVisual>(), null);
var child = new VisualNode(Mock.Of<IVisual>(), parent);
var layers = new SceneLayers(parent.Visual);
var target = new DeferredDrawingContextImpl(null, layers);
@ -32,7 +32,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph
public void Should_Not_Replace_Identical_VisualNode()
{
var parent = new VisualNode(new TestRoot(), null);
var child = new VisualNode(Mock.Of<IVisual>(), null);
var child = new VisualNode(Mock.Of<IVisual>(), parent);
var layers = new SceneLayers(parent.Visual);
parent.AddChild(child);
@ -50,8 +50,8 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph
public void Should_Replace_Different_VisualNode()
{
var parent = new VisualNode(new TestRoot(), null);
var child1 = new VisualNode(Mock.Of<IVisual>(), null);
var child2 = new VisualNode(Mock.Of<IVisual>(), null);
var child1 = new VisualNode(Mock.Of<IVisual>(), parent);
var child2 = new VisualNode(Mock.Of<IVisual>(), parent);
var layers = new SceneLayers(parent.Visual);
parent.AddChild(child1);
@ -78,8 +78,8 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph
var layers = new SceneLayers(root);
var target = new DeferredDrawingContextImpl(null, layers);
var child1 = new VisualNode(Mock.Of<IVisual>(), null) { LayerRoot = root };
var child2 = new VisualNode(Mock.Of<IVisual>(), null) { LayerRoot = root };
var child1 = new VisualNode(Mock.Of<IVisual>(), node) { LayerRoot = root };
var child2 = new VisualNode(Mock.Of<IVisual>(), node) { LayerRoot = root };
target.BeginUpdate(node);
using (target.BeginUpdate(child1)) { }

3
tests/Avalonia.Visuals.UnitTests/Rendering/SceneGraph/SceneBuilderTests.cs

@ -620,10 +620,9 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph
border1.IsVisible = false;
scene = scene.CloneScene();
var panelNode = (VisualNode)scene.FindNode(panel);
sceneBuilder.Update(scene, decorator);
var panelNode = (VisualNode)scene.FindNode(panel);
Assert.Equal(2, panelNode.Children.Count);
Assert.False(panelNode.Children[0].Disposed);
Assert.False(panelNode.Children[1].Disposed);

8
tests/Avalonia.Visuals.UnitTests/Rendering/SceneGraph/VisualNodeTests.cs

@ -24,7 +24,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph
var node = new VisualNode(Mock.Of<IVisual>(), null);
var collection = node.Children;
node.AddChild(Mock.Of<IVisualNode>());
node.AddChild(Mock.Of<IVisualNode>(x => x.Parent == node));
Assert.NotSame(collection, node.Children);
}
@ -106,9 +106,9 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph
public void TrimChildren_Should_Work_Correctly()
{
var parent = new VisualNode(Mock.Of<IVisual>(), null);
var child1 = new VisualNode(Mock.Of<IVisual>(), null);
var child2 = new VisualNode(Mock.Of<IVisual>(), null);
var child3 = new VisualNode(Mock.Of<IVisual>(), null);
var child1 = new VisualNode(Mock.Of<IVisual>(), parent);
var child2 = new VisualNode(Mock.Of<IVisual>(), parent);
var child3 = new VisualNode(Mock.Of<IVisual>(), parent);
parent.AddChild(child1);
parent.AddChild(child2);

Loading…
Cancel
Save