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> </Otherwise>
</Choose> </Choose>
<ItemGroup> <ItemGroup>
<Compile Include="DropDownTests.cs" />
<Compile Include="ItemsControlTests.cs" /> <Compile Include="ItemsControlTests.cs" />
<Compile Include="ContentControlTests.cs" /> <Compile Include="ContentControlTests.cs" />
<Compile Include="DecoratorTests.cs" /> <Compile Include="DecoratorTests.cs" />

42
Perspex.Controls/ContentControl.cs

@ -31,21 +31,7 @@ namespace Perspex.Controls
public ContentControl() public ContentControl()
{ {
this.GetObservableWithHistory(ContentProperty).Subscribe(x => this.GetObservableWithHistory(ContentProperty).Subscribe(this.SetContentParent);
{
var control1 = x.Item1 as Control;
var control2 = x.Item2 as Control;
if (control1 != null)
{
control1.Parent = null;
}
if (control2 != null)
{
control2.Parent = this;
}
});
} }
public object Content public object Content
@ -54,11 +40,6 @@ namespace Perspex.Controls
set { this.SetValue(ContentProperty, value); } set { this.SetValue(ContentProperty, value); }
} }
IReadOnlyPerspexList<ILogical> ILogical.LogicalChildren
{
get { return this.logicalChild; }
}
public HorizontalAlignment HorizontalContentAlignment public HorizontalAlignment HorizontalContentAlignment
{ {
get { return this.GetValue(HorizontalContentAlignmentProperty); } get { return this.GetValue(HorizontalContentAlignmentProperty); }
@ -71,6 +52,11 @@ namespace Perspex.Controls
set { this.SetValue(VerticalContentAlignmentProperty, value); } set { this.SetValue(VerticalContentAlignmentProperty, value); }
} }
IReadOnlyPerspexList<ILogical> ILogical.LogicalChildren
{
get { return this.logicalChild; }
}
protected override void OnTemplateApplied() protected override void OnTemplateApplied()
{ {
if (this.presenterSubscription != null) if (this.presenterSubscription != null)
@ -87,5 +73,21 @@ namespace Perspex.Controls
.Subscribe(x => this.logicalChild.SingleItem = x); .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 namespace Perspex.Controls
{ {
using System; using System;
using Perspex.Collections;
using Perspex.Controls.Presenters;
using Perspex.Controls.Primitives; using Perspex.Controls.Primitives;
using Perspex.Layout; using Perspex.Layout;
public class DropDown : SelectingItemsControl, IContentControl public class DropDown : SelectingItemsControl, IContentControl, ILogical
{ {
public static readonly PerspexProperty<object> ContentProperty = public static readonly PerspexProperty<object> ContentProperty =
ContentControl.ContentProperty.AddOwner<DropDown>(); ContentControl.ContentProperty.AddOwner<DropDown>();
@ -24,6 +26,17 @@ namespace Perspex.Controls
public static readonly PerspexProperty<bool> IsDropDownOpenProperty = public static readonly PerspexProperty<bool> IsDropDownOpenProperty =
PerspexProperty.Register<DropDown, bool>("IsDropDownOpen"); 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 public object Content
{ {
get { return this.GetValue(ContentProperty); } get { return this.GetValue(ContentProperty); }
@ -41,5 +54,43 @@ namespace Perspex.Controls
get { return this.GetValue(VerticalContentAlignmentProperty); } get { return this.GetValue(VerticalContentAlignmentProperty); }
set { this.SetValue(VerticalContentAlignmentProperty, value); } 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