Browse Source

Implement ILogical on DropDown.

pull/39/head
Steven Kirk 11 years ago
parent
commit
7a8a9123c3
  1. 254
      Perspex.Controls.UnitTests/DropDownTests.cs
  2. 1
      Perspex.Controls.UnitTests/Perspex.Controls.UnitTests.csproj
  3. 42
      Perspex.Controls/ContentControl.cs
  4. 53
      Perspex.Controls/DropDown.cs

254
Perspex.Controls.UnitTests/DropDownTests.cs

@ -0,0 +1,254 @@
// -----------------------------------------------------------------------
// <copyright file="DropDownTests.cs" company="Steven Kirk">
// Copyright 2014 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Controls.UnitTests
{
using System;
using System.Collections.Specialized;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using Perspex.Controls;
using Perspex.Controls.Presenters;
using Perspex.Platform;
using Perspex.Styling;
using Perspex.VisualTree;
using Ploeh.AutoFixture;
using Ploeh.AutoFixture.AutoMoq;
using Splat;
[TestClass]
public class DropDownTests
{
[TestMethod]
public void Template_Should_Be_Instantiated()
{
using (var ctx = this.RegisterServices())
{
var target = new DropDown();
target.Content = "Foo";
target.Template = this.GetTemplate();
target.Measure(new Size(100, 100));
var child = ((IVisual)target).VisualChildren.Single();
Assert.IsInstanceOfType(child, typeof(Border));
child = child.VisualChildren.Single();
Assert.IsInstanceOfType(child, typeof(ContentPresenter));
child = child.VisualChildren.Single();
Assert.IsInstanceOfType(child, typeof(TextBlock));
}
}
[TestMethod]
public void Templated_Children_Should_Be_Styled()
{
using (var ctx = this.RegisterServices())
{
var root = new TestRoot();
var target = new DropDown();
var styler = new Mock<IStyler>();
Locator.CurrentMutable.Register(() => styler.Object, typeof(IStyler));
target.Content = "Foo";
target.Template = this.GetTemplate();
root.Content = target;
target.ApplyTemplate();
styler.Verify(x => x.ApplyStyles(It.IsAny<DropDown>()), Times.Once());
styler.Verify(x => x.ApplyStyles(It.IsAny<Border>()), Times.Once());
styler.Verify(x => x.ApplyStyles(It.IsAny<ContentPresenter>()), Times.Once());
styler.Verify(x => x.ApplyStyles(It.IsAny<TextBlock>()), Times.Once());
}
}
[TestMethod]
public void ContentPresenter_Should_Have_TemplatedParent_Set()
{
var target = new DropDown();
var child = new Border();
target.Template = this.GetTemplate();
target.Content = child;
target.ApplyTemplate();
var contentPresenter = child.GetVisualParent<ContentPresenter>();
Assert.AreEqual(target, contentPresenter.TemplatedParent);
}
[TestMethod]
public void Content_Should_Have_TemplatedParent_Set_To_Null()
{
var target = new DropDown();
var child = new Border();
target.Template = this.GetTemplate();
target.Content = child;
target.ApplyTemplate();
Assert.IsNull(child.TemplatedParent);
}
[TestMethod]
public void Setting_Content_Should_Set_Child_Controls_Parent()
{
var target = new DropDown();
var child = new Control();
target.Content = child;
Assert.AreEqual(child.Parent, target);
Assert.AreEqual(((ILogical)child).LogicalParent, target);
}
[TestMethod]
public void Clearing_Content_Should_Clear_Child_Controls_Parent()
{
var target = new DropDown();
var child = new Control();
target.Content = child;
target.Content = null;
Assert.IsNull(child.Parent);
Assert.IsNull(((ILogical)child).LogicalParent);
}
[TestMethod]
public void Setting_Content_To_Control_Should_Make_Control_Appear_In_LogicalChildren()
{
var target = new DropDown();
var child = new Control();
target.Template = this.GetTemplate();
target.Content = child;
target.ApplyTemplate();
CollectionAssert.AreEqual(new[] { child }, ((ILogical)target).LogicalChildren.ToList());
}
[TestMethod]
public void Setting_Content_To_String_Should_Make_TextBlock_Appear_In_LogicalChildren()
{
var target = new DropDown();
var child = new Control();
target.Template = this.GetTemplate();
target.Content = "Foo";
target.ApplyTemplate();
var logical = (ILogical)target;
Assert.AreEqual(1, logical.LogicalChildren.Count);
Assert.IsInstanceOfType(logical.LogicalChildren[0], typeof(TextBlock));
}
[TestMethod]
public void Clearing_Content_Should_Remove_From_LogicalChildren()
{
var target = new DropDown();
var child = new Control();
target.Content = child;
target.Content = null;
CollectionAssert.AreEqual(new ILogical[0], ((ILogical)target).LogicalChildren.ToList());
}
[TestMethod]
public void Setting_Content_Should_Fire_LogicalChildren_CollectionChanged()
{
var target = new DropDown();
var child = new Control();
var called = false;
((ILogical)target).LogicalChildren.CollectionChanged += (s, e) =>
called = e.Action == NotifyCollectionChangedAction.Add;
target.Template = this.GetTemplate();
target.Content = child;
target.ApplyTemplate();
// Need to call ApplyTemplate on presenter for CollectionChanged to be called.
var presenter = target.GetTemplateControls().Single(x => x.Id == "contentPresenter");
presenter.ApplyTemplate();
Assert.IsTrue(called);
}
[TestMethod]
public void Clearing_Content_Should_Fire_LogicalChildren_CollectionChanged()
{
var target = new DropDown();
var child = new Control();
var called = false;
target.Template = this.GetTemplate();
target.Content = child;
target.ApplyTemplate();
((ILogical)target).LogicalChildren.CollectionChanged += (s, e) =>
called = e.Action == NotifyCollectionChangedAction.Remove;
target.Content = null;
// Need to call ApplyTemplate on presenter for CollectionChanged to be called.
var presenter = target.GetTemplateControls().Single(x => x.Id == "contentPresenter");
presenter.ApplyTemplate();
Assert.IsTrue(called);
}
[TestMethod]
public void Changing_Content_Should_Fire_LogicalChildren_CollectionChanged()
{
var target = new DropDown();
var child1 = new Control();
var child2 = new Control();
var called = false;
target.Template = this.GetTemplate();
target.Content = child1;
target.ApplyTemplate();
((ILogical)target).LogicalChildren.CollectionChanged += (s, e) =>
called = e.Action == NotifyCollectionChangedAction.Replace;
target.Content = child2;
// Need to call ApplyTemplate on presenter for CollectionChanged to be called.
var presenter = target.GetTemplateControls().Single(x => x.Id == "contentPresenter");
presenter.ApplyTemplate();
Assert.IsTrue(called);
}
private ControlTemplate GetTemplate()
{
return ControlTemplate.Create<DropDown>(parent =>
{
return new Border
{
Background = new Perspex.Media.SolidColorBrush(0xffffffff),
Content = new ContentPresenter
{
Id = "contentPresenter",
[~ContentPresenter.ContentProperty] = parent[~DropDown.ContentProperty],
}
};
});
}
private IDisposable RegisterServices()
{
var result = Locator.CurrentMutable.WithResolver();
var fixture = new Fixture().Customize(new AutoMoqCustomization());
var renderInterface = fixture.Create<IPlatformRenderInterface>();
Locator.CurrentMutable.RegisterConstant(renderInterface, typeof(IPlatformRenderInterface));
return result;
}
}
}

1
Perspex.Controls.UnitTests/Perspex.Controls.UnitTests.csproj

@ -64,6 +64,7 @@
</Otherwise>
</Choose>
<ItemGroup>
<Compile Include="DropDownTests.cs" />
<Compile Include="ItemsControlTests.cs" />
<Compile Include="ContentControlTests.cs" />
<Compile Include="DecoratorTests.cs" />

42
Perspex.Controls/ContentControl.cs

@ -31,21 +31,7 @@ namespace Perspex.Controls
public ContentControl()
{
this.GetObservableWithHistory(ContentProperty).Subscribe(x =>
{
var control1 = x.Item1 as Control;
var control2 = x.Item2 as Control;
if (control1 != null)
{
control1.Parent = null;
}
if (control2 != null)
{
control2.Parent = this;
}
});
this.GetObservableWithHistory(ContentProperty).Subscribe(this.SetContentParent);
}
public object Content
@ -54,11 +40,6 @@ namespace Perspex.Controls
set { this.SetValue(ContentProperty, value); }
}
IReadOnlyPerspexList<ILogical> ILogical.LogicalChildren
{
get { return this.logicalChild; }
}
public HorizontalAlignment HorizontalContentAlignment
{
get { return this.GetValue(HorizontalContentAlignmentProperty); }
@ -71,6 +52,11 @@ namespace Perspex.Controls
set { this.SetValue(VerticalContentAlignmentProperty, value); }
}
IReadOnlyPerspexList<ILogical> ILogical.LogicalChildren
{
get { return this.logicalChild; }
}
protected override void OnTemplateApplied()
{
if (this.presenterSubscription != null)
@ -87,5 +73,21 @@ namespace Perspex.Controls
.Subscribe(x => this.logicalChild.SingleItem = x);
}
}
private void SetContentParent(Tuple<object, object> change)
{
var control1 = change.Item1 as Control;
var control2 = change.Item2 as Control;
if (control1 != null)
{
control1.Parent = null;
}
if (control2 != null)
{
control2.Parent = this;
}
}
}
}

53
Perspex.Controls/DropDown.cs

@ -7,10 +7,12 @@
namespace Perspex.Controls
{
using System;
using Perspex.Collections;
using Perspex.Controls.Presenters;
using Perspex.Controls.Primitives;
using Perspex.Layout;
public class DropDown : SelectingItemsControl, IContentControl
public class DropDown : SelectingItemsControl, IContentControl, ILogical
{
public static readonly PerspexProperty<object> ContentProperty =
ContentControl.ContentProperty.AddOwner<DropDown>();
@ -24,6 +26,17 @@ namespace Perspex.Controls
public static readonly PerspexProperty<bool> IsDropDownOpenProperty =
PerspexProperty.Register<DropDown, bool>("IsDropDownOpen");
private SingleItemPerspexList<ILogical> logicalChild = new SingleItemPerspexList<ILogical>();
private ContentPresenter presenter;
private IDisposable presenterSubscription;
public DropDown()
{
this.GetObservableWithHistory(ContentProperty).Subscribe(this.SetContentParent);
}
public object Content
{
get { return this.GetValue(ContentProperty); }
@ -41,5 +54,43 @@ namespace Perspex.Controls
get { return this.GetValue(VerticalContentAlignmentProperty); }
set { this.SetValue(VerticalContentAlignmentProperty, value); }
}
IReadOnlyPerspexList<ILogical> ILogical.LogicalChildren
{
get { return this.logicalChild; }
}
protected override void OnTemplateApplied()
{
if (this.presenterSubscription != null)
{
this.presenterSubscription.Dispose();
this.presenterSubscription = null;
}
this.presenter = this.FindTemplateChild<ContentPresenter>("contentPresenter");
if (this.presenter != null)
{
this.presenterSubscription = this.presenter.ChildObservable
.Subscribe(x => this.logicalChild.SingleItem = x);
}
}
private void SetContentParent(Tuple<object, object> change)
{
var control1 = change.Item1 as Control;
var control2 = change.Item2 as Control;
if (control1 != null)
{
control1.Parent = null;
}
if (control2 != null)
{
control2.Parent = this;
}
}
}
}

Loading…
Cancel
Save