Browse Source
Closes #38. Still need to track transforms and clip rectangles, but good enough for now.pull/58/head
8 changed files with 260 additions and 13 deletions
@ -0,0 +1,45 @@ |
|||
// -----------------------------------------------------------------------
|
|||
// <copyright file="BoundsTracker.cs" company="Steven Kirk">
|
|||
// Copyright 2015 MIT Licence. See licence.md for more information.
|
|||
// </copyright>
|
|||
// -----------------------------------------------------------------------
|
|||
|
|||
namespace Perspex.VisualTree |
|||
{ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Reactive.Linq; |
|||
|
|||
public class BoundsTracker |
|||
{ |
|||
public IObservable<TransformedBounds> Track(Visual visual) |
|||
{ |
|||
return this.Track(visual, (Visual)visual.GetVisualRoot()); |
|||
} |
|||
|
|||
public IObservable<TransformedBounds> Track(Visual visual, Visual relativeTo) |
|||
{ |
|||
var visuals = visual.GetSelfAndVisualAncestors() |
|||
.TakeWhile(x => x != relativeTo) |
|||
.Reverse(); |
|||
var boundsSubscriptions = new List<IObservable<Rect>>(); |
|||
|
|||
foreach (var v in visuals.Cast<Visual>()) |
|||
{ |
|||
boundsSubscriptions.Add(v.GetObservable(Visual.BoundsProperty)); |
|||
} |
|||
|
|||
var bounds = Observable.CombineLatest(boundsSubscriptions).Select(ExtractBounds); |
|||
|
|||
// TODO: Track transform and clip rectangle.
|
|||
return Observable.Select(bounds, x => new TransformedBounds((Rect)x, (Rect)new Rect(), (Matrix)Matrix.Identity)); |
|||
} |
|||
|
|||
private static Rect ExtractBounds(IList<Rect> rects) |
|||
{ |
|||
var position = rects.Select(x => x.Position).Aggregate((a, b) => a + b); |
|||
return new Rect(position, rects.Last().Size); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,24 @@ |
|||
// -----------------------------------------------------------------------
|
|||
// <copyright file="TransformedBounds.cs" company="Steven Kirk">
|
|||
// Copyright 2015 MIT Licence. See licence.md for more information.
|
|||
// </copyright>
|
|||
// -----------------------------------------------------------------------
|
|||
|
|||
namespace Perspex.VisualTree |
|||
{ |
|||
public class TransformedBounds |
|||
{ |
|||
public TransformedBounds(Rect bounds, Rect clip, Matrix transform) |
|||
{ |
|||
this.Bounds = bounds; |
|||
this.Clip = clip; |
|||
this.Transform = transform; |
|||
} |
|||
|
|||
public Rect Bounds { get; } |
|||
|
|||
public Rect Clip { get; } |
|||
|
|||
public Matrix Transform { get; } |
|||
} |
|||
} |
|||
@ -0,0 +1,55 @@ |
|||
// -----------------------------------------------------------------------
|
|||
// <copyright file="BoundsTracker.cs" company="Steven Kirk">
|
|||
// Copyright 2015 MIT Licence. See licence.md for more information.
|
|||
// </copyright>
|
|||
// -----------------------------------------------------------------------
|
|||
|
|||
namespace Perspex.SceneGraph.UnitTests.VisualTree |
|||
{ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Reactive.Linq; |
|||
using Perspex.Controls; |
|||
using Perspex.Controls.Shapes; |
|||
using Perspex.VisualTree; |
|||
using Xunit; |
|||
|
|||
public class BoundsTrackerTests |
|||
{ |
|||
[Fact] |
|||
public void Should_Track_Bounds() |
|||
{ |
|||
var target = new BoundsTracker(); |
|||
var control = default(Rectangle); |
|||
var tree = new Decorator |
|||
{ |
|||
Padding = new Thickness(10), |
|||
Content = new Decorator |
|||
{ |
|||
Padding = new Thickness(5), |
|||
Content = (control = new Rectangle |
|||
{ |
|||
Width = 15, |
|||
Height = 15, |
|||
}), |
|||
} |
|||
}; |
|||
|
|||
tree.Measure(Size.Infinity); |
|||
tree.Arrange(new Rect(0, 0, 100, 100)); |
|||
|
|||
var track = target.Track(control, tree); |
|||
var results = new List<TransformedBounds>(); |
|||
track.Subscribe(results.Add); |
|||
|
|||
Assert.Equal(new Rect(15, 15, 15, 15), results.Last().Bounds); |
|||
|
|||
tree.Padding = new Thickness(15); |
|||
tree.Measure(Size.Infinity); |
|||
tree.Arrange(new Rect(0, 0, 100, 100), true); |
|||
|
|||
Assert.Equal(new Rect(20, 20, 15, 15), results.Last().Bounds); |
|||
} |
|||
} |
|||
} |
|||
@ -1,10 +1,16 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<packages> |
|||
<package id="Splat" version="1.6.1" targetFramework="net45" /> |
|||
<package id="xunit" version="2.0.0" targetFramework="net45" /> |
|||
<package id="xunit.abstractions" version="2.0.0" targetFramework="net45" /> |
|||
<package id="xunit.assert" version="2.0.0" targetFramework="net45" /> |
|||
<package id="xunit.core" version="2.0.0" targetFramework="net45" /> |
|||
<package id="xunit.extensibility.core" version="2.0.0" targetFramework="net45" /> |
|||
<package id="xunit.runner.visualstudio" version="2.0.0" targetFramework="net45" /> |
|||
<package id="Moq" version="4.2.1502.911" targetFramework="net45" userInstalled="true" /> |
|||
<package id="Rx-Core" version="2.2.5" targetFramework="net45" userInstalled="true" /> |
|||
<package id="Rx-Interfaces" version="2.2.5" targetFramework="net45" userInstalled="true" /> |
|||
<package id="Rx-Linq" version="2.2.5" targetFramework="net45" userInstalled="true" /> |
|||
<package id="Rx-Main" version="2.2.5" targetFramework="net45" userInstalled="true" /> |
|||
<package id="Rx-PlatformServices" version="2.2.5" targetFramework="net45" userInstalled="true" /> |
|||
<package id="Splat" version="1.6.1" targetFramework="net45" userInstalled="true" /> |
|||
<package id="xunit" version="2.0.0" targetFramework="net45" userInstalled="true" /> |
|||
<package id="xunit.abstractions" version="2.0.0" targetFramework="net45" userInstalled="true" /> |
|||
<package id="xunit.assert" version="2.0.0" targetFramework="net45" userInstalled="true" /> |
|||
<package id="xunit.core" version="2.0.0" targetFramework="net45" userInstalled="true" /> |
|||
<package id="xunit.extensibility.core" version="2.0.0" targetFramework="net45" userInstalled="true" /> |
|||
<package id="xunit.runner.visualstudio" version="2.0.0" targetFramework="net45" userInstalled="true" /> |
|||
</packages> |
|||
Loading…
Reference in new issue