82 changed files with 1603 additions and 319 deletions
@ -0,0 +1,30 @@ |
|||
// Copyright (c) The Perspex Project. All rights reserved.
|
|||
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
|||
|
|||
namespace Perspex.Markup.Xaml.Context |
|||
{ |
|||
internal class NameScopeWrapper : OmniXaml.INameScope |
|||
{ |
|||
private Perspex.INameScope _inner; |
|||
|
|||
public NameScopeWrapper(Perspex.INameScope inner) |
|||
{ |
|||
_inner = inner; |
|||
} |
|||
|
|||
public object Find(string name) |
|||
{ |
|||
return _inner.Find(name); |
|||
} |
|||
|
|||
public void Register(string name, object scopedElement) |
|||
{ |
|||
_inner.Register(name, scopedElement); |
|||
} |
|||
|
|||
public void Unregister(string name) |
|||
{ |
|||
_inner.Unregister(name); |
|||
} |
|||
} |
|||
} |
|||
@ -1 +1 @@ |
|||
Subproject commit 55fc2abc715885d3686f8c8605f34714445cd72f |
|||
Subproject commit 3e3b46ba66941da925092e2977003d0553cfc907 |
|||
@ -0,0 +1,60 @@ |
|||
// Copyright (c) The Perspex Project. All rights reserved.
|
|||
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
|||
|
|||
using System; |
|||
using System.Linq; |
|||
using System.Reactive.Linq; |
|||
using Perspex.Controls; |
|||
|
|||
namespace Perspex.Markup |
|||
{ |
|||
/// <summary>
|
|||
/// Locates controls relative to other controls.
|
|||
/// </summary>
|
|||
public static class ControlLocator |
|||
{ |
|||
/// <summary>
|
|||
/// Tracks a named control relative to another control.
|
|||
/// </summary>
|
|||
/// <param name="relativeTo">
|
|||
/// The control relative from which the other control should be found.
|
|||
/// </param>
|
|||
/// <param name="name">The name of the control to find.</param>
|
|||
public static IObservable<IControl> Track(IControl relativeTo, string name) |
|||
{ |
|||
var attached = Observable.FromEventPattern<VisualTreeAttachmentEventArgs>( |
|||
x => relativeTo.AttachedToVisualTree += x, |
|||
x => relativeTo.DetachedFromVisualTree += x) |
|||
.Select(x => x.EventArgs.NameScope) |
|||
.StartWith(relativeTo.FindNameScope()); |
|||
|
|||
var detached = Observable.FromEventPattern<VisualTreeAttachmentEventArgs>( |
|||
x => relativeTo.DetachedFromVisualTree += x, |
|||
x => relativeTo.DetachedFromVisualTree += x) |
|||
.Select(x => (INameScope)null); |
|||
|
|||
return attached.Merge(detached).Select(nameScope => |
|||
{ |
|||
if (nameScope != null) |
|||
{ |
|||
var registered = Observable.FromEventPattern<NameScopeEventArgs>( |
|||
x => nameScope.Registered += x, |
|||
x => nameScope.Registered -= x) |
|||
.Where(x => x.EventArgs.Name == name) |
|||
.Select(x => x.EventArgs.Element) |
|||
.OfType<IControl>(); |
|||
var unregistered = Observable.FromEventPattern<NameScopeEventArgs>( |
|||
x => nameScope.Unregistered += x, |
|||
x => nameScope.Unregistered -= x); |
|||
return registered |
|||
.StartWith(nameScope.Find<IControl>(name)) |
|||
.TakeUntil(unregistered); |
|||
} |
|||
else |
|||
{ |
|||
return Observable.Return<IControl>(null); |
|||
} |
|||
}).Switch(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,43 @@ |
|||
// Copyright (c) The Perspex Project. All rights reserved.
|
|||
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
|||
|
|||
using System; |
|||
|
|||
namespace Perspex |
|||
{ |
|||
/// <summary>
|
|||
/// Defines a name scope.
|
|||
/// </summary>
|
|||
public interface INameScope |
|||
{ |
|||
/// <summary>
|
|||
/// Raised when an element is registered with the name scope.
|
|||
/// </summary>
|
|||
event EventHandler<NameScopeEventArgs> Registered; |
|||
|
|||
/// <summary>
|
|||
/// Raised when an element is unregistered with the name scope.
|
|||
/// </summary>
|
|||
event EventHandler<NameScopeEventArgs> Unregistered; |
|||
|
|||
/// <summary>
|
|||
/// Registers an element eith the name scope.
|
|||
/// </summary>
|
|||
/// <param name="name">The element name.</param>
|
|||
/// <param name="element">The element.</param>
|
|||
void Register(string name, object element); |
|||
|
|||
/// <summary>
|
|||
/// Finds a named element in the name scope.
|
|||
/// </summary>
|
|||
/// <param name="name">The name.</param>
|
|||
/// <returns>The element, or null if the name was not found.</returns>
|
|||
object Find(string name); |
|||
|
|||
/// <summary>
|
|||
/// Unregisters an element with the name scope.
|
|||
/// </summary>
|
|||
/// <param name="name">The name.</param>
|
|||
void Unregister(string name); |
|||
} |
|||
} |
|||
@ -1,10 +1,16 @@ |
|||
// Copyright (c) The Perspex Project. All rights reserved.
|
|||
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
|||
|
|||
namespace Perspex.Styling |
|||
namespace Perspex |
|||
{ |
|||
/// <summary>
|
|||
/// Interface for named elements.
|
|||
/// </summary>
|
|||
public interface INamed |
|||
{ |
|||
/// <summary>
|
|||
/// Gets the element name.
|
|||
/// </summary>
|
|||
string Name { get; } |
|||
} |
|||
} |
|||
@ -0,0 +1,109 @@ |
|||
// Copyright (c) The Perspex Project. All rights reserved.
|
|||
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
|
|||
namespace Perspex |
|||
{ |
|||
/// <summary>
|
|||
/// Implements a name scope.
|
|||
/// </summary>
|
|||
public class NameScope : INameScope |
|||
{ |
|||
/// <summary>
|
|||
/// Defines the NameScope attached property.
|
|||
/// </summary>
|
|||
public static readonly PerspexProperty<INameScope> NameScopeProperty = |
|||
PerspexProperty.RegisterAttached<NameScope, Visual, INameScope>("NameScope"); |
|||
|
|||
private readonly Dictionary<string, object> _inner = new Dictionary<string, object>(); |
|||
|
|||
/// <summary>
|
|||
/// Raised when an element is registered with the name scope.
|
|||
/// </summary>
|
|||
public event EventHandler<NameScopeEventArgs> Registered; |
|||
|
|||
/// <summary>
|
|||
/// Raised when an element is unregistered with the name scope.
|
|||
/// </summary>
|
|||
public event EventHandler<NameScopeEventArgs> Unregistered; |
|||
|
|||
/// <summary>
|
|||
/// Gets the value of the attached <see cref="NameScopeProperty"/> on a visual.
|
|||
/// </summary>
|
|||
/// <param name="visual">The visual.</param>
|
|||
/// <returns>The value of the NameScope attached property.</returns>
|
|||
public static INameScope GetNameScope(Visual visual) |
|||
{ |
|||
return visual.GetValue(NameScopeProperty); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Sets the value of the attached <see cref="NameScopeProperty"/> on a visual.
|
|||
/// </summary>
|
|||
/// <param name="visual">The visual.</param>
|
|||
/// <param name="value">The value to set.</param>
|
|||
public static void SetNameScope(Visual visual, INameScope value) |
|||
{ |
|||
visual.SetValue(NameScopeProperty, value); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Registers an element with the name scope.
|
|||
/// </summary>
|
|||
/// <param name="name">The element name.</param>
|
|||
/// <param name="element">The element.</param>
|
|||
public void Register(string name, object element) |
|||
{ |
|||
Contract.Requires<ArgumentNullException>(name != null); |
|||
Contract.Requires<ArgumentNullException>(element != null); |
|||
|
|||
object existing; |
|||
|
|||
if (_inner.TryGetValue(name, out existing)) |
|||
{ |
|||
if (existing != element) |
|||
{ |
|||
throw new ArgumentException($"Control with the name '{name}' already registered."); |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
_inner.Add(name, element); |
|||
Registered?.Invoke(this, new NameScopeEventArgs(name, element)); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Finds a named element in the name scope.
|
|||
/// </summary>
|
|||
/// <param name="name">The name.</param>
|
|||
/// <returns>The element, or null if the name was not found.</returns>
|
|||
public object Find(string name) |
|||
{ |
|||
Contract.Requires<ArgumentNullException>(name != null); |
|||
|
|||
object result; |
|||
_inner.TryGetValue(name, out result); |
|||
return result; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Unregisters an element with the name scope.
|
|||
/// </summary>
|
|||
/// <param name="name">The name.</param>
|
|||
public void Unregister(string name) |
|||
{ |
|||
Contract.Requires<ArgumentNullException>(name != null); |
|||
|
|||
object element; |
|||
|
|||
if (_inner.TryGetValue(name, out element)) |
|||
{ |
|||
_inner.Remove(name); |
|||
Registered?.Invoke(this, new NameScopeEventArgs(name, element)); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,19 @@ |
|||
// Copyright (c) The Perspex Project. All rights reserved.
|
|||
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
|||
|
|||
using System; |
|||
|
|||
namespace Perspex |
|||
{ |
|||
public class NameScopeEventArgs : EventArgs |
|||
{ |
|||
public NameScopeEventArgs(string name, object element) |
|||
{ |
|||
Name = name; |
|||
Element = element; |
|||
} |
|||
|
|||
public string Name { get; } |
|||
public object Element { get; } |
|||
} |
|||
} |
|||
@ -0,0 +1,68 @@ |
|||
// Copyright (c) The Perspex Project. All rights reserved.
|
|||
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
|
|||
namespace Perspex |
|||
{ |
|||
/// <summary>
|
|||
/// Extension methods for <see cref="INameScope"/>.
|
|||
/// </summary>
|
|||
public static class NameScopeExtensions |
|||
{ |
|||
/// <summary>
|
|||
/// Finds a named element in an <see cref="INameScope"/>.
|
|||
/// </summary>
|
|||
/// <typeparam name="T">The element type.</typeparam>
|
|||
/// <param name="nameScope">The name scope.</param>
|
|||
/// <param name="name">The name.</param>
|
|||
/// <returns>The named element or null if not found.</returns>
|
|||
public static T Find<T>(this INameScope nameScope, string name) |
|||
where T : class |
|||
{ |
|||
Contract.Requires<ArgumentNullException>(nameScope != null); |
|||
Contract.Requires<ArgumentNullException>(name != null); |
|||
|
|||
var result = nameScope.Find(name); |
|||
|
|||
if (result != null && !(result is T)) |
|||
{ |
|||
throw new InvalidOperationException( |
|||
$"Expected control '{name}' to be '{typeof(T)} but it was '{result.GetType()}'."); |
|||
} |
|||
|
|||
return (T)result; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets a named element from an <see cref="INameScope"/> or throws if no element of the
|
|||
/// requested name was found.
|
|||
/// </summary>
|
|||
/// <typeparam name="T">The element type.</typeparam>
|
|||
/// <param name="nameScope">The name scope.</param>
|
|||
/// <param name="name">The name.</param>
|
|||
/// <returns>The named element.</returns>
|
|||
public static T Get<T>(this INameScope nameScope, string name) |
|||
where T : class |
|||
{ |
|||
Contract.Requires<ArgumentNullException>(nameScope != null); |
|||
Contract.Requires<ArgumentNullException>(name != null); |
|||
|
|||
var result = nameScope.Find(name); |
|||
|
|||
if (result == null) |
|||
{ |
|||
throw new KeyNotFoundException($"Could not find control '{name}'."); |
|||
} |
|||
|
|||
if (!(result is T)) |
|||
{ |
|||
throw new InvalidOperationException( |
|||
$"Expected control '{name}' to be '{typeof(T)} but it was '{result.GetType()}'."); |
|||
} |
|||
|
|||
return (T)result; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,36 @@ |
|||
// Copyright (c) The Perspex Project. All rights reserved.
|
|||
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
|||
|
|||
using System; |
|||
using Perspex.Rendering; |
|||
|
|||
namespace Perspex |
|||
{ |
|||
/// <summary>
|
|||
/// Holds the event arguments for the <see cref="Visual.AttachedToVisualTree"/> and
|
|||
/// <see cref="Visual.DetachedFromVisualTree"/> events.
|
|||
/// </summary>
|
|||
public class VisualTreeAttachmentEventArgs : EventArgs |
|||
{ |
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="VisualTreeAttachmentEventArgs"/> class.
|
|||
/// </summary>
|
|||
/// <param name="root">The root visual.</param>
|
|||
/// <param name="nameScope">The name scope.</param>
|
|||
public VisualTreeAttachmentEventArgs(IRenderRoot root, INameScope nameScope) |
|||
{ |
|||
Root = root; |
|||
NameScope = nameScope; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the root of the visual tree that the visual is being attached to or detached from.
|
|||
/// </summary>
|
|||
public IRenderRoot Root { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the element's name scope.
|
|||
/// </summary>
|
|||
public INameScope NameScope { get; } |
|||
} |
|||
} |
|||
@ -0,0 +1,122 @@ |
|||
// Copyright (c) The Perspex Project. All rights reserved.
|
|||
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Reactive.Linq; |
|||
using Perspex.Controls; |
|||
using Xunit; |
|||
|
|||
namespace Perspex.Markup.UnitTests |
|||
{ |
|||
public class ControlLocatorTests |
|||
{ |
|||
[Fact] |
|||
public async void Track_By_Name_Should_Find_Control_Added_Earlier() |
|||
{ |
|||
TextBlock target; |
|||
TextBlock relativeTo; |
|||
|
|||
var root = new TestRoot |
|||
{ |
|||
Child = new StackPanel |
|||
{ |
|||
Children = new Controls.Controls |
|||
{ |
|||
(target = new TextBlock { Name = "target" }), |
|||
(relativeTo = new TextBlock { Name = "start" }), |
|||
} |
|||
} |
|||
}; |
|||
|
|||
var locator = ControlLocator.Track(relativeTo, "target"); |
|||
var result = await locator.Take(1); |
|||
|
|||
Assert.Same(target, result); |
|||
Assert.Equal(0, root.NameScopeRegisteredSubscribers); |
|||
Assert.Equal(0, root.NameScopeUnregisteredSubscribers); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Track_By_Name_Should_Find_Control_Added_Later() |
|||
{ |
|||
StackPanel panel; |
|||
TextBlock relativeTo; |
|||
|
|||
var root = new TestRoot |
|||
{ |
|||
Child = (panel = new StackPanel |
|||
{ |
|||
Children = new Controls.Controls |
|||
{ |
|||
(relativeTo = new TextBlock |
|||
{ |
|||
Name = "start" |
|||
}), |
|||
} |
|||
}) |
|||
}; |
|||
|
|||
var locator = ControlLocator.Track(relativeTo, "target"); |
|||
var target = new TextBlock { Name = "target" }; |
|||
var result = new List<IControl>(); |
|||
|
|||
using (locator.Subscribe(x => result.Add(x))) |
|||
{ |
|||
panel.Children.Add(target); |
|||
} |
|||
|
|||
Assert.Equal(new[] { null, target }, result); |
|||
Assert.Equal(0, root.NameScopeRegisteredSubscribers); |
|||
Assert.Equal(0, root.NameScopeUnregisteredSubscribers); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Track_By_Name_Should_Find_Control_When_Tree_Changed() |
|||
{ |
|||
TextBlock target1; |
|||
TextBlock target2; |
|||
TextBlock relativeTo; |
|||
|
|||
var root1 = new TestRoot |
|||
{ |
|||
Child = new StackPanel |
|||
{ |
|||
Children = new Controls.Controls |
|||
{ |
|||
(relativeTo = new TextBlock |
|||
{ |
|||
Name = "start" |
|||
}), |
|||
(target1 = new TextBlock { Name = "target" }), |
|||
} |
|||
} |
|||
}; |
|||
|
|||
var root2 = new TestRoot |
|||
{ |
|||
Child = new StackPanel |
|||
{ |
|||
Children = new Controls.Controls |
|||
{ |
|||
(target2 = new TextBlock { Name = "target" }), |
|||
} |
|||
} |
|||
}; |
|||
|
|||
var locator = ControlLocator.Track(relativeTo, "target"); |
|||
var target = new TextBlock { Name = "target" }; |
|||
var result = new List<IControl>(); |
|||
|
|||
using (locator.Subscribe(x => result.Add(x))) |
|||
{ |
|||
((StackPanel)root1.Child).Children.Remove(relativeTo); |
|||
((StackPanel)root2.Child).Children.Add(relativeTo); |
|||
} |
|||
|
|||
Assert.Equal(new[] { target1, null, target2 }, result); |
|||
Assert.Equal(0, root1.NameScopeRegisteredSubscribers); |
|||
Assert.Equal(0, root1.NameScopeUnregisteredSubscribers); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,61 @@ |
|||
// Copyright (c) The Perspex Project. All rights reserved.
|
|||
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
|||
|
|||
using System; |
|||
using Perspex.Controls; |
|||
using Perspex.Platform; |
|||
using Perspex.Rendering; |
|||
|
|||
namespace Perspex.Markup.UnitTests |
|||
{ |
|||
public class TestRoot : Decorator, IRenderRoot, INameScope |
|||
{ |
|||
private NameScope _nameScope = new NameScope(); |
|||
|
|||
event EventHandler<NameScopeEventArgs> INameScope.Registered |
|||
{ |
|||
add { _nameScope.Registered += value; ++NameScopeRegisteredSubscribers; } |
|||
remove { _nameScope.Registered -= value; --NameScopeRegisteredSubscribers; } |
|||
} |
|||
|
|||
public event EventHandler<NameScopeEventArgs> Unregistered |
|||
{ |
|||
add { _nameScope.Unregistered += value; ++NameScopeUnregisteredSubscribers; } |
|||
remove { _nameScope.Unregistered -= value; --NameScopeUnregisteredSubscribers; } |
|||
} |
|||
|
|||
public int NameScopeRegisteredSubscribers { get; private set; } |
|||
|
|||
public int NameScopeUnregisteredSubscribers { get; private set; } |
|||
|
|||
public IRenderTarget RenderTarget |
|||
{ |
|||
get { throw new NotImplementedException(); } |
|||
} |
|||
|
|||
public IRenderQueueManager RenderQueueManager |
|||
{ |
|||
get { throw new NotImplementedException(); } |
|||
} |
|||
|
|||
public Point TranslatePointToScreen(Point p) |
|||
{ |
|||
throw new NotImplementedException(); |
|||
} |
|||
|
|||
public void Register(string name, object element) |
|||
{ |
|||
_nameScope.Register(name, element); |
|||
} |
|||
|
|||
public object Find(string name) |
|||
{ |
|||
return _nameScope.Find(name); |
|||
} |
|||
|
|||
public void Unregister(string name) |
|||
{ |
|||
_nameScope.Unregister(name); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,83 @@ |
|||
// Copyright (c) The Perspex Project. All rights reserved.
|
|||
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
|||
|
|||
using Perspex.Controls; |
|||
using Perspex.Markup.Xaml.Data; |
|||
using Xunit; |
|||
|
|||
namespace Perspex.Markup.Xaml.UnitTests.Data |
|||
{ |
|||
public class BindingTests_ElementName |
|||
{ |
|||
[Fact] |
|||
public void Should_Bind_To_Element() |
|||
{ |
|||
TextBlock target; |
|||
var root = new TestRoot |
|||
{ |
|||
Child = new StackPanel |
|||
{ |
|||
Children = new Controls.Controls |
|||
{ |
|||
new TextBlock |
|||
{ |
|||
Name = "source", |
|||
Text = "foo", |
|||
}, |
|||
(target = new TextBlock |
|||
{ |
|||
Name = "target", |
|||
}) |
|||
} |
|||
} |
|||
}; |
|||
|
|||
var binding = new Binding |
|||
{ |
|||
ElementName = "source", |
|||
Path = "Text", |
|||
}; |
|||
|
|||
binding.Bind(target, TextBlock.TextProperty); |
|||
|
|||
Assert.Equal("foo", target.Text); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_Bind_To_Later_Added_Element() |
|||
{ |
|||
TextBlock target; |
|||
StackPanel stackPanel; |
|||
|
|||
var root = new TestRoot |
|||
{ |
|||
Child = stackPanel = new StackPanel |
|||
{ |
|||
Children = new Controls.Controls |
|||
{ |
|||
(target = new TextBlock |
|||
{ |
|||
Name = "target", |
|||
}), |
|||
} |
|||
} |
|||
}; |
|||
|
|||
var binding = new Binding |
|||
{ |
|||
ElementName = "source", |
|||
Path = "Text", |
|||
}; |
|||
|
|||
binding.Bind(target, TextBlock.TextProperty); |
|||
|
|||
stackPanel.Children.Add(new TextBlock |
|||
{ |
|||
Name = "source", |
|||
Text = "foo", |
|||
}); |
|||
|
|||
Assert.Equal("foo", target.Text); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,61 @@ |
|||
// Copyright (c) The Perspex Project. All rights reserved.
|
|||
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
|||
|
|||
using System; |
|||
using Perspex.Controls; |
|||
using Perspex.Platform; |
|||
using Perspex.Rendering; |
|||
|
|||
namespace Perspex.Markup.Xaml.UnitTests |
|||
{ |
|||
public class TestRoot : Decorator, IRenderRoot, INameScope |
|||
{ |
|||
private readonly NameScope _nameScope = new NameScope(); |
|||
|
|||
event EventHandler<NameScopeEventArgs> INameScope.Registered |
|||
{ |
|||
add { _nameScope.Registered += value; ++NameScopeRegisteredSubscribers; } |
|||
remove { _nameScope.Registered -= value; --NameScopeRegisteredSubscribers; } |
|||
} |
|||
|
|||
public event EventHandler<NameScopeEventArgs> Unregistered |
|||
{ |
|||
add { _nameScope.Unregistered += value; ++NameScopeUnregisteredSubscribers; } |
|||
remove { _nameScope.Unregistered -= value; --NameScopeUnregisteredSubscribers; } |
|||
} |
|||
|
|||
public int NameScopeRegisteredSubscribers { get; private set; } |
|||
|
|||
public int NameScopeUnregisteredSubscribers { get; private set; } |
|||
|
|||
public IRenderTarget RenderTarget |
|||
{ |
|||
get { throw new NotImplementedException(); } |
|||
} |
|||
|
|||
public IRenderQueueManager RenderQueueManager |
|||
{ |
|||
get { throw new NotImplementedException(); } |
|||
} |
|||
|
|||
public Point TranslatePointToScreen(Point p) |
|||
{ |
|||
throw new NotImplementedException(); |
|||
} |
|||
|
|||
public void Register(string name, object element) |
|||
{ |
|||
_nameScope.Register(name, element); |
|||
} |
|||
|
|||
public object Find(string name) |
|||
{ |
|||
return _nameScope.Find(name); |
|||
} |
|||
|
|||
public void Unregister(string name) |
|||
{ |
|||
_nameScope.Unregister(name); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,55 @@ |
|||
// Copyright (c) The Perspex Project. All rights reserved.
|
|||
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
|||
|
|||
using System; |
|||
using Xunit; |
|||
|
|||
namespace Perspex.SceneGraph.UnitTests |
|||
{ |
|||
public class NameScopeTests |
|||
{ |
|||
[Fact] |
|||
public void Register_Registers_Element() |
|||
{ |
|||
var target = new NameScope(); |
|||
var element = new object(); |
|||
|
|||
target.Register("foo", element); |
|||
|
|||
Assert.Same(element, target.Find("foo")); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Unregister_Unregisters_Element() |
|||
{ |
|||
var target = new NameScope(); |
|||
var element = new object(); |
|||
|
|||
target.Register("foo", element); |
|||
target.Unregister("foo"); |
|||
|
|||
Assert.Null(target.Find("foo")); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Cannot_Register_New_Element_With_Existing_Name() |
|||
{ |
|||
var target = new NameScope(); |
|||
|
|||
target.Register("foo", new object()); |
|||
Assert.Throws<ArgumentException>(() => target.Register("foo", new object())); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Can_Register_Same_Element_More_Than_Once() |
|||
{ |
|||
var target = new NameScope(); |
|||
var element = new object(); |
|||
|
|||
target.Register("foo", element); |
|||
target.Register("foo", element); |
|||
|
|||
Assert.Same(element, target.Find("foo")); |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue